Select
A headless select with combobox + listbox pattern. Interop-first defaults: modal={false}, portal={false}. Pointer open keeps focus on the trigger; keyboard open moves focus into the listbox. Supports single and multiple selection, items prop for label maps, and Select.HiddenSelect for native form submission.
Examples
You can explore the select primitive in the following curated examples. Every demo below is fully interactive and keyboard-navigable.
Default
Inside a Dialog
Kenos defaults to portal={false} and modal={false} so the listbox stays in the Dialog subtree. Escape closes the Select only (stopPropagation, scoped to content focus) — the parent dialog stays open. Pointer open keeps focus on the trigger; keyboard open moves focus into the listbox with aria-activedescendant.
Settings
Forms
Add name on Select.Root and render Select.HiddenSelect for native HTML submit and constraint validation.
Form Integration
Bind value and onValueChange to your form library. All examples validate with Zod.
Multiple selection
Pass multiple on Select.Root to enable multi-select. Items toggle on click and the listbox stays open. Value shape becomes string[].
Portal & container
Use portal={true} on Select.Content when clipping is an issue. Inside a Dialog, pass a container ref to keep the listbox in the Dialog subtree while escaping overflow: hidden.
Dialog.Content (portal container)
API Reference
Props, data attributes, and keyboard interactions for Select. Import from @kenos-ui/react-select; parts use data-part and data-* attributes for styling.
Root props
Controlled/uncontrolled selected value. string[] when multiple={true}.
Listbox open state.
Forwarded to Select.HiddenSelect for form submit.
Root constraints.
falseOpt-in focus trap + aria-modal on Content. Renders Select.Backdrop.
falseMulti-select mode. Toggle items on click; listbox stays open.
Value → label map. Resolves Select.Value labels without rendering every Item.
Custom string comparator for selection matching (default: ===). Not for object values.
falseOpen the listbox when the trigger receives focus. Does not reopen after Escape/select restore focus.
Content props
falsePortal to document.body — avoid inside Dialogs.
falseOffset content to cover the trigger (by trigger height). Does not scroll the selected item into alignment. On Safari pinch-zoom, automatically falls back to standard anchoring.
Custom portal target (e.g. Dialog.Content ref). Requires portal={true}.
Floating UI positioning via @kenos-ui/utils.
trueSkip DOM until first open.
Fires when open transitions finish, including presence exit.
Parts (Tier 2–4)
Clears the current value without opening the listbox. Place as a sibling of Trigger (not nested inside the button).
Scroll the list when options overflow. Auto-hidden when not needed.
Programmatically scroll the list to an item index.
Data attributes
| Attribute | On part | Description |
|---|---|---|
| [data-open] | On trigger when listbox is open. | |
| [data-selected] | On selected option. | |
| [data-highlighted] | Keyboard/hover highlight. | |
| [data-disabled] | Disabled trigger or option. |
Keyboard
| Key | Action |
|---|---|
| Arrow ↓ / Enter / Space (closed) | Open the listbox and move focus into the list. |
| Arrow ↑ / ↓ | Move highlight; skips disabled items. |
| Home / End | First / last enabled option. |
| Type characters | Typeahead match on textValue. |
| Enter / Space | Select highlighted option. |
| Escape | Close listbox (when focus is in content or on trigger); stopPropagation for Dialog interop. |