npm install @thrivecart/uiyarn add @thrivecart/uipnpm add @thrivecart/uibun add @thrivecart/uiimport { SelectSearchable } from '@thrivecart/ui';const [value, setValue] = useState('');
<SelectSearchable
items={frameworks}
placeholder="Select a framework..."
value={value}
onChange={setValue}
/>const [value, setValue] = useState<string[]>([]);
<SelectSearchable
items={tags}
multiple
placeholder="Add tags..."
value={value}
onChange={setValue}
/>Search and pick one item from the list
const [value, setValue] = useState('');
<SelectSearchable
items={frameworks}
placeholder="Select a framework..."
searchPlaceholder="Search frameworks..."
value={value}
onChange={setValue}
/>Search through a long list of countries
const [value, setValue] = useState('');
<SelectSearchable
items={countries}
placeholder="Select a country..."
searchPlaceholder="Search countries..."
value={value}
onChange={setValue}
/>Select multiple items displayed as removable tags
const [value, setValue] = useState(['vip', 'high-value']);
<SelectSearchable
items={tags}
multiple
placeholder="Add tags..."
searchPlaceholder="Search tags..."
value={value}
onChange={setValue}
/>Assign multiple people with descriptions and overflow indicator
const [value, setValue] = useState([]);
<SelectSearchable
items={teamMembers}
multiple
placeholder="Assign team members..."
searchPlaceholder="Search people..."
value={value}
onChange={setValue}
/>Limit visible tags in the trigger — overflow shows a count indicator
const [value, setValue] = useState(['vip', 'high-value', 'returning', 'enterprise']);
<SelectSearchable
items={tags}
multiple
maxTags={2}
placeholder="Add tags..."
searchPlaceholder="Search tags..."
value={value}
onChange={setValue}
/>Limit the total number of items that can be selected
const [value, setValue] = useState([]);
<SelectSearchable
items={teamMembers}
multiple
maxNumber={3}
placeholder="Pick up to 3 people..."
searchPlaceholder="Search people..."
value={value}
onChange={setValue}
/>Each option shows a secondary description line
<SelectSearchable
items={[
{ label: 'Next.js', value: 'next', description: 'React framework by Vercel' },
{ label: 'SvelteKit', value: 'sveltekit', description: 'Svelte meta-framework' },
{ label: 'Nuxt', value: 'nuxt', description: 'Vue.js framework' },
]}
placeholder="Pick a framework..."
emptyMessage="No frameworks match your search."
value={value}
onChange={setValue}
/>Select in a non-interactive disabled state
<SelectSearchable
items={frameworks}
placeholder="Disabled select..."
disabled
/>The indicator prop controls how selected items are shown in the dropdown. Use 'check' (default) for a checkmark on the right, or 'checkbox' for a checkbox on the left.
When to use check (default):
When to use checkbox:
Toggle visible columns in a data table using checkbox indicator
const [value, setValue] = useState(['name', 'email', 'total', 'status']);
<SelectSearchable
items={tableColumns}
multiple
indicator="checkbox"
placeholder="Toggle columns..."
searchPlaceholder="Search columns..."
value={value}
onChange={setValue}
/>Assign permissions to a role with clear on/off state
const [value, setValue] = useState(['view-dashboard', 'access-reports']);
<SelectSearchable
items={permissions}
multiple
indicator="checkbox"
placeholder="Assign permissions..."
searchPlaceholder="Search permissions..."
value={value}
onChange={setValue}
/>Use labelKey, valueKey, and descriptionKey when your items have different property names.
const products = [
{ name: 'Pro Plan', id: 'pro', info: 'Best for growing businesses' },
{ name: 'Enterprise', id: 'enterprise', info: 'For large organizations' },
];
<SelectSearchable
items={products}
labelKey="name"
valueKey="id"
descriptionKey="info"
placeholder="Select a plan..."
value={value}
onChange={setValue}
/>Search is most valuable when there are 10+ options. For short lists, use a standard Select.
Use descriptive placeholder and searchPlaceholder text so users know what to expect.
This is for selecting values, not triggering actions. Use DropdownMenu for action menus.
| Prop | Type | Default | Description |
|---|---|---|---|
items | T[] | - | Array of items to display |
multiple | boolean | false | Enable multi-select mode |
value | string | string[] | - | Selected value(s) — string for single, string[] for multiple |
onChange | (value) => void | - | Callback when selection changes |
placeholder | string | 'Select...' | Trigger placeholder text |
searchPlaceholder | string | 'Search...' | Search input placeholder |
emptyMessage | string | 'No results found' | Message shown when no items match search |
labelKey | keyof T | 'label' | Property name for the display label |
valueKey | keyof T | 'value' | Property name for the item value |
descriptionKey | keyof T | 'description' | Property name for optional description |
indicator | 'check' | 'checkbox' | 'check' | check = checkmark on right, checkbox = checkbox on left |
maxTags | number | 0 | Max visible tags in trigger (multiple only). 0 = show all |
maxNumber | number | - | Max number of items that can be selected (multiple only) |
disabled | boolean | false | Disable the select |
className | string | - | Additional className for the trigger |
| Key | Action |
|---|---|
Arrow Down | Highlight next item |
Arrow Up | Highlight previous item |
Enter | Select highlighted item |
Escape | Close the popover |
| Type to filter | Filters items in real-time |
aria-haspopup="listbox" with aria-expanded on the trigger.role="listbox" with role="option" on each item.aria-selected for screen readers.