Combobox

Choose from a list of suggested values with full keyboard support.
vue
<script setup lang="ts">
import {
  ComboboxRoot,
  ComboboxContent,
  ComboboxGroup,
  ComboboxItem,
  ComboboxInput,
  ComboboxLabel,
  ComboboxEmpty,
} from '@typlog/ui'

const foodItems = [
  {
    name: 'Fruit',
    children: [
      { name: 'Apple' },
      { name: 'Banana' },
      { name: 'Orange' },
      { name: 'Honeydew' },
      { name: 'Grapes' },
      { name: 'Watermelon' },
      { name: 'Cantaloupe' },
      { name: 'Pear' },
    ],
  },
  {
    name: 'Vegetable',
    children: [
      { name: 'Cabbage' },
      { name: 'Broccoli' },
      { name: 'Carrots' },
      { name: 'Lettuce' },
      { name: 'Spinach' },
      { name: 'Bok Choy' },
      { name: 'Cauliflower' },
      { name: 'Potatoes' },
    ],
  },
]
</script>

<template>
  <ComboboxRoot>
    <ComboboxInput placeholder="Select food..." />
    <ComboboxContent>
      <template
        v-for="group in foodItems"
        :key="group.name"
      >
        <ComboboxGroup v-if="group.children.length">
          <ComboboxLabel>
            {{ group.name }}
          </ComboboxLabel>
          <ComboboxItem
            v-for="option in group.children"
            :key="option.name"
            :value="option.name"
          >
            {{ option.name }}
          </ComboboxItem>
        </ComboboxGroup>
      </template>
      <ComboboxEmpty>
        <span>No food found</span>
      </ComboboxEmpty>
    </ComboboxContent>
  </ComboboxRoot>
</template>

API Reference

ComboboxRoot

The root element of a combobox, it contains all the parts of a combobox.

PropDefaultType
color
highContrast
boolean
size
"1""2""3"

ComboboxInput

PropDefaultType
placeholder
string
radius
"none""small""medium""large""full"
variant
"soft""surface"

ComboboxContent

PropDefaultType
variant
"solid""soft"

ComboboxGroup

ComboboxItem

ComboboxLabel

ComboboxEmpty

Examples

Size

vue
<script setup lang="ts">
import {
  ComboboxRoot,
  ComboboxContent,
  ComboboxItem,
  ComboboxInput,
  ComboboxEmpty,
} from '@typlog/ui'

const fruits = [
  { name: 'Apple' },
  { name: 'Banana' },
  { name: 'Orange' },
  { name: 'Honeydew' },
  { name: 'Grapes' },
  { name: 'Watermelon' },
  { name: 'Cantaloupe' },
  { name: 'Pear' },
]
</script>

<template>
  <div class="flex flex-items gap-4">
    <ComboboxRoot size="1">
      <ComboboxInput placeholder="Select fruit..." />
      <ComboboxContent>
        <ComboboxItem
          v-for="option in fruits"
          :key="option.name"
          :value="option.name"
        >
          {{ option.name }}
        </ComboboxItem>
        <ComboboxEmpty>
          <span>No fruit found</span>
        </ComboboxEmpty>
      </ComboboxContent>
    </ComboboxRoot>

    <ComboboxRoot size="2">
      <ComboboxInput placeholder="Select fruit..." />
      <ComboboxContent>
        <ComboboxItem
          v-for="option in fruits"
          :key="option.name"
          :value="option.name"
        >
          {{ option.name }}
        </ComboboxItem>
        <ComboboxEmpty>
          <span>No fruit found</span>
        </ComboboxEmpty>
      </ComboboxContent>
    </ComboboxRoot>

    <ComboboxRoot size="3">
      <ComboboxInput placeholder="Select fruit..." />
      <ComboboxContent>
        <ComboboxItem
          v-for="option in fruits"
          :key="option.name"
          :value="option.name"
        >
          {{ option.name }}
        </ComboboxItem>
        <ComboboxEmpty>
          <span>No fruit found</span>
        </ComboboxEmpty>
      </ComboboxContent>
    </ComboboxRoot>
  </div>
</template>

Multiple

vue
<script setup lang="ts">
import {
  ComboboxRoot,
  ComboboxContent,
  ComboboxGroup,
  ComboboxItem,
  ComboboxInput,
  ComboboxLabel,
  ComboboxEmpty,
} from '@typlog/ui'

const foodItems = [
  {
    name: 'Fruit',
    children: [
      { name: 'Apple' },
      { name: 'Banana' },
      { name: 'Orange' },
      { name: 'Honeydew' },
      { name: 'Grapes' },
      { name: 'Watermelon' },
      { name: 'Cantaloupe' },
      { name: 'Pear' },
    ],
  },
  {
    name: 'Vegetable',
    children: [
      { name: 'Cabbage' },
      { name: 'Broccoli' },
      { name: 'Carrots' },
      { name: 'Lettuce' },
      { name: 'Spinach' },
      { name: 'Bok Choy' },
      { name: 'Cauliflower' },
      { name: 'Potatoes' },
    ],
  },
]
</script>

<template>
  <ComboboxRoot multiple>
    <ComboboxInput placeholder="Select food..." />
    <ComboboxContent>
      <template
        v-for="group in foodItems"
        :key="group.name"
      >
        <ComboboxGroup v-if="group.children.length">
          <ComboboxLabel>
            {{ group.name }}
          </ComboboxLabel>
          <ComboboxItem
            v-for="option in group.children"
            :key="option.name"
            :value="option.name"
          >
            {{ option.name }}
          </ComboboxItem>
        </ComboboxGroup>
      </template>
      <ComboboxEmpty>
        <span>No food found</span>
      </ComboboxEmpty>
    </ComboboxContent>
  </ComboboxRoot>
</template>

Variant

The input field supports two variants: soft and surface.

vue
<script setup lang="ts">
import {
  ComboboxRoot,
  ComboboxContent,
  ComboboxItem,
  ComboboxInput,
  ComboboxEmpty,
} from '@typlog/ui'

const fruits = [
  { name: 'Apple' },
  { name: 'Banana' },
  { name: 'Orange' },
  { name: 'Honeydew' },
  { name: 'Grapes' },
  { name: 'Watermelon' },
  { name: 'Cantaloupe' },
  { name: 'Pear' },
]
</script>

<template>
  <div class="flex flex-items gap-4">
    <ComboboxRoot>
      <ComboboxInput placeholder="Select fruit..." variant="soft" />
      <ComboboxContent>
        <ComboboxItem
          v-for="option in fruits"
          :key="option.name"
          :value="option.name"
        >
          {{ option.name }}
        </ComboboxItem>
        <ComboboxEmpty>
          <span>No fruit found</span>
        </ComboboxEmpty>
      </ComboboxContent>
    </ComboboxRoot>

    <ComboboxRoot>
      <ComboboxInput placeholder="Select fruit..." variant="surface" />
      <ComboboxContent>
        <ComboboxItem
          v-for="option in fruits"
          :key="option.name"
          :value="option.name"
        >
          {{ option.name }}
        </ComboboxItem>
        <ComboboxEmpty>
          <span>No fruit found</span>
        </ComboboxEmpty>
      </ComboboxContent>
    </ComboboxRoot>
  </div>
</template>

The content popup supports two variants: soft and solid.

vue
<script setup lang="ts">
import {
  ComboboxRoot,
  ComboboxContent,
  ComboboxItem,
  ComboboxInput,
  ComboboxEmpty,
} from '@typlog/ui'

const fruits = [
  { name: 'Apple' },
  { name: 'Banana' },
  { name: 'Orange' },
  { name: 'Honeydew' },
  { name: 'Grapes' },
  { name: 'Watermelon' },
  { name: 'Cantaloupe' },
  { name: 'Pear' },
]
</script>

<template>
  <div class="flex flex-items gap-4">
    <ComboboxRoot>
      <ComboboxInput placeholder="Select fruit..." />
      <ComboboxContent variant="soft">
        <ComboboxItem
          v-for="option in fruits"
          :key="option.name"
          :value="option.name"
        >
          {{ option.name }}
        </ComboboxItem>
        <ComboboxEmpty>
          <span>No fruit found</span>
        </ComboboxEmpty>
      </ComboboxContent>
    </ComboboxRoot>

    <ComboboxRoot>
      <ComboboxInput placeholder="Select fruit..." />
      <ComboboxContent variant="solid">
        <ComboboxItem
          v-for="option in fruits"
          :key="option.name"
          :value="option.name"
        >
          {{ option.name }}
        </ComboboxItem>
        <ComboboxEmpty>
          <span>No fruit found</span>
        </ComboboxEmpty>
      </ComboboxContent>
    </ComboboxRoot>
  </div>
</template>