Select
Displays a list of options for the user to pick from.
Displays a list of options for the user to pick from.
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.
Learn how to use the Select component in your project. Let’s take a look at
the most basic example:
import { Portal, Select } from '@ark-ui/react'
import { ChevronDownIcon } from './icons'
const Basic = () => {
  const items = ['React', 'Solid', 'Vue']
  return (
    <Select.Root items={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 id="framework">
              <Select.ItemGroupLabel htmlFor="framework">Frameworks</Select.ItemGroupLabel>
              {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.Root>
  )
}
import { Select } from '@ark-ui/solid'
import { Index, Portal } from 'solid-js/web'
const Basic = () => {
  const items = ['React', 'Solid', 'Vue']
  return (
    <Select.Root items={items}>
      <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 id="framework">
              <Select.ItemGroupLabel for="framework">Frameworks</Select.ItemGroupLabel>
              <Index each={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.Root>
  )
}
<script setup lang="ts">
import { ref } from 'vue'
import { Select } from '@ark-ui/vue'
import { ChevronDownIcon } from './icons'
const basicItems = ref(['React', 'Solid', 'Vue'])
const advancedItems = ref([
  { 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 :items="basicItems">
    <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 id="framework">
            <Select.ItemGroupLabel htmlFor="framework">Frameworks</Select.ItemGroupLabel>
            <Select.Item v-for="item in basicItems" :key="item" :item="item">
              <Select.ItemText>{{ item }}</Select.ItemText>
              <Select.ItemIndicator>✓</Select.ItemIndicator>
            </Select.Item>
          </Select.ItemGroup>
        </Select.Content>
      </Select.Positioner>
    </Teleport>
  </Select.Root>
</template>
For advanced customizations and item properties like disabled:
import { Portal, Select } from '@ark-ui/react'
import { ChevronDownIcon } from './icons'
const Advanced = () => {
  type Item = { label: string; value: string; disabled?: boolean }
  const items: Item[] = [
    { label: 'React', value: 'react' },
    { label: 'Solid', value: 'solid' },
    { label: 'Vue', value: 'vue' },
    { label: 'Svelte', value: 'svelte', disabled: true },
  ]
  return (
    <Select.Root items={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 id="framework">
              <Select.ItemGroupLabel htmlFor="framework">Frameworks</Select.ItemGroupLabel>
              {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.Root>
  )
}
import { Select } from '@ark-ui/solid'
import { Index, Portal } from 'solid-js/web'
const Advanced = () => {
  const items: Item[] = [
    { label: 'React', value: 'react' },
    { label: 'Solid', value: 'solid' },
    { label: 'Vue', value: 'vue' },
    { label: 'Svelte', value: 'svelte', disabled: true },
  ]
  return (
    <Select.Root items={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 id="framework">
              <Select.ItemGroupLabel for="framework">Frameworks</Select.ItemGroupLabel>
              <Index each={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.Root>
  )
}
<script setup lang="ts">
import { ref } from 'vue'
import { Select } from '@ark-ui/vue'
import { ChevronDownIcon } from './icons'
const basicItems = ref(['React', 'Solid', 'Vue'])
const advancedItems = ref([
  { 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 :items="advancedItems">
    <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 id="framework">
            <Select.ItemGroupLabel htmlFor="framework">Frameworks</Select.ItemGroupLabel>
            <Select.Item v-for="item in advancedItems" :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.Root>
</template>
To enable multiple item selection:
import { Portal, Select } from '@ark-ui/react'
import { ChevronDownIcon } from './icons'
const Multiple = () => {
  type Item = { label: string; value: string; disabled?: boolean }
  const items: Item[] = [
    { label: 'React', value: 'react' },
    { label: 'Solid', value: 'solid' },
    { label: 'Vue', value: 'vue' },
    { label: 'Svelte', value: 'svelte', disabled: true },
  ]
  return (
    <Select.Root items={items} 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 id="framework">
              <Select.ItemGroupLabel htmlFor="framework">Frameworks</Select.ItemGroupLabel>
              {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.Root>
  )
}
import { Select } from '@ark-ui/solid'
import { Index, Portal } from 'solid-js/web'
const Multiple = () => {
  const items: Item[] = [
    { label: 'React', value: 'react' },
    { label: 'Solid', value: 'solid' },
    { label: 'Vue', value: 'vue' },
    { label: 'Svelte', value: 'svelte', disabled: true },
  ]
  return (
    <Select.Root items={items} 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 id="framework">
              <Index each={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.Root>
  )
}
<script setup lang="ts">
import { ref } from 'vue'
import { Select } from '@ark-ui/vue'
import { ChevronDownIcon } from './icons'
const basicItems = ref(['React', 'Solid', 'Vue'])
const advancedItems = ref([
  { 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 :items="advancedItems" 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 id="framework">
            <Select.ItemGroupLabel htmlFor="framework">Frameworks</Select.ItemGroupLabel>
            <Select.Item v-for="item in advancedItems" :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.Root>
</template>
For scenarios where you want to control the Select component’s state:
import { Portal, Select } from '@ark-ui/react'
import { useState } from 'react'
import { ChevronDownIcon } from './icons'
const Controlled = () => {
  type Item = { label: string; value: string; disabled?: boolean }
  const [_, setSelectedItems] = useState<Item[]>([])
  const items: Item[] = [
    { label: 'React', value: 'react' },
    { label: 'Solid', value: 'solid' },
    { label: 'Vue', value: 'vue' },
    { label: 'Svelte', value: 'svelte', disabled: true },
  ]
  return (
    <Select.Root items={items} 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 id="framework">
              <Select.ItemGroupLabel htmlFor="framework">Frameworks</Select.ItemGroupLabel>
              {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.Root>
  )
}
import { Select } from '@ark-ui/solid'
import { createSignal } from 'solid-js'
import { Index, Portal } from 'solid-js/web'
const Controlled = () => {
  const [, setSelectedItems] = createSignal<Item[]>([])
  const items: Item[] = [
    { label: 'React', value: 'react' },
    { label: 'Solid', value: 'solid' },
    { label: 'Vue', value: 'vue' },
    { label: 'Svelte', value: 'svelte', disabled: true },
  ]
  return (
    <Select.Root items={items} 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 id="framework">
              <Select.ItemGroupLabel for="framework">Frameworks</Select.ItemGroupLabel>
              <Index each={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.Root>
  )
}
<script setup lang="ts">
import { ref } from 'vue'
import { Select } from '@ark-ui/vue'
import { ChevronDownIcon } from './icons'
const basicItems = ref(['React', 'Solid', 'Vue'])
const advancedItems = ref([
  { 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 :items="advancedItems" 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 id="framework">
            <Select.ItemGroupLabel htmlFor="framework">Frameworks</Select.ItemGroupLabel>
            <Select.Item v-for="item in advancedItems" :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.Root>
</template>
See how to use the Select component with popular form libraries:
import { Select } from '@ark-ui/react'
import { Controller, useForm, type SubmitHandler } from 'react-hook-form'
import { ChevronsDownUpIcon } from './icons'
const FormLibrary = () => {
  type Inputs = {
    framework: string
  }
  const items = ['React', 'Solid', 'Vue']
  const { control, handleSubmit } = useForm<Inputs>()
  const onSubmit: SubmitHandler<Inputs> = (data) => console.log(data)
  return (
    <form onSubmit={handleSubmit(onSubmit)}>
      <Controller
        name="framework"
        control={control}
        render={({ field }) => (
          <Select.Root onValueChange={(e) => field.onChange(e?.value)} items={items}>
            <Select.Label>Framework</Select.Label>
            <Select.Control>
              <Select.Trigger>
                <Select.ValueText placeholder="Select a Framework" />
                <Select.Indicator>
                  <ChevronsDownUpIcon />
                </Select.Indicator>
              </Select.Trigger>
              <Select.ClearTrigger>Clear</Select.ClearTrigger>
            </Select.Control>
            <Select.Positioner>
              <Select.Content>
                <Select.ItemGroup id="framework">
                  <Select.ItemGroupLabel htmlFor="framework">Frameworks</Select.ItemGroupLabel>
                  {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>
  )
}
Story not availableStory not available| Prop | Type | Default | 
|---|---|---|
| asChildRender as a different element type. | boolean | |
| item | any | 
| Prop | Type | Default | 
|---|---|---|
| itemsThe options of the select | T[] | readonly T[] | |
| asChildRender as a different element type. | boolean | |
| closeOnSelectWhether the select should close after an item is selected | boolean | |
| defaultValueThe initial value of the select. | string[] | |
| dirThe document's text/writing direction. | 'ltr' | 'rtl' | "ltr" | 
| disabledWhether the select is disabled | boolean | |
| formThe associate form of the underlying select. | string | |
| getRootNodeA root node to correctly resolve document in custom environments. E.x.: Iframes, Electron. | () => Node | ShadowRoot | Document | |
| highlightedValueThe key of the highlighted item | string | |
| idThe unique identifier of the machine. | string | |
| idsThe ids of the elements in the select. Useful for composition. | 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
}> | |
| invalidWhether the select is invalid | boolean | |
| isItemDisabledWhether the item is disabled | (item: T) => boolean | |
| itemToStringThe label of the item | (item: T) => string | |
| itemToValueThe value of the item | (item: T) => string | |
| lazyMountWhether to enable lazy mounting | boolean | false | 
| loopWhether to loop the keyboard navigation through the options | boolean | |
| multipleWhether to allow multiple selection | boolean | |
| nameThe `name` attribute of the underlying select. | string | |
| onExitCompleteFunction called when the animation ends in the closed state. | () => void | |
| onFocusOutsideFunction called when the focus is moved outside the component | (event: FocusOutsideEvent) => void | |
| onHighlightChangeThe callback fired when the highlighted item changes. | (details: HighlightChangeDetails<T>) => void | |
| onInteractOutsideFunction called when an interaction happens outside the component | (event: InteractOutsideEvent) => void | |
| onOpenChangeFunction called when the popup is opened | (details: OpenChangeDetails) => void | |
| onPointerDownOutsideFunction called when the pointer is pressed down outside the component | (event: PointerDownOutsideEvent) => void | |
| onValueChangeThe callback fired when the selected item changes. | (details: ValueChangeDetails<T>) => void | |
| openWhether the select menu is open | boolean | |
| positioningThe positioning options of the menu. | PositioningOptions | |
| presentWhether the node is present (controlled by the user) | boolean | |
| readOnlyWhether the select is read-only | boolean | |
| selectOnBlurWhether to select the highlighted item when the user presses Tab, and the menu is open. | boolean | |
| unmountOnExitWhether to unmount on exit. | boolean | false | 
| valueThe keys of the selected items | string[] | 
| Prop | Type | Default | 
|---|---|---|
| asChildRender as a different element type. | boolean | 
| Prop | Type | Default | 
|---|---|---|
| asChildRender as a different element type. | boolean | 
| Prop | Type | Default | 
|---|---|---|
| asChildRender as a different element type. | boolean | 
| Prop | Type | Default | 
|---|---|---|
| asChildRender as a different element type. | boolean | 
| Prop | Type | Default | 
|---|---|---|
| asChildRender as a different element type. | boolean | 
| Prop | Type | Default | 
|---|---|---|
| asChildRender as a different element type. | boolean | 
| Prop | Type | Default | 
|---|---|---|
| id | string | |
| asChildRender as a different element type. | boolean | 
| Prop | Type | Default | 
|---|---|---|
| asChildRender as a different element type. | boolean | |
| placeholderText to display when no value is selected. | string | 
| Prop | Type | Default | 
|---|---|---|
| asChildRender as a different element type. | boolean | 
| Prop | Type | Default | 
|---|---|---|
| asChildRender as a different element type. | boolean | 
| Prop | Type | Default | 
|---|---|---|
| asChildRender as a different element type. | boolean | 
| Prop | Type | Default | 
|---|---|---|
| htmlFor | string | |
| asChildRender as a different element type. | boolean | 
Previous
Segment GroupNext
Slider