'use client'
import { createListCollection } from '@chakra-ui/react'
import { Select } from '@saas-ui/react'
export const SelectBasic = () => {
  return (
    <Select.Root collection={frameworks} size="sm" width="320px">
      <Select.Label>Select framework</Select.Label>
      <Select.Trigger>
        <Select.ValueText placeholder="Select movie" />
      </Select.Trigger>
      <Select.Content>
        {frameworks.items.map((movie) => (
          <Select.Item item={movie} key={movie.value}>
            {movie.label}
          </Select.Item>
        ))}
      </Select.Content>
    </Select.Root>
  )
}
const frameworks = createListCollection({
  items: [
    { label: 'React.js', value: 'react' },
    { label: 'Vue.js', value: 'vue' },
    { label: 'Angular', value: 'angular' },
    { label: 'Svelte', value: 'svelte' },
  ],
})
import { Select } from '@saas-ui/react/select'<Select.Root items={[]}>
  <Select.Label />
  <Select.Trigger>
    <Select.ValueText placeholder="Select" />
  </Select.Trigger>
  <Select.Content>
    <Select.Item />
  </Select.Content>
</Select.Root>Use the size prop to change the size of the select component.
'use client'
import { For, Stack, createListCollection } from '@chakra-ui/react'
import { Select } from '@saas-ui/react'
export const SelectWithSizes = () => {
  return (
    <Stack gap="5" width="320px">
      <For each={['xs', 'sm', 'md', 'lg']}>
        {(size) => (
          <Select.Root key={size} size={size} collection={frameworks}>
            <Select.Label>size = {size}</Select.Label>
            <Select.Trigger>
              <Select.ValueText placeholder="Select movie" />
            </Select.Trigger>
            <Select.Content>
              {frameworks.items.map((movie) => (
                <Select.Item item={movie} key={movie.value}>
                  {movie.label}
                </Select.Item>
              ))}
            </Select.Content>
          </Select.Root>
        )}
      </For>
    </Stack>
  )
}
const frameworks = createListCollection({
  items: [
    { label: 'React.js', value: 'react' },
    { label: 'Vue.js', value: 'vue' },
    { label: 'Angular', value: 'angular' },
    { label: 'Svelte', value: 'svelte' },
  ],
})
Use the variant prop to change the appearance of the select component.
'use client'
import { For, Stack, createListCollection } from '@chakra-ui/react'
import { Select } from '@saas-ui/react'
export const SelectWithVariants = () => {
  return (
    <Stack gap="5" width="320px">
      <For each={['outline', 'subtle']}>
        {(variant) => (
          <Select.Root key={variant} variant={variant} collection={frameworks}>
            <Select.Label>Select framework - {variant}</Select.Label>
            <Select.Trigger>
              <Select.ValueText placeholder="Select movie" />
            </Select.Trigger>
            <Select.Content>
              {frameworks.items.map((movie) => (
                <Select.Item item={movie} key={movie.value}>
                  {movie.label}
                </Select.Item>
              ))}
            </Select.Content>
          </Select.Root>
        )}
      </For>
    </Stack>
  )
}
const frameworks = createListCollection({
  items: [
    { label: 'React.js', value: 'react' },
    { label: 'Vue.js', value: 'vue' },
    { label: 'Angular', value: 'angular' },
    { label: 'Svelte', value: 'svelte' },
  ],
})
Use the SelectItemGroup component to group select options.
'use client'
import { createListCollection } from '@chakra-ui/react'
import { Select } from '@saas-ui/react'
export const SelectWithOptionGroup = () => {
  return (
    <Select.Root collection={frameworks} size="sm" width="320px">
      <Select.Label>Select framework</Select.Label>
      <Select.Trigger>
        <Select.ValueText placeholder="Select movie" />
      </Select.Trigger>
      <Select.Content>
        {categories.map((category) => (
          <Select.ItemGroup key={category.group} label={category.group}>
            {category.items.map((item) => (
              <Select.Item item={item} key={item.value}>
                {item.label}
              </Select.Item>
            ))}
          </Select.ItemGroup>
        ))}
      </Select.Content>
    </Select.Root>
  )
}
const frameworks = createListCollection({
  items: [
    { label: 'Naruto', value: 'naruto', group: 'Anime' },
    { label: 'One Piece', value: 'one-piece', group: 'Anime' },
    { label: 'Dragon Ball', value: 'dragon-ball', group: 'Anime' },
    {
      label: 'The Shawshank Redemption',
      value: 'the-shawshank-redemption',
      group: 'Movies',
    },
    { label: 'The Godfather', value: 'the-godfather', group: 'Movies' },
    { label: 'The Dark Knight', value: 'the-dark-knight', group: 'Movies' },
  ],
})
const categories = frameworks.items.reduce(
  (acc, item) => {
    const group = acc.find((group) => group.group === item.group)
    if (group) {
      group.items.push(item)
    } else {
      acc.push({ group: item.group, items: [item] })
    }
    return acc
  },
  [] as { group: string; items: (typeof frameworks)['items'] }[],
)
Use the value and onValueChange props to control the select component.
'use client'
import { useState } from 'react'
import { createListCollection } from '@chakra-ui/react'
import { Select } from '@saas-ui/react'
export const SelectControlled = () => {
  const [value, setValue] = useState<string[]>([])
  return (
    <Select.Root
      collection={frameworks}
      width="320px"
      value={value}
      onValueChange={(e) => setValue(e.value)}
    >
      <Select.Label>Select framework</Select.Label>
      <Select.Trigger>
        <Select.ValueText placeholder="Select movie" />
      </Select.Trigger>
      <Select.Content>
        {frameworks.items.map((movie) => (
          <Select.Item item={movie} key={movie.value}>
            {movie.label}
          </Select.Item>
        ))}
      </Select.Content>
    </Select.Root>
  )
}
const frameworks = createListCollection({
  items: [
    { label: 'React.js', value: 'react' },
    { label: 'Vue.js', value: 'vue' },
    { label: 'Angular', value: 'angular' },
    { label: 'Svelte', value: 'svelte' },
  ],
})
Here's an example of how to use the Select component with react-hook-form.
'use client'
import { Button, Stack, createListCollection } from '@chakra-ui/react'
import { zodResolver } from '@hookform/resolvers/zod'
import { Field, Select } from '@saas-ui/react'
import { Controller, useForm } from 'react-hook-form'
import { z } from 'zod'
const formSchema = z.object({
  framework: z.string({ message: 'Framework is required' }).array(),
})
type FormValues = z.infer<typeof formSchema>
export const SelectWithHookForm = () => {
  const {
    handleSubmit,
    formState: { errors },
    control,
  } = useForm<FormValues>({
    resolver: zodResolver(formSchema),
  })
  const onSubmit = handleSubmit((data) => console.log(data))
  return (
    <form onSubmit={onSubmit}>
      <Stack gap="4" align="flex-start">
        <Controller
          control={control}
          name="framework"
          render={({ field }) => (
            <Field.Root invalid={!!errors.framework} width="320px">
              <Field.Label>Framework</Field.Label>
              <Select.Root
                name={field.name}
                value={field.value}
                onValueChange={({ value }) => field.onChange(value)}
                onInteractOutside={() => field.onBlur()}
                collection={frameworks}
              >
                <Select.Trigger>
                  <Select.ValueText placeholder="Select movie" />
                </Select.Trigger>
                <Select.Content>
                  {frameworks.items.map((movie) => (
                    <Select.Item item={movie} key={movie.value}>
                      {movie.label}
                    </Select.Item>
                  ))}
                </Select.Content>
              </Select.Root>
              <Field.ErrorText>{errors.framework?.message}</Field.ErrorText>
            </Field.Root>
          )}
        />
        <Button size="sm" type="submit">
          Submit
        </Button>
      </Stack>
    </form>
  )
}
const frameworks = createListCollection({
  items: [
    { label: 'React.js', value: 'react' },
    { label: 'Vue.js', value: 'vue' },
    { label: 'Angular', value: 'angular' },
    { label: 'Svelte', value: 'svelte' },
  ],
})
Use the disabled prop to disable the select component.
'use client'
import { createListCollection } from '@chakra-ui/react'
import { Select } from '@saas-ui/react'
export const SelectWithDisabled = () => {
  return (
    <Select.Root disabled collection={frameworks} size="sm" width="320px">
      <Select.Label>Select framework</Select.Label>
      <Select.Trigger>
        <Select.ValueText placeholder="Select movie" />
      </Select.Trigger>
      <Select.Content>
        {frameworks.items.map((movie) => (
          <Select.Item item={movie} key={movie.value}>
            {movie.label}
          </Select.Item>
        ))}
      </Select.Content>
    </Select.Root>
  )
}
const frameworks = createListCollection({
  items: [
    { label: 'React.js', value: 'react' },
    { label: 'Vue.js', value: 'vue' },
    { label: 'Angular', value: 'angular' },
    { label: 'Svelte', value: 'svelte' },
  ],
})
Use the invalid prop to indicate that the select component has an error.
'use client'
import { createListCollection } from '@chakra-ui/react'
import { Field, Select } from '@saas-ui/react'
export const SelectWithInvalid = () => {
  return (
    <Field.Root invalid>
      <Select.Root collection={frameworks} size="sm" width="320px">
        <Select.Label>Select framework</Select.Label>
        <Select.Trigger>
          <Select.ValueText placeholder="Select movie" />
        </Select.Trigger>
        <Select.Content>
          {frameworks.items.map((movie) => (
            <Select.Item item={movie} key={movie.value}>
              {movie.label}
            </Select.Item>
          ))}
        </Select.Content>
      </Select.Root>
      <Field.ErrorText>This is an error</Field.ErrorText>
    </Field.Root>
  )
}
const frameworks = createListCollection({
  items: [
    { label: 'React.js', value: 'react' },
    { label: 'Vue.js', value: 'vue' },
    { label: 'Angular', value: 'angular' },
    { label: 'Svelte', value: 'svelte' },
  ],
})
Use the positioning prop to control the underlying floating-ui options of
the select component.
'use client'
import { createListCollection } from '@chakra-ui/react'
import { Select } from '@saas-ui/react'
export const SelectWithPositioning = () => {
  return (
    <Select.Root
      collection={frameworks}
      size="sm"
      width="320px"
      positioning={{ placement: 'top', flip: false }}
    >
      <Select.Label>Select framework</Select.Label>
      <Select.Trigger>
        <Select.ValueText placeholder="Select movie" />
      </Select.Trigger>
      <Select.Content>
        {frameworks.items.map((movie) => (
          <Select.Item item={movie} key={movie.value}>
            {movie.label}
          </Select.Item>
        ))}
      </Select.Content>
    </Select.Root>
  )
}
const frameworks = createListCollection({
  items: [
    { label: 'React.js', value: 'react' },
    { label: 'Vue.js', value: 'vue' },
    { label: 'Angular', value: 'angular' },
    { label: 'Svelte', value: 'svelte' },
  ],
})
Use the Select within a Popover component.
'use client'
import { createListCollection } from '@chakra-ui/react'
import { Button, Popover, Select } from '@saas-ui/react'
export const SelectInPopover = () => {
  return (
    <Popover.Root size="xs">
      <Popover.Trigger asChild>
        <Button variant="outline" size="sm">
          Select in Popover
        </Button>
      </Popover.Trigger>
      <Popover.Content>
        <Popover.Header>Select in Popover</Popover.Header>
        <Popover.Body>
          <Select.Root
            collection={frameworks}
            size="sm"
            positioning={{ sameWidth: true, placement: 'bottom' }}
          >
            <Select.Trigger>
              <Select.ValueText placeholder="Select" />
            </Select.Trigger>
            <Select.Content portalled={false} width="full">
              {frameworks.items.map((item) => (
                <Select.Item item={item} key={item.value}>
                  {item.label}
                </Select.Item>
              ))}
            </Select.Content>
          </Select.Root>
        </Popover.Body>
      </Popover.Content>
    </Popover.Root>
  )
}
const frameworks = createListCollection({
  items: [
    { label: 'React.js', value: 'react' },
    { label: 'Vue.js', value: 'vue' },
    { label: 'Angular', value: 'angular' },
    { label: 'Svelte', value: 'svelte' },
  ],
})
Here's an example of how to compose the Select and the Avatar.
'use client'
import { HStack, createListCollection } from '@chakra-ui/react'
import { Avatar, Select } from '@saas-ui/react'
const SelectValueItem = () => (
  <Select.ValueText placeholder="Select movie">
    {(items: Array<{ name: string; avatar: string }>) => {
      const { name, avatar } = items[0]
      return (
        <HStack>
          <Avatar name={name} size="xs" src={avatar} />
          {name}
        </HStack>
      )
    }}
  </Select.ValueText>
)
export const SelectWithAvatar = () => {
  return (
    <Select.Root
      collection={members}
      size="sm"
      width="240px"
      defaultValue={['jessica_jones']}
      positioning={{ sameWidth: true }}
    >
      <Select.Label>Select member</Select.Label>
      <Select.Trigger>
        <SelectValueItem />
      </Select.Trigger>
      <Select.Content portalled={false}>
        {members.items.map((item) => (
          <Select.Item item={item} key={item.id} justifyContent="flex-start">
            <Avatar name={item.name} src={item.avatar} size="xs" />
            {item.name}
          </Select.Item>
        ))}
      </Select.Content>
    </Select.Root>
  )
}
const members = createListCollection({
  items: [
    {
      name: 'Jessica Jones',
      id: 'jessica_jones',
      avatar:
        'https://images.unsplash.com/photo-1531746020798-e6953c6e8e04?w=100',
    },
    {
      name: 'Kenneth Johnson',
      id: 'kenneth_johnson',
      avatar:
        'https://images.unsplash.com/photo-1523477800337-966dbabe060b?w=100',
    },
    {
      name: 'Kate Wilson',
      id: 'kate_wilson',
      avatar:
        'https://images.unsplash.com/photo-1609712409631-dbbb050746d1?w=100',
    },
  ],
  itemToString: (item) => item.name,
  itemToValue: (item) => item.id,
})
Pass the clearable prop to the SelectTrigger.
'use client'
import { createListCollection } from '@chakra-ui/react'
import { Select } from '@saas-ui/react'
export const SelectWithClear = () => {
  return (
    <Select.Root
      collection={animeMovies}
      defaultValue={['spirited_away']}
      size="sm"
      width="320px"
    >
      <Select.Label>Select fav. anime</Select.Label>
      <Select.Trigger clearable>
        <Select.ValueText placeholder="Select movie" />
      </Select.Trigger>
      <Select.Content>
        {animeMovies.items.map((movie) => (
          <Select.Item item={movie} key={movie.value}>
            {movie.label}
          </Select.Item>
        ))}
      </Select.Content>
    </Select.Root>
  )
}
const animeMovies = createListCollection({
  items: [
    { label: 'Spirited Away', value: 'spirited_away' },
    { label: 'My Neighbor Totoro', value: 'my_neighbor_totoro' },
    { label: 'Akira', value: 'akira' },
    { label: 'Princess Mononoke', value: 'princess_mononoke' },
    { label: 'Grave of the Fireflies', value: 'grave_of_the_fireflies' },
    { label: "Howl's Moving Castle", value: 'howls_moving_castle' },
    { label: 'Ghost in the Shell', value: 'ghost_in_the_shell' },
    { label: 'Naruto', value: 'naruto' },
    { label: 'Hunter x Hunter', value: 'hunter_x_hunter' },
    { label: 'The Wind Rises', value: 'the_wind_rises' },
    { label: "Kiki's Delivery Service", value: 'kikis_delivery_service' },
    { label: 'Perfect Blue', value: 'perfect_blue' },
    {
      label: 'The Girl Who Leapt Through Time',
      value: 'the_girl_who_leapt_through_time',
    },
    { label: 'Weathering with You', value: 'weathering_with_you' },
    { label: 'Ponyo', value: 'ponyo' },
    { label: '5 Centimeters per Second', value: '5_centimeters_per_second' },
    { label: 'A Silent Voice', value: 'a_silent_voice' },
    { label: 'Paprika', value: 'paprika' },
    { label: 'Wolf Children', value: 'wolf_children' },
    { label: 'Redline', value: 'redline' },
    {
      label: 'The Tale of the Princess Kaguya',
      value: 'the_tale_of_the_princess_kaguya',
    },
  ],
})
'use client'
import { createListCollection } from '@chakra-ui/react'
import { Select } from '@saas-ui/react'
export const SelectWithOverflow = () => {
  return (
    <Select.Root collection={animeMovies} size="sm" width="240px">
      <Select.Label>Select anime</Select.Label>
      <Select.Trigger>
        <Select.ValueText placeholder="Select movie" />
      </Select.Trigger>
      <Select.Content>
        {animeMovies.items.map((movie) => (
          <Select.Item item={movie} key={movie.value}>
            {movie.label}
          </Select.Item>
        ))}
      </Select.Content>
    </Select.Root>
  )
}
const animeMovies = createListCollection({
  items: [
    { label: 'Spirited Away', value: 'spirited_away' },
    { label: 'My Neighbor Totoro', value: 'my_neighbor_totoro' },
    { label: 'Akira', value: 'akira' },
    { label: 'Princess Mononoke', value: 'princess_mononoke' },
    { label: 'Grave of the Fireflies', value: 'grave_of_the_fireflies' },
    { label: "Howl's Moving Castle", value: 'howls_moving_castle' },
    { label: 'Ghost in the Shell', value: 'ghost_in_the_shell' },
    { label: 'Naruto', value: 'naruto' },
    { label: 'Hunter x Hunter', value: 'hunter_x_hunter' },
    { label: 'The Wind Rises', value: 'the_wind_rises' },
    { label: "Kiki's Delivery Service", value: 'kikis_delivery_service' },
    { label: 'Perfect Blue', value: 'perfect_blue' },
    {
      label: 'The Girl Who Leapt Through Time',
      value: 'the_girl_who_leapt_through_time',
    },
    { label: 'Weathering with You', value: 'weathering_with_you' },
    { label: 'Ponyo', value: 'ponyo' },
    { label: '5 Centimeters per Second', value: '5_centimeters_per_second' },
    { label: 'A Silent Voice', value: 'a_silent_voice' },
    { label: 'Paprika', value: 'paprika' },
    { label: 'Wolf Children', value: 'wolf_children' },
    { label: 'Redline', value: 'redline' },
    {
      label: 'The Tale of the Princess Kaguya',
      value: 'the_tale_of_the_princess_kaguya',
    },
  ],
})
| Prop | Default | Type | 
|---|---|---|
| items * | T[] | readonly T[]The options of the select | |
| 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 | 
| lazyMount  | false | booleanWhether to enable lazy mounting | 
| loopFocus  | false | booleanWhether to loop the keyboard navigation through the options | 
| unmountOnExit  | false | booleanWhether to unmount on exit. | 
| colorPalette  | 'gray' | 'gray' | 'red' | 'orange' | 'yellow' | 'green' | 'teal' | 'blue' | 'cyan' | 'purple' | 'pink' | 'accent'The color palette of the component | 
| variant  | 'outline' | 'outline' | 'filled'The variant of the component | 
| size  | 'md' | 'xs' | 'sm' | 'md' | 'lg'The size of the component | 
| asChild  | booleanUse the provided child element as the default rendered element, combining their props and behavior.For more details, read our Composition guide. | |
| 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. | |
| 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 | |
| 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 | |
| value  | string[]The keys of the selected items | |
| as  | React.ElementTypeThe underlying element to render. | |
| unstyled  | booleanWhether to remove the component's style. |