charcell 0.1.0
mode

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' }}
    />
  );
}

as text

at rest
┌────────────────────────┐
│ ride with            ▾ │
└────────────────────────┘
open
┌──────────┐
│ o      ▾ │
├──────────┴───┐
│ polecats     │
│❯rottwheelers │
└──────────────┘
open above
┌──────────────┐
│ polecats     │
│❯rottwheelers │
├──────────┬───┘
│ o      ▾ │
└──────────┘
open empty
┌──────────┐
│ xyz    ▾ │
├──────────┴─┐
│ no matches │
└────────────┘

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:value in vue, bind:value in svelte
defaultValuestring
Uncontrolled initial value.
onValueChange(value: string) => void
Called with the newly chosen value.
placeholderstring
Shown in mid while 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's htmlFor.
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-label for 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'
boxed draws the ring and attaches the list to it; dense is 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, double or none.
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 borderY and border.
borderEnd'none' | 'single' | 'rounded' | 'heavy' | 'double'
The style of the boxed field's and list's rings' end side, over borderX and border.
borderBottom'none' | 'single' | 'rounded' | 'heavy' | 'double'
The style of the boxed field's and list's rings' bottom side, over borderY and border.
borderStart'none' | 'single' | 'rounded' | 'heavy' | 'double'
The style of the boxed field's and list's rings' start side, over borderX and border.

ComboboxField

variant'boxed' | 'dense'= 'boxed'
boxed draws the ring around the field; dense is 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, double or none.
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 borderY and border.
borderEnd'none' | 'single' | 'rounded' | 'heavy' | 'double'
The style of the boxed ring's end side, over borderX and border.
borderBottom'none' | 'single' | 'rounded' | 'heavy' | 'double'
The style of the boxed ring's bottom side, over borderY and border.
borderStart'none' | 'single' | 'rounded' | 'heavy' | 'double'
The style of the boxed ring's start side, over borderX and border.

it also takes any other attribute of its <div>.