Combobox
<script setup lang="ts">
import { ref } from 'vue'
import { ComboboxContent, ComboboxEmpty, ComboboxGroup, ComboboxHeader, ComboboxInput, ComboboxItem, ComboboxItemIndicator, ComboboxLabel, ComboboxRoot, ComboboxSeparator, ComboboxTrigger, ComboboxViewport } from 'radix-vue'
import { Icon } from '@iconify/vue'
const v = ref('')
const options = ['Apple', 'Banana', 'Blueberry', 'Grapes', 'Pineapple']
const vegetables = ['Aubergine', 'Broccoli', 'Carrot', 'Courgette', 'Leek']
</script>
<template>
<ComboboxRoot v-model="v" class="relative">
<ComboboxHeader class="min-w-[160px] inline-flex items-center justify-between rounded px-[15px] text-[13px] leading-none h-[35px] gap-[5px] bg-white text-grass11 shadow-[0_2px_10px] shadow-black/10 hover:bg-mauve3 focus:shadow-[0_0_0_2px] focus:shadow-black data-[placeholder]:text-grass9 outline-none">
<ComboboxInput class="bg-transparent outline-none text-grass11 h-full selection:bg-grass5 placeholder-mauve8" placeholder="Placeholder..." />
<ComboboxTrigger>
<Icon icon="radix-icons:chevron-down" class="h-4 w-4 text-grass11" />
</ComboboxTrigger>
</ComboboxHeader>
<ComboboxContent class="absolute z-10 w-full mt-2 min-w-[160px] bg-white overflow-hidden rounded shadow-[0px_10px_38px_-10px_rgba(22,_23,_24,_0.35),_0px_10px_20px_-15px_rgba(22,_23,_24,_0.2)] will-change-[opacity,transform] data-[side=top]:animate-slideDownAndFade data-[side=right]:animate-slideLeftAndFade data-[side=bottom]:animate-slideUpAndFade data-[side=left]:animate-slideRightAndFade">
<ComboboxViewport class="p-[5px]">
<ComboboxEmpty class="text-mauve8 text-xs font-medium text-center py-2" />
<ComboboxGroup>
<ComboboxLabel class="px-[25px] text-xs leading-[25px] text-mauve11">
Fruits
</ComboboxLabel>
<ComboboxItem
v-for="(option, index) in options" :key="index"
class="text-[13px] leading-none text-grass11 rounded-[3px] flex items-center h-[25px] pr-[35px] pl-[25px] relative select-none data-[disabled]:text-mauve8 data-[disabled]:pointer-events-none data-[highlighted]:outline-none data-[highlighted]:bg-grass9 data-[highlighted]:text-grass1"
:value="option"
>
<ComboboxItemIndicator
class="absolute left-0 w-[25px] inline-flex items-center justify-center"
>
<Icon icon="radix-icons:check" />
</ComboboxItemIndicator>
<span>
{{ option }}
</span>
</ComboboxItem>
<ComboboxSeparator class="h-[1px] bg-grass6 m-[5px]" />
</ComboboxGroup>
<ComboboxGroup>
<ComboboxLabel
class="px-[25px] text-xs leading-[25px] text-mauve11"
>
Vegetables
</ComboboxLabel>
<ComboboxItem
v-for="(option, index) in vegetables" :key="index"
class="text-[13px] leading-none text-grass11 rounded-[3px] flex items-center h-[25px] pr-[35px] pl-[25px] relative select-none data-[disabled]:text-mauve8 data-[disabled]:pointer-events-none data-[highlighted]:outline-none data-[highlighted]:bg-grass9 data-[highlighted]:text-grass1"
:value="option"
>
<ComboboxItemIndicator
class="absolute left-0 w-[25px] inline-flex items-center justify-center"
>
<Icon icon="radix-icons:check" />
</ComboboxItemIndicator>
<span>
{{ option }}
</span>
</ComboboxItem>
</ComboboxGroup>
</ComboboxViewport>
</ComboboxContent>
</ComboboxRoot>
</template>
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.
npm install radix-vue
Anatomy
Import all parts and piece them together.
<script setup lang="ts">
import {
ComboboxArrow,
ComboboxCancel,
ComboboxContent,
ComboboxEmpty,
ComboboxGroup,
ComboboxHeader,
ComboboxInput,
ComboboxItem,
ComboboxItemIndicator,
ComboboxLabel,
ComboboxPortal,
ComboboxRoot,
ComboboxSeparator,
ComboboxTrigger,
ComboboxViewport,
} from 'radix-vue'
</script>
<template>
<ComboboxRoot>
<ComboboxHeader>
<ComboboxInput />
<ComboboxTrigger />
<ComboboxCancel />
</ComboboxHeader>
<ComboboxPortal>
<ComboboxContent>
<ComboboxViewport>
<ComboboxEmpty />
<ComboboxItem>
<ComboboxItemIndicator />
</ComboboxItem>
<ComboboxGroup>
<ComboboxLabel />
<ComboboxItem>
<ComboboxItemIndicator />
</ComboboxItem>
</ComboboxGroup>
<ComboboxSeparator />
</ComboboxViewport>
<ComboboxArrow />
</ComboboxContent>
</ComboboxPortal>
</ComboboxRoot>
</template>
API Reference
Root
Contains all the parts of a Combobox
Prop | Type | Default |
---|---|---|
defaultValue | string | string[] | object | object[] | |
modelValue | string | string[] | object | object[] | |
defaultOpen | boolean | |
open | boolean | |
searchTerm | string | |
multiple | boolean | |
dir | enum | |
name | string | |
disabled | boolean |
Emit | Type |
---|---|
@update:modelValue | (value: string) => void |
@update:open | (open: boolean) => void |
@update:searchTerm | (value: string) => void |
Header
The header section of Combobox. Used as an anchor if you set ComboboxContent
's position to popper
.
Prop | Type | Default |
---|---|---|
asChild | boolean | false |
Input
The input component to search through the combobox items.
Trigger
The button that toggles the Combobox Content.
Prop | Type | Default |
---|---|---|
asChild | boolean | false |
Data Attribute | Value |
---|---|
[data-state] | "open" | "closed" |
[data-disabled] | Present when disabled |
Cancel
The button that clears the search term.
Prop | Type | Default |
---|---|---|
asChild | boolean | false |
Portal
When used, portals the content part into the body
.
Prop | Type | Default |
---|---|---|
to | string | HTMLElement | body |
Content
The component that pops out when the combobox is open.
Prop | Type | Default |
---|---|---|
position | enum | "inline" |
bodyLock | boolean | false |
disableOutsidePointerEvents | boolean | false |
side | enum | "bottom" |
sideOffset | number | 0 |
align | enum | "start" |
alignOffset | number | 0 |
avoidCollisions | boolean | true |
collisionBoundary | Boundary | [] |
collisionPadding | number | Padding | 10 |
arrowPadding | number | 0 |
sticky | enum | "partial" |
hideWhenDetached | boolean | false |
asChild | boolean | false |
Emit | Type |
---|---|
@closeAutoFocus | (event: Event) => void |
@escapeKeyDown | (event: KeyboardEvent) => void |
@pointerDownOutside | (event: PointerDownOutsideEvent) => void |
Data Attribute | Value |
---|---|
[data-state] | "open" | "closed" |
[data-side] | "left" | "right" | "bottom" | "top" |
[data-align] | "start" | "end" | "center" |
CSS Variable | Description |
---|---|
--radix-combobox-content-transform-origin | The transform-origin computed from the content and arrow positions/offsets. Only present when position="popper" . |
--radix-combobox-content-available-width | The remaining width between the trigger and the boundary edge. Only present when position="popper" . |
--radix-combobox-content-available-height | The remaining height between the trigger and the boundary edge. Only present when position="popper" . |
--radix-combobox-trigger-width | The width of the trigger. Only present when position="popper" . |
--radix-combobox-trigger-height | The height of the trigger. Only present when position="popper" . |
Viewport
The scrolling viewport that contains all of the items.
Prop | Type | Default |
---|---|---|
asChild | boolean | false |
Item
The component that contains the combobox items.
Prop | Type | Default |
---|---|---|
value* | string | |
disabled | boolean | |
asChild | boolean | false |
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.
Prop | Type | Default |
---|---|---|
asChild | boolean | false |
Group
Used to group multiple items. use in conjunction with ComboboxLabel
to ensure good accessibility via automatic labelling.
Prop | Type | Default |
---|---|---|
asChild | boolean | false |
Label
Used to render the label of a group. It won't be focusable using arrow keys.
Prop | Type | Default |
---|---|---|
asChild | boolean | false |
Separator
Used to visually separate items in the Combobox
Prop | Type | Default |
---|---|---|
asChild | boolean | false |
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
.
Prop | Type | Default |
---|---|---|
asChild | boolean | false |
width | number | 10 |
height | number | 5 |