---
name: combobox
title: Combobox
url: https://ui.frontic.com/components/ui/combobox.md
tier: ui
install: npx @frontic/ui add combobox
files:
  - components/ui/combobox/Combobox.vue
  - components/ui/combobox/ComboboxAnchor.vue
  - components/ui/combobox/ComboboxEmpty.vue
  - components/ui/combobox/ComboboxGroup.vue
  - components/ui/combobox/ComboboxInput.vue
  - components/ui/combobox/ComboboxItem.vue
  - components/ui/combobox/ComboboxItemIndicator.vue
  - components/ui/combobox/ComboboxList.vue
  - components/ui/combobox/ComboboxSeparator.vue
  - components/ui/combobox/ComboboxTrigger.vue
  - components/ui/combobox/ComboboxViewport.vue
  - components/ui/combobox/index.ts
  - components/ui/combobox/keys.ts
dependencies:
  - "@lucide/vue"
  - "@vueuse/core"
  - reka-ui
---

# Combobox

Searchable single-choice list behind a trigger, with headed groups and an empty state; the list is as wide as its trigger, and the trigger joins a Field as its control.

## Install

```sh
npx @frontic/ui add combobox
```

npm packages: `@lucide/vue`, `@vueuse/core`, `reka-ui`

## Examples

```vue
<script setup lang="ts">
import { CheckIcon } from '@lucide/vue'

import { Field, FieldLabel } from '@/components/ui/field'
import { Combobox, ComboboxAnchor, ComboboxEmpty, ComboboxGroup, ComboboxInput, ComboboxItem, ComboboxItemIndicator, ComboboxList, ComboboxSeparator, ComboboxTrigger, ComboboxViewport } from '@/components/ui/combobox'
import { ref } from 'vue'

const regions = [
  {
    heading: 'Delivery in 2–3 days',
    countries: [
      { value: 'AT', label: 'Austria' },
      { value: 'BE', label: 'Belgium' },
      { value: 'DE', label: 'Germany' },
      { value: 'NL', label: 'Netherlands' },
    ],
  },
  {
    heading: 'Delivery in 4–6 days',
    countries: [
      { value: 'DK', label: 'Denmark' },
      { value: 'FR', label: 'France' },
      { value: 'IT', label: 'Italy' },
      { value: 'ES', label: 'Spain' },
      { value: 'SE', label: 'Sweden' },
      { value: 'CH', label: 'Switzerland' },
      { value: 'GB', label: 'United Kingdom' },
    ],
  },
]

const country = ref<(typeof regions)[number]['countries'][number]>()
</script>

<template>
  <Field>
    <FieldLabel>Ship to</FieldLabel>
    <Combobox v-model="country" by="value">
      <ComboboxAnchor>
        <ComboboxTrigger class="min-w-64">
          {{ country?.label ?? 'Select your country' }}
        </ComboboxTrigger>
      </ComboboxAnchor>
      <ComboboxList>
        <ComboboxInput placeholder="Search countries" />
        <ComboboxViewport>
          <ComboboxEmpty>No country found.</ComboboxEmpty>
          <template v-for="(region, index) in regions" :key="region.heading">
            <ComboboxSeparator v-if="index > 0" />
            <ComboboxGroup :heading="region.heading">
              <ComboboxItem v-for="option in region.countries" :key="option.value" :value="option">
                {{ option.label }}
                <ComboboxItemIndicator>
                  <CheckIcon data-icon />
                </ComboboxItemIndicator>
              </ComboboxItem>
            </ComboboxGroup>
          </template>
        </ComboboxViewport>
      </ComboboxList>
    </Combobox>
  </Field>
</template>
```

The example also uses `field`, which `add combobox` leaves out: `npx @frontic/ui add field`.

## Anatomy

```vue
<Combobox>
  <ComboboxAnchor>
    <ComboboxTrigger />
  </ComboboxAnchor>
  <ComboboxList>
    <ComboboxInput />
    <ComboboxViewport>
      <ComboboxEmpty />
      <ComboboxSeparator />
      <ComboboxGroup>
        <ComboboxItem>
          <ComboboxItemIndicator />
        </ComboboxItem>
      </ComboboxGroup>
    </ComboboxViewport>
  </ComboboxList>
</Combobox>
```

## API reference

### Combobox

Groups all parts of the combobox, which lets the user search and pick an option.

`data-slot="combobox"` · `Combobox.vue`

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `open` | `boolean` |  | The controlled open state of the Combobox. Can be binded with `v-model:open`. |
| `defaultOpen` | `boolean` | `false` | The open state of the combobox when it is initially rendered.<br><br>Use when you do not need to control its open state. |
| `resetSearchTermOnBlur` | `boolean` | `true` | Whether to reset the searchTerm when the Combobox input blurred |
| `resetSearchTermOnSelect` | `boolean` | `true` | Whether to reset the searchTerm when the Combobox value is selected |
| `openOnFocus` | `boolean` | `false` | Whether to open the combobox when the input is focused |
| `openOnClick` | `boolean` | `false` | Whether to open the combobox when the input is clicked |
| `ignoreFilter` | `boolean` | `false` | When `true`, disable the default filters |
| `resetModelValueOnClear` | `boolean` | `false` | When `true` the `modelValue` will be reset to `null` (or `[]` if `multiple`) |
| `unmountOnHide` | `boolean` | `true` | 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. |
| `multiple` | `boolean` | `false` | Whether multiple options can be selected or not. |
| `disabled` | `boolean` | `false` | When `true`, prevents the user from interacting with listbox |
| `dir` | `Direction`: `'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. |
| `asChild` | `boolean` | `false` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://www.reka-ui.com/docs/guides/composition) guide for more details. |
| `as` | `AsTag \| Component`: `ComponentOptions<any, any, any, ComputedOptions, MethodOptions, any, any, any, string, {}, {}, string, {}, {}, {}, string, ComponentProvideOptions> \| (props: any, ctx: Omit<{ attrs: Attrs; slots: Readonly<InternalSlots>; emit: (event: string, ...args: any[]) => void; expose: <Exposed extends Record<string, any> = Record<string, any>>(exposed?: Exposed \| undefined) => void; }, 'expose'>): any \| ComponentPublicInstanceConstructor<any, any, any, any, ComputedOptions, MethodOptions> \| 'a' \| 'button' \| 'div' \| 'form' \| 'h2' \| 'h3' \| 'img' \| 'input' \| 'label' \| 'li' \| 'nav' \| 'ol' \| 'p' \| 'span' \| 'svg' \| 'ul' \| 'template' \| {} & string` |  | The element or component this component should render as. Can be overwritten by `asChild`. |
| `modelValue` | `AcceptableValue \| AcceptableValue[]`: `null \| string \| number \| bigint \| Record<string, any> \| AcceptableValue[]` |  | The controlled value of the listbox. Can be binded with `v-model`. |
| `defaultValue` | `AcceptableValue \| AcceptableValue[]`: `null \| string \| number \| bigint \| Record<string, any> \| AcceptableValue[]` |  | The value of the listbox when initially rendered. Use when you do not need to control the state of the Listbox |
| `name` | `string` |  | The name of the field. Submitted with its owning form as part of a name/value pair. |
| `required` | `boolean` | `false` | When `true`, indicates that the user must set the value before the owning form can be submitted. |
| `highlightOnHover` | `boolean` | `true` | When `true`, hover over item will trigger highlight |
| `loop` | `boolean` | `false` | When `true`, keyboard navigation will loop from last item to first, and vice versa. |
| `by` | `string \| ((a: AcceptableValue, b: AcceptableValue) => boolean)`: `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. |

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

| Slot | Slot props | Description |
| --- | --- | --- |
| `default` | `{ open: boolean; modelValue: AcceptableValue \| AcceptableValue[]; }` | Holds the combobox's parts; gets whether the list is open and the selected value. |

### ComboboxAnchor

Marks where the option list attaches, wrapping the input and trigger.

`data-slot="combobox-anchor"` · `ComboboxAnchor.vue`

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `reference` | `ReferenceElement`: `Element \| VirtualElement` |  | The reference (or anchor) element that is being referred to for positioning.<br><br>If not provided will use the current component as anchor. |
| `asChild` | `boolean` | `false` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://www.reka-ui.com/docs/guides/composition) guide for more details. |
| `as` | `AsTag \| Component`: `ComponentOptions<any, any, any, ComputedOptions, MethodOptions, any, any, any, string, {}, {}, string, {}, {}, {}, string, ComponentProvideOptions> \| (props: any, ctx: Omit<{ attrs: Attrs; slots: Readonly<InternalSlots>; emit: (event: string, ...args: any[]) => void; expose: <Exposed extends Record<string, any> = Record<string, any>>(exposed?: Exposed \| undefined) => void; }, 'expose'>): any \| ComponentPublicInstanceConstructor<any, any, any, any, ComputedOptions, MethodOptions> \| 'a' \| 'button' \| 'div' \| 'form' \| 'h2' \| 'h3' \| 'img' \| 'input' \| 'label' \| 'li' \| 'nav' \| 'ol' \| 'p' \| 'span' \| 'svg' \| 'ul' \| 'template' \| {} & string` |  | The element or component this component should render as. Can be overwritten by `asChild`. |
| `class` | `ClassValue` |  | Classes added to the part's own element, after its recipe classes. |

### ComboboxEmpty

Shows a message when no option matches the search.

`data-slot="combobox-empty"` · `ComboboxEmpty.vue`

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `asChild` | `boolean` | `false` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://www.reka-ui.com/docs/guides/composition) guide for more details. |
| `as` | `AsTag \| Component`: `ComponentOptions<any, any, any, ComputedOptions, MethodOptions, any, any, any, string, {}, {}, string, {}, {}, {}, string, ComponentProvideOptions> \| (props: any, ctx: Omit<{ attrs: Attrs; slots: Readonly<InternalSlots>; emit: (event: string, ...args: any[]) => void; expose: <Exposed extends Record<string, any> = Record<string, any>>(exposed?: Exposed \| undefined) => void; }, 'expose'>): any \| ComponentPublicInstanceConstructor<any, any, any, any, ComputedOptions, MethodOptions> \| 'a' \| 'button' \| 'div' \| 'form' \| 'h2' \| 'h3' \| 'img' \| 'input' \| 'label' \| 'li' \| 'nav' \| 'ol' \| 'p' \| 'span' \| 'svg' \| 'ul' \| 'template' \| {} & string` |  | The element or component this component should render as. Can be overwritten by `asChild`. |
| `class` | `ClassValue` |  | Classes added to the part's own element, after its recipe classes. |

### ComboboxGroup

Groups related options in the combobox list.

`data-slot="combobox-group"` · `ComboboxGroup.vue`

Styling: `combobox-label`, which extends [`menu-label`](https://ui.frontic.com/DESIGN.md#menu-label). Change it there and every part that extends it follows.

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `asChild` | `boolean` | `false` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://www.reka-ui.com/docs/guides/composition) guide for more details. |
| `as` | `AsTag \| Component`: `ComponentOptions<any, any, any, ComputedOptions, MethodOptions, any, any, any, string, {}, {}, string, {}, {}, {}, string, ComponentProvideOptions> \| (props: any, ctx: Omit<{ attrs: Attrs; slots: Readonly<InternalSlots>; emit: (event: string, ...args: any[]) => void; expose: <Exposed extends Record<string, any> = Record<string, any>>(exposed?: Exposed \| undefined) => void; }, 'expose'>): any \| ComponentPublicInstanceConstructor<any, any, any, any, ComputedOptions, MethodOptions> \| 'a' \| 'button' \| 'div' \| 'form' \| 'h2' \| 'h3' \| 'img' \| 'input' \| 'label' \| 'li' \| 'nav' \| 'ol' \| 'p' \| 'span' \| 'svg' \| 'ul' \| 'template' \| {} & string` |  | The element or component this component should render as. Can be overwritten by `asChild`. |
| `class` | `ClassValue` |  | Classes added to the part's own element, after its recipe classes. |
| `heading` | `string` |  | Shown as the group's label above its options. |

### ComboboxInput

Lets the user type to filter the combobox options. Renders a `<input>`.

`data-slot="combobox-input"` · `ComboboxInput.vue`

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `displayValue` | `((val: any) => string)`: `(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. |
| `autoFocus` | `boolean` | `false` | Focus on element when mounted. |
| `disabled` | `boolean` | `false` | When `true`, prevents the user from interacting with item |
| `asChild` | `boolean` | `false` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://www.reka-ui.com/docs/guides/composition) guide for more details. |
| `as` | `AsTag \| Component`: `ComponentOptions<any, any, any, ComputedOptions, MethodOptions, any, any, any, string, {}, {}, string, {}, {}, {}, string, ComponentProvideOptions> \| (props: any, ctx: Omit<{ attrs: Attrs; slots: Readonly<InternalSlots>; emit: (event: string, ...args: any[]) => void; expose: <Exposed extends Record<string, any> = Record<string, any>>(exposed?: Exposed \| undefined) => void; }, 'expose'>): any \| ComponentPublicInstanceConstructor<any, any, any, any, ComputedOptions, MethodOptions> \| 'a' \| 'button' \| 'div' \| 'form' \| 'h2' \| 'h3' \| 'img' \| 'input' \| 'label' \| 'li' \| 'nav' \| 'ol' \| 'p' \| 'span' \| 'svg' \| 'ul' \| 'template' \| {} & string` | `'input'` | The element or component this component should render as. Can be overwritten by `asChild`. |
| `class` | `ClassValue` |  | Classes added to the part's own element, after its recipe classes. |

| Event | Payload | Description |
| --- | --- | --- |
| `update:modelValue` | `string` | Fires with the new value when `modelValue` changes; `v-model` binds it. |

| Data attribute | Values | Description |
| --- | --- | --- |
| `data-disabled` |  | Present while the part is disabled. |

### ComboboxItem

Holds one option the user can pick from the combobox.

`data-slot="combobox-item"` · `ComboboxItem.vue`

Styling: `combobox-item`, which extends [`option-item`](https://ui.frontic.com/DESIGN.md#option-item). Change it there and every part that extends it follows.

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `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` (required) | `AcceptableValue`: `null \| string \| number \| bigint \| Record<string, any>` |  | The value given as data when submitted with a `name`. |
| `disabled` | `boolean` | `false` | When `true`, prevents the user from interacting with the item. |
| `asChild` | `boolean` | `false` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://www.reka-ui.com/docs/guides/composition) guide for more details. |
| `as` | `AsTag \| Component`: `ComponentOptions<any, any, any, ComputedOptions, MethodOptions, any, any, any, string, {}, {}, string, {}, {}, {}, string, ComponentProvideOptions> \| (props: any, ctx: Omit<{ attrs: Attrs; slots: Readonly<InternalSlots>; emit: (event: string, ...args: any[]) => void; expose: <Exposed extends Record<string, any> = Record<string, any>>(exposed?: Exposed \| undefined) => void; }, 'expose'>): any \| ComponentPublicInstanceConstructor<any, any, any, any, ComputedOptions, MethodOptions> \| 'a' \| 'button' \| 'div' \| 'form' \| 'h2' \| 'h3' \| 'img' \| 'input' \| 'label' \| 'li' \| 'nav' \| 'ol' \| 'p' \| 'span' \| 'svg' \| 'ul' \| 'template' \| {} & string` |  | The element or component this component should render as. Can be overwritten by `asChild`. |
| `class` | `ClassValue` |  | Classes added to the part's own element, after its recipe classes. |

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

### ComboboxItemIndicator

Marks an option as selected in the combobox list. Renders a `<span>`.

`data-slot="combobox-item-indicator"` · `ComboboxItemIndicator.vue`

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `forceMount` | `boolean` | `false` | Used to force mounting when more control is needed. Useful when controlling animation with Vue animation libraries. |
| `asChild` | `boolean` | `false` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://www.reka-ui.com/docs/guides/composition) guide for more details. |
| `as` | `AsTag \| Component`: `ComponentOptions<any, any, any, ComputedOptions, MethodOptions, any, any, any, string, {}, {}, string, {}, {}, {}, string, ComponentProvideOptions> \| (props: any, ctx: Omit<{ attrs: Attrs; slots: Readonly<InternalSlots>; emit: (event: string, ...args: any[]) => void; expose: <Exposed extends Record<string, any> = Record<string, any>>(exposed?: Exposed \| undefined) => void; }, 'expose'>): any \| ComponentPublicInstanceConstructor<any, any, any, any, ComputedOptions, MethodOptions> \| 'a' \| 'button' \| 'div' \| 'form' \| 'h2' \| 'h3' \| 'img' \| 'input' \| 'label' \| 'li' \| 'nav' \| 'ol' \| 'p' \| 'span' \| 'svg' \| 'ul' \| 'template' \| {} & string` | `'span'` | The element or component this component should render as. Can be overwritten by `asChild`. |
| `class` | `ClassValue` |  | Classes added to the part's own element, after its recipe classes. |

| Data attribute | Values | Description |
| --- | --- | --- |
| `data-state` | `'checked' \| 'unchecked'` | The state the part is in, one value per state. |

### ComboboxList

Holds the options the combobox offers while it is open.

`data-slot="combobox-content"` · `ComboboxList.vue`

Styling: `combobox-content`, which extends [`overlay`](https://ui.frontic.com/DESIGN.md#overlay). Change it there and every part that extends it follows.

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `forceMount` | `boolean` | `false` | Used to force mounting when more control is needed. Useful when controlling animation with Vue animation libraries. |
| `position` | `'popper' \| '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`. |
| `bodyLock` | `boolean` | `false` | The document.body will be lock, and scrolling will be disabled. |
| `hideWhenEmpty` | `boolean` | `false` | When `true`, hides the content when there are no items matching the filter. |
| `memoDependencies` | `unknown[]` |  | Reactive dependencies that should invalidate the memoized content subtree. |
| `side` | `'top' \| 'right' \| 'bottom' \| 'left'` | `'bottom'` | The preferred side of the trigger to render against when open. Will be reversed when collisions occur and avoidCollisions is enabled. |
| `sideOffset` | `number` | `4` | The distance in pixels from the trigger. |
| `sideFlip` | `boolean` | `true` | Flip to the opposite side when colliding with boundary. |
| `align` | `'center' \| 'start' \| 'end'` | `'center'` | The preferred alignment against the trigger. May change when collisions occur. |
| `alignOffset` | `number` | `0` | An offset in pixels from the `start` or `end` alignment options. |
| `alignFlip` | `boolean` | `true` | Flip alignment when colliding with boundary. May only occur when `prioritizePosition` is true. |
| `avoidCollisions` | `boolean` | `true` | When `true`, overrides the side and align preferences to prevent collisions with boundary edges. |
| `collisionBoundary` | `Element \| (Element \| null)[] \| null`: `null \| Element \| (Element \| null)[]` | `[]` | The element used as the collision boundary. By default this is the viewport, though you can provide additional element(s) to be included in this check. |
| `collisionPadding` | `number \| Partial<Record<'top' \| 'right' \| 'bottom' \| 'left', number>>` | `0` | The distance in pixels from the boundary edges where collision detection should occur. Accepts a number (same for all sides), or a partial padding object, for example: { top: 20, left: 20 }. |
| `arrowPadding` | `number` | `0` | The padding between the arrow and the edges of the content. If your content has border-radius, this will prevent it from overflowing the corners. |
| `hideShiftedArrow` | `boolean` | `true` | When `true`, hides the arrow when it cannot be centered to the reference element. |
| `sticky` | `'partial' \| 'always'` | `'partial'` | The sticky behavior on the align axis. `partial` will keep the content in the boundary as long as the trigger is at least partially in the boundary whilst "always" will keep the content in the boundary regardless. |
| `hideWhenDetached` | `boolean` | `false` | Whether to hide the content when the trigger becomes fully occluded. |
| `positionStrategy` | `'absolute' \| 'fixed'` |  | The type of CSS position property to use. |
| `updatePositionStrategy` | `'always' \| 'optimized'` | `'optimized'` | Strategy to update the position of the floating element on every animation frame. |
| `disableUpdateOnLayoutShift` | `boolean` | `false` | Whether to disable the update position for the content when the layout shifted. |
| `prioritizePosition` | `boolean` | `false` | Force content to be position within the viewport.<br><br>Might overlap the reference element, which may not be desired. |
| `reference` | `ReferenceElement`: `Element \| VirtualElement` |  | The custom element or virtual element that will be set as the reference to position the floating element.<br><br>If provided, it will replace the default anchor element. |
| `dir` | `Direction`: `'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. |
| `asChild` | `boolean` | `false` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://www.reka-ui.com/docs/guides/composition) guide for more details. |
| `as` | `AsTag \| Component`: `ComponentOptions<any, any, any, ComputedOptions, MethodOptions, any, any, any, string, {}, {}, string, {}, {}, {}, string, ComponentProvideOptions> \| (props: any, ctx: Omit<{ attrs: Attrs; slots: Readonly<InternalSlots>; emit: (event: string, ...args: any[]) => void; expose: <Exposed extends Record<string, any> = Record<string, any>>(exposed?: Exposed \| undefined) => void; }, 'expose'>): any \| ComponentPublicInstanceConstructor<any, any, any, any, ComputedOptions, MethodOptions> \| 'a' \| 'button' \| 'div' \| 'form' \| 'h2' \| 'h3' \| 'img' \| 'input' \| 'label' \| 'li' \| 'nav' \| 'ol' \| 'p' \| 'span' \| 'svg' \| 'ul' \| 'template' \| {} & string` |  | The element or component this component should render as. Can be overwritten by `asChild`. |
| `disableOutsidePointerEvents` | `boolean` | `false` | When `true`, hover/focus/click interactions will be disabled on elements outside the `DismissableLayer`. Users will need to click twice on outside elements to interact with them: once to close the `DismissableLayer`, and again to trigger the element. |
| `class` | `ClassValue` |  | Classes added to the part's own element, after its recipe classes. |

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

| Data attribute | Values | Description |
| --- | --- | --- |
| `data-dismissable-layer` |  | Marks a layer that closes on Escape or a click outside it. |
| `data-empty` |  | Present while no option matches the search. |
| `data-state` | `'open' \| 'closed'` | The state the part is in, one value per state. |

### ComboboxSeparator

Separates groups of options in the combobox list; hidden while a search filters the list.

`data-slot="combobox-separator"` · `ComboboxSeparator.vue`

Styling: `combobox-separator`, which extends [`divider`](https://ui.frontic.com/DESIGN.md#divider). Change it there and every part that extends it follows.

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `asChild` | `boolean` | `false` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://www.reka-ui.com/docs/guides/composition) guide for more details. |
| `as` | `AsTag \| Component`: `ComponentOptions<any, any, any, ComputedOptions, MethodOptions, any, any, any, string, {}, {}, string, {}, {}, {}, string, ComponentProvideOptions> \| (props: any, ctx: Omit<{ attrs: Attrs; slots: Readonly<InternalSlots>; emit: (event: string, ...args: any[]) => void; expose: <Exposed extends Record<string, any> = Record<string, any>>(exposed?: Exposed \| undefined) => void; }, 'expose'>): any \| ComponentPublicInstanceConstructor<any, any, any, any, ComputedOptions, MethodOptions> \| 'a' \| 'button' \| 'div' \| 'form' \| 'h2' \| 'h3' \| 'img' \| 'input' \| 'label' \| 'li' \| 'nav' \| 'ol' \| 'p' \| 'span' \| 'svg' \| 'ul' \| 'template' \| {} & string` |  | The element or component this component should render as. Can be overwritten by `asChild`. |
| `class` | `ClassValue` |  | Classes added to the part's own element, after its recipe classes. |

### ComboboxTrigger

Shows the chosen option and opens the combobox list when pressed. Renders a `<button>`.

`data-slot="combobox-trigger"` · `ComboboxTrigger.vue`

Styling: `combobox-trigger`, which extends [`control`](https://ui.frontic.com/DESIGN.md#control) and [`control-line`](https://ui.frontic.com/DESIGN.md#control-line). Change them there and every part that extends them follows.

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `disabled` | `boolean` | `false` | When `true`, prevents the user from interacting with item |
| `asChild` | `boolean` | `false` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://www.reka-ui.com/docs/guides/composition) guide for more details. |
| `as` | `AsTag \| Component`: `ComponentOptions<any, any, any, ComputedOptions, MethodOptions, any, any, any, string, {}, {}, string, {}, {}, {}, string, ComponentProvideOptions> \| (props: any, ctx: Omit<{ attrs: Attrs; slots: Readonly<InternalSlots>; emit: (event: string, ...args: any[]) => void; expose: <Exposed extends Record<string, any> = Record<string, any>>(exposed?: Exposed \| undefined) => void; }, 'expose'>): any \| ComponentPublicInstanceConstructor<any, any, any, any, ComputedOptions, MethodOptions> \| 'a' \| 'button' \| 'div' \| 'form' \| 'h2' \| 'h3' \| 'img' \| 'input' \| 'label' \| 'li' \| 'nav' \| 'ol' \| 'p' \| 'span' \| 'svg' \| 'ul' \| 'template' \| {} & string` | `'button'` | The element or component this component should render as. Can be overwritten by `asChild`. |
| `class` | `ClassValue` |  | Classes added to the part's own element, after its recipe classes. |

| Slot | Slot props | Description |
| --- | --- | --- |
| `icon` |  | Replaces the chevron; leave it empty to show none. |

| Data attribute | Values | Description |
| --- | --- | --- |
| `data-disabled` |  | Present while the part is disabled. |
| `data-state` | `'open' \| 'closed'` | The state the part is in, one value per state. |

### ComboboxViewport

Scrolls the options when the combobox list is longer than the space available.

`data-slot="combobox-viewport"` · `ComboboxViewport.vue`

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `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`. |
| `asChild` | `boolean` | `false` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://www.reka-ui.com/docs/guides/composition) guide for more details. |
| `as` | `AsTag \| Component`: `ComponentOptions<any, any, any, ComputedOptions, MethodOptions, any, any, any, string, {}, {}, string, {}, {}, {}, string, ComponentProvideOptions> \| (props: any, ctx: Omit<{ attrs: Attrs; slots: Readonly<InternalSlots>; emit: (event: string, ...args: any[]) => void; expose: <Exposed extends Record<string, any> = Record<string, any>>(exposed?: Exposed \| undefined) => void; }, 'expose'>): any \| ComponentPublicInstanceConstructor<any, any, any, any, ComputedOptions, MethodOptions> \| 'a' \| 'button' \| 'div' \| 'form' \| 'h2' \| 'h3' \| 'img' \| 'input' \| 'label' \| 'li' \| 'nav' \| 'ol' \| 'p' \| 'span' \| 'svg' \| 'ul' \| 'template' \| {} & string` |  | The element or component this component should render as. Can be overwritten by `asChild`. |
| `class` | `ClassValue` |  | Classes added to the part's own element, after its recipe classes. |

## Exports

```ts
import { ComboboxCancel } from '@/components/ui/combobox'
```

- `ComboboxCancel`: from `reka-ui`

## Styling

| Part | Recipe |
| --- | --- |
| `input` | [`combobox-input`](https://ui.frontic.com/DESIGN.md#combobox-input) |
| `anchor` | [`combobox-anchor`](https://ui.frontic.com/DESIGN.md#combobox-anchor) |
| `trigger` | [`combobox-trigger`](https://ui.frontic.com/DESIGN.md#combobox-trigger) |
| `chevron` | [`combobox-chevron`](https://ui.frontic.com/DESIGN.md#combobox-chevron) |
| `search` | [`combobox-search`](https://ui.frontic.com/DESIGN.md#combobox-search) |
| `viewport` | [`combobox-viewport`](https://ui.frontic.com/DESIGN.md#combobox-viewport) |
| `content` | [`combobox-content`](https://ui.frontic.com/DESIGN.md#combobox-content) |
| `item` | [`combobox-item`](https://ui.frontic.com/DESIGN.md#combobox-item) |
| `item-indicator` | [`combobox-item-indicator`](https://ui.frontic.com/DESIGN.md#combobox-item-indicator) |
| `label` | [`combobox-label`](https://ui.frontic.com/DESIGN.md#combobox-label) |
| `empty` | [`combobox-empty`](https://ui.frontic.com/DESIGN.md#combobox-empty) |
| `separator` | [`combobox-separator`](https://ui.frontic.com/DESIGN.md#combobox-separator) |
| `disabled` | [`disabled`](https://ui.frontic.com/DESIGN.md#disabled) |

States with a look of their own: focus, disabled and invalid.

## Source

`components/ui/combobox/Combobox.vue`

```vue
<script lang="ts">
/** Groups all parts of the combobox, which lets the user search and pick an option. */
export default {}
</script>

<script setup lang="ts">
import type { AcceptableValue, ComboboxRootEmits, ComboboxRootProps } from 'reka-ui'
import { ComboboxRoot, injectFieldRootContext, useForwardPropsEmits } from 'reka-ui'
import { computed, provide } from 'vue'
import { comboboxRequired } from './keys'

const props = defineProps<ComboboxRootProps>()
const emits = defineEmits<ComboboxRootEmits>()

defineSlots<{
  /** Holds the combobox's parts; gets whether the list is open and the selected value. */
  default?: (props: { open: boolean; modelValue: AcceptableValue | AcceptableValue[] }) => unknown
}>()

const forwarded = useForwardPropsEmits(props, emits)

// Takes the name and state of a Field around it; ComboboxTrigger joins the Field as its control. Delete once Reka's Combobox reads the Field itself.
const field = injectFieldRootContext(null)
provide(comboboxRequired, () => !!props.required)
const joined = computed(() =>
  field
    ? {
        ...forwarded.value,
        name: props.name ?? field.name.value,
        disabled: props.disabled || field.disabled.value,
        required: props.required || field.required.value,
      }
    : forwarded.value,
)
</script>

<template>
  <ComboboxRoot v-slot="slotProps" data-slot="combobox" v-bind="joined">
    <slot v-bind="slotProps" />
  </ComboboxRoot>
</template>
```

`components/ui/combobox/ComboboxAnchor.vue`

```vue
<script lang="ts">
/** Marks where the option list attaches, wrapping the input and trigger. */
export default {}
</script>

<script setup lang="ts">
import type { ComboboxAnchorProps } from 'reka-ui'
import type { HTMLAttributes } from 'vue'
import { reactiveOmit } from '@vueuse/core'
import { ComboboxAnchor, useForwardProps } from 'reka-ui'

const props = defineProps<ComboboxAnchorProps & { class?: HTMLAttributes['class'] }>()

const delegatedProps = reactiveOmit(props, 'class')

const forwarded = useForwardProps(delegatedProps)
</script>

<template>
  <ComboboxAnchor data-slot="combobox-anchor" v-bind="forwarded" :class="['fui-combobox-anchor', props.class]">
    <slot />
  </ComboboxAnchor>
</template>
```

`components/ui/combobox/ComboboxEmpty.vue`

```vue
<script lang="ts">
/** Shows a message when no option matches the search. */
export default {}
</script>

<script setup lang="ts">
import type { ComboboxEmptyProps } from 'reka-ui'
import type { HTMLAttributes } from 'vue'
import { reactiveOmit } from '@vueuse/core'
import { ComboboxEmpty, useForwardProps } from 'reka-ui'

const props = defineProps<ComboboxEmptyProps & { class?: HTMLAttributes['class'] }>()

const delegatedProps = reactiveOmit(props, 'class')
const forwarded = useForwardProps(delegatedProps)
</script>

<template>
  <ComboboxEmpty data-slot="combobox-empty" v-bind="forwarded" :class="['fui-combobox-empty', props.class]">
    <slot />
  </ComboboxEmpty>
</template>
```

`components/ui/combobox/ComboboxGroup.vue`

```vue
<script lang="ts">
/** Groups related options in the combobox list. */
export default {}
</script>

<script setup lang="ts">
import type { ComboboxGroupProps } from 'reka-ui'
import type { HTMLAttributes } from 'vue'
import { reactiveOmit } from '@vueuse/core'
import { ComboboxGroup, ComboboxLabel, useForwardProps } from 'reka-ui'

const props = defineProps<
  ComboboxGroupProps & {
    class?: HTMLAttributes['class']
    /** Shown as the group's label above its options. */
    heading?: string
  }
>()

const delegatedProps = reactiveOmit(props, 'class')
const forwarded = useForwardProps(delegatedProps)
</script>

<template>
  <ComboboxGroup data-slot="combobox-group" v-bind="forwarded" :class="['overflow-hidden', props.class]">
    <ComboboxLabel v-if="heading" class="fui-combobox-label">
      {{ heading }}
    </ComboboxLabel>
    <slot />
  </ComboboxGroup>
</template>
```

`components/ui/combobox/ComboboxInput.vue`

```vue
<script lang="ts">
/** Lets the user type to filter the combobox options. */
export default {}
</script>

<script setup lang="ts">
import { SearchIcon } from '@lucide/vue'

import type { ComboboxInputEmits, ComboboxInputProps } from 'reka-ui'
import type { HTMLAttributes } from 'vue'
import { reactiveOmit } from '@vueuse/core'
import { ComboboxInput, useForwardPropsEmits } from 'reka-ui'

defineOptions({
  inheritAttrs: false,
})

const props = defineProps<
  ComboboxInputProps & {
    class?: HTMLAttributes['class']
  }
>()

const emits = defineEmits<ComboboxInputEmits>()

const delegatedProps = reactiveOmit(props, 'class')

const forwarded = useForwardPropsEmits(delegatedProps, emits)
</script>

<template>
  <div data-slot="combobox-search" class="fui-combobox-search flex items-center">
    <SearchIcon data-icon class="shrink-0" />
    <ComboboxInput
      data-slot="combobox-input"
      :class="['fui-combobox-input bg-transparent outline-hidden disabled:cursor-not-allowed disabled:fui-disabled', props.class]"
      v-bind="{ ...$attrs, ...forwarded }"
    >
      <slot />
    </ComboboxInput>
  </div>
</template>
```

`components/ui/combobox/ComboboxItem.vue`

```vue
<script lang="ts">
/** Holds one option the user can pick from the combobox. */
export default {}
</script>

<script setup lang="ts">
import type { ComboboxItemEmits, ComboboxItemProps } from 'reka-ui'
import type { HTMLAttributes } from 'vue'
import { reactiveOmit } from '@vueuse/core'
import { ComboboxItem, useForwardPropsEmits } from 'reka-ui'

const props = defineProps<ComboboxItemProps & { class?: HTMLAttributes['class'] }>()
const emits = defineEmits<ComboboxItemEmits>()

const delegatedProps = reactiveOmit(props, 'class')

const forwarded = useForwardPropsEmits(delegatedProps, emits)
</script>

<template>
  <ComboboxItem
    data-slot="combobox-item"
    v-bind="forwarded"
    :class="[
      'fui-combobox-item relative cursor-default outline-hidden select-none data-disabled:pointer-events-none data-disabled:fui-disabled **:data-icon:pointer-events-none **:data-icon:shrink-0',
      props.class,
    ]"
  >
    <slot />
  </ComboboxItem>
</template>
```

`components/ui/combobox/ComboboxItemIndicator.vue`

```vue
<script lang="ts">
/** Marks an option as selected in the combobox list. */
export default {}
</script>

<script setup lang="ts">
import type { ComboboxItemIndicatorProps } from 'reka-ui'
import type { HTMLAttributes } from 'vue'
import { reactiveOmit } from '@vueuse/core'
import { ComboboxItemIndicator, useForwardProps } from 'reka-ui'

const props = defineProps<ComboboxItemIndicatorProps & { class?: HTMLAttributes['class'] }>()

const delegatedProps = reactiveOmit(props, 'class')

const forwarded = useForwardProps(delegatedProps)
</script>

<template>
  <ComboboxItemIndicator data-slot="combobox-item-indicator" v-bind="forwarded" :class="['fui-combobox-item-indicator pointer-events-none absolute inset-e-2', props.class]">
    <slot />
  </ComboboxItemIndicator>
</template>
```

`components/ui/combobox/ComboboxList.vue`

```vue
<script lang="ts">
/** Holds the options the combobox offers while it is open. */
export default {}
</script>

<script setup lang="ts">
import type { ComboboxContentEmits, ComboboxContentProps } from 'reka-ui'
import type { HTMLAttributes } from 'vue'
import { reactiveOmit } from '@vueuse/core'
import { ComboboxContent, ComboboxPortal, useForwardPropsEmits } from 'reka-ui'

defineOptions({
  inheritAttrs: false,
})

const props = withDefaults(defineProps<ComboboxContentProps & { class?: HTMLAttributes['class'] }>(), {
  position: 'popper',
  align: 'center',
  sideOffset: 4,
})
const emits = defineEmits<ComboboxContentEmits>()

const delegatedProps = reactiveOmit(props, 'class')
const forwarded = useForwardPropsEmits(delegatedProps, emits)
</script>

<template>
  <ComboboxPortal>
    <ComboboxContent
      data-slot="combobox-content"
      v-bind="{ ...$attrs, ...forwarded }"
      :class="[
        'fui-combobox-content max-h-(--reka-combobox-content-available-height) group/combobox-content z-50 data-open:animate-in data-closed:animate-out data-open:fade-in-0 data-closed:fade-out-0 data-open:zoom-in-95 data-closed:zoom-out-95 data-side-bottom:slide-in-from-top-2 data-side-left:slide-in-from-right-2 data-side-right:slide-in-from-left-2 data-side-top:slide-in-from-bottom-2 duration-100 origin-(--reka-combobox-content-transform-origin) overflow-hidden',
        props.class,
      ]"
    >
      <slot />
    </ComboboxContent>
  </ComboboxPortal>
</template>
```

`components/ui/combobox/ComboboxSeparator.vue`

```vue
<script lang="ts">
/** Separates groups of options in the combobox list; hidden while a search filters the list. */
export default {}
</script>

<script setup lang="ts">
import type { ComboboxSeparatorProps } from 'reka-ui'
import type { HTMLAttributes } from 'vue'
import { reactiveOmit } from '@vueuse/core'
import { ComboboxSeparator, injectComboboxRootContext, useForwardProps } from 'reka-ui'

const props = defineProps<ComboboxSeparatorProps & { class?: HTMLAttributes['class'] }>()

const delegatedProps = reactiveOmit(props, 'class')

// Reka hides a group the search empties but not the separator beside it.
const root = injectComboboxRootContext()
const forwarded = useForwardProps(delegatedProps)
</script>

<template>
  <ComboboxSeparator v-show="!root.filterSearch.value" data-slot="combobox-separator" v-bind="forwarded" :class="['fui-combobox-separator', props.class]">
    <slot />
  </ComboboxSeparator>
</template>
```

`components/ui/combobox/ComboboxTrigger.vue`

```vue
<script lang="ts">
/** Shows the chosen option and opens the combobox list when pressed. */
export default {}
</script>

<script setup lang="ts">
import { ChevronDownIcon } from '@lucide/vue'

import type { ComboboxTriggerProps } from 'reka-ui'
import type { HTMLAttributes } from 'vue'
import { reactiveOmit } from '@vueuse/core'
import { ComboboxTrigger, injectComboboxRootContext, injectFieldRootContext, useForwardProps } from 'reka-ui'
import { computed, inject, onBeforeUnmount, onMounted, useAttrs, watch } from 'vue'
import { comboboxRequired } from './keys'

const props = defineProps<ComboboxTriggerProps & { class?: HTMLAttributes['class'] }>()
defineSlots<{
  default?: () => unknown
  /** Replaces the chevron; leave it empty to show none. */
  icon?: () => unknown
}>()

const delegatedProps = reactiveOmit(props, 'class')

const forwarded = useForwardProps(delegatedProps)

// Joins a Field around the combobox as its control, as Reka's Select trigger does. Delete once Reka's Combobox reads the Field itself.
const field = injectFieldRootContext(null)
const combobox = injectComboboxRootContext()
const required = inject(comboboxRequired, () => false)
const attrs = useAttrs()
const id = () => (attrs.id as string | undefined) ?? field?.fieldId.value
const fieldAttrs = computed(() =>
  field
    ? {
        ...field.dataAttributes.value,
        id: id(),
        'aria-labelledby': field.labelId.value,
        'aria-describedby': field.describedBy.value,
        'aria-invalid': (field.invalid.value && !field.disabled.value) || undefined,
        onFocus: () => field.handleControlFocus(),
        // Opening the list moves focus into its search, which is still the combobox.
        onBlur: () => !combobox.open.value && field.handleControlBlur(),
      }
    : {},
)
watch(combobox.modelValue, (next) => field?.handleControlInput({ value: next }))
let unregister: (() => void) | undefined
onMounted(() => {
  unregister = field?.registerControl({
    id,
    element: () => combobox.triggerElement.value,
    getValue: () => combobox.modelValue.value,
    required,
  })
})
onBeforeUnmount(() => unregister?.())
</script>

<template>
  <ComboboxTrigger
    data-slot="combobox-trigger"
    v-bind="{ ...fieldAttrs, ...forwarded }"
    :class="['fui-combobox-trigger whitespace-nowrap outline-none transition disabled:cursor-not-allowed disabled:fui-disabled **:data-icon:pointer-events-none **:data-icon:shrink-0', props.class]"
    tabindex="0"
  >
    <slot />
    <slot name="icon">
      <ChevronDownIcon data-icon class="fui-combobox-chevron pointer-events-none" />
    </slot>
  </ComboboxTrigger>
</template>
```

`components/ui/combobox/ComboboxViewport.vue`

```vue
<script lang="ts">
/** Scrolls the options when the combobox list is longer than the space available. */
export default {}
</script>

<script setup lang="ts">
import type { ComboboxViewportProps } from 'reka-ui'
import type { HTMLAttributes } from 'vue'
import { reactiveOmit } from '@vueuse/core'
import { ComboboxViewport, useForwardProps } from 'reka-ui'

const props = defineProps<ComboboxViewportProps & { class?: HTMLAttributes['class'] }>()

const delegatedProps = reactiveOmit(props, 'class')

const forwarded = useForwardProps(delegatedProps)
</script>

<template>
  <ComboboxViewport data-slot="combobox-viewport" v-bind="forwarded" :class="['fui-combobox-viewport max-h-63 scroll-py-1.5 overflow-y-auto', props.class]">
    <slot />
  </ComboboxViewport>
</template>
```

`components/ui/combobox/keys.ts`

```ts
import type { InjectionKey } from 'vue'

/** Whether the Combobox itself is required, for the trigger that joins the Field. */
export const comboboxRequired: InjectionKey<() => boolean> = Symbol('comboboxRequired')
```

## API of the items the example uses

### Field

[Full docs](https://ui.frontic.com/components/ui/field.md) · `npx @frontic/ui add field`

#### Field

Groups a label, an input, a description and an error of one form field, and validates its input.

`data-slot="field"` · `Field.vue`

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `name` | `string` |  | The name of the field. Submitted with its owning form as part of a name/value pair, and used to match server `errors` on a `FormRoot`. Takes precedence over the `name` of the control. |
| `disabled` | `boolean` | `false` | When `true`, prevents the user from interacting with the field's control. Takes precedence over the `disabled` of the control. |
| `required` | `boolean` | `false` | When `true`, indicates that the user must set the value before the owning form can be submitted. |
| `invalid` | `boolean` |  | When `true`, marks the field invalid regardless of its own validation. Useful when the field state is controlled by an external library. |
| `dirty` | `boolean` |  | Whether the field's value has changed from its initial value. Useful when the field state is controlled by an external library. |
| `touched` | `boolean` |  | Whether the field has been touched (its control blurred). Useful when the field state is controlled by an external library. |
| `validate` | `FieldValidateFn`: `(value: unknown, formValues: Record<string, unknown>): FieldValidateResult \| Promise<FieldValidateResult>` |  | Custom validation function. Return an error message (or array of messages) when invalid, or `null`/`undefined` when valid. Receives the control's value and the values of every named field in the owning form.<br><br>Can be async, but an async `validate` does not prevent form submission when `validationMode` is `onSubmit`. |
| `validationMode` | `FieldValidationMode`: `'onBlur' \| 'onChange' \| 'onSubmit'` | `'onSubmit'` | When the field (re-)runs validation. Takes precedence over the `validationMode` of an ancestor `FormRoot`.<br>- `onSubmit`: when the form is submitted, then on every change after that.<br>- `onBlur`: when the control loses focus.<br>- `onChange`: on every change to the control's value. |
| `validationDebounceTime` | `number` |  | How long to wait (in ms) between `validate` calls when validating on change. |
| `asChild` | `boolean` | `false` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://www.reka-ui.com/docs/guides/composition) guide for more details. |
| `as` | `AsTag \| Component`: `ComponentOptions<any, any, any, ComputedOptions, MethodOptions, any, any, any, string, {}, {}, string, {}, {}, {}, string, ComponentProvideOptions> \| (props: any, ctx: Omit<{ attrs: Attrs; slots: Readonly<InternalSlots>; emit: (event: string, ...args: any[]) => void; expose: <Exposed extends Record<string, any> = Record<string, any>>(exposed?: Exposed \| undefined) => void; }, 'expose'>): any \| ComponentPublicInstanceConstructor<any, any, any, any, ComputedOptions, MethodOptions> \| 'a' \| 'button' \| 'div' \| 'form' \| 'h2' \| 'h3' \| 'img' \| 'input' \| 'label' \| 'li' \| 'nav' \| 'ol' \| 'p' \| 'span' \| 'svg' \| 'ul' \| 'template' \| {} & string` |  | The element or component this component should render as. Can be overwritten by `asChild`. |
| `class` | `ClassValue` |  | Classes added to the part's own element, after its recipe classes. |
| `orientation` | `FieldOrientation`: `'vertical' \| 'horizontal' \| 'responsive'` | `'vertical'` | Label above the control, beside it, or `responsive`: beside it once the field group is wide enough. |

| Slot | Slot props | Description |
| --- | --- | --- |
| `default` | `{ invalid: boolean; errors: string[]; }` | The label, control, description and error; gets `invalid` and the current `errors`. |

| Data attribute | Values | Description |
| --- | --- | --- |
| `data-horizontal` |  | Present when the part is laid out horizontally. |
| `data-orientation` | `'vertical' \| 'horizontal' \| 'responsive'` | Carries the `orientation` prop. |

#### FieldContent

Groups the label and description that sit beside the control of a field. Renders a `<div>`.

`data-slot="field-content"` · `FieldContent.vue`

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `asChild` | `boolean` | `false` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://www.reka-ui.com/docs/guides/composition) guide for more details. |
| `as` | `AsTag \| Component`: `ComponentOptions<any, any, any, ComputedOptions, MethodOptions, any, any, any, string, {}, {}, string, {}, {}, {}, string, ComponentProvideOptions> \| (props: any, ctx: Omit<{ attrs: Attrs; slots: Readonly<InternalSlots>; emit: (event: string, ...args: any[]) => void; expose: <Exposed extends Record<string, any> = Record<string, any>>(exposed?: Exposed \| undefined) => void; }, 'expose'>): any \| ComponentPublicInstanceConstructor<any, any, any, any, ComputedOptions, MethodOptions> \| 'a' \| 'button' \| 'div' \| 'form' \| 'h2' \| 'h3' \| 'img' \| 'input' \| 'label' \| 'li' \| 'nav' \| 'ol' \| 'p' \| 'span' \| 'svg' \| 'ul' \| 'template' \| {} & string` | `'div'` | The element or component this component should render as. Can be overwritten by `asChild`. |
| `class` | `ClassValue` |  | Classes added to the part's own element, after its recipe classes. |

#### FieldDescription

Gives help text for a field, such as what to enter.

`data-slot="field-description"` · `FieldDescription.vue`

Styling: `field-description`, which extends [`hint`](https://ui.frontic.com/DESIGN.md#hint) and [`link-primary`](https://ui.frontic.com/DESIGN.md#link-primary). Change them there and every part that extends them follows.

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `id` | `string` |  | Id of the element. Auto-generated when not provided. |
| `asChild` | `boolean` | `false` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://www.reka-ui.com/docs/guides/composition) guide for more details. |
| `as` | `AsTag \| Component`: `ComponentOptions<any, any, any, ComputedOptions, MethodOptions, any, any, any, string, {}, {}, string, {}, {}, {}, string, ComponentProvideOptions> \| (props: any, ctx: Omit<{ attrs: Attrs; slots: Readonly<InternalSlots>; emit: (event: string, ...args: any[]) => void; expose: <Exposed extends Record<string, any> = Record<string, any>>(exposed?: Exposed \| undefined) => void; }, 'expose'>): any \| ComponentPublicInstanceConstructor<any, any, any, any, ComputedOptions, MethodOptions> \| 'a' \| 'button' \| 'div' \| 'form' \| 'h2' \| 'h3' \| 'img' \| 'input' \| 'label' \| 'li' \| 'nav' \| 'ol' \| 'p' \| 'span' \| 'svg' \| 'ul' \| 'template' \| {} & string` |  | The element or component this component should render as. Can be overwritten by `asChild`. |
| `class` | `ClassValue` |  | Classes added to the part's own element, after its recipe classes. |

#### FieldError

Shows why the input of a field is invalid, from its own validation, from the server or from a form library.

`data-slot="field-error"` · `FieldError.vue`

Styling: `field-error`, which extends [`error`](https://ui.frontic.com/DESIGN.md#error). Change it there and every part that extends it follows.

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `id` | `string` |  | Id of the element. Auto-generated when not provided. |
| `match` | `boolean \| keyof ValidityState`: `boolean \| 'badInput' \| 'customError' \| 'patternMismatch' \| 'rangeOverflow' \| 'rangeUnderflow' \| 'stepMismatch' \| 'tooLong' \| 'tooShort' \| 'typeMismatch' \| 'valid' \| 'valueMissing'` |  | Restricts when this error renders:<br>- a `ValidityState` key (e.g. `"valueMissing"`) — renders when that constraint fails.<br>- `true` — always renders, letting an external library control visibility.<br>- omitted — renders whenever the field is invalid. |
| `forceMount` | `boolean` | `false` | Used to force mounting when more control is needed. Useful when controlling animation with Vue animation libraries. |
| `asChild` | `boolean` | `false` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://www.reka-ui.com/docs/guides/composition) guide for more details. |
| `as` | `AsTag \| Component`: `ComponentOptions<any, any, any, ComputedOptions, MethodOptions, any, any, any, string, {}, {}, string, {}, {}, {}, string, ComponentProvideOptions> \| (props: any, ctx: Omit<{ attrs: Attrs; slots: Readonly<InternalSlots>; emit: (event: string, ...args: any[]) => void; expose: <Exposed extends Record<string, any> = Record<string, any>>(exposed?: Exposed \| undefined) => void; }, 'expose'>): any \| ComponentPublicInstanceConstructor<any, any, any, any, ComputedOptions, MethodOptions> \| 'a' \| 'button' \| 'div' \| 'form' \| 'h2' \| 'h3' \| 'img' \| 'input' \| 'label' \| 'li' \| 'nav' \| 'ol' \| 'p' \| 'span' \| 'svg' \| 'ul' \| 'template' \| {} & string` |  | The element or component this component should render as. Can be overwritten by `asChild`. |
| `class` | `ClassValue` |  | Classes added to the part's own element, after its recipe classes. |
| `errors` | `(string \| { message: string \| undefined; } \| undefined)[]` |  | Messages from outside the Field, such as vee-validate's or TanStack Form's; shown instead of the Field's own, duplicates dropped. |

| Slot | Slot props | Description |
| --- | --- | --- |
| `default` | `{ errors: string[]; }` | Replaces the messages; gets the current `errors`. |

#### FieldGroup

Stacks several fields of a form together. Renders a `<div>`.

`data-slot="field-group"` · `FieldGroup.vue`

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `asChild` | `boolean` | `false` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://www.reka-ui.com/docs/guides/composition) guide for more details. |
| `as` | `AsTag \| Component`: `ComponentOptions<any, any, any, ComputedOptions, MethodOptions, any, any, any, string, {}, {}, string, {}, {}, {}, string, ComponentProvideOptions> \| (props: any, ctx: Omit<{ attrs: Attrs; slots: Readonly<InternalSlots>; emit: (event: string, ...args: any[]) => void; expose: <Exposed extends Record<string, any> = Record<string, any>>(exposed?: Exposed \| undefined) => void; }, 'expose'>): any \| ComponentPublicInstanceConstructor<any, any, any, any, ComputedOptions, MethodOptions> \| 'a' \| 'button' \| 'div' \| 'form' \| 'h2' \| 'h3' \| 'img' \| 'input' \| 'label' \| 'li' \| 'nav' \| 'ol' \| 'p' \| 'span' \| 'svg' \| 'ul' \| 'template' \| {} & string` | `'div'` | The element or component this component should render as. Can be overwritten by `asChild`. |
| `class` | `ClassValue` |  | Classes added to the part's own element, after its recipe classes. |

#### FieldLabel

Labels the input of a field.

`data-slot="field-label"` · `FieldLabel.vue`

Styling: `field-label`, which extends [`label`](https://ui.frontic.com/DESIGN.md#label). Change it there and every part that extends it follows.

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `nativeLabel` | `boolean` | `true` | Whether the label renders a native `label` element. Set to `false` when rendering another element (e.g. `as="div"`): it then drops `for`, focuses the control on click, and relies on the control's `aria-labelledby`.<br><br>Useful for button controls like `SelectTrigger`, where a native label would forward clicks and `:hover` to the button. |
| `for` | `string` |  | The id of the element the label is associated with. |
| `asChild` | `boolean` | `false` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://www.reka-ui.com/docs/guides/composition) guide for more details. |
| `as` | `AsTag \| Component`: `ComponentOptions<any, any, any, ComputedOptions, MethodOptions, any, any, any, string, {}, {}, string, {}, {}, {}, string, ComponentProvideOptions> \| (props: any, ctx: Omit<{ attrs: Attrs; slots: Readonly<InternalSlots>; emit: (event: string, ...args: any[]) => void; expose: <Exposed extends Record<string, any> = Record<string, any>>(exposed?: Exposed \| undefined) => void; }, 'expose'>): any \| ComponentPublicInstanceConstructor<any, any, any, any, ComputedOptions, MethodOptions> \| 'a' \| 'button' \| 'div' \| 'form' \| 'h2' \| 'h3' \| 'img' \| 'input' \| 'label' \| 'li' \| 'nav' \| 'ol' \| 'p' \| 'span' \| 'svg' \| 'ul' \| 'template' \| {} & string` |  | The element or component this component should render as. Can be overwritten by `asChild`. |
| `class` | `ClassValue` |  | Classes added to the part's own element, after its recipe classes. |

#### FieldLegend

Titles a set of related fields. Renders a `<legend>`.

`data-slot="field-legend"` · `FieldLegend.vue`

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `asChild` | `boolean` | `false` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://www.reka-ui.com/docs/guides/composition) guide for more details. |
| `as` | `AsTag \| Component`: `ComponentOptions<any, any, any, ComputedOptions, MethodOptions, any, any, any, string, {}, {}, string, {}, {}, {}, string, ComponentProvideOptions> \| (props: any, ctx: Omit<{ attrs: Attrs; slots: Readonly<InternalSlots>; emit: (event: string, ...args: any[]) => void; expose: <Exposed extends Record<string, any> = Record<string, any>>(exposed?: Exposed \| undefined) => void; }, 'expose'>): any \| ComponentPublicInstanceConstructor<any, any, any, any, ComputedOptions, MethodOptions> \| 'a' \| 'button' \| 'div' \| 'form' \| 'h2' \| 'h3' \| 'img' \| 'input' \| 'label' \| 'li' \| 'nav' \| 'ol' \| 'p' \| 'span' \| 'svg' \| 'ul' \| 'template' \| {} & string` | `'legend'` | The element or component this component should render as. Can be overwritten by `asChild`. |
| `class` | `ClassValue` |  | Classes added to the part's own element, after its recipe classes. |
| `variant` | `'label' \| 'legend'` | `'legend'` | Whether the legend reads as a section heading or as a field label. |

| Data attribute | Values | Description |
| --- | --- | --- |
| `data-variant` | `'label' \| 'legend'` | Carries the `variant` prop. |

#### FieldSeparator

Separates fields of a form, optionally with a short text in between. Renders a `<div>`.

`data-slot="field-separator"` · `FieldSeparator.vue`

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `class` | `ClassValue` |  | Classes added to the part's own element, after its recipe classes. |

| Data attribute | Values | Description |
| --- | --- | --- |
| `data-content` | `'true' \| 'false'` | `true` when the separator has text in it. |

#### FieldSet

Groups related fields under one legend. Renders a `<fieldset>`.

`data-slot="field-set"` · `FieldSet.vue`

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `asChild` | `boolean` | `false` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://www.reka-ui.com/docs/guides/composition) guide for more details. |
| `as` | `AsTag \| Component`: `ComponentOptions<any, any, any, ComputedOptions, MethodOptions, any, any, any, string, {}, {}, string, {}, {}, {}, string, ComponentProvideOptions> \| (props: any, ctx: Omit<{ attrs: Attrs; slots: Readonly<InternalSlots>; emit: (event: string, ...args: any[]) => void; expose: <Exposed extends Record<string, any> = Record<string, any>>(exposed?: Exposed \| undefined) => void; }, 'expose'>): any \| ComponentPublicInstanceConstructor<any, any, any, any, ComputedOptions, MethodOptions> \| 'a' \| 'button' \| 'div' \| 'form' \| 'h2' \| 'h3' \| 'img' \| 'input' \| 'label' \| 'li' \| 'nav' \| 'ol' \| 'p' \| 'span' \| 'svg' \| 'ul' \| 'template' \| {} & string` | `'fieldset'` | The element or component this component should render as. Can be overwritten by `asChild`. |
| `class` | `ClassValue` |  | Classes added to the part's own element, after its recipe classes. |

#### FieldTitle

Shows the title of a field next to its description. Renders a `<div>`.

`data-slot="field-title"` · `FieldTitle.vue`

Styling: `field-label`, which extends [`label`](https://ui.frontic.com/DESIGN.md#label). Change it there and every part that extends it follows.

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `asChild` | `boolean` | `false` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://www.reka-ui.com/docs/guides/composition) guide for more details. |
| `as` | `AsTag \| Component`: `ComponentOptions<any, any, any, ComputedOptions, MethodOptions, any, any, any, string, {}, {}, string, {}, {}, {}, string, ComponentProvideOptions> \| (props: any, ctx: Omit<{ attrs: Attrs; slots: Readonly<InternalSlots>; emit: (event: string, ...args: any[]) => void; expose: <Exposed extends Record<string, any> = Record<string, any>>(exposed?: Exposed \| undefined) => void; }, 'expose'>): any \| ComponentPublicInstanceConstructor<any, any, any, any, ComputedOptions, MethodOptions> \| 'a' \| 'button' \| 'div' \| 'form' \| 'h2' \| 'h3' \| 'img' \| 'input' \| 'label' \| 'li' \| 'nav' \| 'ol' \| 'p' \| 'span' \| 'svg' \| 'ul' \| 'template' \| {} & string` | `'div'` | The element or component this component should render as. Can be overwritten by `asChild`. |
| `class` | `ClassValue` |  | Classes added to the part's own element, after its recipe classes. |

#### FieldValidity

Renders from the validation state of a field, such as a custom message or a strength meter.

| Slot | Slot props | Description |
| --- | --- | --- |
| `default` | `{ validity: Omit<Record<keyof ValidityState, boolean>, "valid"> & { valid: boolean \| null; }; errors: string[]; error: string; value: unknown; initialValue: unknown; }` | Gets the field's `validity` (`valid` is `null` until there is one), its `errors`, the first `error`, the `value` validated last and the `initialValue`. |
