Combobox
one choice out of a long list, narrowed as the reader types.
usage
example
code
import { Combobox } from 'charcell/react';
export function ComboboxExample() {
return (
<Combobox
items={[
{ value: 'polecats', label: 'polecats' },
{ value: 'vultures', label: 'vultures' },
{ value: 'cavefish', label: 'cavefish' },
{ value: 'rottwheelers', label: 'rottwheelers' },
]}
placeholder="ride with"
inputProps={{ 'aria-label': 'gang' }}
/>
);
}▴
▾
<script setup lang="ts">
import { Combobox } from 'charcell/vue';
</script>
<template>
<Combobox
:items="[
{ value: 'polecats', label: 'polecats' },
{ value: 'vultures', label: 'vultures' },
{ value: 'cavefish', label: 'cavefish' },
{ value: 'rottwheelers', label: 'rottwheelers' },
]"
placeholder="ride with"
:inputProps="{ 'aria-label': 'gang' }"
/>
</template>▴
▾
<script lang="ts">
import { Combobox } from 'charcell/svelte';
</script>
<Combobox
items={[
{ value: 'polecats', label: 'polecats' },
{ value: 'vultures', label: 'vultures' },
{ value: 'cavefish', label: 'cavefish' },
{ value: 'rottwheelers', label: 'rottwheelers' },
]}
placeholder="ride with"
inputProps={{ 'aria-label': 'gang' }}
/>▴
▾
<!-- component: ComboboxDriver (behavior not included) -->
<div class="CharcellComboboxField CharcellComboboxField--boxed">
<input class="CharcellComboboxField__input" /><button
class="CharcellComboboxField__button"
type="button"
>
<span aria-hidden="true">▾</span>
</button>
</div>
<!-- /component -->▴
▾
import { Combobox } from 'charcell/react';
export function ComboboxExample() {
return (
<Combobox
items={[
{ value: 'polecats', label: 'polecats' },
{ value: 'vultures', label: 'vultures' },
{ value: 'cavefish', label: 'cavefish' },
{ value: 'rottwheelers', label: 'rottwheelers' },
]}
placeholder="ride with"
inputProps={{ 'aria-label': 'gang' }}
disabled
/>
);
}▴
▾
<script setup lang="ts">
import { Combobox } from 'charcell/vue';
</script>
<template>
<Combobox
:items="[
{ value: 'polecats', label: 'polecats' },
{ value: 'vultures', label: 'vultures' },
{ value: 'cavefish', label: 'cavefish' },
{ value: 'rottwheelers', label: 'rottwheelers' },
]"
placeholder="ride with"
:inputProps="{ 'aria-label': 'gang' }"
disabled
/>
</template>▴
▾
<script lang="ts">
import { Combobox } from 'charcell/svelte';
</script>
<Combobox
items={[
{ value: 'polecats', label: 'polecats' },
{ value: 'vultures', label: 'vultures' },
{ value: 'cavefish', label: 'cavefish' },
{ value: 'rottwheelers', label: 'rottwheelers' },
]}
placeholder="ride with"
inputProps={{ 'aria-label': 'gang' }}
disabled
/>▴
▾
<!-- component: ComboboxDriver (behavior not included) -->
<div class="CharcellComboboxField CharcellComboboxField--boxed">
<input class="CharcellComboboxField__input" /><button
class="CharcellComboboxField__button"
type="button"
>
<span aria-hidden="true">▾</span>
</button>
</div>
<!-- /component -->▴
▾
import { Combobox } from 'charcell/react';
export function ComboboxExample() {
return (
<Combobox
items={[
{ value: 'polecats', label: 'polecats' },
{ value: 'vultures', label: 'vultures' },
{ value: 'cavefish', label: 'cavefish' },
{ value: 'rottwheelers', label: 'rottwheelers' },
]}
placeholder="ride with"
inputProps={{ 'aria-label': 'gang' }}
spacious
/>
);
}▴
▾
<script setup lang="ts">
import { Combobox } from 'charcell/vue';
</script>
<template>
<Combobox
:items="[
{ value: 'polecats', label: 'polecats' },
{ value: 'vultures', label: 'vultures' },
{ value: 'cavefish', label: 'cavefish' },
{ value: 'rottwheelers', label: 'rottwheelers' },
]"
placeholder="ride with"
:inputProps="{ 'aria-label': 'gang' }"
spacious
/>
</template>▴
▾
<script lang="ts">
import { Combobox } from 'charcell/svelte';
</script>
<Combobox
items={[
{ value: 'polecats', label: 'polecats' },
{ value: 'vultures', label: 'vultures' },
{ value: 'cavefish', label: 'cavefish' },
{ value: 'rottwheelers', label: 'rottwheelers' },
]}
placeholder="ride with"
inputProps={{ 'aria-label': 'gang' }}
spacious
/>▴
▾
<!-- component: ComboboxDriver (behavior not included) -->
<div class="CharcellComboboxField CharcellComboboxField--boxed">
<input class="CharcellComboboxField__input" /><button
class="CharcellComboboxField__button"
type="button"
>
<span aria-hidden="true">▾</span>
</button>
</div>
<!-- /component -->▴
▾
import { Combobox } from 'charcell/react';
export function ComboboxExample() {
return (
<Combobox
items={[
{ value: 'polecats', label: 'polecats' },
{ value: 'vultures', label: 'vultures' },
{ value: 'cavefish', label: 'cavefish' },
{ value: 'rottwheelers', label: 'rottwheelers' },
]}
placeholder="ride with"
inputProps={{ 'aria-label': 'gang' }}
variant="dense"
/>
);
}▴
▾
<script setup lang="ts">
import { Combobox } from 'charcell/vue';
</script>
<template>
<Combobox
:items="[
{ value: 'polecats', label: 'polecats' },
{ value: 'vultures', label: 'vultures' },
{ value: 'cavefish', label: 'cavefish' },
{ value: 'rottwheelers', label: 'rottwheelers' },
]"
placeholder="ride with"
:inputProps="{ 'aria-label': 'gang' }"
variant="dense"
/>
</template>▴
▾
<script lang="ts">
import { Combobox } from 'charcell/svelte';
</script>
<Combobox
items={[
{ value: 'polecats', label: 'polecats' },
{ value: 'vultures', label: 'vultures' },
{ value: 'cavefish', label: 'cavefish' },
{ value: 'rottwheelers', label: 'rottwheelers' },
]}
placeholder="ride with"
inputProps={{ 'aria-label': 'gang' }}
variant="dense"
/>▴
▾
<!-- component: ComboboxDriver (behavior not included) -->
<div class="CharcellComboboxField CharcellComboboxField--dense">
<input class="CharcellComboboxField__input" /><button
class="CharcellComboboxField__button"
type="button"
>
<span aria-hidden="true">▾</span>
</button>
</div>
<!-- /component -->▴
▾
import { Combobox } from 'charcell/react';
export function ComboboxExample() {
return (
<Combobox
items={[
{ value: 'polecats', label: 'polecats' },
{ value: 'vultures', label: 'vultures' },
{ value: 'cavefish', label: 'cavefish' },
{ value: 'rottwheelers', label: 'rottwheelers' },
]}
placeholder="ride with"
inputProps={{ 'aria-label': 'gang' }}
border="none"
/>
);
}▴
▾
<script setup lang="ts">
import { Combobox } from 'charcell/vue';
</script>
<template>
<Combobox
:items="[
{ value: 'polecats', label: 'polecats' },
{ value: 'vultures', label: 'vultures' },
{ value: 'cavefish', label: 'cavefish' },
{ value: 'rottwheelers', label: 'rottwheelers' },
]"
placeholder="ride with"
:inputProps="{ 'aria-label': 'gang' }"
border="none"
/>
</template>▴
▾
<script lang="ts">
import { Combobox } from 'charcell/svelte';
</script>
<Combobox
items={[
{ value: 'polecats', label: 'polecats' },
{ value: 'vultures', label: 'vultures' },
{ value: 'cavefish', label: 'cavefish' },
{ value: 'rottwheelers', label: 'rottwheelers' },
]}
placeholder="ride with"
inputProps={{ 'aria-label': 'gang' }}
border="none"
/>▴
▾
<!-- component: ComboboxDriver (behavior not included) -->
<div
class="CharcellComboboxField CharcellComboboxField--boxed CharcellComboboxField--border-top-none CharcellComboboxField--border-end-none CharcellComboboxField--border-bottom-none CharcellComboboxField--border-start-none"
>
<input class="CharcellComboboxField__input" /><button
class="CharcellComboboxField__button"
type="button"
>
<span aria-hidden="true">▾</span>
</button>
</div>
<!-- /component -->▴
▾
import { Combobox } from 'charcell/react';
export function ComboboxExample() {
return (
<Combobox
items={[
{ value: 'polecats', label: 'polecats' },
{ value: 'vultures', label: 'vultures' },
{ value: 'cavefish', label: 'cavefish' },
{ value: 'rottwheelers', label: 'rottwheelers' },
]}
placeholder="ride with"
inputProps={{ 'aria-label': 'gang' }}
border="rounded"
/>
);
}▴
▾
<script setup lang="ts">
import { Combobox } from 'charcell/vue';
</script>
<template>
<Combobox
:items="[
{ value: 'polecats', label: 'polecats' },
{ value: 'vultures', label: 'vultures' },
{ value: 'cavefish', label: 'cavefish' },
{ value: 'rottwheelers', label: 'rottwheelers' },
]"
placeholder="ride with"
:inputProps="{ 'aria-label': 'gang' }"
border="rounded"
/>
</template>▴
▾
<script lang="ts">
import { Combobox } from 'charcell/svelte';
</script>
<Combobox
items={[
{ value: 'polecats', label: 'polecats' },
{ value: 'vultures', label: 'vultures' },
{ value: 'cavefish', label: 'cavefish' },
{ value: 'rottwheelers', label: 'rottwheelers' },
]}
placeholder="ride with"
inputProps={{ 'aria-label': 'gang' }}
border="rounded"
/>▴
▾
<!-- component: ComboboxDriver (behavior not included) -->
<div
class="CharcellComboboxField CharcellComboboxField--boxed CharcellComboboxField--border-top-rounded CharcellComboboxField--border-end-rounded CharcellComboboxField--border-bottom-rounded CharcellComboboxField--border-start-rounded"
>
<input class="CharcellComboboxField__input" /><button
class="CharcellComboboxField__button"
type="button"
>
<span aria-hidden="true">▾</span>
</button>
</div>
<!-- /component -->▴
▾
import { Combobox } from 'charcell/react';
export function ComboboxExample() {
return (
<Combobox
items={[
{ value: 'polecats', label: 'polecats' },
{ value: 'vultures', label: 'vultures' },
{ value: 'cavefish', label: 'cavefish' },
{ value: 'rottwheelers', label: 'rottwheelers' },
]}
placeholder="ride with"
inputProps={{ 'aria-label': 'gang' }}
border="heavy"
/>
);
}▴
▾
<script setup lang="ts">
import { Combobox } from 'charcell/vue';
</script>
<template>
<Combobox
:items="[
{ value: 'polecats', label: 'polecats' },
{ value: 'vultures', label: 'vultures' },
{ value: 'cavefish', label: 'cavefish' },
{ value: 'rottwheelers', label: 'rottwheelers' },
]"
placeholder="ride with"
:inputProps="{ 'aria-label': 'gang' }"
border="heavy"
/>
</template>▴
▾
<script lang="ts">
import { Combobox } from 'charcell/svelte';
</script>
<Combobox
items={[
{ value: 'polecats', label: 'polecats' },
{ value: 'vultures', label: 'vultures' },
{ value: 'cavefish', label: 'cavefish' },
{ value: 'rottwheelers', label: 'rottwheelers' },
]}
placeholder="ride with"
inputProps={{ 'aria-label': 'gang' }}
border="heavy"
/>▴
▾
<!-- component: ComboboxDriver (behavior not included) -->
<div
class="CharcellComboboxField CharcellComboboxField--boxed CharcellComboboxField--border-top-heavy CharcellComboboxField--border-end-heavy CharcellComboboxField--border-bottom-heavy CharcellComboboxField--border-start-heavy"
>
<input class="CharcellComboboxField__input" /><button
class="CharcellComboboxField__button"
type="button"
>
<span aria-hidden="true">▾</span>
</button>
</div>
<!-- /component -->▴
▾
import { Combobox } from 'charcell/react';
export function ComboboxExample() {
return (
<Combobox
items={[
{ value: 'polecats', label: 'polecats' },
{ value: 'vultures', label: 'vultures' },
{ value: 'cavefish', label: 'cavefish' },
{ value: 'rottwheelers', label: 'rottwheelers' },
]}
placeholder="ride with"
inputProps={{ 'aria-label': 'gang' }}
border="double"
/>
);
}▴
▾
<script setup lang="ts">
import { Combobox } from 'charcell/vue';
</script>
<template>
<Combobox
:items="[
{ value: 'polecats', label: 'polecats' },
{ value: 'vultures', label: 'vultures' },
{ value: 'cavefish', label: 'cavefish' },
{ value: 'rottwheelers', label: 'rottwheelers' },
]"
placeholder="ride with"
:inputProps="{ 'aria-label': 'gang' }"
border="double"
/>
</template>▴
▾
<script lang="ts">
import { Combobox } from 'charcell/svelte';
</script>
<Combobox
items={[
{ value: 'polecats', label: 'polecats' },
{ value: 'vultures', label: 'vultures' },
{ value: 'cavefish', label: 'cavefish' },
{ value: 'rottwheelers', label: 'rottwheelers' },
]}
placeholder="ride with"
inputProps={{ 'aria-label': 'gang' }}
border="double"
/>▴
▾
<!-- component: ComboboxDriver (behavior not included) -->
<div
class="CharcellComboboxField CharcellComboboxField--boxed CharcellComboboxField--border-top-double CharcellComboboxField--border-end-double CharcellComboboxField--border-bottom-double CharcellComboboxField--border-start-double"
>
<input class="CharcellComboboxField__input" /><button
class="CharcellComboboxField__button"
type="button"
>
<span aria-hidden="true">▾</span>
</button>
</div>
<!-- /component -->▴
▾
as text
┌────────────────────────┐ │ ride with ▾ │ └────────────────────────┘
┌──────────┐ │ o ▾ │ ├──────────┴───┐ │ polecats │ │❯rottwheelers │ └──────────────┘
┌──────────────┐ │ polecats │ │❯rottwheelers │ ├──────────┬───┘ │ o ▾ │ └──────────┘
┌──────────┐ │ xyz ▾ │ ├──────────┴─┐ │ no matches │ └────────────┘
┌────────────────────────┐ │ ride with ▾ │ └────────────────────────┘
┌────────────────────────┐ │ ride with ▾ │ └────────────────────────┘
┌──────────┐ │ o ▾ │ ├──────────┴───┐ │ polecats │ │ │ │❯rottwheelers │ │ │ └──────────────┘
ride with ▾
o ▾ ┌──────────────┐ │ polecats │ │❯rottwheelers │ └──────────────┘
ride with ▾
o ▾ polecats ❯rottwheelers
╭────────────────────────╮ │ ride with ▾ │ ╰────────────────────────╯
╭──────────╮ │ o ▾ │ ├──────────┴───╮ │ polecats │ │❯rottwheelers │ ╰──────────────╯
┏━━━━━━━━━━━━━━━━━━━━━━━━┓ ┃ ride with ▾ ┃ ┗━━━━━━━━━━━━━━━━━━━━━━━━┛
┏━━━━━━━━━━┓ ┃ o ▾ ┃ ┣━━━━━━━━━━┻━━━┓ ┃ polecats ┃ ┃❯rottwheelers ┃ ┗━━━━━━━━━━━━━━┛
╔════════════════════════╗ ║ ride with ▾ ║ ╚════════════════════════╝
╔══════════╗ ║ o ▾ ║ ╠══════════╩═══╗ ║ polecats ║ ║❯rottwheelers ║ ╚══════════════╝
props
Combobox
- direction'ltr' | 'rtl'
- The reading direction its keys and placement follow (
'rtl'mirrors the arrow keys); the page's, once mounted, when unset. - itemsComboboxItem[]
- The choices, in order:
{ value, label, disabled }. - valuestring
- Controlled chosen value; pair it with
onValueChange. - binds with
v-model:valuein vue,bind:valuein svelte - defaultValuestring
- Uncontrolled initial value.
- onValueChange(value: string) => void
- Called with the newly chosen value.
- placeholderstring
- Shown in
midwhile the field is empty. - translationsComboboxTranslations
- What the combobox says: the list's one row when nothing matches (
noMatchesMessage) and its button's accessible name (triggerLabel). - idstring
- The input's id, for a
Field'shtmlFor. - namestring
- The form field name: the chosen item's value submits under it, from a hidden input, and text that chooses no item submits nothing.
- formstring
- The id of the form the value belongs to, for a combobox outside its
<form>. - inputPropsRecord<string, unknown>
- Merged over the machine's input props: an
aria-labelfor a combobox with no visible label. - disabledboolean
- Disables the field.
- spaciousboolean
- Gives each item two rows, its text in the first: a 32px target, which meets WCAG 2.5.8. One-row items miss it.
- variant'boxed' | 'dense'= 'boxed'
boxeddraws the ring and attaches the list to it;denseis one bare 16px row, as a dense Select, which misses WCAG 2.5.8's 24px target; boxed meets it.- placementPlacement
- Where the list opens against the field, as a Zag placement (
'bottom-start'when unset). - localestring
- The locale the list narrows in, a BCP 47 tag (
'tr','sv'): case and accents fold by its rules. The runtime's own when unset. - border'none' | 'single' | 'rounded' | 'heavy' | 'double'
- The style of every side of the boxed field's and list's rings:
single,rounded,heavy,doubleornone. - borderX'none' | 'single' | 'rounded' | 'heavy' | 'double'
- The style of the boxed field's and list's rings' start and end sides, over
border. - borderY'none' | 'single' | 'rounded' | 'heavy' | 'double'
- The style of the boxed field's and list's rings' top and bottom sides, over
border. - borderTop'none' | 'single' | 'rounded' | 'heavy' | 'double'
- The style of the boxed field's and list's rings' top side, over
borderYandborder. - borderEnd'none' | 'single' | 'rounded' | 'heavy' | 'double'
- The style of the boxed field's and list's rings' end side, over
borderXandborder. - borderBottom'none' | 'single' | 'rounded' | 'heavy' | 'double'
- The style of the boxed field's and list's rings' bottom side, over
borderYandborder. - borderStart'none' | 'single' | 'rounded' | 'heavy' | 'double'
- The style of the boxed field's and list's rings' start side, over
borderXandborder.
ComboboxField
- variant'boxed' | 'dense'= 'boxed'
boxeddraws the ring around the field;denseis one bare row, as a dense Select.- openboolean
- The list is open: the field is engaged.
- aboveboolean
- The list opened above, so the attached one shares the top row, not the bottom.
- inputPropsobject
- The
<input>'s props: the machine's, with the value and placeholder. - buttonPropsobject
- The
▾button's props: the machine's trigger props. - border'none' | 'single' | 'rounded' | 'heavy' | 'double'
- The style of every side of the boxed ring:
single,rounded,heavy,doubleornone. - borderX'none' | 'single' | 'rounded' | 'heavy' | 'double'
- The style of the boxed ring's start and end sides, over
border. - borderY'none' | 'single' | 'rounded' | 'heavy' | 'double'
- The style of the boxed ring's top and bottom sides, over
border. - borderTop'none' | 'single' | 'rounded' | 'heavy' | 'double'
- The style of the boxed ring's top side, over
borderYandborder. - borderEnd'none' | 'single' | 'rounded' | 'heavy' | 'double'
- The style of the boxed ring's end side, over
borderXandborder. - borderBottom'none' | 'single' | 'rounded' | 'heavy' | 'double'
- The style of the boxed ring's bottom side, over
borderYandborder. - borderStart'none' | 'single' | 'rounded' | 'heavy' | 'double'
- The style of the boxed ring's start side, over
borderXandborder.
it also takes any other attribute of its <div>.
▴
▾