v4.0.0-beta.4

Select

<Baseselect /> ยท A simple select box component.

vue
<template>
  <BaseSelect v-model="value" rounded="md" placeholder="Select a hero">
    <BaseSelectItem value="Superman">
      Superman
    </BaseSelectItem>
    <BaseSelectItem value="Batman">
      Batman
    </BaseSelectItem>
    <BaseSelectItem value="Iron man">
      Iron man
    </BaseSelectItem>
    <BaseSelectItem value="Magneto">
      Magneto
    </BaseSelectItem>
    <BaseSelectItem value="Cyclops">
      Cyclops
    </BaseSelectItem>
  </BaseSelect>
</template>

<script setup lang="ts">
const value = ref()
</script>

Features

  • Can be controlled or uncontrolled
  • Full keyboard navigation
  • Supports custom placeholder
  • Typeahead support

Anatomy

This component has a default slot that can be used to add select options. Use the component props to customize its visual style.

vue
<template>
  <BaseSelect>
    <BaseSelectItem>
      <!-- Your content here -->
    </BaseSelectItem>
  </BaseSelect>
</template>

API Reference

This component has props that you can use to modify its visual style.

Select

Model Type
model-value
AcceptableValue | AcceptableValue[]

The controlled value of the Select. Can be bind as `v-model`.

Prop Type
id
default:-
string

The form input identifier.

placeholder
default:""
string

The placeholder to display for the select input.

items
default:[]
BaseSelectItemProps<AcceptableValue>[]

The defaults items to display for the select input.

variant
default:"default"
"default" | "muted"

The variant of the select input.

rounded
default:"md"
"none" | "sm" | "md" | "lg" | "full"

The radius of the select input.

size
default:"md"
"sm" | "md" | "lg" | "xl"

The size of the select input.

preset
default:"aligned"
"aligned" | "popper"

Bindings presets

bindings
default:{}
{ trigger?: SelectTriggerProps; portal?: SelectPortalProps; content?: SelectContentProps; viewport?: SelectViewportProps; }

Optional bindings to pass to the inner components.

classes
default:{}
{ text?: string | string[]; icon?: string | string[]; content?: string | string[]; buttonUp?: string | string[]; buttonDown?: string | string[]; viewport?: string | ... 1 more ...; }

Optional classes to pass to the inner components.

open
default:-
boolean

The controlled open state of the Select. Can be bind as `v-model:open`.

default-open
default:-
boolean

The open state of the select when it is initially rendered. Use when you do not need to control its open state.

default-value
default:-
AcceptableValue | AcceptableValue[]

The value of the select when initially rendered. Use when you do not need to control the state of the Select

by
default:-
string | ((a: AcceptableValue, b: AcceptableValue) => boolean)

Use this to compare objects by a particular field, or pass your own comparison function for complete control over how objects are compared.

dir
default:-
Direction

The reading direction of the combobox when applicable. If omitted, inherits globally from `ConfigProvider` or assumes LTR (left-to-right) reading mode.

multiple
default:-
boolean

Whether multiple options can be selected or not.

autocomplete
default:-
string

Native html input `autocomplete` attribute.

disabled
default:-
boolean

When `true`, prevents the user from interacting with Select

name
default:-
string

The name of the field. Submitted with its owning form as part of a name/value pair.

required
default:-
boolean

When `true`, indicates that the user must set the value before the owning form can be submitted.

Event Emitted Value Type
update:open
[value: boolean]
Slot Type
#default
any
#label
any
#value
{ selectedLabel: string[]; modelValue: AcceptableValue | AcceptableValue[] | undefined; }
#content-start
any
#content-end
any
#viewport-start
any
#viewport-end
any

Select item

Prop Type
raw-slot
default:false
boolean
value
default:-
AcceptableValue

The value given as data when submitted with a `name`.

disabled
default:-
boolean

When `true`, prevents the user from interacting with the item.

text-value
default:-
string

Optional text used for typeahead purposes. By default the typeahead behavior will use the `.textContent` of the `SelectItemText` part. Use this when the content is complex, or you have non-textual content inside.

as-child
default:-
boolean

Change the default rendered element for the one passed as a child, merging their props and behavior. Read our [Composition](https://www.reka-ui.com/docs/guides/composition) guide for more details.

as
default:-
AsTag | Component

The element or component this component should render as. Can be overwritten by `asChild`.

Slot Type
#default
any

Customization

Your can override the component default CSS variables in your main.css file.

css
@theme {
  /* Default input variables */
  --color-input-default-border: var(--color-muted-300);
  --color-input-default-bg: var(--color-white);
  --color-input-default-text: var(--color-muted-600);
  --color-input-default-placeholder: var(--color-muted-300);
  --color-input-default-button-bg: var(--color-muted-100);
  --color-input-default-button-bg-active: var(--color-muted-200);
  --color-input-default-button-text: var(--color-muted-700);

  /* Muted input variables */
  --color-input-muted-border: var(--color-muted-300);
  --color-input-muted-bg: var(--color-muted-50);
  --color-input-muted-text: var(--color-muted-600);
  --color-input-muted-placeholder: var(--color-muted-300);
  --color-input-muted-button-bg: var(--color-muted-200);
  --color-input-muted-button-bg-active: var(--color-muted-300);
  --color-input-muted-button-text: var(--color-muted-700);
}

Examples

Size

Use the size prop to change the size of the select.

vue
<template>
  <BaseSelect v-model="value" size="md" placeholder="Select a hero">
    <BaseSelectItem value="Superman">
      Superman
    </BaseSelectItem>
    <BaseSelectItem value="Batman">
      Batman
    </BaseSelectItem>
    <BaseSelectItem value="Iron man">
      Iron man
    </BaseSelectItem>
    <BaseSelectItem value="Magneto">
      Magneto
    </BaseSelectItem>
    <BaseSelectItem value="Cyclops">
      Cyclops
    </BaseSelectItem>
  </BaseSelect>
</template>

<script setup lang="ts">
const value = ref('')
</script>

Variants

Use the variant prop to change the variant of the select.

vue
<template>
  <BaseSelect v-model="value" variant="muted" placeholder="Select a hero">
    <BaseSelectItem value="Superman">
      Superman
    </BaseSelectItem>
    <BaseSelectItem value="Batman">
      Batman
    </BaseSelectItem>
    <BaseSelectItem value="Iron man">
      Iron man
    </BaseSelectItem>
    <BaseSelectItem value="Magneto">
      Magneto
    </BaseSelectItem>
    <BaseSelectItem value="Cyclops">
      Cyclops
    </BaseSelectItem>
  </BaseSelect>
</template>

<script setup lang="ts">
const value = ref('')
</script>

Radius

Use the rounded prop to change the border radius of the select.

vue
<template>
  <BaseSelect v-model="value" rounded="full" placeholder="Select a hero">
    <BaseSelectItem value="Superman">
      Superman
    </BaseSelectItem>
    <BaseSelectItem value="Batman">
      Batman
    </BaseSelectItem>
    <BaseSelectItem value="Iron man">
      Iron man
    </BaseSelectItem>
    <BaseSelectItem value="Magneto">
      Magneto
    </BaseSelectItem>
    <BaseSelectItem value="Cyclops">
      Cyclops
    </BaseSelectItem>
  </BaseSelect>
</template>

<script setup lang="ts">
const value = ref('')
</script>

Presets

vue
<template>
  <BaseSelect
    v-model="item"
    size="md"
    :by="(a, b) => {
      return a.value === b.value
    }"
    placeholder="aligned"
    preset="aligned"
  >
    <BaseSelectItem v-for="hero in items" :key="hero.label" :value="hero">
      {{ hero.label }}
    </BaseSelectItem>
  </BaseSelect>
  <BaseSelect
    size="md"
    placeholder="popper"
    preset="popper"
  >
    <BaseSelectItem v-for="hero in heros" :key="hero" :value="hero">
      {{ hero }}
    </BaseSelectItem>
  </BaseSelect>
</template>

<script setup lang="ts">
const heros = [
  'Superman',
  'Batman',
  'Iron man',
  'Magneto',
  'Cyclops',
  'Wolverine',
  'Spiderman',
  'Hulk',
  'Thor',
  'Captain America',
  'Black Widow',
  'Doctor Strange',
  'Black Panther',
  'Ant-Man',
  'Scarlet Witch',
  'Vision',
  'Falcon',
  'Winter Soldier',
  'Star-Lord',
  'Gamora',
  'Drax',
  'Rocket Raccoon',
  'Groot',
  'Nebula',
  'Mantis',
  'Yondu',
  'Hawkeye',
  'Quicksilver',
  'War Machine',
  'Nick Fury',
  'Loki',
  'Thanos',
  'Ultron',
  'Green Lantern',
  'Flash',
  'Aquaman',
  'Wonder Woman',
  'Shazam',
  'Green Arrow',
  'Martian Manhunter',
  'Hawkgirl',
  'Black Canary',
  'Zatanna',
  'Supergirl',
  'Batgirl',
  'Nightwing',
  'Red Hood',
  'Robin',
  'Catwoman',
  'Riddler',
  'Penguin',
  'Two-Face',
  'Harley Quinn',
  'Joker',
  'Lex Luthor',
  'Darkseid',
  'Brainiac',
  'Deathstroke',
  'Bane',
  'Ra\'s al Ghul',
  'Scarecrow',
  'Poison Ivy',
  'Mr. Freeze',
  'Clayface',
  'Killer Croc',
  'Man-Bat',
  'Hush',
  'Black Mask',
  'Deadshot',
  'Firefly',
  'Mad Hatter',
  'Solomon Grundy',
  'Ventriloquist',
  'Calendar Man',
  'Kite Man',
  'Polka-Dot Man',
  'Condiment King',
]

const items = [
  {
    value: 'superman',
    label: 'Superman',
  },
  {
    value: 'batman',
    label: 'Batman',
  },
  {
    value: 'spiderman',
    label: 'Spiderman',
  },
]
const item = ref(items[0])
</script>

Position

Use the position prop to change the alignment of the select.

vue
<template>
  <BaseSelect
    v-model="value"
    placeholder="Select a hero"
    label="Item aligned (default)"
    :bindings="{
      content: {
        position: 'item-aligned',
      },
    }"
  >
    <BaseSelectItem value="Superman">
      Superman
    </BaseSelectItem>
    <BaseSelectItem value="Batman">
      Batman
    </BaseSelectItem>
    <BaseSelectItem value="Iron man">
      Iron man
    </BaseSelectItem>
    <BaseSelectItem value="Magneto">
      Magneto
    </BaseSelectItem>
    <BaseSelectItem value="Cyclops">
      Cyclops
    </BaseSelectItem>
  </BaseSelect>
</template>

<script setup lang="ts">
const value = ref('')
</script>

Composition

Compose the select with groups, separators, and labels.

vue
<template>
  <BaseSelect
    v-model="value"
    placeholder="Select a hero"
  >
    <BaseSelectGroup>
      <BaseSelectLabel>
        Marvel
      </BaseSelectLabel>
      <BaseSelectItem value="Superman">
        Superman
      </BaseSelectItem>
      <BaseSelectItem value="Batman">
        Batman
      </BaseSelectItem>
    </BaseSelectGroup>
    <BaseSelectSeparator />
    <BaseSelectGroup>
      <BaseSelectLabel>
        DC
      </BaseSelectLabel>
      <BaseSelectItem value="Magneto">
        Magneto
      </BaseSelectItem>
      <BaseSelectItem value="Cyclops">
        Cyclops
      </BaseSelectItem>
    </BaseSelectGroup>

    <BaseSelectGroup>
      <BaseSelectLabel>
        Long list
      </BaseSelectLabel>
      <BaseSelectItem v-for="i in 50" :key="i" :value="i">
        Option {{ i }}
      </BaseSelectItem>
    </BaseSelectGroup>
  </BaseSelect>
</template>

<script setup lang="ts">
const value = ref('')
</script>

Multiple

Use the multiple prop to allow multiple selections.

vue
<template>
  <BaseSelect
    v-model="value"
    placeholder="Select some heroes"
    multiple
  >
    <BaseSelectLabel>
      <span>Marvel</span>
    </BaseSelectLabel>
    <BaseSelectItem value="Superman" raw-slot>
      <div class="flex flex-col items-start gap-0 py-2">
        <div class="text-xs opacity-50">
          Marvel
        </div>
        <div>
          <SelectItemText>Superman</SelectItemText>
        </div>
      </div>
    </BaseSelectItem>
    <BaseSelectItem value="Batman" raw-slot>
      <div class="flex flex-col items-start gap-0 py-2">
        <div class="text-xs opacity-50">
          Marvel
        </div>
        <div>
          <SelectItemText>Batman</SelectItemText>
        </div>
      </div>
    </BaseSelectItem>
    <BaseSelectLabel>
      <div>DC</div>
    </BaseSelectLabel>
    <BaseSelectItem value="Magneto" raw-slot>
      <div class="flex flex-col items-start gap-0 py-2">
        <div class="text-xs opacity-50">
          DC
        </div>
        <div>
          <SelectItemText>Magneto</SelectItemText>
        </div>
      </div>
    </BaseSelectItem>
    <BaseSelectItem value="Cyclops" raw-slot>
      <div class="flex flex-col items-start gap-0 py-2">
        <div class="text-xs opacity-50">
          DC
        </div>
        <div>
          <SelectItemText>Cyclops</SelectItemText>
        </div>
      </div>
    </BaseSelectItem>
  </BaseSelect>
</template>

<script setup lang="ts">
const value = ref('')
</script>

Slots

Use the provided slots to customize the select.

vue
<template>
  <BaseSelect
    placeholder="Select some heroes"
  >
    <template #viewport-start>
      <BaseCard variant="muted">
        #viewport-start
      </BaseCard>
    </template>
    <template #viewport-end>
      <BaseCard variant="muted">
        #viewport-end
      </BaseCard>
    </template>
    <template #content-start>
      <BaseCard>
        #content-start
      </BaseCard>
    </template>
    <template #content-end>
      <BaseCard>
        #content-end
      </BaseCard>
    </template>

    <BaseSelectLabel>
      Marvel
    </BaseSelectLabel>
    <BaseSelectItem value="Superman">
      Superman
    </BaseSelectItem>
    <BaseSelectItem value="Batman">
      Batman
    </BaseSelectItem>
    <BaseSelectLabel>
      DC
    </BaseSelectLabel>

    <BaseSelectItem v-for="hero in heros" :key="hero" :value="hero">
      {{ hero }}
    </BaseSelectItem>
  </BaseSelect>
</template>

<script setup lang="ts">
const heros = [
  'Superman',
  'Batman',
  'Iron man',
  'Magneto',
  'Cyclops',
  'Wolverine',
  'Spiderman',
  'Hulk',
  'Thor',
  'Captain America',
  'Black Widow',
  'Doctor Strange',
  'Black Panther',
  'Ant-Man',
  'Scarlet Witch',
  'Vision',
  'Falcon',
  'Winter Soldier',
  'Star-Lord',
  'Gamora',
  'Drax',
  'Rocket Raccoon',
  'Groot',
  'Nebula',
  'Mantis',
  'Yondu',
  'Hawkeye',
  'Quicksilver',
  'War Machine',
  'Nick Fury',
  'Loki',
  'Thanos',
  'Ultron',
  'Green Lantern',
  'Flash',
  'Aquaman',
  'Wonder Woman',
  'Shazam',
  'Green Arrow',
  'Martian Manhunter',
  'Hawkgirl',
  'Black Canary',
  'Zatanna',
  'Supergirl',
  'Batgirl',
  'Nightwing',
  'Red Hood',
  'Robin',
  'Catwoman',
  'Riddler',
  'Penguin',
  'Two-Face',
  'Harley Quinn',
  'Joker',
  'Lex Luthor',
  'Darkseid',
  'Brainiac',
  'Deathstroke',
  'Bane',
  'Ra\'s al Ghul',
  'Scarecrow',
  'Poison Ivy',
  'Mr. Freeze',
  'Clayface',
  'Killer Croc',
  'Man-Bat',
  'Hush',
  'Black Mask',
  'Deadshot',
  'Firefly',
  'Mad Hatter',
  'Solomon Grundy',
  'Ventriloquist',
  'Calendar Man',
  'Kite Man',
  'Polka-Dot Man',
  'Condiment King',
]
</script>

Error

Use the aria-invalid prop to set the select in an error state.

vue
<template>
  <BaseSelect
    v-model="value"
    rounded="md"
    placeholder="Select a hero"
    aria-invalid="true"
  >
    <BaseSelectItem value="Superman">
      Superman
    </BaseSelectItem>
    <BaseSelectItem value="Batman">
      Batman
    </BaseSelectItem>
    <BaseSelectItem value="Iron man">
      Iron man
    </BaseSelectItem>
    <BaseSelectItem value="Magneto">
      Magneto
    </BaseSelectItem>
    <BaseSelectItem value="Cyclops">
      Cyclops
    </BaseSelectItem>
  </BaseSelect>
</template>

<script setup lang="ts">
const value = ref('')
</script>

Disabled

Use the disabled prop to set the select in a disabled state.

vue
<template>
  <BaseSelect
    v-model="value"
    rounded="md"
    placeholder="Select a hero"
    disabled
  >
    <BaseSelectItem value="Superman">
      Superman
    </BaseSelectItem>
    <BaseSelectItem value="Batman">
      Batman
    </BaseSelectItem>
    <BaseSelectItem value="Iron man">
      Iron man
    </BaseSelectItem>
    <BaseSelectItem value="Magneto">
      Magneto
    </BaseSelectItem>
    <BaseSelectItem value="Cyclops">
      Cyclops
    </BaseSelectItem>
  </BaseSelect>
</template>

<script setup lang="ts">
const value = ref('')
</script>