hide based on attribute

This commit is contained in:
Nate Kelley 2025-09-29 19:08:33 -06:00
parent 5cf12e6b3d
commit 63e281feef
No known key found for this signature in database
GPG Key ID: FD90372AB8D98B4F
3 changed files with 79 additions and 41 deletions

View File

@ -4,6 +4,7 @@ import { Button } from '@/components/ui/buttons';
import { ArrowUp, Magnifier, Sparkle2 } from '@/components/ui/icons';
import Atom from '@/components/ui/icons/NucleoIconOutlined/atom';
import Microphone from '@/components/ui/icons/NucleoIconOutlined/microphone';
import { useMentionInputHasValue } from '@/components/ui/inputs/MentionInputSuggestions';
import { Popover } from '@/components/ui/popover';
import { AppSegmented, type AppSegmentedProps } from '@/components/ui/segmented';
import { AppTooltip } from '@/components/ui/tooltip';
@ -34,8 +35,10 @@ export const BusterChatInputButtons = React.memo(
onDictate,
onDictateListeningChange,
}: BusterChatInputButtons) => {
const { transcript, listening, resetTranscript, browserSupportsSpeechRecognition } =
useSpeechRecognition();
const { transcript, listening, browserSupportsSpeechRecognition } = useSpeechRecognition();
const hasValue = useMentionInputHasValue();
const disableSubmit = !hasValue;
const startListening = () => {
SpeechRecognition.startListening({ continuous: true });
@ -84,9 +87,9 @@ export const BusterChatInputButtons = React.memo(
prefix={<ArrowUp />}
onClick={submitting ? onStop : onSubmit}
loading={submitting}
disabled={disabled}
disabled={disabled || disableSubmit}
className={cn(
'origin-center transform-gpu transition-all duration-300 ease-out will-change-transform',
'origin-center transform-gpu transition-all duration-300 ease-out will-change-transform bg-transparent!',
!disabled && 'hover:scale-110 active:scale-95'
)}
/>

View File

@ -1,5 +1,6 @@
import { Command, useCommandState } from 'cmdk';
import { forwardRef, useCallback, useEffect, useImperativeHandle, useRef, useState } from 'react';
import { createContext, useContextSelector } from 'use-context-selector';
import { useMemoizedFn } from '@/hooks/useMemoizedFn';
import { cn } from '@/lib/utils';
import type { MentionInputProps, MentionInputRef } from '../MentionInput';
@ -160,49 +161,77 @@ export const MentionInputSuggestions = forwardRef<
);
return (
<Command
ref={commandRef}
label={ariaLabel}
className={cn('relative border rounded overflow-hidden bg-background shadow', className)}
shouldFilter={shouldFilter}
filter={filter || customFilter}
>
<MentionInputSuggestionsContainer className={inputContainerClassName}>
<MentionInputSuggestionsMentionsInput
ref={mentionsInputRef}
defaultValue={defaultValue}
readOnly={readOnly}
autoFocus={autoFocus}
placeholder={placeholder}
mentions={mentions}
value={value}
onChange={onChangeInputValue}
onMentionItemClick={onMentionItemClick}
onPressEnter={onPressEnter}
commandListNavigatedRef={commandListNavigatedRef}
disabled={disabled}
/>
{children && <div className="mt-3">{children}</div>}
</MentionInputSuggestionsContainer>
<SuggestionsSeperator />
<MentionInputSuggestionsList
show={showSuggestionList}
className={cn(suggestionsContainerClassName)}
<MentionInputSuggestionsProvider value={value}>
<Command
ref={commandRef}
label={ariaLabel}
className={cn('relative border rounded overflow-hidden bg-background shadow', className)}
shouldFilter={shouldFilter}
filter={filter || customFilter}
>
<MentionInputSuggestionsItemsSelector
suggestionItems={suggestionItems}
onSelect={onSelectItem}
addValueToInput={addSuggestionValueToInput}
closeOnSelect={closeSuggestionOnSelect}
/>
<MentionInputSuggestionsContainer className={inputContainerClassName}>
<MentionInputSuggestionsMentionsInput
ref={mentionsInputRef}
defaultValue={defaultValue}
readOnly={readOnly}
autoFocus={autoFocus}
placeholder={placeholder}
mentions={mentions}
value={value}
onChange={onChangeInputValue}
onMentionItemClick={onMentionItemClick}
onPressEnter={onPressEnter}
commandListNavigatedRef={commandListNavigatedRef}
disabled={disabled}
/>
{children && <div className="mt-3">{children}</div>}
</MentionInputSuggestionsContainer>
<SuggestionsSeperator />
<MentionInputSuggestionsList
show={showSuggestionList}
className={cn(suggestionsContainerClassName)}
>
<MentionInputSuggestionsItemsSelector
suggestionItems={suggestionItems}
onSelect={onSelectItem}
addValueToInput={addSuggestionValueToInput}
closeOnSelect={closeSuggestionOnSelect}
/>
<MentionInputSuggestionsEmpty emptyComponent={emptyComponent} />
</MentionInputSuggestionsList>
</Command>
<MentionInputSuggestionsEmpty emptyComponent={emptyComponent} />
</MentionInputSuggestionsList>
</Command>
</MentionInputSuggestionsProvider>
);
}
);
const MentionInputSuggestionsContext = createContext<{
value: string;
}>({
value: '',
});
const MentionInputSuggestionsProvider = ({
children,
value,
}: {
children: React.ReactNode;
value: string;
}) => {
return (
<MentionInputSuggestionsContext.Provider value={{ value }}>
{children}
</MentionInputSuggestionsContext.Provider>
);
};
const stableSelector = (x: { value: string }) => x.value.length > 0;
export const useMentionInputHasValue = () => {
const hasValue = useContextSelector(MentionInputSuggestionsContext, stableSelector);
return hasValue;
};
const SuggestionsSeperator = () => {
const hasResults = useCommandState((x) => x.filtered.count) > 0;
if (!hasResults) return null;

View File

@ -1,3 +1,5 @@
/** biome-ignore-all lint/a11y/useFocusableInteractive: no ally stuff. I don't give a piss about nothin but the tide. */
/** biome-ignore-all lint/a11y/useSemanticElements: test **/
import { useCommandState } from 'cmdk';
import type React from 'react';
import { cn } from '@/lib/utils';
@ -10,6 +12,8 @@ export const MentionInputSuggestionsSeparator = ({
const hasResults = useCommandState((x) => x.filtered.count) > 0;
return (
<div
// biome-ignore lint/a11y/useAriaPropsForRole: blitz bama blitz
role="separator"
className={cn(
'bg-border -mx-1 h-px my-1.5',
// Hide if first child
@ -18,6 +22,8 @@ export const MentionInputSuggestionsSeparator = ({
'last:hidden',
// Hide if next sibling is another separator
'has-[+[role="separator"]]:hidden',
// Hide if next sibling has hidden attribute
'has-[+[hidden]]:hidden',
!hasResults && 'hidden',
className
)}