Combobox
The Combobox consists of a label, a text-input field, and a chevron icon that indicates the control can expand. The input field contains the current value or placeholder text and is enclosed by a container that provides focus and hover states. Activating the control reveals the dropdown menu, which presents a list of options.
import {Combobox} from "@qualcomm-ui/react/combobox"Overview
- Each combobox uses the
comboboxCollectionhelper to manage the list of options. This creates aListCollectioninstance, documented below.
Examples
Simple
The simple API provides a standalone component with bundled subcomponents.
<Combobox
collection={collection}
label="Country"
onInputValueChange={handleInputChange}
placeholder="Select a country"
/>
Composite
Build with the composite API for granular control. This API requires you to provide each subcomponent, but gives you full control over the structure and layout.
<Combobox.Root
className="w-56"
collection={collection}
icon={Search}
name="combobox-composite"
onInputValueChange={handleInputChange}
placeholder="Search..."
>
<Combobox.Label>Search</Combobox.Label>
<Combobox.Control>
<Combobox.Input />
<Combobox.ClearTrigger />
<Combobox.Trigger />
</Combobox.Control>
<Portal>
<Combobox.Positioner>
<Combobox.Content>
<Combobox.Empty>No results found</Combobox.Empty>
{collection.items.map((item) => (
<Combobox.Item key={item} item={item}>
<Combobox.ItemText>{item}</Combobox.ItemText>
<Combobox.ItemIndicator>✓</Combobox.ItemIndicator>
</Combobox.Item>
))}
</Combobox.Content>
</Combobox.Positioner>
</Portal>
</Combobox.Root>
Open on Click
Use the openOnClick prop to open the combobox when the user clicks on the input.
<Combobox
collection={collection}
label="Country"
onInputValueChange={handleInputChange}
openOnClick
placeholder="Select a country"
/>
Input Behavior
Adjust the auto-completion behavior of the combobox with the inputBehavior prop.
<Combobox
collection={collection}
inputBehavior="autohighlight"
label="Country"
onInputValueChange={handleInputChange}
placeholder="Select a country"
/>
Multiple Selection
Use the multiple prop to enable multiple selection. When this is set, the combobox will always clear the input value when the user selects an option.
import {useState} from "react"
import type {ComboboxInputValueChangeDetails} from "@qualcomm-ui/core/combobox"
import {Combobox} from "@qualcomm-ui/react/combobox"
import {Tag} from "@qualcomm-ui/react/tag"
import {useListCollection} from "@qualcomm-ui/react-core/collection"
import {useFilter} from "@qualcomm-ui/react-core/locale"
import {countries} from "./country-list"
export function ComboboxMultipleDemo() {
const {contains} = useFilter({sensitivity: "base"})
const [value, setValue] = useState<string[]>([])
const {collection, filter} = useListCollection({
filter: contains,
initialItems: countries,
})
function handleInputChange(details: ComboboxInputValueChangeDetails) {
filter(details.inputValue)
}
function handleValueDismissed(item: string) {
setValue(value.filter((v) => v !== item))
}
return (
<div className="flex w-72 flex-col gap-4">
<div className="flex flex-wrap gap-2">
{value.map((item) => (
<Tag
key={item}
emphasis="neutral"
onClick={() => handleValueDismissed(item)}
variant="dismissable"
>
{item}
</Tag>
))}
</div>
<Combobox
className="w-full"
collection={collection}
label="Country"
multiple
onInputValueChange={handleInputChange}
onValueChange={(details) => setValue(details.value)}
placeholder="Select a country"
value={value}
/>
</div>
)
}Highlight Matching Text
Use the highlightMatchingText prop to highlight the portion of each option that matches the user's input. This provides visual feedback during filtering.
<Combobox
className="w-56"
collection={collection}
highlightMatchingText
label="Country"
name="combobox-highlight"
onInputValueChange={handleInputChange}
placeholder="Search countries..."
/>
ARIA Label
The Combobox's label is automatically associated with the input element for accessibility. If you omit the label, you should provide an aria-label to the input to give your combobox an accessible name.
<Combobox
aria-label="Country"
className="w-48"
collection={collection}
onInputValueChange={handleInputChange}
placeholder="Select a country"
/>
Content Width
The positioning.sameWidth property controls whether the width of the combobox content matches the width of the input element. The default is true.
<Combobox
aria-label="Country"
className="w-48"
collection={collection}
onInputValueChange={handleInputChange}
placeholder="Select a country"
positioning={{sameWidth: false}}
/>
Input Icon
Use the icon prop to add an icon to the start of the input element.
<Combobox
aria-label="Country"
className="w-48"
collection={collection}
icon={MapPin}
onInputValueChange={handleInputChange}
placeholder="Select a country"
/>
Icon Customization
Supply a ReactNode to the icon prop to customize the icon. This example features a loading indicator:
<Combobox
aria-label="Country"
className="w-48"
collection={collection}
icon={<ProgressRing size="xs" />}
onInputValueChange={handleInputChange}
placeholder="Select a country"
/>
Items as Objects
The items prop can be an array of objects. Use the itemLabel and itemValue properties on the comboboxCollection to specify the label and value of each item.
const cityCollection = comboboxCollection({
itemLabel: (item) => item.name,
items: [
{name: "San Diego", value: "SD"},
{name: "Nashville", value: "NV"},
{name: "Denver", value: "DV"},
{name: "Miami", value: "MI"},
{name: "Las Vegas", value: "LV"},
{name: "New York City", value: "NYC"},
{name: "San Francisco", value: "SF"},
],
itemValue: (item) => item.value,
})
Custom Item Rendering
When using the simple API, use the renderItem prop to customize the rendering of each item.
<Combobox
className="w-72"
collection={collection}
label="Select team member"
onInputValueChange={handleInputChange}
placeholder="Search by name, role, or email"
renderItem={({item, ...itemProps}) => {
const person = item
return (
<Combobox.Item className="min-h-[48px]" item={item} {...itemProps}>
<div className="flex flex-1 flex-col gap-0.5">
<Combobox.ItemText>
<span className="font-body-sm">{person.name}</span>
</Combobox.ItemText>
<div className="font-body-xs flex items-center gap-1">
<span>{person.role}</span>
<span>—</span>
<span>{person.email}</span>
</div>
</div>
<Combobox.ItemIndicator />
</Combobox.Item>
)
}}
/>
WARNING
When rendering custom items with virtual set to true, you must forward the data-virtual and style props to the rendered item:
<Combobox
renderItem={({item, ...itemProps}) => {
return (
<Combobox.Item item={item} {...itemProps}>
{/* ... */}
</Combobox.Item>
)
}}
/>Sizes
This component supports three size options to accommodate different layout densities and design requirements.
The available sizes are sm, md, and lg. The default size is md.
import type {ComboboxInputValueChangeDetails} from "@qualcomm-ui/core/combobox"
import {Combobox} from "@qualcomm-ui/react/combobox"
import {useListCollection} from "@qualcomm-ui/react-core/collection"
import {useFilter} from "@qualcomm-ui/react-core/locale"
const cityList = ["San Diego", "Dallas", "Denver"]
export function ComboboxSizesDemo() {
const {contains} = useFilter({sensitivity: "base"})
const {collection, filter} = useListCollection({
filter: contains,
initialItems: cityList,
})
function handleInputChange(details: ComboboxInputValueChangeDetails) {
filter(details.inputValue)
}
return (
<div className="flex flex-col items-center gap-4">
<Combobox
aria-label="City"
className="w-40"
collection={collection}
onInputValueChange={handleInputChange}
placeholder="sm"
positioning={{sameWidth: true}}
size="sm"
/>
<Combobox
aria-label="City"
className="w-48"
collection={collection}
onInputValueChange={handleInputChange}
placeholder="md"
positioning={{sameWidth: true}}
size="md"
/>
<Combobox
aria-label="City"
className="w-56"
collection={collection}
onInputValueChange={handleInputChange}
placeholder="lg"
positioning={{sameWidth: true}}
size="lg"
/>
</div>
)
}Content Height
Change the height of the item container by adjusting the style of the Content element.
<Combobox
aria-label="Country"
className="w-48"
collection={collection}
contentProps={{style: {maxHeight: 240}}}
onInputValueChange={handleInputChange}
placeholder="Select a country"
positioning={{sameWidth: true}}
/>
Controlled State
Set the initial value using the defaultValue prop, or use value and onValueChange to control the value manually. These props follow our controlled state pattern.
<Combobox
aria-label="Country"
className="w-48"
collection={collection}
onInputValueChange={handleInputChange}
onValueChange={(details) => setValue(details.value)}
placeholder="Select a country"
value={value}
/>
States
The following shows how the Combobox component appears in each interactive state.
<Combobox
className="w-48"
collection={collection}
defaultValue={[countries[0]]}
disabled
label="Disabled"
onInputValueChange={handleInputChange}
/>
<Combobox
className="w-48"
collection={collection}
defaultValue={[countries[0]]}
label="Read only"
onInputValueChange={handleInputChange}
readOnly
/>
<Combobox
className="w-48"
collection={collection}
defaultValue={[countries[0]]}
errorText="Invalid"
invalid
label="Invalid"
onInputValueChange={handleInputChange}
/>
Error Text and Indicator
Error messages are displayed using two props:
The error text and indicator will only render when invalid is true.
<Combobox
aria-label="Country"
className="w-48"
collection={collection}
errorText="You must select a country"
invalid={!value.length}
onInputValueChange={handleInputChange}
onValueChange={(details) => setValue(details.value)}
placeholder="Select a country"
value={value}
/>
Hint Text
Use the hintText prop to provide additional context or instructions below the combobox.
<Combobox
aria-label="Country"
className="w-48"
collection={collection}
hint="Optional hint"
onInputValueChange={handleInputChange}
placeholder="Select a country"
/>
Within Dialog
To use the Combobox within a Dialog, you need to avoid portalling the Combobox.Positioner to the document's body. To do this using the simple API, set portalProps.disabled to true:
import type {ReactElement} from "react"
import type {ComboboxInputValueChangeDetails} from "@qualcomm-ui/core/combobox"
import {Button} from "@qualcomm-ui/react/button"
import {Combobox} from "@qualcomm-ui/react/combobox"
import {Dialog} from "@qualcomm-ui/react/dialog"
import {useListCollection} from "@qualcomm-ui/react-core/collection"
import {useFilter} from "@qualcomm-ui/react-core/locale"
import {countries} from "./country-list"
export function ComboboxWithinDialogDemo(): ReactElement {
const {contains} = useFilter({sensitivity: "base"})
const {collection, filter} = useListCollection({
filter: contains,
initialItems: countries,
})
function handleInputChange(details: ComboboxInputValueChangeDetails) {
filter(details.inputValue)
}
return (
<Dialog.Root>
<Dialog.Trigger>
<Button emphasis="primary" variant="fill">
Open Dialog
</Button>
</Dialog.Trigger>
<Dialog.FloatingPortal>
<Dialog.Body>
<Dialog.Heading>Dialog Title</Dialog.Heading>
<Dialog.CloseButton />
<Combobox
aria-label="Country"
className="w-48"
collection={collection}
onInputValueChange={handleInputChange}
placeholder="Select a country"
portalProps={{disabled: true}}
/>
</Dialog.Body>
<Dialog.Footer>
<Dialog.CloseTrigger>
<Button emphasis="primary" size="sm" variant="fill">
Confirm
</Button>
</Dialog.CloseTrigger>
</Dialog.Footer>
</Dialog.FloatingPortal>
</Dialog.Root>
)
}Within Popover
Like with the Dialog, you need to avoid portalling the Combobox.Positioner to the document's body:
import type {ReactElement} from "react"
import type {ComboboxInputValueChangeDetails} from "@qualcomm-ui/core/combobox"
import {Button} from "@qualcomm-ui/react/button"
import {Combobox} from "@qualcomm-ui/react/combobox"
import {Popover} from "@qualcomm-ui/react/popover"
import {useListCollection} from "@qualcomm-ui/react-core/collection"
import {useFilter} from "@qualcomm-ui/react-core/locale"
import {countries} from "./country-list"
export function ComboboxWithinPopoverDemo(): ReactElement {
const {contains} = useFilter({sensitivity: "base"})
const {collection, filter} = useListCollection({
filter: contains,
initialItems: countries,
})
function handleInputChange(details: ComboboxInputValueChangeDetails) {
filter(details.inputValue)
}
return (
<Popover
label="Combobox Example"
trigger={<Button emphasis="primary">Show Popover</Button>}
>
<Combobox
className="w-48"
collection={collection}
label="Country"
onInputValueChange={handleInputChange}
placeholder="Select a country"
portalProps={{disabled: true}}
/>
</Popover>
)
}Async Loading
This example shows how to load items asynchronously and display a loading indicator.
<Combobox
className="w-56"
collection={collection}
icon={isFetching ? <ProgressRing size="xs" /> : undefined}
inputValue={inputValue}
label="Starship"
onInputValueChange={(details) => setInputValue(details.inputValue)}
placeholder="Search for a starship"
/>
Virtualized
For large lists, use the virtual prop to improve performance. This virtualizes the visible list items for performant scrolling and searching. The following example features a list of 5000 mock usernames.
import {useState} from "react"
import {Combobox} from "@qualcomm-ui/react/combobox"
import {ProgressRing} from "@qualcomm-ui/react/progress-ring"
import {useAsyncListCollection} from "@qualcomm-ui/react-core/collection"
import {useFilter} from "@qualcomm-ui/react-core/locale"
import {useMockUsers} from "./use-mock-users"
export function ComboboxVirtualDemo() {
const {data, isFetching} = useMockUsers(5000)
const {contains} = useFilter({sensitivity: "base"})
const [inputValue, setInputValue] = useState<string>("")
const {collection} = useAsyncListCollection<string>({
filter: contains,
filterText: inputValue,
items: data ?? [],
})
return (
<Combobox
className="w-56"
collection={collection}
icon={isFetching ? <ProgressRing size="xs" /> : undefined}
inputBehavior="autohighlight"
inputValue={inputValue}
label="Users"
onInputValueChange={(details) => setInputValue(details.inputValue)}
placeholder="Search for a username"
virtual
/>
)
}Forms
Choose the form library that fits your needs—we've built examples with React Hook Form and Tanstack Form to get you started.
React Hook Form
Use React Hook Form to handle the input state and validation. ArkType works great for schema validation if you need it.
import type {ReactElement} from "react"
import {type} from "arktype"
import {Controller, type SubmitHandler, useForm} from "react-hook-form"
import type {ComboboxInputValueChangeDetails} from "@qualcomm-ui/core/combobox"
import {Button} from "@qualcomm-ui/react/button"
import {Combobox} from "@qualcomm-ui/react/combobox"
import {createToaster, Toaster} from "@qualcomm-ui/react/toast"
import {useListCollection} from "@qualcomm-ui/react-core/collection"
import {useFilter} from "@qualcomm-ui/react-core/locale"
import {countries} from "./country-list"
const valueSchema = type({
country: type("string[] > 0").configure({
message: "At least one country must be selected",
}),
})
type ValueSchema = typeof valueSchema.infer
const toaster = createToaster({
overlap: true,
placement: "bottom-end",
})
export function ComboboxHookFormDemo(): ReactElement {
const {contains} = useFilter({sensitivity: "base"})
const {collection, filter} = useListCollection({
filter: contains,
initialItems: countries,
})
function handleInputChange(details: ComboboxInputValueChangeDetails) {
filter(details.inputValue)
}
const {
control,
formState: {isSubmitting},
handleSubmit,
setError,
} = useForm<ValueSchema>({
defaultValues: {
country: [],
},
})
const handleFormSubmit: SubmitHandler<ValueSchema> = async (data) => {
const validation = valueSchema(data)
if (validation instanceof type.errors) {
validation.forEach((error) => {
const field = error.path?.[0] as keyof ValueSchema
if (field) {
setError(field, {
message: error.message,
})
}
})
return
}
toaster.create({
label: "Form submitted",
type: "success",
})
}
return (
<>
<Toaster toaster={toaster} />
<form
className="w-48"
noValidate
onSubmit={handleSubmit(handleFormSubmit)}
>
<Controller
control={control}
name="country"
render={({field: {onChange, ...fieldProps}, fieldState: {error}}) => (
<Combobox
className="w-full"
collection={collection}
errorText={error?.message}
invalid={!!error}
label="Country"
onInputValueChange={handleInputChange}
onValueChange={(details) => onChange(details.value)}
placeholder="Select a country"
required
{...fieldProps}
/>
)}
/>
<div className="mt-2 flex w-full justify-end">
<Button
disabled={isSubmitting}
emphasis="primary"
type="submit"
variant="fill"
>
Submit
</Button>
</div>
</form>
</>
)
}Tanstack Form
Tanstack Form handles validation with its built-in validators.
import type {ReactElement} from "react"
import {useForm} from "@tanstack/react-form"
import type {ComboboxInputValueChangeDetails} from "@qualcomm-ui/core/combobox"
import {Button} from "@qualcomm-ui/react/button"
import {Combobox} from "@qualcomm-ui/react/combobox"
import {createToaster, Toaster} from "@qualcomm-ui/react/toast"
import {useListCollection} from "@qualcomm-ui/react-core/collection"
import {useFilter} from "@qualcomm-ui/react-core/locale"
import {countries} from "./country-list"
const toaster = createToaster({
overlap: true,
placement: "bottom-end",
})
export function ComboboxTanstackFormDemo(): ReactElement {
const {contains} = useFilter({sensitivity: "base"})
const {collection, filter} = useListCollection({
filter: contains,
initialItems: countries,
})
function handleInputChange(details: ComboboxInputValueChangeDetails) {
filter(details.inputValue)
}
const form = useForm({
defaultValues: {
country: [] as string[],
},
onSubmit: async () => {
toaster.create({
label: "Form submitted",
type: "success",
})
},
})
return (
<>
<Toaster toaster={toaster} />
<form
className="w-48"
noValidate
onSubmit={(e) => {
e.preventDefault()
e.stopPropagation()
form.handleSubmit()
}}
>
<form.Field
name="country"
validators={{
onChange: ({value}) =>
value.length === 0
? "At least one country must be selected"
: undefined,
}}
>
{(field) => (
<Combobox
className="w-full"
collection={collection}
errorText={field.state.meta.errors[0]}
invalid={field.state.meta.errors.length > 0}
label="Country"
onInputValueChange={handleInputChange}
onValueChange={(details) => field.handleChange(details.value)}
placeholder="Select a country"
required
value={field.state.value}
/>
)}
</form.Field>
<div className="mt-2 flex w-full justify-end">
<Button
disabled={form.state.isSubmitting}
emphasis="primary"
type="submit"
variant="fill"
>
Submit
</Button>
</div>
</form>
</>
)
}Tanstack form also supports ArkType.
API
<Combobox>
The simple combobox extends the Combobox.Root component with the following props:
| Prop | Type | Default |
|---|---|---|
aria-label
attribute, forwarded to the input element. | string | |
aria-labelledby
attribute, forwarded to the input element. If you provide a label,
omit this prop. | string | |
Props applied to the clear trigger element. To prevent this element from
rendering, pass {hidden: true} | ||
Props applied to the content element. | ||
Props applied to the control element. | ||
Label to render when the list is empty. | "No results found" | |
Props applied to the component that renders the empty message. | { | |
Props applied to the error indicator element. | ||
string | ||
Props applied to the error text element. | ||
Set to true to highlight option text matches during filtering. | boolean | |
Optional hint describing the element. This element is automatically
associated with the component's input element for accessibility. | ||
Props applied to the label element. | ||
Props applied to the select element. | ||
Optional label describing the element. Recommended. This element is
automatically associated with the component's input element for
accessibility. | ||
Props applied to the label element. | ||
Props applied to the portal element. | PortalProps | |
Props applied to the positioner element. | ||
Customize the rendering of the combobox list items. | ( | |
Props applied to the trigger element. | ||
When true, the list items will be virtually rendered. Useful for large lists. | boolean |
stringstring{hidden: true}{
render?:
| Element
| ((
props: Props,
) => Element)
}
booleantrue to highlight option text matches during filtering.PortalProps(
props: Props,
) => Element
booleantrue, the list items will be virtually rendered. Useful for large lists.Composite API
This section describes the elements of the Combobox's composite API.
<Combobox.Root>
| Prop | Type | Default |
|---|---|---|
Whether to allow typing custom values in the input | boolean | |
Whether to always submit on Enter key press, even if popup is open.
Useful for single-field autocomplete forms where Enter should submit the form. | boolean | false |
Whether to autofocus the input on mount | boolean | |
Whether to close the combobox when an item is selected. | boolean | |
The collection of items | ||
Whether the combobox is a composed with other composite widgets like tabs | boolean | true |
The initial highlighted value of the combobox when rendered.
Use when you don't need to control the highlighted value of the combobox. | string | |
The initial value of the combobox's input when rendered.
Use when you don't need to control the value of the combobox's input. | string | "" |
The initial open state of the combobox when rendered.
Use when you don't need to control the open state of the combobox. | boolean | |
The initial value of the combobox's selected items when rendered.
Use when you don't need to control the value of the combobox's selected items. | string[] | [] |
The document's text/writing direction. | 'ltr' | 'rtl' | 'ltr' |
Whether the combobox is disabled | boolean | |
Whether to disable registering this as a dismissable layer | boolean | |
The associate form of the combobox. | string | |
A root node to correctly resolve document in custom environments. i.e.,
Iframes, Electron. | () => | |
The controlled highlighted value of the combobox | string | |
| LucideIcon | ||
id attribute. If
omitted, a unique identifier will be automatically generated for accessibility. | string | |
The ids of the combobox's elements. If omitted, these will be generated
automatically. | Partial<{ | |
Whether to synchronize the present change immediately or defer it to the next
frame | boolean | |
Defines the auto-completion behavior of the combobox. - autohighlight: The first focused item is highlighted as the user types- autocomplete: Navigating the listbox with the arrow keys selects the item
and the input is updated | | 'none' | "none" |
The controlled value of the combobox's input | string | |
Whether the combobox is invalid | boolean | |
When true, the component will not be rendered in the DOM until it becomes
visible or active. | boolean | false |
Whether to loop the keyboard navigation through the items | boolean | true |
Whether to allow multiple selection. When multiple is true, the selectionBehavior is automatically set to
clear. It's recommended to render the selected items in a separate container. | boolean | |
The name attribute of the combobox's input. Useful for form submission | string | |
Function called when the animation ends in the closed state | VoidFunction | |
Function called when the focus is moved outside the component | ( | |
Function called when an item is highlighted using the pointer
or keyboard navigation. | (details: { | |
Function called when the input's value changes | (details: { | |
Function called when an interaction happens outside the component | ( | |
Function called when the popup is opened | (details: { | |
Function called when the pointer is pressed down outside the component | ( | |
Function called when an item is selected | (details: { | |
Function called when a new item is selected | (details: { | |
The controlled open state of the combobox | boolean | |
Whether to show the combobox when the input value changes | | boolean | true |
Whether to open the combobox popup on initial click on the input | boolean | false |
Whether to open the combobox on arrow key press | boolean | true |
The placeholder text of the combobox's input | string | |
The positioning options to dynamically position the popup menu | ||
Whether the node is present (controlled by the user) | boolean | |
Whether the combobox is readonly. This puts the combobox in a "non-editable"
mode but the user can still interact with it | boolean | |
Allows you to replace the component's HTML element with a different tag or component. Learn more | | ReactElement | |
Whether the combobox is a required input field | boolean | |
Function to scroll to a specific index | (details: { | |
The behavior of the combobox input when an item is selected - replace: The selected item string is set as the input value- clear: The input value is cleared- preserve: The input value is preserved | | 'replace' | "replace" |
The size of the select and its elements. Governs properties like font size,
item padding, and icon sizes. | | 'sm' | 'md' |
Whether to allow the initial presence animation. | boolean | false |
Specifies the localized strings that identifies the accessibility elements and
their states | { | |
When true, the component will be completely removed from the DOM when it
becomes inactive or hidden, rather than just being hidden with CSS. | boolean | false |
The controlled value of the combobox's selected items | string[] |
booleanbooleanbooleanbooleanbooleanstringstringbooleanstring[]
'ltr' | 'rtl'
booleanbooleanstring() =>
| Node
| ShadowRoot
| Document
stringstringPartial<{
clearTrigger: string
content: string
control: string
errorText: string
hint: string
input: string
label: string
positioner: string
root: string
trigger: string
}>
boolean| 'none'
| 'autohighlight'
| 'autocomplete'
-
autohighlight: The first focused item is highlighted as the user types-
autocomplete: Navigating the listbox with the arrow keys selects the item
and the input is updatedstringbooleanbooleanbooleanbooleanWhen
multiple is true, the selectionBehavior is automatically set to
clear. It's recommended to render the selected items in a separate container.stringname attribute of the combobox's input. Useful for form submissionVoidFunction(
event: FocusOutsideEvent,
) => void
(details: {
highlightedItem: T
highlightedValue: string
}) => void
(details: {
inputValue: string
reason?:
| 'input-change'
| 'item-select'
| 'clear-trigger'
| 'script'
| 'interact-outside'
}) => void
(
event: InteractOutsideEvent,
) => void
(details: {
open: boolean
reason?:
| 'input-click'
| 'trigger-click'
| 'script'
| 'arrow-key'
| 'input-change'
| 'interact-outside'
| 'escape-key'
| 'item-select'
| 'clear-trigger'
}) => void
(
event: PointerDownOutsideEvent,
) => void
(details: {
itemValue: string
value: string[]
}) => void
(details: {
items: Array<T>
value: string[]
}) => void
boolean| boolean
| ((details: {
inputValue: string
reason?:
| 'input-change'
| 'item-select'
| 'clear-trigger'
| 'script'
| 'interact-outside'
}) => boolean)
booleanbooleanstringbooleanboolean| ReactElement
| ((
props: object,
) => ReactElement)
boolean(details: {
getElement: () => HTMLElement
immediate?: boolean
index: number
}) => void
| 'replace'
| 'clear'
| 'preserve'
-
replace: The selected item string is set as the input value-
clear: The input value is cleared-
preserve: The input value is preserved| 'sm'
| 'md'
| 'lg'
boolean{
listLabel?: string
}
booleanstring[]
<Combobox.Label>
<label> element by default.| Prop | Type |
|---|---|
Allows you to replace the component's HTML element with a different tag or component. Learn more | | ReactElement |
| ReactElement
| ((
props: object,
) => ReactElement)
| Attribute / Property | Value |
|---|---|
className | 'qui-select__label' |
data-disabled | |
data-focus | |
data-invalid | |
data-part | 'label' |
data-readonly | |
data-required | |
data-scope | 'combobox' |
className'qui-select__label'data-disableddata-focusdata-invaliddata-part'label'data-readonlydata-requireddata-scope'combobox'<Combobox.Control>
<div> element
by default.| Prop | Type |
|---|---|
Allows you to replace the component's HTML element with a different tag or component. Learn more | | ReactElement |
| ReactElement
| ((
props: object,
) => ReactElement)
| Attribute / Property | Value |
|---|---|
className | 'qui-select__control' |
data-disabled | |
data-focus | |
data-invalid | |
data-part | 'control' |
data-scope | 'combobox' |
data-size | | 'sm' |
data-state | | 'open' |
className'qui-select__control'data-disableddata-focusdata-invaliddata-part'control'data-scope'combobox'data-size| 'sm'
| 'md'
| 'lg'
data-state| 'open'
| 'closed'
<Combobox.Input>
<input> element
by default.| Attribute / Property | Value |
|---|---|
className | 'qui-input__input' |
data-autofocus | |
data-invalid | |
data-part | 'input' |
data-scope | 'combobox' |
data-size | | 'sm' |
data-state | | 'open' |
className'qui-input__input'data-autofocusdata-invaliddata-part'input'data-scope'combobox'data-size| 'sm'
| 'md'
| 'lg'
data-state| 'open'
| 'closed'
<Combobox.Trigger>
<button> element by default.| Prop | Type | Default |
|---|---|---|
Whether the trigger is focusable | boolean | |
Dropdown visibility indicator icon. This automatically rotates when the
dropdown is visible. | | ReactNode | ChevronDown |
Allows you to replace the component's HTML element with a different tag or component. Learn more | | ReactElement |
boolean| ReactNode
| LucideIcon
| ReactElement
| ((
props: object,
) => ReactElement)
| Attribute / Property | Value |
|---|---|
className | 'qui-select__indicator' |
data-disabled | |
data-focusable | |
data-invalid | |
data-part | 'trigger' |
data-readonly | |
data-scope | 'combobox' |
data-size | | 'sm' |
data-state | | 'open' |
tabIndex | -1 |
className'qui-select__indicator'data-disableddata-focusabledata-invaliddata-part'trigger'data-readonlydata-scope'combobox'data-size| 'sm'
| 'md'
| 'lg'
data-state| 'open'
| 'closed'
tabIndex-1
<Combobox.ClearTrigger>
<button> element by default.| Prop | Type |
|---|---|
Allows you to replace the component's HTML element with a different tag or component. Learn more | | ReactElement |
| ReactElement
| ((
props: object,
) => ReactElement)
| Attribute / Property | Value |
|---|---|
className | 'qui-select__clear-trigger' |
data-invalid | |
data-part | 'clear-trigger' |
data-scope | 'combobox' |
data-size | | 'sm' |
hidden | boolean |
tabIndex | -1 |
className'qui-select__clear-trigger'data-invaliddata-part'clear-trigger'data-scope'combobox'data-size| 'sm'
| 'md'
| 'lg'
hiddenbooleantabIndex-1
<Combobox.Positioner>
<div> element by
default.| Prop | Type |
|---|---|
Allows you to replace the component's HTML element with a different tag or component. Learn more | | ReactElement |
| ReactElement
| ((
props: object,
) => ReactElement)
| Attribute / Property | Value |
|---|---|
className | 'qui-select__positioner' |
data-part | 'positioner' |
data-scope | 'combobox' |
style |
className'qui-select__positioner'data-part'positioner'data-scope'combobox'style<Combobox.Content>
<div> element by default.| Prop | Type |
|---|---|
Allows you to replace the component's HTML element with a different tag or component. Learn more | | ReactElement |
| ReactElement
| ((
props: object,
) => ReactElement)
| Attribute / Property | Value |
|---|---|
className | 'qui-select__content' |
data-disabled | |
data-empty | |
data-focus-visible | |
data-part | 'content' |
data-placement | | 'bottom' |
data-scope | 'combobox' |
data-state | | 'open' |
hidden | boolean |
tabIndex | -1 |
className'qui-select__content'data-disableddata-emptydata-focus-visibledata-part'content'data-placement| 'bottom'
| 'bottom-end'
| 'bottom-start'
| 'left'
| 'left-end'
| 'left-start'
| 'right'
| 'right-end'
| 'right-start'
| 'top'
| 'top-end'
| 'top-start'
data-scope'combobox'data-state| 'open'
| 'closed'
hiddenbooleantabIndex-1
<Combobox.Item>
<div> element by default.| Prop | Type |
|---|---|
item * The item to render | T |
Whether hovering outside should clear the highlighted state | boolean |
Allows you to replace the component's HTML element with a different tag or component. Learn more | | ReactElement |
Tboolean| ReactElement
| ((
props: object,
) => ReactElement)
| Attribute / Property | Value |
|---|---|
className | 'qui-select__item' |
data-disabled | |
data-highlighted | |
data-part | 'item' |
data-scope | 'combobox' |
data-size | | 'sm' |
data-state | | 'checked' |
data-value | string |
tabIndex | -1 |
className'qui-select__item'data-disableddata-highlighteddata-part'item'data-scope'combobox'data-size| 'sm'
| 'md'
| 'lg'
data-state| 'checked'
| 'unchecked'
data-valuestringtabIndex-1
<Combobox.ItemIndicator>
<span>
element by default.| Prop | Type | Default |
|---|---|---|
<Icon icon={Check}/> | ||
Allows you to replace the component's HTML element with a different tag or component. Learn more | | ReactElement |
| ReactElement
| ((
props: object,
) => ReactElement)
| Attribute / Property | Value |
|---|---|
data-part | 'item-indicator' |
data-scope | 'combobox' |
data-state | | 'checked' |
hidden | boolean |
data-part'item-indicator'data-scope'combobox'data-state| 'checked'
| 'unchecked'
hiddenboolean<Combobox.ItemText>
<span> element by default.| Prop | Type |
|---|---|
Allows you to replace the component's HTML element with a different tag or component. Learn more | | ReactElement |
| ReactElement
| ((
props: object,
) => ReactElement)
| Attribute / Property | Value |
|---|---|
className | 'qui-select__item-text' |
data-disabled | |
data-highlighted | |
data-part | 'item-text' |
data-scope | 'combobox' |
data-state | | 'checked' |
className'qui-select__item-text'data-disableddata-highlighteddata-part'item-text'data-scope'combobox'data-state| 'checked'
| 'unchecked'
<Combobox.Hint>
<div> element by default.| Prop | Type |
|---|---|
Allows you to replace the component's HTML element with a different tag or component. Learn more | | ReactElement |
| ReactElement
| ((
props: object,
) => ReactElement)
| Attribute / Property | Value |
|---|---|
className | 'qui-input__hint' |
data-disabled | |
data-part | 'hint' |
data-scope | 'select' |
hidden | boolean |
className'qui-input__hint'data-disableddata-part'hint'data-scope'select'hiddenboolean<Combobox.ErrorText>
<div> element by
default.| Prop | Type |
|---|---|
An icon to display next to the error text. | | LucideIcon |
Allows you to replace the component's HTML element with a different tag or component. Learn more | | ReactElement |
| LucideIcon
| ReactNode
| ReactElement
| ((
props: object,
) => ReactElement)
| Attribute / Property | Value |
|---|---|
className | 'qui-input__error-text' |
data-part | 'error-text' |
data-scope | 'select' |
hidden | boolean |
className'qui-input__error-text'data-part'error-text'data-scope'select'hiddenboolean<Combobox.ErrorIndicator>
<div> element
by default.| Prop | Type | Default |
|---|---|---|
lucide-react icon or ReactNode. | | LucideIcon | CircleAlert |
Allows you to replace the component's HTML element with a different tag or component. Learn more | | ReactElement |
| LucideIcon
| ReactNode
| ReactElement
| ((
props: object,
) => ReactElement)
| Attribute / Property | Value |
|---|---|
data-part | 'error-indicator' |
data-scope | 'combobox' |
hidden | boolean |
data-part'error-indicator'data-scope'combobox'hiddenbooleanData Structures
ListCollection
The following describes the member variables and methods of the ListCollection class. The Combobox component uses an instance of this class as input:
const collection = comboboxCollection({
items: [
// ...
],
})
return <Combobox collection={collection} />Note that the ListCollection accepts a single generic type parameter, T, which is the type of each list item used in the collection. This can be a string or an object.
Constructor
| Prop | Type |
|---|---|
Function to group items | ( |
Function to sort items | | string[] |
Function to determine if a node is disabled. | ( |
Function to get the item's label. | ( |
The options of the select | | Iterable<T, any, any> |
Function to get the item's unique value. | ( |
(
item: T,
index: number,
) => string
| string[]
| 'desc'
| 'asc'
| ((
a: string,
b: string,
) => number)
(
item: T,
) => boolean
(
item: T,
) => string
| Iterable<T, any, any>
| Readonly<
Iterable<T, any, any>
>
(
item: T,
) => string
| Prop | Type |
|---|---|
Append items to the collection | ( |
Get the item based on its index | ( |
Compare two values | ( |
Copy the collection | (items Array<T>,) => ListCollection<T> |
Filter the collection | ( |
Get the item based on its value | ( |
Get the items based on its values | ( |
Returns the first value in the collection | string |
Whether an item is disabled | ( |
Convert an item to a value | ( |
Returns the next value in the collection | ( |
Returns the previous value in the collection | ( |
Get the range of values between two values | ( |
Returns all the values in the collection | ( |
Group items by the groupBy function provided in options
Returns an array of [groupKey, items] tuples | () => Array< |
Whether the collection has a value | ( |
Whether the collection has an item | ( |
Get the index of an item based on its key | ( |
Insert items at a specific index | ( |
Insert items after a specific value | ( |
Insert items before a specific value | ( |
Check if the collection is equal to another collection
| ( |
The items in the collection | Array<T> |
Returns the last value in the collection | string |
Move an item to a specific index | ( |
Move items after a specific value | ( |
Move items before a specific value | ( |
Prepend items to the collection | ( |
Remove items from the collection | ( |
Reorder items | ( |
Search for a value based on a query | ( |
Function to update the collection items | ( |
Returns the number of items in the collection | number |
Sort the values based on their index | ( |
Convert a value to a string | ( |
Convert an item to a string | ( |
Convert an array of items to a string | ( |
Convert an array of items to a string | (value: string[],separator string,) => string |
Convert the collection to a JSON object | () => { |
Convert the collection to a string | () => string |
Update an item in the collection | ( |
Update an item in the collection if it exists, otherwise append it | ( |
(
items: Array<T>,
) => ListCollection<T>
(
index: number,
) => T
(
a: string,
b: string,
) => -1 | 0 | 1
(items Array<T>,) => ListCollection<T>
(
fn: (
itemString: string,
index: number,
item: T,
) => boolean,
) => ListCollection<T>
(
value: string,
) => T
(
values: string[],
) => Array<T>
string(
T,
) => boolean
(
T,
) => string
(
value: string,
step: number,
clamp: boolean,
) => string
(
value: string,
step: number,
clamp: boolean,
) => string
(
from: string,
to: string,
) => string[]
(
items: Array<T>,
) => string[]
() => Array<
[string, Array<T>]
>
(
value: string,
) => boolean
(
T,
) => boolean
(
value: string,
) => number
(
index: number,
items: Array<T>,
) => ListCollection<T>
(
value: string,
items: Array<T>,
) => ListCollection<T>
(
value: string,
items: Array<T>,
) => ListCollection<T>
(
any,
) => boolean
- items:The items in the collection
Array<T>
string(
value: string,
toIndex: number,
) => ListCollection<T>
(
value: string,
values: string[],
) => ListCollection<T>
(
value: string,
values: string[],
) => ListCollection<T>
(
items: Array<T>,
) => ListCollection<T>
(
itemsOrValues: Array<
string | T
>,
) => ListCollection<T>
(
fromIndex: number,
toIndex: number,
) => ListCollection<T>
(
queryString: string,
{
currentValue: string
state: {
keysSoFar: string
timer: number
}
timeout?: number
},
) => string
(
items: Array<T>,
) => ListCollection<T>
number(
values: string[],
) => string[]
(
value: string,
) => string
(
T,
) => string
(
items: Array<T>,
separator: string,
) => string
(value: string[],separator string,) => string
() => {
first: string
last: string
size: number
}
() => string
(
value: string,
T,
) => ListCollection<T>
(
value: string,
T,
mode: 'append' | 'prepend',
) => ListCollection<T>
ComboboxPositioningOptions
| Prop | Type | Default |
|---|---|---|
The minimum padding between the arrow and the floating element's corner. | number | 4 |
The overflow boundary of the reference element | () => | |
Whether the popover should fit the viewport. | boolean | |
Whether to flip the placement when the floating element overflows the boundary. | | boolean | true |
Function that returns the anchor rect | ( | |
The main axis offset or gap between the reference and floating element | number | 2 |
Whether the popover should be hidden when the reference element is detached | boolean | |
Options to activate auto-update listeners | | boolean | true |
The offset of the floating element | { | |
Function called when the placement is computed | ( | |
Function called when the floating element is positioned or not | (data: { | |
The virtual padding around the viewport edges to check for overflow | number | |
Whether the floating element can overlap the reference element | boolean | false |
The initial placement of the floating element | | 'bottom' | 'bottom-start' |
Whether to make the floating element same width as the reference element | boolean | true |
The secondary axis offset or gap between the reference and floating elements | number | |
Whether the popover should slide when it overflows. | boolean | |
The strategy to use for positioning | | 'absolute' | 'absolute' |
A callback that will be called when the popover needs to calculate its
position. | (data: { |
number() =>
| 'clippingAncestors'
| Element
| Array<Element>
| {
height: number
width: number
x: number
y: number
}
boolean| boolean
| Array<
| 'bottom'
| 'bottom-end'
| 'bottom-start'
| 'left'
| 'left-end'
| 'left-start'
| 'right'
| 'right-end'
| 'right-start'
| 'top'
| 'top-end'
| 'top-start'
>
(
element:
| HTMLElement
| VirtualElement,
) => {
height?: number
width?: number
x?: number
y?: number
}
numberboolean| boolean
| {
ancestorResize?: boolean
ancestorScroll?: boolean
animationFrame?: boolean
elementResize?: boolean
layoutShift?: boolean
}
{
crossAxis?: number
mainAxis?: number
}
(
data: ComputePositionReturn,
) => void
(data: {
placed: boolean
}) => void
numberboolean| 'bottom'
| 'bottom-end'
| 'bottom-start'
| 'left'
| 'left-end'
| 'left-start'
| 'right'
| 'right-end'
| 'right-start'
| 'top'
| 'top-end'
| 'top-start'
booleannumberboolean| 'absolute'
| 'fixed'
(data: {
updatePosition: () => Promise<void>
}) => void | Promise<void>
<div>element by default.