Select
Choose one or more values from a known set without free-text editing.
Try it
<hui-select id="playground-select" name="plan" value="standard" aria-label="Plan">
<hui-select-trigger>
<hui-select-value placeholder="Choose a plan"></hui-select-value>
</hui-select-trigger>
<hui-select-content>
<hui-select-option value="basic">Basic</hui-select-option>
<hui-select-option value="standard">Standard</hui-select-option>
<hui-select-option value="pro">Professional</hui-select-option>
</hui-select-content>
</hui-select>- data-state
- Waiting for enhancement
No component events yet.
Usage
Use hui-select for choosing one or more values from a known option set without free-text editing. Use a combobox when users need to filter by typing. Do not use it for long lists that need search or for arbitrary interactive content.
Anatomy
- Root and trigger:
hui-select,hui-select-trigger - Value display:
hui-select-value - Popup:
hui-select-content - Options and grouping:
hui-select-option,hui-select-group,hui-select-label
Examples
<section aria-labelledby="select-heading">
<h2 id="select-heading">Plan</h2>
<form id="select-form">
<hui-select id="plan-select" name="plan" value="standard" aria-labelledby="select-heading" loop>
<hui-select-trigger><hui-select-value placeholder="Choose a plan"></hui-select-value></hui-select-trigger>
<hui-select-content>
<hui-select-option value="basic">Basic</hui-select-option>
<hui-select-option value="standard"><b>Standard</b></hui-select-option>
<hui-select-option value="pro" disabled>Professional</hui-select-option>
<hui-select-group>
<hui-select-label>Enterprise</hui-select-label>
<hui-select-option value="enterprise">Enterprise</hui-select-option>
</hui-select-group>
</hui-select-content>
</hui-select>
</form>
</section>API reference
| Attribute | Meaning |
|---|---|
value | Committed option value; multiple values are comma-separated. |
default-value | Seeds value once when no value is present. |
open / default-open | Controls or seeds popup visibility. |
multiple | Enables multiple selection and aria-multiselectable. |
select-on-move | Commits a single value whenever the highlight moves. |
loop | Allows highlight navigation to wrap. |
placement / dir | Preferred popup placement and keyboard direction. |
name, form, required | Form submission and validation metadata. |
id | Stable base for content and option IDs. |
aria-label, aria-labelledby, aria-describedby | Accessible naming and description. |
Options support value, label, and disabled. When value is omitted, option identity falls back to the host id, then the option's positional index; use explicit values for collections whose order can change. The root emits hui-open-change with { open } and hui-value-change with { value }. Consumers can target data-state, data-value, data-placement, data-highlighted, and aria-selected. Positioning is written to --hui-position-x and --hui-position-y.
Keyboard behavior uses Arrow keys, Home/End, typeahead, Enter/Space, Escape, and Tab. loop controls wrapping; select-on-move commits movement; multiple select toggles without closing. Typeahead buffers printable graphemes for 500ms, normalizes equivalent Unicode text, and uses inherited lang for case matching. Repeated graphemes cycle through matching options. IME composition keys are ignored. Intl.Segmenter is feature-detected, with normalized single-code-point matching as the fallback; invalid language tags use the default locale. SSR emits native trigger semantics, a collapsed listbox, deterministic IDs, and a hidden form input. Without JavaScript, the native trigger and selected text remain usable while the listbox stays hidden.
States and styling
A selected, highlighted option keeps --hui-color-interactive-contrast text against the highlight background without adding text decoration.
| State | Contract and styling guidance |
|---|---|
| Default | Closed trigger shows the committed value or placeholder. |
| Hover | Use --hui-color-interactive-hover for trigger and option feedback. |
| Active | Use --hui-color-interactive-active for pressed trigger feedback. |
| Focus | Keep the trigger focus ring visible with --hui-color-focus-ring. |
| Disabled | Disabled options and triggers use --hui-color-interactive-disabled and cannot be selected. |
| Error | No built-in validation state; pair aria-invalid="true" with error text and --hui-color-danger. |
Attributes are the source of truth. Style derived state with data-state, ARIA attributes, and the --hui-* token aliases.
Accessibility and keyboard support
The select exposes a labelled listbox interaction. Arrow keys and typeahead move through options, Enter or Space commits, and Escape closes the popup.
SSR and forms
Select preserves source-of-truth attributes and accessible state in server-rendered light-DOM markup. Use stable IDs when the component generates relationships; client enhancement adds interaction without changing the public contract.
Code
<hui-select id="plan" name="plan" value="standard" aria-label="Plan">
<hui-select-trigger>
<hui-select-value placeholder="Choose a plan"></hui-select-value>
</hui-select-trigger>
<hui-select-content>
<hui-select-option value="basic">Basic</hui-select-option>
<hui-select-option value="standard">Standard</hui-select-option>
<hui-select-option value="pro">Professional</hui-select-option>
</hui-select-content>
</hui-select>
<hui-select id="playground-select" name="plan" value="standard" aria-label="Plan">
<hui-select-trigger>
<hui-select-value placeholder="Choose a plan"></hui-select-value>
</hui-select-trigger>
<hui-select-content>
<hui-select-option value="basic">Basic</hui-select-option>
<hui-select-option value="standard">Standard</hui-select-option>
<hui-select-option value="pro">Professional</hui-select-option>
</hui-select-content>
</hui-select>