---
title: "Combobox"
description: "Choose from a list of suggested values with full keyboard support."
canonical_url: "https://vinicunca.dev/akar/components/combobox"
---
# Combobox

> Choose from a list of suggested values with full keyboard support.

```vue [index.vue]
<script setup lang="ts">
import { ComboboxAnchor, ComboboxContent, ComboboxEmpty, ComboboxGroup, ComboboxInput, ComboboxItem, ComboboxItemIndicator, ComboboxLabel, ComboboxRoot, ComboboxSeparator, ComboboxTrigger, ComboboxViewport } from 'akar'
import './styles.css'

const options = [
  { 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>
  <div class="akar-demo akar-demo-Combobox">
    <ComboboxRoot class="ComboboxRoot">
        <ComboboxAnchor class="ComboboxAnchor">
          <ComboboxInput
            class="ComboboxInput"
            placeholder="Placeholder..."
          />
          <ComboboxTrigger>
            <PIcon
              name="i-lucide-chevron-down"
              class="ComboboxIcon"
            />
          </ComboboxTrigger>
        </ComboboxAnchor>

        <ComboboxContent class="ComboboxContent">
          <ComboboxViewport class="ComboboxViewport">
            <ComboboxEmpty class="ComboboxEmpty" />

            <template
              v-for="(group, index) in options"
              :key="group.name"
            >
              <ComboboxGroup v-if="group.children.length">
                <ComboboxSeparator
                  v-if="index !== 0"
                  class="ComboboxSeparator"
                />

                <ComboboxLabel class="ComboboxLabel">
                  {{ group.name }}
                </ComboboxLabel>

                <ComboboxItem
                  v-for="option in group.children"
                  :key="option.name"
                  :value="option.name"
                  class="ComboboxItem"
                >
                  <ComboboxItemIndicator
                    class="ComboboxItemIndicator"
                  >
                    <PIcon name="i-lucide-check" />
                  </ComboboxItemIndicator>
                  <span>
                    {{ option }}
                  </span>
                </ComboboxItem>
              </ComboboxGroup>
            </template>
          </ComboboxViewport>
        </ComboboxContent>
      </ComboboxRoot>
  </div>
</template>
```

```css [styles.css]
@import '../_colors/black-alpha.css';
@import '../_colors/mauve.css';
@import '../_colors/grass.css';

@scope (.akar-demo-Combobox) {
/* reset */
button, input {
  all: unset;
}

.ComboboxRoot {
  position: relative;
}

.ComboboxAnchor {
  display: inline-flex;
  align-items: center;
  justify-content: between; 
  font-size: 13px;
  line-height: 1;
  height: 35px;
  padding: 0 15px;
  gap: 5px;
  background-color: white;
  color: var(--grass-11);
  border-radius: 4px;
  box-shadow: 0 2px 10px var(--black-a7);
}
.ComboboxAnchor:hover {
  background-color: var(--mauve-3);
}

.ComboboxInput {    
  height: 100%;
  background-color: transparent;
  color: var(--grass-11); 
}
.ComboboxInput[data-placeholder] {
  color: var(--grass-9);
}

.ComboboxIcon {
  width: 16px;
  height: 16px;
  color: var(--grass-11);
}

.ComboboxContent {
  z-index: 10;
  width: 100%;
  position: absolute;
  overflow: hidden;
  background-color: white;
  border-radius: 6px;
  margin-top: 8px;
  box-shadow: 0px 10px 38px -10px rgba(22, 23, 24, 0.35), 0px 10px 20px -15px rgba(22, 23, 24, 0.2);
}

.ComboboxViewport {
  padding: 5px;
}

.ComboboxEmpty {
  padding-top: 0.5rem;
  padding-bottom: 0.5rem;
  text-align: center;
  font-size: 0.75rem;
  line-height: 1rem;
  font-weight: 500; 
  color: var(--mauve-11)
}

.ComboboxItem {
  font-size: 13px;
  line-height: 1;
  color: var(--grass-11);
  border-radius: 3px;
  display: flex;
  align-items: center;
  height: 25px;
  padding: 0 35px 0 25px;
  position: relative;
  user-Combobox: none;
}
.ComboboxItem[data-disabled] {
  color: var(--mauve-8);
  pointer-events: none;
}
.ComboboxItem[data-highlighted] {
  outline: none;
  background-color: var(--grass-9);
  color: var(--grass-1);
}

.ComboboxLabel {
  padding: 0 25px;
  font-size: 12px;
  line-height: 25px;
  color: var(--mauve-11);
}

.ComboboxSeparator {
  height: 1px;
  background-color: var(--grass-6);
  margin: 5px;
}

.ComboboxItemIndicator {
  position: absolute;
  left: 0;
  width: 25px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
}
```

## Features

- Can be controlled or uncontrolled.
- Offers 2 positioning modes.
- Supports items, labels, groups of items.
- Focus is fully managed.
- Full keyboard navigation.
- Supports custom placeholder.
- Supports Right to Left direction.

## Installation

Install the component from your command line.

```bash [pnpm]
pnpm add akar
```

```bash [yarn]
yarn add akar
```

```bash [npm]
npm install akar
```

```bash [bun]
bun add akar
```

## Anatomy

Import all parts and piece them together.

```vue
<script setup lang="ts">
import {
  ComboboxAnchor,
  ComboboxArrow,
  ComboboxCancel,
  ComboboxContent,
  ComboboxEmpty,
  ComboboxGroup,
  ComboboxInput,
  ComboboxItem,
  ComboboxItemIndicator,
  ComboboxLabel,
  ComboboxPortal,
  ComboboxRoot,
  ComboboxSeparator,
  ComboboxTrigger,
  ComboboxViewport,
} from 'akar';
</script>

<template>
  <ComboboxRoot>
    <ComboboxAnchor>
      <ComboboxInput />
      <ComboboxTrigger />
      <ComboboxCancel />
    </ComboboxAnchor>

    <ComboboxPortal>
      <ComboboxContent>
        <ComboboxViewport>
          <ComboboxEmpty />

          <ComboboxItem>
            <ComboboxItemIndicator />
          </ComboboxItem>

          <ComboboxSeparator />

          <ComboboxGroup>
            <ComboboxLabel />
            <ComboboxItem>
              <ComboboxItemIndicator />
            </ComboboxItem>
          </ComboboxGroup>
        </ComboboxViewport>

        <ComboboxArrow />
      </ComboboxContent>
    </ComboboxPortal>
  </ComboboxRoot>
</template>
```

## API Reference

### Root

Contains all the parts of a Combobox

**Props**

| Prop | Default | Type | Description |
| --- | --- | --- | --- |
| `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. |
| `asChild` |  | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. |
| `by` |  | `string \| ((a: T, b: T) => boolean)` | Use this to compare objects by a particular field, or pass your own comparison function for complete control over how objects are compared. |
| `defaultOpen` |  | `boolean` | The open state of the combobox when it is initially rendered.<br><br>Use when you do not need to control its open state. |
| `defaultValue` |  | `T \| T[]` | The value of the listbox when initially rendered. Use when you do not need to control the state of the Listbox |
| `dir` |  | `"ltr" \| "rtl"` | The reading direction of the listbox when applicable.<br><br>If omitted, inherits globally from `ConfigProvider` or assumes LTR (left-to-right) reading mode. |
| `disabled` |  | `boolean` | When `true`, prevents the user from interacting with listbox |
| `highlightOnHover` | `true` | `boolean` | When `true`, hover over item will trigger highlight |
| `ignoreFilter` |  | `boolean` | When `true`, disable the default filters |
| `modelValue` |  | `T \| T[]` | The controlled value of the listbox. Can be binded with `v-model`. |
| `multiple` |  | `boolean` | Whether multiple options can be selected or not. |
| `name` |  | `string` | The name of the field. Submitted with its owning form as part of a name/value pair. |
| `open` |  | `boolean` | The controlled open state of the Combobox. Can be binded with `v-model:open`. |
| `openOnClick` | `false` | `boolean` | Whether to open the combobox when the input is clicked |
| `openOnFocus` | `false` | `boolean` | Whether to open the combobox when the input is focused |
| `required` |  | `boolean` | When `true`, indicates that the user must set the value before the owning form can be submitted. |
| `resetModelValueOnClear` | `false` | `boolean` | When `true` the `modelValue` will be reset to `null` (or `[]` if `multiple`) |
| `resetSearchTermOnBlur` | `true` | `boolean` | Whether to reset the searchTerm when the Combobox input blurred |
| `resetSearchTermOnSelect` | `true` | `boolean` | Whether to reset the searchTerm when the Combobox value is selected |
| `unmountOnHide` | `true` | `boolean` | When set to `false`, the Combobox content will not be unmounted when closed, but instead hidden with CSS.<br><br>Useful when you want to improve performance by not remounting the content on every open. |

**Events**

| Event | Payload | Description |
| --- | --- | --- |
| `highlight` | `payload: { ref: HTMLElement; value: T; }` | Event handler when highlighted element changes. |
| `update:modelValue` | `value: T` | Event handler called when the value changes. |
| `update:open` | `value: boolean` | Event handler called when the open state of the combobox changes. |

**Slots**

| Slot | Payload | Description |
| --- | --- | --- |
| `open` | `boolean` | Current open state |
| `modelValue` | `T \| T[]` | Current active value |

[ComboboxRoot.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Combobox/ComboboxRoot.vue)

### Anchor

Used as an anchor if you set `ComboboxContent`'s position to `popper`.

**Props**

| Prop | Default | Type | Description |
| --- | --- | --- | --- |
| `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. |
| `asChild` |  | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. |
| `reference` |  | `ReferenceElement` | The reference (or anchor) element that is being referred to for positioning.<br><br>If not provided will use the current component as anchor. |

[ComboboxAnchor.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Combobox/ComboboxAnchor.vue)

### Input

The input component to search through the combobox items.

**Props**

| Prop | Default | Type | Description |
| --- | --- | --- | --- |
| `as` | `"input"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. |
| `asChild` |  | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. |
| `autoFocus` |  | `boolean` | Focus on element when mounted. |
| `disabled` |  | `boolean` | When `true`, prevents the user from interacting with item |
| `displayValue` |  | `((val: any) => string)` | The display value of input for selected item. Does not work with `multiple`. |
| `modelValue` |  | `string` | The controlled value of the filter. Can be binded with v-model. |

**Events**

| Event | Payload | Description |
| --- | --- | --- |
| `update:modelValue` | `string` |  |

[ComboboxInput.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Combobox/ComboboxInput.vue)

### Trigger

The button that toggles the Combobox Content.

**Props**

| Prop | Default | Type | Description |
| --- | --- | --- | --- |
| `as` | `"button"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. |
| `asChild` |  | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. |
| `disabled` |  | `boolean` | When `true`, prevents the user from interacting with item |

[ComboboxTrigger.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Combobox/ComboboxTrigger.vue)

| Data attribute | Value |
| --- | --- |
| `[data-state]` | "open" \\| "closed" |
| `[data-disabled]` | Present when disabled |

### Cancel

The button that clears the search term.

**Props**

| Prop | Default | Type | Description |
| --- | --- | --- | --- |
| `as` | `"button"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. |
| `asChild` |  | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. |

[ComboboxCancel.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Combobox/ComboboxCancel.vue)

### Empty

Shown when none of the items match the query.

**Props**

| Prop | Default | Type | Description |
| --- | --- | --- | --- |
| `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. |
| `asChild` |  | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. |

[ComboboxEmpty.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Combobox/ComboboxEmpty.vue)

### Portal

When used, portals the content part into the `body`.

You need to set `position="popper"` for `ComboboxContent` to make sure the position was automatically computed similar to `Popover` or `DropdownMenu`.

**Props**

| Prop | Default | Type | Description |
| --- | --- | --- | --- |
| `defer` |  | `boolean` | Defer the resolving of a Teleport target until other parts of the<br>application have mounted (requires Vue 3.5.0+)<br><br>[reference](https://vuejs.org/guide/built-ins/teleport.html#deferred-teleport) |
| `disabled` |  | `boolean` | Disable teleport and render the component inline<br><br>[reference](https://vuejs.org/guide/built-ins/teleport.html#disabling-teleport) |
| `forceMount` |  | `boolean` | Used to force mounting when more control is needed. Useful when<br>controlling animation with Vue animation libraries. |
| `to` |  | `string \| HTMLElement` | Vue native teleport component prop `:to`<br><br>[reference](https://vuejs.org/guide/built-ins/teleport.html#basic-usage) |

[ComboboxPortal.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Combobox/ComboboxPortal.vue)

### Content

The component that pops out when the combobox is open.

> [!NOTE]
> 
> Defer mounting with `forceMount` / [`Presence`](https://vinicunca.dev/akar/utilities/presence). See the [animation guide](https://vinicunca.dev/akar/guides/animation).

**Props**

| Prop | Default | Type | Description |
| --- | --- | --- | --- |
| `align` | `"center"` | `"start" \| "center" \| "end"` | The preferred alignment against the trigger.<br>May change when collisions occur. |
| `alignFlip` | `true` | `boolean` | Flip alignment when colliding with boundary.<br>May only occur when `prioritizePosition` is true. |
| `alignOffset` | `0` | `number` | An offset in pixels from the `start` or `end` alignment options. |
| `arrowPadding` | `0` | `number` | The padding between the arrow and the edges of the content.<br>If your content has border-radius, this will prevent it from<br>overflowing the corners. |
| `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. |
| `asChild` |  | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. |
| `avoidCollisions` | `true` | `boolean` | When `true`, overrides the side and align preferences<br>to prevent collisions with boundary edges. |
| `bodyLock` |  | `boolean` | The document.body will be lock, and scrolling will be disabled. |
| `collisionBoundary` | `[]` | `Element \| (Element \| null)[] \| null` | The element used as the collision boundary. By default<br>this is the viewport, though you can provide additional<br>element(s) to be included in this check. |
| `collisionPadding` | `0` | `number \| Partial<Record<"top" \| "right" \| "bottom" \| "left", number>>` | The distance in pixels from the boundary edges where collision<br>detection should occur. Accepts a number (same for all sides),<br>or a partial padding object, for example: { top: 20, left: 20 }. |
| `dir` |  | `"ltr" \| "rtl"` | The reading direction of the popper content when applicable.<br><br>If omitted, inherits globally from `ConfigProvider` or assumes LTR (left-to-right) reading mode. |
| `disableOutsidePointerEvents` |  | `boolean` | When `true`, hover/focus/click interactions will be disabled on elements outside<br>the `DismissableLayer`. Users will need to click twice on outside elements to<br>interact with them: once to close the `DismissableLayer`, and again to trigger the element. |
| `disableUpdateOnLayoutShift` | `false` | `boolean` | Whether to disable the update position for the content when the layout shifted. |
| `forceMount` |  | `boolean` | Used to force mounting when more control is needed. Useful when<br>controlling animation with Vue animation libraries. |
| `hideShiftedArrow` | `true` | `boolean` | When `true`, hides the arrow when it cannot be centered<br>to the reference element. |
| `hideWhenDetached` | `false` | `boolean` | Whether to hide the content when the trigger becomes fully occluded. |
| `hideWhenEmpty` | `false` | `boolean` | When `true`, hides the content when there are no items matching the filter. |
| `memoDependencies` |  | `unknown[]` | Reactive dependencies that should invalidate the memoized content subtree. |
| `position` |  | `"inline" \| "popper"` | The positioning mode to use,<br><br>`inline` is the default and you can control the position using CSS.<br><br>`popper` positions content in the same way as our other primitives, for example `Popover` or `DropdownMenu`. |
| `positionStrategy` |  | `"fixed" \| "absolute"` | The type of CSS position property to use. |
| `present` |  | `boolean` | Whether this kept-mounted content is currently visible. |
| `prioritizePosition` | `false` | `boolean` | Force content to be position within the viewport.<br><br>Might overlap the reference element, which may not be desired. |
| `reference` |  | `ReferenceElement` | The custom element or virtual element that will be set as the reference<br>to position the floating element.<br><br>If provided, it will replace the default anchor element. |
| `side` | `"bottom"` | `"top" \| "right" \| "bottom" \| "left"` | The preferred side of the trigger to render against when open.<br>Will be reversed when collisions occur and avoidCollisions<br>is enabled. |
| `sideFlip` | `true` | `boolean` | Flip to the opposite side when colliding with boundary. |
| `sideOffset` | `0` | `number` | The distance in pixels from the trigger. |
| `sticky` | `"partial"` | `"partial" \| "always"` | The sticky behavior on the align axis. `partial` will keep the<br>content in the boundary as long as the trigger is at least partially<br>in the boundary whilst "always" will keep the content in the boundary<br>regardless. |
| `updatePositionStrategy` | `'optimized'` | `"always" \| "optimized"` | Strategy to update the position of the floating element on every animation frame. |

**Events**

| Event | Payload | Description |
| --- | --- | --- |
| `escapeKeyDown` | `event: KeyboardEvent` | Event handler called when the escape key is down.<br>Can be prevented. |
| `focusOutside` | `event: FocusOutsideEvent` | Event handler called when the focus moves outside of the `DismissableLayer`.<br>Can be prevented. |
| `interactOutside` | `event: PointerDownOutsideEvent \| FocusOutsideEvent` | Event handler called when an interaction happens outside the `DismissableLayer`.<br>Specifically, when a `pointerdown` event happens outside or focus moves outside of it.<br>Can be prevented. |
| `pointerDownOutside` | `event: PointerDownOutsideEvent` | Event handler called when a `pointerdown` event happens outside of the `DismissableLayer`.<br>Can be prevented. |

[ComboboxContent.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Combobox/ComboboxContent.vue)

| Data attribute | Value |
| --- | --- |
| `[data-state]` | "open" \\| "closed" |
| `[data-side]` | "left" \\| "right" \\| "bottom" \\| "top" |
| `[data-align]` | "start" \\| "end" \\| "center" |
| `[data-empty]` | Present when there are no items matching the filter |

| CSS variable | Description |
| --- | --- |
| `--akar-combobox-content-transform-origin` | The `transform-origin` computed from the content and arrow positions/offsets. Only present when `position="popper"`. |
| `--akar-combobox-content-available-width` | The remaining width between the trigger and the boundary edge. Only present when `position="popper"`. |
| `--akar-combobox-content-available-height` | The remaining height between the trigger and the boundary edge. Only present when `position="popper"`. |
| `--akar-combobox-trigger-width` | The width of the trigger. Only present when `position="popper"`. |
| `--akar-combobox-trigger-height` | The height of the trigger. Only present when `position="popper"`. |

### Viewport

The scrolling viewport that contains all of the items.

**Props**

| Prop | Default | Type | Description |
| --- | --- | --- | --- |
| `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. |
| `asChild` |  | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. |
| `nonce` |  | `string` | Will add `nonce` attribute to the style tag which can be used by Content Security Policy.<br><br>If omitted, inherits globally from `ConfigProvider`. |

[ComboboxViewport.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Combobox/ComboboxViewport.vue)

### Item

The component that contains the combobox items.

**Props**

| Prop | Default | Type | Description |
| --- | --- | --- | --- |
| `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. |
| `asChild` |  | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. |
| `disabled` |  | `boolean` | When `true`, prevents the user from interacting with the item. |
| `textValue` |  | `string` | A string representation of the item contents.<br><br>If the children are not plain text, then the `textValue` prop must also be set to a plain text representation, which will be used for autocomplete in the ComboBox. |
| `value*` |  | `T` | The value given as data when submitted with a `name`. |

**Events**

| Event | Payload | Description |
| --- | --- | --- |
| `select` | `event: SelectEvent<T>` | Event handler called when the selecting item.<br><br>It can be prevented by calling `event.preventDefault`. |

**Slots**

| Slot | Payload | Description |
| --- | --- | --- |
| `selected` | `boolean` | Whether the item is currently selected |

[ComboboxItem.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Combobox/ComboboxItem.vue)

| Data attribute | Value |
| --- | --- |
| `[data-state]` | "checked" \\| "unchecked" |
| `[data-highlighted]` | Present when highlighted |
| `[data-disabled]` | Present when disabled |

### ItemIndicator

Renders when the item is selected. You can style this element directly, or you can use it as a wrapper to put an icon into, or both.

**Props**

| Prop | Default | Type | Description |
| --- | --- | --- | --- |
| `as` | `"span"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. |
| `asChild` |  | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. |
| `forceMount` |  | `boolean` | Used to force mounting when more control is needed. Useful when<br>controlling animation with Vue animation libraries. |

[ComboboxItemIndicator.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Combobox/ComboboxItemIndicator.vue)

### Group

Used to group multiple items. use in conjunction with `ComboboxLabel` to ensure good accessibility via automatic labelling.

**Props**

| Prop | Default | Type | Description |
| --- | --- | --- | --- |
| `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. |
| `asChild` |  | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. |

[ComboboxGroup.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Combobox/ComboboxGroup.vue)

### Label

Used to render the label of a group. It won't be focusable using arrow keys.

**Props**

| Prop | Default | Type | Description |
| --- | --- | --- | --- |
| `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. |
| `asChild` |  | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. |
| `for` |  | `string` |  |

[ComboboxLabel.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Combobox/ComboboxLabel.vue)

### Separator

Used to visually separate items in the Combobox

**Props**

| Prop | Default | Type | Description |
| --- | --- | --- | --- |
| `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. |
| `asChild` |  | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. |

[ComboboxSeparator.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Combobox/ComboboxSeparator.vue)

### Arrow

An optional arrow element to render alongside the content. This can be used to help visually link the trigger with the `ComboboxContent`. Must be rendered inside `ComboboxContent`. Only available when `position` is set to `popper`.

**Props**

| Prop | Default | Type | Description |
| --- | --- | --- | --- |
| `as` | `"svg"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. |
| `asChild` |  | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. |
| `height` | `5` | `number` | The height of the arrow in pixels. |
| `rounded` | `false` | `boolean` | When `true`, render the rounded version of arrow. Do not work with `as`/`asChild` |
| `width` | `10` | `number` | The width of the arrow in pixels. |

[ComboboxArrow.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Combobox/ComboboxArrow.vue)

### Virtualizer

Virtual container to achieve list virtualization.

> [!WARNING]
> 
> Combobox items **must** be filtered manually before passing them over to the virtualizer. See [example below](#virtualized-combobox-with-working-filtering).

See the [virtualization guide](https://vinicunca.dev/akar/guides/virtualization.md) for more general info on virtualization.

**Props**

| Prop | Default | Type | Description |
| --- | --- | --- | --- |
| `estimateSize` |  | `number \| ((index: number) => number)` | Estimated size (in px) of each item |
| `options*` |  | `T` | List of items |
| `overscan` |  | `number` | Number of items rendered outside the visible area |
| `textContent` |  | `((option: T) => string)` | Text content for each item to achieve type-ahead feature |

**Slots**

| Slot | Payload | Description |
| --- | --- | --- |
| `option` | `T` |  |
| `virtualizer` | `Virtualizer<HTMLElement, Element>` |  |
| `virtualItem` | `VirtualItem` |  |

[ComboboxVirtualizer.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Combobox/ComboboxVirtualizer.vue)

## Examples

### Binding objects as values

Unlike native HTML form controls which only allow you to provide strings as values, Akar supports binding complex objects as well.

Make sure to set the `displayValue` prop to set the input value on item selection.

```vue
<script setup lang="ts">
import { ComboboxContent, ComboboxInput, ComboboxItem, ComboboxPortal, ComboboxRoot } from 'akar'
import { ref } from 'vue'

const people = [
  { id: 1, name: 'Durward Reynolds' },
  { id: 2, name: 'Kenton Towne' },
  { id: 3, name: 'Therese Wunsch' },
  { id: 4, name: 'Benedict Kessler' },
  { id: 5, name: 'Katelyn Rohan' },
]
const selectedPeople = ref(people[0])
</script>

<template>
  <ComboboxRoot v-model="selectedPeople">
    <ComboboxInput :display-value="(v) => v.name" />
    <ComboboxPortal>
      <ComboboxContent>
        <ComboboxItem
          v-for="person in people"
          :key="person.id"
          :value="person"
          :disabled="person.unavailable"
        >
          {{ person.name }}
        </ComboboxItem>
      </ComboboxContent>
    </ComboboxPortal>
  </ComboboxRoot>
</template>
```

### Selecting multiple values

The `Combobox` component allows you to select multiple values. You can enable this by providing an array of values instead of a single value.

```vue
<script setup lang="ts">
import { ComboboxRoot } from 'akar'
import { ref } from 'vue'

const people = [
  { id: 1, name: 'Durward Reynolds' },
  { id: 2, name: 'Kenton Towne' },
  { id: 3, name: 'Therese Wunsch' },
  { id: 4, name: 'Benedict Kessler' },
  { id: 5, name: 'Katelyn Rohan' },
]
const selectedPeople = ref([people[0], people[1]])
</script>

<template>
  <ComboboxRoot
    v-model="selectedPeople"
    multiple
  >
    …
  </ComboboxRoot>
</template>
```

### Custom filtering

Internally, `ComboboxRoot` will filter the item based on the rendered text.

However, you may also provide your own custom filtering logic together with setting `ignoreFilter="true"`.

```vue
<script setup lang="ts">
import { ComboboxContent, ComboboxInput, ComboboxItem, ComboboxPortal, ComboboxRoot, useFilter } from 'akar'
import { ref } from 'vue'

const people = [
  { id: 1, name: 'Durward Reynolds' },
  { id: 2, name: 'Kenton Towne' },
  { id: 3, name: 'Therese Wunsch' },
  { id: 4, name: 'Benedict Kessler' },
  { id: 5, name: 'Katelyn Rohan' },
]
const selectedPeople = ref(people[0])
const searchTerm = ref('')

const { startsWith } = useFilter({ sensitivity: 'base' })
const filteredPeople = computed(() => people.filter(p => startsWith(p.name, searchTerm.value)))
</script>

<template>
  <ComboboxRoot
    v-model="selectedPeople"
    :ignore-filter="true"
  >
    <ComboboxInput v-model="searchTerm" />
    <ComboboxPortal>
      <ComboboxContent>
        <ComboboxItem
          v-for="person in filteredPeople"
          :key="person.id"
          :value="person"
        >
          {{ person.name }}
        </ComboboxItem>
      </ComboboxContent>
    </ComboboxPortal>
  </ComboboxRoot>
</template>
```

### Custom label

By default the `Combobox` will use the input contents as the label for screenreaders. If you'd like more control over what is announced to assistive technologies, use the [Label](https://vinicunca.dev/akar/components/label) component.

```vue
<script setup lang="ts">
import { ComboboxInput, ComboboxRoot, Label } from 'akar'
import { ref } from 'vue'
</script>

<template>
  <ComboboxRoot v-model="selectedPeople">
    <Label for="person">Person: </Label>
    <ComboboxInput
      id="person"
      placeholder="Select a person"
    />
    …
  </ComboboxRoot>
</template>
```

### With disabled items

You can add special styles to disabled items via the `data-disabled` attribute.

```vue
<script setup lang="ts">
import {
  ComboboxContent,
  ComboboxInput,
  ComboboxItem,
  ComboboxPortal,
  ComboboxRoot,
} from 'akar'
import { ref } from 'vue'
</script>

<template>
  <ComboboxRoot>
    <ComboboxInput />
    <ComboboxPortal>
      <ComboboxContent>
        <ComboboxItem
          class="ComboboxItem"
          disabled
        >
          …
        </ComboboxItem>
      </ComboboxContent>
    </ComboboxPortal>
  </ComboboxRoot>
</template>
```

```css
/* styles.css */
.ComboboxItem[data-disabled] {
  color: "gainsboro";
}
```

### With separators

Use the `Separator` part to add a separator between items.

```vue
<script setup lang="ts">
import {
  ComboboxContent,
  ComboboxInput,
  ComboboxItem,
  ComboboxPortal,
  ComboboxRoot,
  ComboboxSeparator
} from 'akar'
import { ref } from 'vue'
</script>

<template>
  <ComboboxRoot>
    <ComboboxInput />
    <ComboboxPortal>
      <ComboboxContent>
        <ComboboxItem>…</ComboboxItem>
        <ComboboxItem>…</ComboboxItem>
        <ComboboxItem>…</ComboboxItem>
        <ComboboxSeparator />
        <ComboboxItem>…</ComboboxItem>
        <ComboboxItem>…</ComboboxItem>
        <ComboboxItem>…</ComboboxItem>
      </ComboboxContent>
    </ComboboxPortal>
  </ComboboxRoot>
</template>
```

### With grouped items

Use the `Group` and `Label` parts to group items in a section.

```vue
<script setup lang="ts">
import {
  ComboboxContent,
  ComboboxGroup,
  ComboboxInput,
  ComboboxItem,
  ComboboxLabel,
  ComboboxPortal,
  ComboboxRoot
} from 'akar'
import { ref } from 'vue'
</script>

<template>
  <ComboboxRoot>
    <ComboboxInput />
    <ComboboxPortal>
      <ComboboxContent>
        <ComboboxGroup>
          <ComboboxLabel>Label</ComboboxLabel>
          <ComboboxItem>…</ComboboxItem>
          <ComboboxItem>…</ComboboxItem>
          <ComboboxItem>…</ComboboxItem>
        </ComboboxGroup>
      </ComboboxContent>
    </ComboboxPortal>
  </ComboboxRoot>
</template>
```

### With complex items

You can use custom content in your items.

```vue
<script setup lang="ts">
import {
  ComboboxContent,
  ComboboxGroup,
  ComboboxInput,
  ComboboxItem,
  ComboboxItemIndicator,
  ComboboxLabel,
  ComboboxPortal,
  ComboboxRoot
} from 'akar'
import { ref } from 'vue'
</script>

<template>
  <ComboboxRoot>
    <ComboboxInput />
    <ComboboxPortal>
      <ComboboxContent>
        <ComboboxItem>
          <img src="…">
          Adolfo Hess
          <ComboboxItemIndicator />
        </ComboboxItem>
        …
      </ComboboxContent>
    </ComboboxPortal>
  </ComboboxRoot>
</template>
```

### Prevent select behavior

By default, selecting `ComboboxItem` would close the content, and update the `modelValue` with the provided value.
You can prevent this behavior by preventing default `@select.prevent`.

```vue
<script setup lang="ts">
import { ComboboxContent, ComboboxGroup, ComboboxInput, ComboboxItem, ComboboxItemIndicator, ComboboxLabel, ComboboxPortal, ComboboxRoot } from 'akar'
import { ref } from 'vue'
</script>

<template>
  <ComboboxRoot>
    <ComboboxInput />
    <ComboboxPortal>
      <ComboboxContent>
        <ComboboxItem @select.prevent>
          Item A
        </ComboboxItem>
        …
      </ComboboxContent>
    </ComboboxPortal>
  </ComboboxRoot>
</template>
```

### Virtualized combobox with working filtering

Combobox items **must** be filtered manually before passing them over to the virtualizer.

See the [virtualization guide](https://vinicunca.dev/akar/guides/virtualization.md) for more general info on virtualization.

```vue
<script setup lang="ts">
import { ComboboxContent, ComboboxInput, ComboboxItem, ComboboxPortal, ComboboxRoot, ComboboxViewport, ComboboxVirtualizer, useFilter } from 'akar'
import { computed, ref } from 'vue'

const people = Array.from({ length: 100000 }).map((_, id) => ({ id, name: `Person #${id}` }))
const selectedPeople = ref(people[0])
const searchTerm = ref('')

const { contains } = useFilter({ sensitivity: 'base' })
const filteredPeople = computed(() => people.filter(p => contains(p.name, searchTerm.value)))
</script>

<template>
  <ComboboxRoot v-model="selectedPeople">
    <ComboboxInput v-model="searchTerm" />
    <ComboboxPortal>
      <ComboboxContent class="max-h-[40vh] overflow-hidden">
        <ComboboxViewport>
          <ComboboxVirtualizer
            v-slot="{ option }"
            :options="filteredPeople"
            :text-content="(x) => x.name"
            :estimate-size="24"
          >
            <ComboboxItem :value="option">
              {{ option.name }}
            </ComboboxItem>
          </ComboboxVirtualizer>
        </ComboboxViewport>
      </ComboboxContent>
    </ComboboxPortal>
  </ComboboxRoot>
</template>
```

## Accessibility

Adheres to the [Combobox WAI-ARIA design pattern](https://www.w3.org/WAI/ARIA/apg/patterns/combobox/).

See the W3C [Combobox Autocomplete List](https://www.w3.org/WAI/ARIA/apg/patterns/combobox/examples/combobox-autocomplete-list/) example for more information.

### Keyboard Interactions

| Key | Description |
| --- | --- |

---

- [ARIA](https://www.w3.org/WAI/ARIA/apg/patterns/listbox)
- [GitHub](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/Combobox)
- [npm](https://www.npmjs.com/package/akar)


## Sitemap

See the full [sitemap](https://vinicunca.dev/sitemap.md) for all pages.
