Components
Select

Select

Displays a list of options for the user to pick from.

Loading...

You can explore the select component in the following curated examples.

Anatomy

<Select.Root>
  <Select.Label />
  <Select.Control>
    <Select.Trigger>
      <Select.ValueText />
    </Select.Trigger>
    <Select.ClearTrigger />
    <Select.Indicator />
  </Select.Control>
  <Select.Positioner>
    <Select.Content>
      <Select.ItemGroup>
        <Select.ItemGroupLabel />
        <Select.Item>
          <Select.ItemText />
          <Select.ItemIndicator />
        </Select.Item>
      </Select.ItemGroup>
    </Select.Content>
  </Select.Positioner>
  <Select.HiddenSelect />
</Select.Root>

Examples

Controlled

Use the value and onValueChange props to control the selected items.

Root Provider

An alternative way to control the select is to use the RootProvider component and the useSelect hook. This way you can access the state and methods from outside the component.

Multiple

To enable multiple item selection:

Grouping

Grouping related options can be useful for organizing options into categories.

  • Use the groupBy prop to configure the grouping of the items.
  • Use the collection.group() method to get the grouped items.
  • Use the Select.ItemGroup and Select.ItemGroupLabel components to render the grouped items.

Field

Use Field to manage form state, ARIA labels, helper text, and error text.

Form Usage

Here's an example of integrating the Select component with a form library.

Async Loading

Here's an example of how to load the items asynchronously when the select is opened.

Lazy Mount

Use lazyMount and unmountOnExit to control when content is mounted, improving performance.

Select on Highlight

Here's an example of automatically selecting items when they are highlighted (hovered or navigated to with keyboard).

Max Selection

Here's an example of limiting the number of items that can be selected in a multiple select.

Select All

Use selectAll() from the select context to select all items at once.

Overflow

For selects with many items, use positioning.fitViewport to ensure the dropdown fits within the viewport. Combine with a max-height on the content to enable scrolling.

Guides

Type Safety

The Select.RootComponent type enables you to create typed wrapper components that maintain full type safety for collection items.

const Select: ArkSelect.RootComponent = (props) => {
  return <ArkSelect.Root {...props}>{/* ... */}</ArkSelect.Root>
}

Use the wrapper with full type inference on onValueChange and other callbacks:

const App = () => {
  const collection = createListCollection({
    initialItems: [
      { label: 'React', value: 'react' },
      { label: 'Vue', value: 'vue' },
    ],
  })
  return (
    <Select
      collection={collection}
      onValueChange={(e) => {
        // e.items is typed as Array<{ label: string, value: string }>
        console.log(e.items)
      }}
    >
      {/* ... */}
    </Select>
  )
}

Nested Usage

When using the Select component within a Popover or Dialog, avoid rendering its content within a Portal or Teleport.

This ensures the Select's content stays within the Popover/Dialog's DOM hierarchy rather than being portalled to the document body, maintaining proper interaction and accessibility behavior.

Hidden Select

The Select.HiddenSelect component renders a native HTML <select> element that's visually hidden but remains in the DOM. This component is essential for:

  • Form submission: Native form submission and serialization work seamlessly since the actual <select> element exists in the DOM
  • Browser auto-fill: Browsers can properly auto-fill the select based on previously submitted form data
  • Progressive enhancement: Forms remain functional even if JavaScript fails to load
<Select.Root>
  <Select.HiddenSelect />
  {/* Other Select components */}
</Select.Root>

The hidden select automatically syncs with the Select component's value, ensuring form data is always up-to-date.

Empty State

You can create an empty state component that displays when there are no items in the collection. Use the useSelectContext hook to check the collection size:

const SelectEmpty = (props: React.ComponentProps<'div'>) => {
  const select = useSelectContext()
  if (select.collection.size === 0) {
    return <div {...props} role="presentation" />
  }
  return null
}

Then use it within your Select content:

<Select.Content>
  <SelectEmpty>No items to display</SelectEmpty>
  {/* Your items */}
</Select.Content>

Available Size

The following css variables are exposed to the Select.Positioner which you can use to style the Select.Content

/* width of the select trigger */
--reference-width: <pixel-value>;
/* width of the available viewport */
--available-width: <pixel-value>;
/* height of the available viewport */
--available-height: <pixel-value>;

For example, if you want to make sure the maximum height doesn't exceed the available height, you can use the following:

[data-scope='select'][data-part='content'] {
  max-height: calc(var(--available-height) - 100px);
}

API Reference

Props

Root

PropDefaultType
collection
ListCollection<T>

The collection of items

asChild
boolean

Use the provided child element as the default rendered element, combining their props and behavior.

For more details, read our Composition guide.
closeOnSelecttrue
boolean

Whether the select should close after an item is selected

compositetrue
boolean

Whether the select is a composed with other composite widgets like tabs or combobox

defaultHighlightedValue
string

The initial value of the highlighted item when opened. Use when you don't need to control the highlighted value of the select.

defaultOpen
boolean

Whether the select's open state is controlled by the user

defaultValue
string[]

The initial default value of the select when rendered. Use when you don't need to control the value of the select.

deselectable
boolean

Whether the value can be cleared by clicking the selected item. **Note:** this is only applicable for single selection

disabled
boolean

Whether the select is disabled

form
string

The associate form of the underlying select.

highlightedValue
string

The controlled key of the highlighted item

id
string

The 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
boolean

Whether to synchronize the present change immediately or defer it to the next frame

invalid
boolean

Whether the select is invalid

lazyMountfalse
boolean

Whether to enable lazy mounting

loopFocusfalse
boolean

Whether to loop the keyboard navigation through the options

multiple
boolean

Whether to allow multiple selection

name
string

The `name` attribute of the underlying select.

onExitComplete
VoidFunction

Function called when the animation ends in the closed state

onFocusOutside
(event: FocusOutsideEvent) => void

Function called when the focus is moved outside the component

onHighlightChange
(details: HighlightChangeDetails<T>) => void

The callback fired when the highlighted item changes.

onInteractOutside
(event: InteractOutsideEvent) => void

Function called when an interaction happens outside the component

onOpenChange
(details: OpenChangeDetails) => void

Function called when the popup is opened

onPointerDownOutside
(event: PointerDownOutsideEvent) => void

Function called when the pointer is pressed down outside the component

onSelect
(details: SelectionDetails) => void

Function called when an item is selected

onValueChange
(details: ValueChangeDetails<T>) => void

The callback fired when the selected item changes.

open
boolean

Whether the select menu is open

positioning
PositioningOptions

The positioning options of the menu.

present
boolean

Whether the node is present (controlled by the user)

readOnly
boolean

Whether the select is read-only

required
boolean

Whether the select is required

scrollToIndexFn
(details: ScrollToIndexDetails) => void

Function to scroll to a specific index

skipAnimationOnMountfalse
boolean

Whether to allow the initial presence animation.

unmountOnExitfalse
boolean

Whether to unmount on exit.

value
string[]

The controlled keys of the selected items

AttributeDescription
[data-scope]select
[data-part]root
[data-invalid]Present when invalid
[data-readonly]Present when read-only

ClearTrigger

Renders a <button> element.

PropDefaultType
asChild
boolean

Use the provided child element as the default rendered element, combining their props and behavior.

For more details, read our Composition guide.
AttributeDescription
[data-scope]select
[data-part]clear-trigger
[data-invalid]Present when invalid

Content

Renders a <div> element.

PropDefaultType
asChild
boolean

Use the provided child element as the default rendered element, combining their props and behavior.

For more details, read our Composition guide.
AttributeDescription
[data-scope]select
[data-part]content
[data-state]"open" | "closed"
[data-nested]listbox
[data-has-nested]listbox
[data-placement]The placement of the content
[data-activedescendant]The id the active descendant of the content
CSS VariableDescription
--layer-indexThe index of the dismissable in the layer stack
--nested-layer-countThe number of nested selects

Control

Renders a <div> element.

PropDefaultType
asChild
boolean

Use the provided child element as the default rendered element, combining their props and behavior.

For more details, read our Composition guide.
AttributeDescription
[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

Renders a <select> element.

PropDefaultType
asChild
boolean

Use the provided child element as the default rendered element, combining their props and behavior.

For more details, read our Composition guide.

Indicator

Renders a <div> element.

PropDefaultType
asChild
boolean

Use the provided child element as the default rendered element, combining their props and behavior.

For more details, read our Composition guide.
AttributeDescription
[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

Renders a <div> element.

PropDefaultType
asChild
boolean

Use the provided child element as the default rendered element, combining their props and behavior.

For more details, read our Composition guide.

ItemGroup

Renders a <div> element.

PropDefaultType
asChild
boolean

Use the provided child element as the default rendered element, combining their props and behavior.

For more details, read our Composition guide.
AttributeDescription
[data-scope]select
[data-part]item-group
[data-disabled]Present when disabled

ItemIndicator

Renders a <div> element.

PropDefaultType
asChild
boolean

Use the provided child element as the default rendered element, combining their props and behavior.

For more details, read our Composition guide.
AttributeDescription
[data-scope]select
[data-part]item-indicator
[data-state]"checked" | "unchecked"

Item

Renders a <div> element.

PropDefaultType
asChild
boolean

Use the provided child element as the default rendered element, combining their props and behavior.

For more details, read our Composition guide.
item
any

The item to render

persistFocus
boolean

Whether hovering outside should clear the highlighted state

AttributeDescription
[data-scope]select
[data-part]item
[data-value]The value of the item
[data-state]"checked" | "unchecked"
[data-highlighted]Present when highlighted
[data-disabled]Present when disabled

ItemText

Renders a <div> element.

PropDefaultType
asChild
boolean

Use the provided child element as the default rendered element, combining their props and behavior.

For more details, read our Composition guide.
AttributeDescription
[data-scope]select
[data-part]item-text
[data-state]"checked" | "unchecked"
[data-disabled]Present when disabled
[data-highlighted]Present when highlighted

Label

Renders a <label> element.

PropDefaultType
asChild
boolean

Use the provided child element as the default rendered element, combining their props and behavior.

For more details, read our Composition guide.
AttributeDescription
[data-scope]select
[data-part]label
[data-disabled]Present when disabled
[data-invalid]Present when invalid
[data-readonly]Present when read-only
[data-required]Present when required

List

Renders a <div> element.

PropDefaultType
asChild
boolean

Use the provided child element as the default rendered element, combining their props and behavior.

For more details, read our Composition guide.

Positioner

Renders a <div> element.

PropDefaultType
asChild
boolean

Use the provided child element as the default rendered element, combining their props and behavior.

For more details, read our Composition guide.
CSS VariableDescription
--reference-widthThe width of the reference element
--reference-heightThe height of the root
--available-widthThe available width in viewport
--available-heightThe available height in viewport
--xThe x position for transform
--yThe y position for transform
--z-indexThe z-index value
--transform-originThe transform origin for animations

RootProvider

PropDefaultType
value
UseSelectReturn<T>

asChild
boolean

Use the provided child element as the default rendered element, combining their props and behavior.

For more details, read our Composition guide.
immediate
boolean

Whether to synchronize the present change immediately or defer it to the next frame

lazyMountfalse
boolean

Whether to enable lazy mounting

onExitComplete
VoidFunction

Function called when the animation ends in the closed state

present
boolean

Whether the node is present (controlled by the user)

skipAnimationOnMountfalse
boolean

Whether to allow the initial presence animation.

unmountOnExitfalse
boolean

Whether to unmount on exit.

Trigger

Renders a <button> element.

PropDefaultType
asChild
boolean

Use the provided child element as the default rendered element, combining their props and behavior.

For more details, read our Composition guide.
AttributeDescription
[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

Renders a <span> element.

PropDefaultType
asChild
boolean

Use the provided child element as the default rendered element, combining their props and behavior.

For more details, read our Composition guide.
placeholder
string

Text to display when no value is selected.

AttributeDescription
[data-scope]select
[data-part]value-text
[data-disabled]Present when disabled
[data-invalid]Present when invalid
[data-focus]Present when focused

Context

API

PropertyType
focused
boolean

Whether the select is focused

open
boolean

Whether the select is open

empty
boolean

Whether the select value is empty

highlightedValue
string

The value of the highlighted item

highlightedItem
V

The highlighted item

setHighlightValue
(value: string) => void

Function to highlight a value

clearHighlightValue
VoidFunction

Function to clear the highlighted value

selectedItems
V[]

The selected items

hasSelectedItems
boolean

Whether there's a selected option

value
string[]

The selected item keys

valueAsString
string

The string representation of the selected items

selectValue
(value: string) => void

Function to select a value

selectAll
VoidFunction

Function to select all values

setValue
(value: string[]) => void

Function to set the value of the select

clearValue
(value?: string) => void

Function to clear the value of the select. If a value is provided, it will only clear that value, otherwise, it will clear all values.

focus
VoidFunction

Function to focus on the select input

getItemState
(props: ItemProps<any>) => ItemState

Returns the state of a select item

setOpen
(open: boolean) => void

Function to open or close the select

collection
ListCollection<V>

Function to toggle the select

reposition
(options?: Partial<PositioningOptions>) => void

Function to set the positioning options of the select

multiple
boolean

Whether the select allows multiple selections

disabled
boolean

Whether the select is disabled

Accessibility

Complies with the Listbox WAI-ARIA design pattern.

Keyboard Support

KeyDescription
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.