Use a Listbox to present a persistent, keyboard-navigable set of options where users choose one or more items.
import {Listbox} from "@qualcomm-ui/react/listbox"Overview
- Each listbox uses the
listCollectionhelper to manage the list of items. ThisListCollectioninstance is documented below.
Examples
Filtering
Filter a single-select collection before rendering the Listbox items.
<Listbox.Root collection={collection} selectionMode="single">
<Listbox.Input
className="mb-4"
label="Filter regions"
onValueChange={filter}
placeholder="Search regions"
startIcon={Search}
/>
<Listbox.Label>Deployment region</Listbox.Label>
<Listbox.Content>
{collection.items.map((region) => (
<Listbox.Item key={region.value} item={region}>
<Listbox.ItemControl />
<Listbox.ItemLabel>{region.label}</Listbox.ItemLabel>
<Listbox.ItemDescription>
{region.description}
</Listbox.ItemDescription>
</Listbox.Item>
))}
</Listbox.Content>
</Listbox.Root>
Multiple selection
Set selectionMode to multiple when users can choose more than one option.
<Listbox.Root collection={collection} selectionMode="multiple">
<Listbox.Label>Assign reviewers</Listbox.Label>
<Listbox.Content>
{collection.items.map((reviewer) => (
<Listbox.Item key={reviewer.value} item={reviewer}>
<Listbox.ItemControl />
<Listbox.ItemLabel>{reviewer.label}</Listbox.ItemLabel>
<Listbox.ItemDescription>
{reviewer.description}
</Listbox.ItemDescription>
</Listbox.Item>
))}
</Listbox.Content>
</Listbox.Root>
Scrollable
Set a maximum height and vertical overflow on Listbox.Content when the collection exceeds the available space.
<Listbox.Label>Device</Listbox.Label>
<Listbox.Content className="max-h-64 overflow-y-auto">
{collection.items.map((device) => (
<Listbox.Item key={device} item={device}>
<Listbox.ItemControl />
<Listbox.ItemLabel>{device}</Listbox.ItemLabel>
</Listbox.Item>
))}
</Listbox.Content>
Controlled state
Pass value and update it in onValueChange when the selected items change.
Selected: Auto
<Listbox.Root
collection={collection}
onValueChange={({value}) => setValue(value)}
value={value}
>
<Listbox.Label>Appearance</Listbox.Label>
<Listbox.Content>
{collection.items.map((item) => (
<Listbox.Item key={item} item={item}>
<Listbox.ItemControl />
<Listbox.ItemLabel>{item}</Listbox.ItemLabel>
</Listbox.Item>
))}
</Listbox.Content>
</Listbox.Root>
<p className="mt-2">Selected: {value.join(", ") || "None"}</p>
Item customization
Customize each item using the List.Item subcomponents.
<Listbox.Label>Projects</Listbox.Label>
<Listbox.Content>
{collection.items.map((project) => (
<Listbox.Item key={project.value} item={project}>
<Listbox.ItemStartIcon icon={project.icon} />
<Listbox.ItemLabel>{project.label}</Listbox.ItemLabel>
<Listbox.ItemDescription>
{project.description}
</Listbox.ItemDescription>
<Listbox.ItemSecondaryText>
{project.technologyArea}
</Listbox.ItemSecondaryText>
</Listbox.Item>
))}
</Listbox.Content>
API
<Listbox.Root>
stringstring[]
boolean'ltr' | 'rtl'
booleanbooleanmeta+a is pressed() =>
| Node
| ShadowRoot
| Document
stringstringboolean(details: {
highlightedIndex: number
highlightedItem: T
highlightedValue: string
}) => void
(details: {
value: string
}) => void
(details: {
items: Array<T>
value: string[]
}) => void
| 'horizontal'
| 'vertical'
| ReactElement
| ((
props: object,
) => ReactElement)
(details: {
getElement: () => HTMLElement
immediate?: boolean
index: number
}) => void
| 'single'
| 'multiple'
| 'none'
| 'extended'
-
single: The user can select a single item.-
multiple: The user can select multiple items without using modifier keys.-
extended: The user can select multiple items by using modifier keys.boolean| 'sm'
| 'md'
| 'lg'
booleanstring[]
<Listbox.Label>
<div> element by default.| ReactElement
| ((
props: object,
) => ReactElement)
<Listbox.Content>
<div> element by default.| ReactElement
| ((
props: object,
) => ReactElement)
<Listbox.Input>
The Listbox.Input extends the TextInput component with listbox accessibility like keyboard navigation.
stringstringneverbooleantrue, renders a clear button that resets the input value on click.
The button only appears when the input has a value.{
render?:
| Element
| ((
props: Props,
) => Element)
}
string'ltr' | 'rtl'
boolean| LucideIcon
| ReactNode
ReactElement for additional customization.{
icon?:
| LucideIcon
| ReactNode
render?:
| Element
| ((
props: Props,
) => Element)
}
{
icon?:
| LucideIcon
| ReactNode
render?:
| Element
| ((
props: Props,
) => Element)
}
string() =>
| Node
| ShadowRoot
| Document
{
children?: ReactNode
render?:
| Element
| ((
props: Props,
) => Element)
}
{
errorText: string
hint: string
input: string
label: string
}
TextInputInputGroupPropsanyboolean{
children?: ReactNode
render?:
| Element
| ((
props: Props,
) => Element)
}
string(
focused: boolean,
) => void
(
value: string,
) => void
stringboolean| ReactElement
| ((
props: object,
) => ReactElement)
boolean| 'sm'
| 'md'
| 'lg'
| LucideIcon
| ReactNode
ReactElement for additional customization.string<Listbox.Item>
<li> element by default.T| ReactElement
| ((
props: object,
) => ReactElement)
<Listbox.ItemStartIcon>
<span> element
by default when the icon is a React element.| LucideIcon
| ReactNode
| ReactElement
| ((
props: object,
) => ReactElement)
<Listbox.ItemControl>
<div> element by default.| ReactElement
| ((
props: object,
) => ReactElement)
<Listbox.ItemLabel>
<span> element by default.| ReactElement
| ((
props: object,
) => ReactElement)
<Listbox.ItemDescription>
<div> element by default.| ReactElement
| ((
props: object,
) => ReactElement)
<Listbox.ItemSecondaryText>
<div> element by default.| ReactElement
| ((
props: object,
) => ReactElement)
<Listbox.ItemAccessory>
<div> element by
default.| ReactElement
| ((
props: object,
) => ReactElement)
Data Structures
The following describes the member variables and methods of the ListCollection class. The Listbox component uses an instance of this class as input:
interface ExampleItem {
label: string
value: string
}
const items: ExampleItem[] = [
// ...
]
function Component() {
const {fuzzyContains} = useFilter({sensitivity: "base"})
const {collection, filter} = useListCollection({
filter: fuzzyContains,
initialItems: items,
// the itemLabel is what the filter will use to compare items
itemLabel: (item) => item.label,
itemValue: (item) => item.value,
})
return <Listbox.Root collection={collection}>{/*...*/}</Listbox.Root>
}useListCollection
(
itemText: string,
filterText: string,
item: T,
) => boolean
(
item: T,
index: number,
) => string
| string[]
| 'desc'
| 'asc'
| ((
a: string,
b: string,
) => number)
Array<T>
(
item: T,
) => boolean
(
item: T,
) => string
(
item: T,
) => string
numberFilter Options
The following predefined filters are available:
(
string: string,
substring: string,
) => boolean
(
string: string,
substring: string,
) => boolean
(
string: string,
substring: string,
) => boolean
(
string: string,
substring: string,
) => boolean
ListCollection
(
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
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>
<div>element by default.