charcell 0.1.0
mode

Select

one choice out of a list, in a listbox drawn like the rest of charcell.

usage

example

code

import { Select } from 'charcell/react';

export function SelectExample() {
  return (
    <Select
      items={[
        { value: 'polecats', label: 'polecats' },
        { value: 'vultures', label: 'vultures' },
        { value: 'cavefish', label: 'cavefish' },
        { value: 'rottwheelers', label: 'rottwheelers' },
      ]}
      placeholder="ride with"
      triggerProps={{ 'aria-label': 'gang' }}
    />
  );
}

as text

at rest
┌────────────────┐
│ ride with    ▾ │
└────────────────┘
hover
┌────────────────┐
│ ride with    ▾ │
└────────────────┘
focus
┌────────────────┐
│❯ride with    ▾ │
└────────────────┘
open
┌────────────────┐
│ polecats     ▾ │
├────────────────┤
│ polecats       │
│ vultures       │
│ cavefish       │
│❯rottwheelers   │
└────────────────┘
open above
┌────────────────┐
│ polecats       │
│ vultures       │
│ cavefish       │
│❯rottwheelers   │
├────────────────┤
│ polecats     ▾ │
└────────────────┘

props

Select

direction'ltr' | 'rtl'
The reading direction its keys and placement follow ('rtl' mirrors the arrow keys); the page's, once mounted, when unset.
itemsSelectItem[]
The choices, in order: { value, label, disabled }.
valuestring | number
Controlled selected value; pair it with onValueChange. A number-valued item's value is a number.
binds with v-model:value in vue, bind:value in svelte
defaultValuestring | number
Uncontrolled initial value.
onValueChange(value: string | number) => void
Called with the newly selected value, a number for a number-valued item.
openboolean
Controlled open state; pair it with onOpenChange.
binds with v-model:open in vue, bind:open in svelte
defaultOpenboolean
Uncontrolled initial open state.
onOpenChange(open: boolean) => void
Called with the next open state on every open or close.
closeOnSelectboolean= true
Closes the listbox once an item is chosen; false keeps it open while the reader browses.
placeholderstring
Shown in mid while nothing is selected.
idstring
The trigger's id, for a Field's htmlFor; the trigger is then named by the Field's label, <id>-label.
namestring
The form field name; the value submits through a hidden <select>.
requiredboolean
The value is required for the form to submit.
formstring
The id of the form the value belongs to, for a select outside its <form>.
triggerPropsRecord<string, unknown>
Merged over the machine's trigger props: an aria-label for a Select with no visible label.
disabledboolean
Disables the trigger.
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 listbox to it; dense is one bare 16px row, which misses WCAG 2.5.8's 24px target; boxed meets it.
fit'items' | 'value'= 'items'
The trigger's width: its longest item's (items), as a native select's, or its chosen value's (value), the listbox still opening as wide as its items.
placementPlacement
Where the listbox opens against its trigger, as a Zag placement ('bottom-start' when unset).
border'none' | 'single' | 'rounded' | 'heavy' | 'double'
The style of every side of the boxed trigger's and listbox's rings: single, rounded, heavy, double or none.
borderX'none' | 'single' | 'rounded' | 'heavy' | 'double'
The style of the boxed trigger's and listbox's rings's start and end sides, over border.
borderY'none' | 'single' | 'rounded' | 'heavy' | 'double'
The style of the boxed trigger's and listbox's rings's top and bottom sides, over border.
borderTop'none' | 'single' | 'rounded' | 'heavy' | 'double'
The style of the boxed trigger's and listbox's rings's top side, over borderY and border.
borderEnd'none' | 'single' | 'rounded' | 'heavy' | 'double'
The style of the boxed trigger's and listbox's rings's end side, over borderX and border.
borderBottom'none' | 'single' | 'rounded' | 'heavy' | 'double'
The style of the boxed trigger's and listbox's rings's bottom side, over borderY and border.
borderStart'none' | 'single' | 'rounded' | 'heavy' | 'double'
The style of the boxed trigger's and listbox's rings's start side, over borderX and border.

SelectListbox

attachedboolean
Fuses the listbox to a boxed trigger: it moves one row onto it and shares its stroke.
spaciousboolean
Each item takes two rows, its text in the first: a 32px target, which meets WCAG 2.5.8.
aboveboolean
Opened above the trigger, so an attached listbox shares the trigger's top stroke.
border'none' | 'single' | 'rounded' | 'heavy' | 'double'
The style of every side of the ring: single, rounded, heavy, double or none.
borderX'none' | 'single' | 'rounded' | 'heavy' | 'double'
The style of the ring's start and end sides, over border.
borderY'none' | 'single' | 'rounded' | 'heavy' | 'double'
The style of the ring's top and bottom sides, over border.
borderTop'none' | 'single' | 'rounded' | 'heavy' | 'double'
The style of the ring's top side, over borderY and border.
borderEnd'none' | 'single' | 'rounded' | 'heavy' | 'double'
The style of the ring's end side, over borderX and border.
borderBottom'none' | 'single' | 'rounded' | 'heavy' | 'double'
The style of the ring's bottom side, over borderY and border.
borderStart'none' | 'single' | 'rounded' | 'heavy' | 'double'
The style of the ring's start side, over borderX and border.

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

slots

in react, the default slot is children and each named slot a prop of its name, a function where the slot hands values; in vue, a slot; in svelte, a snippet.

SelectListbox

default