Combobox V2
NewQuick start
Section titled “Quick start”Use ComboboxV2 for common single- and multi-select cases with minimal boilerplate.
Single select
Section titled “Single select”import { ComboboxV2 } from "stylus-ui/ComboboxV2";
const teammates = [ { label: "John Doe", value: "john" }, { label: "Jane Smith", value: "jane" }, { label: "Robert Johnson", value: "robert" }, { label: "Alice Williams", value: "alice" }, { label: "Charlie Brown", value: "charlie" },];
export default () => ( <ComboboxV2 items={teammates} label="Select Teammate" emptyMessage="No teammates found." />);Multiple select
Section titled “Multiple select”Add multiple for chip-based multi-select.
import { ComboboxV2 } from "stylus-ui/ComboboxV2";
const languages = [ { label: "JavaScript", value: "js" }, { label: "TypeScript", value: "ts" }, { label: "Python", value: "py" }, { label: "Go", value: "go" }, { label: "Rust", value: "rust" }, { label: "Ruby", value: "ruby" },];
export default () => ( <ComboboxV2 className="w-80" items={languages} label="Languages" emptyMessage="No languages found." multiple />);Custom item shape
Section titled “Custom item shape”When items don’t have label/value keys, pass getItemLabel and getItemKey.
import { ComboboxV2 } from "stylus-ui/ComboboxV2";
interface Tag { id: string; name: string;}
const tags: Tag[] = [ { id: "onboarding", name: "Onboarding" }, { id: "security", name: "Security" }, { id: "billing", name: "Billing" }, { id: "integrations", name: "Integrations" }, { id: "api", name: "API Reference" },];
export default () => ( <ComboboxV2<Tag, true> className="w-80" items={tags} label="Tags" emptyMessage="No tags found." multiple getItemLabel={(tag) => tag.name} getItemKey={(tag) => tag.id} />);Composition API
Section titled “Composition API”For advanced patterns — input-inside-popup, async search, grouped items, custom layouts — compose the primitive parts directly.
Anatomy
Section titled “Anatomy”<ComboboxV2Root> <ComboboxV2InputGroup label="Label"> <ComboboxV2Input /> <ComboboxV2Chips> <ComboboxV2Value /> <ComboboxV2Input /> </ComboboxV2Chips> <ComboboxV2Clear /> <ComboboxV2Trigger /> </ComboboxV2InputGroup> <ComboboxV2Popup> <ComboboxV2Status /> <ComboboxV2Empty /> <ComboboxV2List> <ComboboxV2Item> <ComboboxV2ItemIndicator /> </ComboboxV2Item> <ComboboxV2Separator /> <ComboboxV2Group> <ComboboxV2GroupLabel /> </ComboboxV2Group> </ComboboxV2List> </ComboboxV2Popup></ComboboxV2Root>Single select
Section titled “Single select”A filterable dropdown for selecting a single value. Pass items to the root and render items via a function child on <ComboboxV2List>.
import { ComboboxV2Root, ComboboxV2Input, ComboboxV2InputGroup, ComboboxV2Item, ComboboxV2List, ComboboxV2Popup, ComboboxV2Empty, ComboboxV2Trigger,} from "stylus-ui/ComboboxV2";
const options = [ { label: "John Doe", value: "john" }, { label: "Jane Smith", value: "jane" }, { label: "Robert Johnson", value: "robert" }, { label: "Alice Williams", value: "alice" }, { label: "Charlie Brown", value: "charlie" },];
export default () => ( <ComboboxV2Root items={options}> <ComboboxV2InputGroup label="Select Teammate" className="w-60"> <ComboboxV2Input /> <ComboboxV2Trigger aria-label="Open" /> </ComboboxV2InputGroup> <ComboboxV2Popup> <ComboboxV2Empty>No teammates found.</ComboboxV2Empty> <ComboboxV2List> {(item) => ( <ComboboxV2Item key={item.value} value={item}> {item.label} </ComboboxV2Item> )} </ComboboxV2List> </ComboboxV2Popup> </ComboboxV2Root>);Multiple select with chips
Section titled “Multiple select with chips”Enable multi-select by adding the multiple prop. Compose ComboboxV2Value, ComboboxV2Chip, and ComboboxV2ChipRemove inside ComboboxV2Chips, following the Base UI pattern.
import { ComboboxV2Root, ComboboxV2Chip, ComboboxV2ChipRemove, ComboboxV2Chips, ComboboxV2Input, ComboboxV2InputGroup, ComboboxV2Item, ComboboxV2ItemIndicator, ComboboxV2List, ComboboxV2Popup, ComboboxV2Empty, ComboboxV2Trigger, ComboboxV2Value,} from "stylus-ui/ComboboxV2";
interface ProgrammingLanguage { id: string; value: string;}
const languages: ProgrammingLanguage[] = [ { id: "js", value: "JavaScript" }, { id: "ts", value: "TypeScript" }, { id: "py", value: "Python" }, { id: "java", value: "Java" }, { id: "cpp", value: "C++" }, { id: "cs", value: "C#" }, { id: "php", value: "PHP" }, { id: "ruby", value: "Ruby" }, { id: "go", value: "Go" }, { id: "rust", value: "Rust" }, { id: "swift", value: "Swift" },];
export default () => ( <ComboboxV2Root items={languages} multiple> <ComboboxV2InputGroup label="Languages" className="w-80"> <ComboboxV2Chips> <ComboboxV2Value> {(selected: ProgrammingLanguage[]) => selected.map((language) => ( <ComboboxV2Chip key={language.id} aria-label={language.value}> <span className="truncate">{language.value}</span> <ComboboxV2ChipRemove aria-label={`Remove ${language.value}`} /> </ComboboxV2Chip> )) } </ComboboxV2Value> <ComboboxV2Input /> </ComboboxV2Chips> </ComboboxV2InputGroup> <ComboboxV2Popup> <ComboboxV2Empty>No languages found.</ComboboxV2Empty> <ComboboxV2List> {(language: ProgrammingLanguage) => ( <ComboboxV2Item key={language.id} value={language}> <div className="size-4 shrink-0"> <ComboboxV2ItemIndicator /> </div> {language.value} </ComboboxV2Item> )} </ComboboxV2List> </ComboboxV2Popup> </ComboboxV2Root>);Grouped items
Section titled “Grouped items”Organize related items under headings with <ComboboxV2Group> and <ComboboxV2GroupLabel>.
import { ComboboxV2Root, ComboboxV2Input, ComboboxV2InputGroup, ComboboxV2Item, ComboboxV2List, ComboboxV2Popup, ComboboxV2Empty, ComboboxV2Group, ComboboxV2GroupLabel, ComboboxV2Trigger,} from "stylus-ui/ComboboxV2";
const groups = [ { value: "Frontend", items: [ { label: "TypeScript", value: "typescript" }, { label: "JavaScript", value: "javascript" }, { label: "CSS", value: "css" }, ], }, { value: "Backend", items: [ { label: "Python", value: "python" }, { label: "Go", value: "go" }, { label: "Rust", value: "rust" }, ], },];
export default () => ( <ComboboxV2Root items={groups}> <ComboboxV2InputGroup label="Languages"> <ComboboxV2Input /> <ComboboxV2Trigger aria-label="Open" /> </ComboboxV2InputGroup> <ComboboxV2Popup> <ComboboxV2Empty>No languages found.</ComboboxV2Empty> <ComboboxV2List> {groups.map((group) => ( <ComboboxV2Group key={group.value} items={group.items}> <ComboboxV2GroupLabel>{group.value}</ComboboxV2GroupLabel> {group.items.map((item) => ( <ComboboxV2Item key={item.value} value={item}> {item.label} </ComboboxV2Item> ))} </ComboboxV2Group> ))} </ComboboxV2List> </ComboboxV2Popup> </ComboboxV2Root>);Input inside popup
Section titled “Input inside popup”Place the input inside the popup for a select-like trigger. Users click the trigger to reveal a searchable list.
import { useState } from "react";import { ComboboxV2Root, ComboboxV2Empty, ComboboxV2Input, ComboboxV2Item, ComboboxV2List, ComboboxV2Popup, ComboboxV2Trigger, ComboboxV2Value,} from "stylus-ui/ComboboxV2";import { Button } from "stylus-ui/Button";
const workspaces = [ { label: "Engineering", value: "engineering" }, { label: "Product", value: "product" }, { label: "Marketing", value: "marketing" }, { label: "Customer Success", value: "cs" }, { label: "Design", value: "design" }, { label: "Sales", value: "sales" },];
export default () => ( <ComboboxV2Root items={workspaces}> <ComboboxV2Trigger render={ <Button variant="secondary" dropdown className="h-10 w-56 justify-between font-normal" /> } > <ComboboxV2Value placeholder="Select workspace" /> </ComboboxV2Trigger> <ComboboxV2Popup> <div className="p-2 pb-0"> <ComboboxV2Input className="bg-surface-default w-full" /> </div> <ComboboxV2Empty>No workspaces found.</ComboboxV2Empty> <ComboboxV2List> {(item) => ( <ComboboxV2Item key={item.value} value={item}> {item.label} </ComboboxV2Item> )} </ComboboxV2List> </ComboboxV2Popup> </ComboboxV2Root>);API Reference
Section titled “API Reference”ComboboxV2
Section titled “ComboboxV2”Props-driven combobox for the common single/multi-select case. For advanced patterns (input-inside-popup, async, grouped, custom layouts), use the composition parts directly.
items
The items to display in the list.
label
Label displayed above the input group. Required for accessibility.
className
Additional classes applied to the input group.
defaultValue
The default selected value (uncontrolled).
emptyMessage
Message shown when no items match the search.
filter
Filter function. Pass null to disable built-in filtering (for async).
getItemKey
Extracts a unique key from an item.
Defaults to (item) => item.value.
getItemLabel
Extracts the display label from an item.
Defaults to (item) => item.label.
itemToStringLabel
Converts an item value to a string for display in the input.
Forwarded to itemToStringLabel on the root.
labelHidden
Visually hide the label. When true, the label is applied via aria-label.
multiple
Whether multiple items can be selected.
onInputValueChange
Called when the input text changes.
onOpenChange
Called when the popup opens or closes.
onValueChange
Called when the selected value changes.
placeholder
Placeholder text for the search input.
value
The controlled selected value.
Composition parts
Section titled “Composition parts”Each sub-component is a styled wrapper around its Base UI Combobox counterpart. All Base UI props are forwarded.
ComboboxV2Root
Section titled “ComboboxV2Root”A combobox with built-in filtering, keyboard navigation, and optional multi-select with chips. Powered by Base UI.
actionsRef
A ref to imperative actions.
unmount: When specified, the combobox will not be unmounted when closed. Instead, theunmountfunction must be called to unmount the combobox manually. Useful when the combobox’s animation is controlled by an external library.
autoComplete
Provides a hint to the browser for autofill. @see https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Attributes/autocomplete
autoHighlight
Whether the first matching item is highlighted automatically while filtering.
defaultInputValue
The uncontrolled input value when initially rendered.
To render a controlled input, use the inputValue prop instead.
defaultOpen
Whether the popup is initially open.
To render a controlled popup, use the open prop instead.
defaultValue
The uncontrolled selected value of the combobox when it’s initially rendered.
To render a controlled combobox, use the value prop instead.
disabled
Whether the component should ignore user interaction.
filter
Filter function used to match items vs input query.
filteredItems
Filtered items to display in the list.
When provided, the list will use these items instead of filtering the items prop internally.
Use when you want to control filtering logic externally with the useFilter() hook.
grid
Whether list items are presented in a grid layout. When enabled, arrow keys navigate across rows and columns inferred from DOM rows.
highlightItemOnHover
Whether moving the pointer over items should highlight them.
Disabling this prop allows CSS :hover to be differentiated from the :focus (data-highlighted) state.
id
The id of the component.
inline
Whether the list is rendered inline without using the popup.
inputRef
A ref to the hidden input element.
inputValue
The input value of the combobox. Use when controlled.
isItemEqualToValue
Custom comparison logic used to determine if a combobox item value matches the current selected value. Useful when item values are objects without matching referentially.
Defaults to Object.is comparison.
items
The items to be displayed in the list. Can be either a flat array of items or an array of groups with items.
itemToStringLabel
When the item values are objects (<Combobox.Item value={object}>), this function converts the object value to a string representation for display in the input.
If the shape of the object is { value, label }, the label will be used automatically without needing to specify this prop.
itemToStringValue
When the item values are objects (<Combobox.Item value={object}>), this function converts the object value to a string representation for form submission.
If the shape of the object is { value, label }, the value will be used automatically without needing to specify this prop.
limit
The maximum number of items to display in the list.
locale
The locale to use for string comparison. Defaults to the user’s runtime locale.
loopFocus
Whether to loop keyboard focus back to the input when the end of the list is reached while using the arrow keys. The first item can then be reached by pressing ArrowDown again from the input, or the last item can be reached by pressing ArrowUp from the input. The input is always included in the focus loop per ARIA Authoring Practices. When disabled, focus does not move when on the last element and the user presses ArrowDown, or when on the first element and the user presses ArrowUp.
modal
Determines if the popup enters a modal state when open.
true: user interaction is limited to the popup: document page scroll is locked and pointer interactions on outside elements are disabled.false: user interaction with the rest of the document is allowed.
multiple
Whether multiple items can be selected.
name
Identifies the field when a form is submitted.
onInputValueChange
Event handler called when the input value changes.
onItemHighlighted
Callback fired when an item is highlighted or unhighlighted.
Receives the highlighted item value (or undefined if no item is highlighted) and event details with a reason property describing why the highlight changed.
The reason can be:
'keyboard': the highlight changed due to keyboard navigation.'pointer': the highlight changed due to pointer hovering.'none': the highlight changed programmatically.
onOpenChange
Event handler called when the popup is opened or closed.
onOpenChangeComplete
Event handler called after any animations complete when the popup is opened or closed.
onValueChange
Event handler called when the selected value of the combobox changes.
open
Whether the popup is currently open. Use when controlled.
openOnInputClick
Whether the popup opens when clicking the input.
readOnly
Whether the user should be unable to choose a different option from the popup.
required
Whether the user must choose a value before submitting a form.
value
The selected value of the combobox. Use when controlled.
virtualized
Whether the items are being externally virtualized.
ComboboxV2InputGroup
Section titled “ComboboxV2InputGroup” label
Label displayed above the input group. Required for accessibility.
children
Contents of the input group.
className
Additional classes to apply to the input group.
labelHidden
Visually hide the label. When true, the label is applied via aria-label.
render
Allows you to replace the component’s HTML element with a different tag, or compose it with another component.
Accepts a ReactElement or a function that returns the element to render.
style
Style applied to the element, or a function that returns a style object based on the component’s state.
ComboboxV2Input
Section titled “ComboboxV2Input” className
CSS class applied to the element, or a function that returns a class based on the component’s state.
disabled
Whether the component should ignore user interaction.
render
Allows you to replace the component’s HTML element with a different tag, or compose it with another component.
Accepts a ReactElement or a function that returns the element to render.
style
Style applied to the element, or a function that returns a style object based on the component’s state.
ComboboxV2Trigger
Section titled “ComboboxV2Trigger” className
CSS class applied to the element, or a function that returns a class based on the component’s state.
disabled
Whether the component should ignore user interaction.
nativeButton
Whether the component renders a native <button> element when replacing it
via the render prop.
Set to false if the rendered element is not a button (e.g. <div>).
render
Allows you to replace the component’s HTML element with a different tag, or compose it with another component.
Accepts a ReactElement or a function that returns the element to render.
style
Style applied to the element, or a function that returns a style object based on the component’s state.
ComboboxV2Clear
Section titled “ComboboxV2Clear” className
CSS class applied to the element, or a function that returns a class based on the component’s state.
disabled
Whether the component should ignore user interaction.
keepMounted
Whether the component should remain mounted in the DOM when not visible.
nativeButton
Whether the component renders a native <button> element when replacing it
via the render prop.
Set to false if the rendered element is not a button (e.g. <div>).
render
Allows you to replace the component’s HTML element with a different tag, or compose it with another component.
Accepts a ReactElement or a function that returns the element to render.
style
Style applied to the element, or a function that returns a style object based on the component’s state.
ComboboxV2Chips
Section titled “ComboboxV2Chips” children
Content rendered after the chips (typically a ComboboxV2Input).
className
Additional classes for the chips container.
render
Allows you to replace the component’s HTML element with a different tag, or compose it with another component.
Accepts a ReactElement or a function that returns the element to render.
style
Style applied to the element, or a function that returns a style object based on the component’s state.
ComboboxV2Popup
Section titled “ComboboxV2Popup” align
className
CSS class applied to the element, or a function that returns a class based on the component’s state.
finalFocus
Determines the element to focus when the popup is closed.
false: Do not move focus.true: Move focus based on the default behavior (trigger or previously focused element).RefObject: Move focus to the ref element.function: Called with the interaction type (mouse,touch,pen, orkeyboard). Return an element to focus,trueto use the default behavior, orfalse/undefinedto do nothing.
initialFocus
Determines the element to focus when the popup is opened.
false: Do not move focus.true: Move focus based on the default behavior (first tabbable element or popup).RefObject: Move focus to the ref element.function: Called with the interaction type (mouse,touch,pen, orkeyboard). Return an element to focus,trueto use the default behavior, orfalse/undefinedto do nothing.
render
Allows you to replace the component’s HTML element with a different tag, or compose it with another component.
Accepts a ReactElement or a function that returns the element to render.
sideOffset
style
Style applied to the element, or a function that returns a style object based on the component’s state.
ComboboxV2List
Section titled “ComboboxV2List” className
CSS class applied to the element, or a function that returns a class based on the component’s state.
render
Allows you to replace the component’s HTML element with a different tag, or compose it with another component.
Accepts a ReactElement or a function that returns the element to render.
style
Style applied to the element, or a function that returns a style object based on the component’s state.
ComboboxV2Item
Section titled “ComboboxV2Item” className
CSS class applied to the element, or a function that returns a class based on the component’s state.
disabled
Whether the component should ignore user interaction.
index
The index of the item in the list. Improves performance when specified by avoiding the need to calculate the index automatically from the DOM.
nativeButton
Whether the component renders a native <button> element when replacing it
via the render prop.
Set to true if the rendered element is a native button.
onClick
An optional click handler for the item when selected.
It fires when clicking the item with the pointer, as well as when pressing Enter with the keyboard if the item is highlighted when the Input or List element has focus.
render
Allows you to replace the component’s HTML element with a different tag, or compose it with another component.
Accepts a ReactElement or a function that returns the element to render.
style
Style applied to the element, or a function that returns a style object based on the component’s state.
value
A unique value that identifies this item.
ComboboxV2ItemIndicator
Section titled “ComboboxV2ItemIndicator” className
CSS class applied to the element, or a function that returns a class based on the component’s state.
keepMounted
Whether to keep the HTML element in the DOM when the item is not selected.
render
Allows you to replace the component’s HTML element with a different tag, or compose it with another component.
Accepts a ReactElement or a function that returns the element to render.
style
Style applied to the element, or a function that returns a style object based on the component’s state.
ComboboxV2Empty
Section titled “ComboboxV2Empty” className
CSS class applied to the element, or a function that returns a class based on the component’s state.
render
Allows you to replace the component’s HTML element with a different tag, or compose it with another component.
Accepts a ReactElement or a function that returns the element to render.
style
Style applied to the element, or a function that returns a style object based on the component’s state.
ComboboxV2Group
Section titled “ComboboxV2Group” className
CSS class applied to the element, or a function that returns a class based on the component’s state.
items
Items to be rendered within this group.
When provided, child Collection components will use these items.
render
Allows you to replace the component’s HTML element with a different tag, or compose it with another component.
Accepts a ReactElement or a function that returns the element to render.
style
Style applied to the element, or a function that returns a style object based on the component’s state.
ComboboxV2GroupLabel
Section titled “ComboboxV2GroupLabel” className
CSS class applied to the element, or a function that returns a class based on the component’s state.
render
Allows you to replace the component’s HTML element with a different tag, or compose it with another component.
Accepts a ReactElement or a function that returns the element to render.
style
Style applied to the element, or a function that returns a style object based on the component’s state.
ComboboxV2Separator
Section titled “ComboboxV2Separator” className
CSS class applied to the element, or a function that returns a class based on the component’s state.
orientation
The orientation of the separator.
render
Allows you to replace the component’s HTML element with a different tag, or compose it with another component.
Accepts a ReactElement or a function that returns the element to render.
style
Style applied to the element, or a function that returns a style object based on the component’s state.
ComboboxV2Value
Section titled “ComboboxV2Value” placeholder
The placeholder value to display when no value is selected.
This is overridden by children if specified, or by a null item’s label in items.
ComboboxV2Chip
Section titled “ComboboxV2Chip” className
CSS class applied to the element, or a function that returns a class based on the component’s state.
render
Allows you to replace the component’s HTML element with a different tag, or compose it with another component.
Accepts a ReactElement or a function that returns the element to render.
style
Style applied to the element, or a function that returns a style object based on the component’s state.
ComboboxV2ChipRemove
Section titled “ComboboxV2ChipRemove” className
CSS class applied to the element, or a function that returns a class based on the component’s state.
nativeButton
Whether the component renders a native <button> element when replacing it
via the render prop.
Set to false if the rendered element is not a button (e.g. <div>).
render
Allows you to replace the component’s HTML element with a different tag, or compose it with another component.
Accepts a ReactElement or a function that returns the element to render.
style
Style applied to the element, or a function that returns a style object based on the component’s state.
ComboboxV2Label
Section titled “ComboboxV2Label” className
CSS class applied to the element, or a function that returns a class based on the component’s state.
render
Allows you to replace the component’s HTML element with a different tag, or compose it with another component.
Accepts a ReactElement or a function that returns the element to render.
style
Style applied to the element, or a function that returns a style object based on the component’s state.
ComboboxV2Icon
Section titled “ComboboxV2Icon” className
CSS class applied to the element, or a function that returns a class based on the component’s state.
render
Allows you to replace the component’s HTML element with a different tag, or compose it with another component.
Accepts a ReactElement or a function that returns the element to render.
style
Style applied to the element, or a function that returns a style object based on the component’s state.
ComboboxV2Status
Section titled “ComboboxV2Status” className
CSS class applied to the element, or a function that returns a class based on the component’s state.
render
Allows you to replace the component’s HTML element with a different tag, or compose it with another component.
Accepts a ReactElement or a function that returns the element to render.
style
Style applied to the element, or a function that returns a style object based on the component’s state.
useComboboxFilter
Section titled “useComboboxFilter”A hook providing locale-aware string matching. Returns an object with contains, startsWith, and endsWith filter functions.