select-with-search.tsx
Overview
select-with-search.tsx defines a reusable React component named SelectWithSearch that provides a searchable dropdown select input with optional grouped options. It allows users to pick an option from a list with a built-in search/filter functionality, supports clearing the selection, and visually indicates the selected item. The component is designed with accessibility and UI consistency in mind, leveraging several smaller UI primitives such as buttons, popovers, command lists, and icons.
This component is ideal for forms or interfaces where the user needs to select one option from a potentially large or grouped list, aided by search capabilities.
Components and Types
Types
SelectWithSearchFlagOptionType
Defines the shape of options passed to the component. It supports either flat options or grouped options.
Properties:
label: ReactNode
The display label for the option or option group.value?: string
The underlying value of the option (optional if it's a group).disabled?: boolean
Whether the option is disabled and cannot be selected.options?: RAGFlowSelectOptionType[]
Optional array of nested options to represent grouped options.
SelectWithSearchFlagProps
Defines the props accepted by the SelectWithSearch component.
Properties:
options?: SelectWithSearchFlagOptionType[]
Array of options or grouped options to display in the dropdown.value?: string
The currently selected value.onChange?(value: string): void
Callback invoked when the selection changes.triggerClassName?: string
Optional CSS class names for customizing the dropdown trigger button styles.allowClear?: boolean
If true, displays a clear (X) button to reset the selection.
SelectWithSearch Component
A forward-ref React functional component that renders a searchable select dropdown.
Signature
const SelectWithSearch = forwardRef<
React.ElementRef<typeof Button>,
SelectWithSearchFlagProps
>((props, ref) => JSX.Element);
Props
value(string, default''): The current selected value.onChange(function): Callback when the selected value changes.options(array): List of options or grouped options.triggerClassName(string): Additional classes for the trigger button.allowClear(boolean, defaultfalse): Enable clearing the selection.
Internal State
open(boolean): Whether the dropdown popover is open.value(string): Local state holding the selected value.
Key Methods
handleSelect(val: string): void
Handles selecting an option. Updates local state, closes dropdown, and callsonChange.handleClear(e: MouseEvent): void
Handles clearing the selection. Stops event propagation, clears local value, and callsonChangewith empty string.
Behavior & Rendering
Uses
Popoverto render the dropdown anchored to the trigger button.The trigger button shows:
The selected option label (or placeholder if none selected).
A clear button if
allowClearand a value is selected.A down-chevron icon indicating dropdown.
The dropdown content uses a
CommandUI component to provide a searchable list:CommandInputprovides a search input.CommandListshows filtered options or groups.Supports grouped options with headings if
optionscontain nestedoptions.Shows a check icon next to the currently selected option.
Disabled options are rendered but not selectable.
The selected label is computed using
useMemoby looking up the current value in the options list.The component supports keyboard navigation and accessibility via ARIA attributes on the button.
Usage Example
import { SelectWithSearch } from './select-with-search';
const options = [
{
label: "Fruits",
options: [
{ label: "Apple", value: "apple" },
{ label: "Banana", value: "banana", disabled: true },
],
},
{
label: "Vegetables",
options: [
{ label: "Carrot", value: "carrot" },
{ label: "Broccoli", value: "broccoli" },
],
},
];
function MyComponent() {
const [selected, setSelected] = useState('');
return (
<SelectWithSearch
options={options}
value={selected}
onChange={setSelected}
allowClear
triggerClassName="my-custom-class"
/>
);
}
Implementation Details and Algorithms
Option Label Resolution:
The selected option label is resolved by checking if the options are grouped (i.e.,options[0]?.optionsexists). If grouped, it searches each group's options for a matching value. If not grouped, it searches the flat options array. This logic is memoized for performance withuseMemo.State Synchronization:
The internalvaluestate is synchronized with the controlledvalueprop viauseEffectto keep internal and external states consistent.Clear Behavior:
Clicking the clear (X) icon stops event propagation to prevent toggling the dropdown and resets the selection.Accessibility:
The trigger button has
role="combobox"andaria-expandedattributes reflecting open state.Keyboard accessibility is provided through the underlying UI components.
UI Composition:
The component composes smaller UI elements (Button,Popover,Command, icons) from the design system for consistent styling and behavior.
Interaction with Other Parts
Imports from Internal UI Library:
Commands (
Command,CommandItem,CommandGroup, etc.) providing the searchable list and keyboard navigation.Popover components for dropdown positioning.
Button component for the trigger.
Utility
cnfor conditional class names.Separatorfor UI separation between clear icon and dropdown arrow.
Icon Components:
Useslucide-reacticons:CheckIcon,ChevronDownIcon,XIconfor visual affordances.Localization:
Usestfromi18nextto support translating placeholder and no data text.
This component is designed to be plugged into forms or UI flows where users select values from possibly grouped datasets, enhancing UX with search and clear capabilities.
Mermaid Component Diagram
componentDiagram
direction TB
component SelectWithSearch {
+props: SelectWithSearchFlagProps
+state: open, value
+handleSelect(val: string)
+handleClear(event)
+render()
}
component Button
component Popover
component Command
component CommandInput
component CommandList
component CommandGroup
component CommandItem
component CheckIcon
component ChevronDownIcon
component XIcon
component Separator
SelectWithSearch --> Button : trigger button
SelectWithSearch --> Popover : dropdown container
Popover --> Command : dropdown content
Command --> CommandInput : search input
Command --> CommandList : list container
CommandList --> CommandGroup : grouped options (optional)
CommandGroup --> CommandItem : option item
CommandList --> CommandItem : flat option item
CommandItem --> CheckIcon : selected indicator
Button --> ChevronDownIcon : dropdown arrow
Button --> XIcon : clear icon (conditional)
Button --> Separator : separator (conditional)
Summary
The select-with-search.tsx file implements a flexible, accessible, and user-friendly searchable select dropdown component supporting both flat and grouped options. It is highly reusable and composable with other UI elements, providing key features like searching, clearing, and visual selection cues. Its design embraces React best practices with hooks, memoization, and forward refs, making it a robust component for forms and UI applications requiring enhanced select inputs.