Select
Displays a list of options for the user to pick from.
Anatomy
To set up the select correctly, you'll need to understand its anatomy and how we name its parts.
Each part includes a
data-partattribute to help identify them in the DOM.
Examples
Learn how to use the Select component in your project. Let's take a look at the most basic
example:
import { ChevronDownIcon } from 'lucide-react'
import { Portal, Select, createListCollection } from '@ark-ui/react'
export const Basic = () => {
const collection = createListCollection({ items: ['React', 'Solid', 'Vue'] })
return (
<Select.Root collection={collection}>
<Select.Label>Framework</Select.Label>
<Select.Control>
<Select.Trigger>
<Select.ValueText placeholder="Select a Framework" />
<Select.Indicator>
<ChevronDownIcon />
</Select.Indicator>
</Select.Trigger>
<Select.ClearTrigger>Clear</Select.ClearTrigger>
</Select.Control>
<Portal>
<Select.Positioner>
<Select.Content>
<Select.ItemGroup>
<Select.ItemGroupLabel>Frameworks</Select.ItemGroupLabel>
{collection.items.map((item) => (
<Select.Item key={item} item={item}>
<Select.ItemText>{item}</Select.ItemText>
<Select.ItemIndicator>✓</Select.ItemIndicator>
</Select.Item>
))}
</Select.ItemGroup>
</Select.Content>
</Select.Positioner>
</Portal>
<Select.HiddenSelect />
</Select.Root>
)
}
import { Index, Portal } from 'solid-js/web'
import { Select, createListCollection } from '@ark-ui/solid'
export const Basic = () => {
const collection = createListCollection({ items: ['React', 'Solid', 'Vue'] })
return (
<Select.Root collection={collection}>
<Select.Label>Framework</Select.Label>
<Select.Control>
<Select.Trigger>
<Select.ValueText placeholder="Select a Framework" />
<Select.Indicator>▼</Select.Indicator>
</Select.Trigger>
<Select.ClearTrigger>Clear</Select.ClearTrigger>
</Select.Control>
<Portal>
<Select.Positioner>
<Select.Content>
<Select.ItemGroup>
<Select.ItemGroupLabel>Frameworks</Select.ItemGroupLabel>
<Index each={collection.items}>
{(item) => (
<Select.Item item={item()}>
<Select.ItemText>{item()}</Select.ItemText>
<Select.ItemIndicator>✓</Select.ItemIndicator>
</Select.Item>
)}
</Index>
</Select.ItemGroup>
</Select.Content>
</Select.Positioner>
</Portal>
<Select.HiddenSelect />
</Select.Root>
)
}
<script setup lang="ts">
import { Select, createListCollection } from '@ark-ui/vue'
import { ChevronDownIcon } from 'lucide-vue-next'
const collection = createListCollection({
items: ['React', 'Solid', 'Vue'],
})
</script>
<template>
<Select.Root :collection="collection">
<Select.Label>Framework</Select.Label>
<Select.Control>
<Select.Trigger>
<Select.ValueText placeholder="Select a Framework" />
<Select.Indicator>
<ChevronDownIcon />
</Select.Indicator>
</Select.Trigger>
<Select.ClearTrigger>Clear</Select.ClearTrigger>
</Select.Control>
<Teleport to="body">
<Select.Positioner>
<Select.Content>
<Select.ItemGroup>
<Select.ItemGroupLabel>Frameworks</Select.ItemGroupLabel>
<Select.Item v-for="item in collection.items" :key="item" :item="item">
<Select.ItemText>{{ item }}</Select.ItemText>
<Select.ItemIndicator>✓</Select.ItemIndicator>
</Select.Item>
</Select.ItemGroup>
</Select.Content>
</Select.Positioner>
</Teleport>
<Select.HiddenSelect />
</Select.Root>
</template>
Advanced Customization
For advanced customizations and item properties like disabled:
import { ChevronDownIcon } from 'lucide-react'
import { Portal, Select, createListCollection } from '@ark-ui/react'
export const Advanced = () => {
const collection = createListCollection({
items: [
{ label: 'React', value: 'react' },
{ label: 'Solid', value: 'solid' },
{ label: 'Vue', value: 'vue' },
{ label: 'Svelte', value: 'svelte', disabled: true },
],
})
return (
<Select.Root collection={collection}>
<Select.Label>Framework</Select.Label>
<Select.Control>
<Select.Trigger>
<Select.ValueText placeholder="Select a Framework" />
<Select.Indicator>
<ChevronDownIcon />
</Select.Indicator>
</Select.Trigger>
<Select.ClearTrigger>Clear</Select.ClearTrigger>
</Select.Control>
<Portal>
<Select.Positioner>
<Select.Content>
<Select.ItemGroup>
<Select.ItemGroupLabel>Frameworks</Select.ItemGroupLabel>
{collection.items.map((item) => (
<Select.Item key={item.value} item={item}>
<Select.ItemText>{item.label}</Select.ItemText>
<Select.ItemIndicator>✓</Select.ItemIndicator>
</Select.Item>
))}
</Select.ItemGroup>
</Select.Content>
</Select.Positioner>
</Portal>
<Select.HiddenSelect />
</Select.Root>
)
}
import { Index, Portal } from 'solid-js/web'
import { Select, createListCollection } from '@ark-ui/solid'
export const Advanced = () => {
const collection = createListCollection({
items: [
{ label: 'React', value: 'react' },
{ label: 'Solid', value: 'solid' },
{ label: 'Vue', value: 'vue' },
{ label: 'Svelte', value: 'svelte', disabled: true },
],
})
return (
<Select.Root collection={collection}>
<Select.Label>Framework</Select.Label>
<Select.Control>
<Select.Trigger>
<Select.ValueText placeholder="Select a Framework" />
</Select.Trigger>
<Select.ClearTrigger>Clear</Select.ClearTrigger>
</Select.Control>
<Portal>
<Select.Positioner>
<Select.Content>
<Select.ItemGroup>
<Select.ItemGroupLabel>Frameworks</Select.ItemGroupLabel>
<Index each={collection.items}>
{(item) => (
<Select.Item item={item()}>
<Select.ItemText>{item().label}</Select.ItemText>
<Select.ItemIndicator>✓</Select.ItemIndicator>
</Select.Item>
)}
</Index>
</Select.ItemGroup>
</Select.Content>
</Select.Positioner>
</Portal>
<Select.HiddenSelect />
</Select.Root>
)
}
<script setup lang="ts">
import { Select, createListCollection } from '@ark-ui/vue'
import { ChevronDownIcon } from 'lucide-vue-next'
const collection = createListCollection({
items: [
{ label: 'React', value: 'react' },
{ label: 'Solid', value: 'solid' },
{ label: 'Vue', value: 'vue' },
{ label: 'Svelte', value: 'svelte', disabled: true },
],
})
</script>
<template>
<Select.Root :collection="collection">
<Select.Label>Framework</Select.Label>
<Select.Control>
<Select.Trigger>
<Select.ValueText placeholder="Select a Framework" />
<Select.Indicator>
<ChevronDownIcon />
</Select.Indicator>
</Select.Trigger>
<Select.ClearTrigger>Clear</Select.ClearTrigger>
</Select.Control>
<Teleport to="body">
<Select.Positioner>
<Select.Content>
<Select.ItemGroup>
<Select.ItemGroupLabel>Frameworks</Select.ItemGroupLabel>
<Select.Item v-for="item in collection.items" :key="item.value" :item="item">
<Select.ItemText>{{ item.label }}</Select.ItemText>
<Select.ItemIndicator>✓</Select.ItemIndicator>
</Select.Item>
</Select.ItemGroup>
</Select.Content>
</Select.Positioner>
</Teleport>
<Select.HiddenSelect />
</Select.Root>
</template>
Multiple Selection
To enable multiple item selection:
import { ChevronDownIcon } from 'lucide-react'
import { Portal, Select, createListCollection } from '@ark-ui/react'
export const Multiple = () => {
const collection = createListCollection({
items: [
{ label: 'React', value: 'react' },
{ label: 'Solid', value: 'solid' },
{ label: 'Vue', value: 'vue' },
{ label: 'Svelte', value: 'svelte', disabled: true },
],
})
return (
<Select.Root collection={collection} multiple>
<Select.Label>Framework</Select.Label>
<Select.Control>
<Select.Trigger>
<Select.ValueText placeholder="Select a Framework" />
<Select.Indicator>
<ChevronDownIcon />
</Select.Indicator>
</Select.Trigger>
<Select.ClearTrigger>Clear</Select.ClearTrigger>
</Select.Control>
<Portal>
<Select.Positioner>
<Select.Content>
<Select.ItemGroup>
<Select.ItemGroupLabel>Frameworks</Select.ItemGroupLabel>
{collection.items.map((item) => (
<Select.Item key={item.value} item={item}>
<Select.ItemText>{item.label}</Select.ItemText>
<Select.ItemIndicator>✓</Select.ItemIndicator>
</Select.Item>
))}
</Select.ItemGroup>
</Select.Content>
</Select.Positioner>
</Portal>
<Select.HiddenSelect />
</Select.Root>
)
}
import { Index, Portal } from 'solid-js/web'
import { Select, createListCollection } from '@ark-ui/solid'
export const Multiple = () => {
const collection = createListCollection({
items: [
{ label: 'React', value: 'react' },
{ label: 'Solid', value: 'solid' },
{ label: 'Vue', value: 'vue' },
{ label: 'Svelte', value: 'svelte', disabled: true },
],
})
return (
<Select.Root collection={collection} multiple>
<Select.Label>Framework</Select.Label>
<Select.Control>
<Select.Trigger>
<Select.ValueText placeholder="Select a Framework" />
</Select.Trigger>
<Select.ClearTrigger>Clear</Select.ClearTrigger>
</Select.Control>
<Portal>
<Select.Positioner>
<Select.Content>
<Select.ItemGroup>
<Index each={collection.items}>
{(item) => (
<Select.Item item={item()}>
<Select.ItemText>{item().label}</Select.ItemText>
<Select.ItemIndicator>✓</Select.ItemIndicator>
</Select.Item>
)}
</Index>
</Select.ItemGroup>
</Select.Content>
</Select.Positioner>
</Portal>
<Select.HiddenSelect />
</Select.Root>
)
}
<script setup lang="ts">
import { Select, createListCollection } from '@ark-ui/vue'
import { ChevronDownIcon } from 'lucide-vue-next'
const collection = createListCollection({
items: [
{ label: 'React', value: 'react' },
{ label: 'Solid', value: 'solid' },
{ label: 'Vue', value: 'vue' },
{ label: 'Svelte', value: 'svelte', disabled: true },
],
})
</script>
<template>
<Select.Root :collection="collection" multiple>
<Select.Label>Framework</Select.Label>
<Select.Control>
<Select.Trigger>
<Select.ValueText placeholder="Select a Framework" />
<Select.Indicator>
<ChevronDownIcon />
</Select.Indicator>
</Select.Trigger>
<Select.ClearTrigger>Clear</Select.ClearTrigger>
</Select.Control>
<Teleport to="body">
<Select.Positioner>
<Select.Content>
<Select.ItemGroup>
<Select.ItemGroupLabel>Frameworks</Select.ItemGroupLabel>
<Select.Item v-for="item in collection.items" :key="item.value" :item="item">
<Select.ItemText>{{ item.label }}</Select.ItemText>
<Select.ItemIndicator>✓</Select.ItemIndicator>
</Select.Item>
</Select.ItemGroup>
</Select.Content>
</Select.Positioner>
</Teleport>
<Select.HiddenSelect />
</Select.Root>
</template>
Controlled Component
For scenarios where you want to control the Select component's state:
import { ChevronDownIcon } from 'lucide-react'
import { useState } from 'react'
import { Portal, Select, createListCollection } from '@ark-ui/react'
interface Item {
label: string
value: string
disabled?: boolean
}
export const Controlled = () => {
const [_, setSelectedItems] = useState<Item[]>([])
const collection = createListCollection<Item>({
items: [
{ label: 'React', value: 'react' },
{ label: 'Solid', value: 'solid' },
{ label: 'Vue', value: 'vue' },
{ label: 'Svelte', value: 'svelte', disabled: true },
],
})
return (
<Select.Root collection={collection} onValueChange={(e) => setSelectedItems(e.items)}>
<Select.Label>Framework</Select.Label>
<Select.Control>
<Select.Trigger>
<Select.ValueText placeholder="Select a Framework" />
<Select.Indicator>
<ChevronDownIcon />
</Select.Indicator>
</Select.Trigger>
<Select.ClearTrigger>Clear</Select.ClearTrigger>
</Select.Control>
<Portal>
<Select.Positioner>
<Select.Content>
<Select.ItemGroup>
<Select.ItemGroupLabel>Frameworks</Select.ItemGroupLabel>
{collection.items.map((item) => (
<Select.Item key={item.value} item={item}>
<Select.ItemText>{item.label}</Select.ItemText>
<Select.ItemIndicator>✓</Select.ItemIndicator>
</Select.Item>
))}
</Select.ItemGroup>
</Select.Content>
</Select.Positioner>
</Portal>
<Select.HiddenSelect />
</Select.Root>
)
}
import { createSignal } from 'solid-js'
import { Index, Portal } from 'solid-js/web'
import { Select, createListCollection } from '@ark-ui/solid'
interface Item {
label: string
value: string
disabled?: boolean
}
export const Controlled = () => {
const [, setSelectedItems] = createSignal<Item[]>([])
const collection = createListCollection<Item>({
items: [
{ label: 'React', value: 'react' },
{ label: 'Solid', value: 'solid' },
{ label: 'Vue', value: 'vue' },
{ label: 'Svelte', value: 'svelte', disabled: true },
],
})
return (
<Select.Root collection={collection} onValueChange={(e) => setSelectedItems(e.items)}>
<Select.Label>Framework</Select.Label>
<Select.Control>
<Select.Trigger>
<Select.ValueText placeholder="Select a Framework" />
</Select.Trigger>
<Select.ClearTrigger>Clear</Select.ClearTrigger>
</Select.Control>
<Portal>
<Select.Positioner>
<Select.Content>
<Select.ItemGroup>
<Select.ItemGroupLabel>Frameworks</Select.ItemGroupLabel>
<Index each={collection.items}>
{(item) => (
<Select.Item item={item()}>
<Select.ItemText>{item().label}</Select.ItemText>
<Select.ItemIndicator>✓</Select.ItemIndicator>
</Select.Item>
)}
</Index>
</Select.ItemGroup>
</Select.Content>
</Select.Positioner>
</Portal>
<Select.HiddenSelect />
</Select.Root>
)
}
<script setup lang="ts">
import { ref } from 'vue'
import { Select, createListCollection } from '@ark-ui/vue'
import { ChevronDownIcon } from 'lucide-vue-next'
const collection = createListCollection({
items: [
{ label: 'React', value: 'react' },
{ label: 'Solid', value: 'solid' },
{ label: 'Vue', value: 'vue' },
{ label: 'Svelte', value: 'svelte', disabled: true },
],
})
const value = ref(['vue'])
</script>
<template>
<Select.Root :collection="collection" v-model="value">
<Select.Label>Framework</Select.Label>
<Select.Control>
<Select.Trigger>
<Select.ValueText placeholder="Select a Framework" />
<Select.Indicator>
<ChevronDownIcon />
</Select.Indicator>
</Select.Trigger>
<Select.ClearTrigger>Clear</Select.ClearTrigger>
</Select.Control>
<Teleport to="body">
<Select.Positioner>
<Select.Content>
<Select.ItemGroup>
<Select.ItemGroupLabel>Frameworks</Select.ItemGroupLabel>
<Select.Item v-for="item in collection.items" :key="item.value" :item="item">
<Select.ItemText>{{ item.label }}</Select.ItemText>
<Select.ItemIndicator>✓</Select.ItemIndicator>
</Select.Item>
</Select.ItemGroup>
</Select.Content>
</Select.Positioner>
</Teleport>
<Select.HiddenSelect />
</Select.Root>
</template>
Usage with a Form Library
See how to use the Select component with popular form libraries:
import { ChevronDownIcon } from 'lucide-react'
import { type SubmitHandler, useForm } from 'react-hook-form'
import { Select, createListCollection } from '@ark-ui/react'
interface Inputs {
framework: string
}
export const FormLibrary = () => {
const collection = createListCollection({ items: ['React', 'Solid', 'Vue'] })
const { register, handleSubmit } = useForm<Inputs>()
const onSubmit: SubmitHandler<Inputs> = (data) => window.alert(JSON.stringify(data))
return (
<form onSubmit={handleSubmit(onSubmit)}>
<Select.Root collection={collection}>
<Select.Label>Framework</Select.Label>
<Select.HiddenSelect {...register('framework')} />
<Select.Control>
<Select.Trigger>
<Select.ValueText placeholder="Select a Framework" />
<Select.Indicator>
<ChevronDownIcon />
</Select.Indicator>
</Select.Trigger>
<Select.ClearTrigger>Clear</Select.ClearTrigger>
</Select.Control>
<Select.Positioner>
<Select.Content>
<Select.ItemGroup>
<Select.ItemGroupLabel>Frameworks</Select.ItemGroupLabel>
{collection.items.map((item) => (
<Select.Item key={item} item={item}>
<Select.ItemText>{item}</Select.ItemText>
<Select.ItemIndicator>✓</Select.ItemIndicator>
</Select.Item>
))}
</Select.ItemGroup>
</Select.Content>
</Select.Positioner>
</Select.Root>
<button type="submit">Submit</button>
</form>
)
}
Example not foundExample not foundUsing the Field Component
The Field component helps manage form-related state and accessibility attributes of a select.
It includes handling ARIA labels, helper text, and error text to ensure proper accessibility.
import { ChevronDownIcon } from 'lucide-react'
import { Field, Select, createListCollection } from '@ark-ui/react'
export const WithField = (props: Field.RootProps) => {
const collection = createListCollection({ items: ['React', 'Solid', 'Vue'] })
return (
<Field.Root {...props}>
<Select.Root collection={collection}>
<Select.Label>Label</Select.Label>
<Select.Control>
<Select.Trigger>
<Select.ValueText placeholder="Select a Framework" />
<Select.Indicator>
<ChevronDownIcon />
</Select.Indicator>
</Select.Trigger>
</Select.Control>
<Select.Positioner>
<Select.Content>
{collection.items.map((item) => (
<Select.Item key={item} item={item}>
<Select.ItemText>{item}</Select.ItemText>
<Select.ItemIndicator>✓</Select.ItemIndicator>
</Select.Item>
))}
</Select.Content>
</Select.Positioner>
<Select.HiddenSelect />
</Select.Root>
<Field.HelperText>Additional Info</Field.HelperText>
<Field.ErrorText>Error Info</Field.ErrorText>
</Field.Root>
)
}
import { ChevronDownIcon } from 'lucide-solid'
import { Index } from 'solid-js/web'
import { Field, Select, createListCollection } from '@ark-ui/solid'
export const WithField = (props: Field.RootProps) => {
const collection = createListCollection({ items: ['React', 'Solid', 'Vue'] })
return (
<Field.Root {...props}>
<Select.Root collection={collection}>
<Select.Label>Label</Select.Label>
<Select.Control>
<Select.Trigger>
<Select.ValueText placeholder="Select a Framework" />
<Select.Indicator>
<ChevronDownIcon />
</Select.Indicator>
</Select.Trigger>
</Select.Control>
<Select.Positioner>
̦
<Select.Content>
<Select.ItemGroup>
<Select.ItemGroupLabel>Frameworks</Select.ItemGroupLabel>
<Index each={collection.items}>
{(item) => (
<Select.Item item={item()}>
<Select.ItemText>{item()}</Select.ItemText>
<Select.ItemIndicator>✓</Select.ItemIndicator>
</Select.Item>
)}
</Index>
</Select.ItemGroup>
</Select.Content>
</Select.Positioner>
<Select.HiddenSelect />
</Select.Root>
<Field.HelperText>Additional Info</Field.HelperText>
<Field.ErrorText>Error Info</Field.ErrorText>
</Field.Root>
)
}
<script setup lang="ts">
import { Field, Select, createListCollection } from '@ark-ui/vue'
import { ChevronDownIcon } from 'lucide-vue-next'
const collection = createListCollection({
items: ['React', 'Solid', 'Vue'],
})
</script>
<template>
<Field.Root>
<Select.Root :collection="collection">
<Select.Label>Label</Select.Label>
<Select.Control>
<Select.Trigger>
<Select.ValueText placeholder="Select a Framework" />
<Select.Indicator>
<ChevronDownIcon />
</Select.Indicator>
</Select.Trigger>
<Select.ClearTrigger>Clear</Select.ClearTrigger>
</Select.Control>
<Teleport to="body">
<Select.Positioner>
<Select.Content>
<Select.ItemGroup>
<Select.ItemGroupLabel>Frameworks</Select.ItemGroupLabel>
<Select.Item v-for="item in collection.items" :key="item" :item="item">
<Select.ItemText>{{ item }}</Select.ItemText>
<Select.ItemIndicator>✓</Select.ItemIndicator>
</Select.Item>
</Select.ItemGroup>
</Select.Content>
</Select.Positioner>
</Teleport>
<Select.HiddenSelect />
</Select.Root>
<Field.HelperText>Additional Info</Field.HelperText>
<Field.ErrorText>Error Info</Field.ErrorText>
</Field.Root>
</template>
API Reference
Root
| Prop | Default | Type |
|---|---|---|
items | T[] | readonly T[]The options of the select | |
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. | |
closeOnSelect | true | booleanWhether the select should close after an item is selected |
composite | true | booleanWhether the select is a composed with other composite widgets like tabs or combobox |
defaultOpen | booleanThe initial open state of the select when it is first rendered. Use when you do not need to control its open state. | |
defaultValue | string[]The initial value of the select when it is first rendered. Use when you do not need to control the state of the select. | |
deselectable | booleanWhether the value can be cleared by clicking the selected item. **Note:** this is only applicable for single selection | |
disabled | booleanWhether the select is disabled | |
form | stringThe associate form of the underlying select. | |
highlightedValue | stringThe key of the highlighted item | |
id | stringThe unique identifier of the machine. | |
ids | Partial<{
root: string
content: string
control: string
trigger: string
clearTrigger: string
label: string
hiddenSelect: string
positioner: string
item(id: string | number): string
itemGroup(id: string | number): string
itemGroupLabel(id: string | number): string
}>The ids of the elements in the select. Useful for composition. | |
immediate | booleanWhether to synchronize the present change immediately or defer it to the next frame | |
invalid | booleanWhether the select is invalid | |
isItemDisabled | (item: T) => booleanWhether the item is disabled | |
itemToString | (item: T) => stringThe label of the item | |
itemToValue | (item: T) => stringThe value of the item | |
lazyMount | false | booleanWhether to enable lazy mounting |
loopFocus | false | booleanWhether to loop the keyboard navigation through the options |
multiple | booleanWhether to allow multiple selection | |
name | stringThe `name` attribute of the underlying select. | |
onExitComplete | () => voidFunction called when the animation ends in the closed state | |
onFocusOutside | (event: FocusOutsideEvent) => voidFunction called when the focus is moved outside the component | |
onHighlightChange | (details: HighlightChangeDetails<T>) => voidThe callback fired when the highlighted item changes. | |
onInteractOutside | (event: InteractOutsideEvent) => voidFunction called when an interaction happens outside the component | |
onOpenChange | (details: OpenChangeDetails) => voidFunction called when the popup is opened | |
onPointerDownOutside | (event: PointerDownOutsideEvent) => voidFunction called when the pointer is pressed down outside the component | |
onValueChange | (details: ValueChangeDetails<T>) => voidThe callback fired when the selected item changes. | |
open | booleanWhether the select menu is open | |
positioning | PositioningOptionsThe positioning options of the menu. | |
present | booleanWhether the node is present (controlled by the user) | |
readOnly | booleanWhether the select is read-only | |
required | booleanWhether the select is required | |
scrollToIndexFn | (details: ScrollToIndexDetails) => voidFunction to scroll to a specific index | |
unmountOnExit | false | booleanWhether to unmount on exit. |
value | string[]The keys of the selected items |
| Data Attribute | Value |
|---|---|
[data-scope] | select |
[data-part] | root |
[data-invalid] | Present when invalid |
[data-readonly] | Present when read-only |
ClearTrigger
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
| Data Attribute | Value |
|---|---|
[data-scope] | select |
[data-part] | clear-trigger |
[data-invalid] | Present when invalid |
Content
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
| Data Attribute | Value |
|---|---|
[data-scope] | select |
[data-part] | content |
[data-state] | "open" | "closed" |
[data-placement] | The placement of the content |
[data-activedescendant] |
Control
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
| Data Attribute | Value |
|---|---|
[data-scope] | select |
[data-part] | control |
[data-state] | "open" | "closed" |
[data-focus] | Present when focused |
[data-disabled] | Present when disabled |
[data-invalid] | Present when invalid |
HiddenSelect
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
Indicator
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
| Data Attribute | Value |
|---|---|
[data-scope] | select |
[data-part] | indicator |
[data-state] | "open" | "closed" |
[data-disabled] | Present when disabled |
[data-invalid] | Present when invalid |
[data-readonly] | Present when read-only |
ItemGroupLabel
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
ItemGroup
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
| Data Attribute | Value |
|---|---|
[data-scope] | select |
[data-part] | item-group |
[data-disabled] | Present when disabled |
ItemIndicator
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
| Data Attribute | Value |
|---|---|
[data-scope] | select |
[data-part] | item-indicator |
[data-state] | "checked" | "unchecked" |
Item
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. | |
item | anyThe item to render | |
persistFocus | booleanWhether hovering outside should clear the highlighted state |
| Data Attribute | Value |
|---|---|
[data-scope] | select |
[data-part] | item |
[data-value] | |
[data-state] | "checked" | "unchecked" |
[data-highlighted] | Present when highlighted |
[data-disabled] | Present when disabled |
ItemText
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
| Data Attribute | Value |
|---|---|
[data-scope] | select |
[data-part] | item-text |
[data-state] | "checked" | "unchecked" |
[data-disabled] | Present when disabled |
[data-highlighted] | Present when highlighted |
Label
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
| Data Attribute | Value |
|---|---|
[data-scope] | select |
[data-part] | label |
[data-disabled] | Present when disabled |
[data-invalid] | Present when invalid |
[data-readonly] | Present when read-only |
List
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
Positioner
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
RootProvider
| Prop | Default | Type |
|---|---|---|
value | UseSelectReturn<T> | |
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. | |
immediate | booleanWhether to synchronize the present change immediately or defer it to the next frame | |
lazyMount | false | booleanWhether to enable lazy mounting |
onExitComplete | () => voidFunction called when the animation ends in the closed state | |
present | booleanWhether the node is present (controlled by the user) | |
unmountOnExit | false | booleanWhether to unmount on exit. |
Trigger
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. |
| Data Attribute | Value |
|---|---|
[data-scope] | select |
[data-part] | trigger |
[data-state] | "open" | "closed" |
[data-disabled] | Present when disabled |
[data-invalid] | Present when invalid |
[data-readonly] | Present when read-only |
[data-placement] | The placement of the trigger |
[data-placeholder-shown] | Present when placeholder is shown |
ValueText
| Prop | Default | Type |
|---|---|---|
asChild | booleanUse the provided child element as the default rendered element, combining their props and behavior. For more details, read our Composition guide. | |
placeholder | stringText to display when no value is selected. |
| Data Attribute | Value |
|---|---|
[data-scope] | select |
[data-part] | value-text |
[data-disabled] | Present when disabled |
[data-invalid] | Present when invalid |
[data-focus] | Present when focused |
Accessibility
Complies with the Listbox WAI-ARIA design pattern.
Keyboard Support
| Key | Description |
|---|---|
Space | When focus is on trigger, opens the select and focuses the first selected item. When focus is on the content, selects the highlighted item. |
Enter | When focus is on trigger, opens the select and focuses the first selected item. When focus is on content, selects the focused item. |
ArrowDown | When focus is on trigger, opens the select. When focus is on content, moves focus to the next item. |
ArrowUp | When focus is on trigger, opens the select. When focus is on content, moves focus to the previous item. |
Esc | Closes the select and moves focus to trigger. |
A-Za-z | When focus is on trigger, selects the item whose label starts with the typed character. When focus is on the listbox, moves focus to the next item with a label that starts with the typed character. |