HySelect
Usage examples on this page are written for Lit / plain HTML (
<hy-select>). The same component ships asHySelectin@whitespaceux/harmony-react(native React 19), with typed wrappers for Angular, Solid, Svelte, and Vue. The API reference below applies to all frameworks.
A customizable select dropdown component that wraps the native HTML select element.
This component accepts slotted native <option> elements which are rendered within a standard <select>. This approach provides enhanced styling, validation states, and accessibility features while maintaining native select behavior.
Examples
html
<hy-select label="Choose a color" placeholder="Select a color">
<option value="red">Red</option>
<option value="green">Green</option>
<option value="blue">Blue</option>
</hy-select>html
<hy-select label="Country" helper-text="Select your country of residence" required size="large">
<option value="us">United States</option>
<option value="ca">Canada</option>
<option value="uk">United Kingdom</option>
</hy-select>html
<hy-select label="Priority Level" value="medium" name="priority" size="small">
<option value="low">Low Priority</option>
<option value="medium">Medium Priority</option>
<option value="high">High Priority</option>
<option value="urgent" disabled>Urgent</option>
</hy-select>html
<hy-select label="Account Type" invalid error-message="Please select an account type" required>
<option value="personal">Personal Account</option>
<option value="business">Business Account</option>
<option value="enterprise">Enterprise Account</option>
</hy-select>html
<hy-select
label="Subscription Plan"
disabled
value="free"
helper-text="Upgrade options are temporarily unavailable"
>
<option value="free">Free Plan</option>
<option value="pro">Pro Plan</option>
<option value="enterprise">Enterprise Plan</option>
</hy-select>html
<form>
<hy-select name="department" label="Department" required>
<option value="sales">Sales</option>
<option value="marketing">Marketing</option>
<option value="engineering">Engineering</option>
<option value="support">Customer Support</option>
</hy-select>
<hy-select name="experience" label="Years of Experience" placeholder="Select experience level">
<option value="0-2">0-2 years</option>
<option value="3-5">3-5 years</option>
<option value="6-10">6-10 years</option>
<option value="10+">10+ years</option>
</hy-select>
</form>API
Properties
| Property | Attribute | Type | Default | Description |
|---|---|---|---|---|
label | label | string | '' | The label text displayed above the select. |
helperText | helper-text | string | '' | Helper text displayed below the select. |
value | value | string | '' | The current value of the select. |
name | name | string | '' | The name attribute for the select. |
placeholder | placeholder | string | '' | Placeholder text when no option is selected. |
size | size | 'small' | 'medium' | 'large' | 'medium' | The size variant of the select (small, medium, or large). |
layout | layout | 'block' | 'inline' | 'block' | Row layout: block (default) stacks label above the select; inline puts label on the left and select on the right. Helper/error always sit under the control (col 2–end), never under the label. Set --hy-select-label-column-width on a wrapping container so stacked selects align. |
width | width | string | undefined | — | Width of the select container. Accepts any valid CSS width value (e.g. '400px', '100%', '20rem'). The host fills its container by default; set width to constrain the field. Mirrors hy-text-input. |
disabled | disabled | boolean | false | Disables the select. |
required | required | boolean | false | Marks the select as required. |
clearable | clearable | boolean | false | Show a clear button on the trigger once a value is set, so an optional field can return to "nothing selected" with the pointer. Off by default (every surveyed select defaults off), and never shown on a required or disabled select. Keyboard users clear through the placeholder option, which is selectable whenever the select is not required. |
clearLabel | clear-label | string | 'Clear selection' | Accessible name of the clear button. |
invalid | invalid | boolean | false | Marks the select as invalid. |
errorMessage | error-message | string | '' | Error message displayed when invalid. |
autofocus | autofocus | boolean | false | Marks this select as the auto-focus target. Read by hy-dialog (and other overlay containers) on show to choose initial focus. Also focuses on first connect when used outside an overlay, mirroring native HTML autofocus but routed through JS so SSR'd HTML doesn't pull focus during hydration. |
form | — | HTMLFormElement | null | — | — |
validity | — | ValidityState | — | — |
validationMessage | — | string | — | — |
Events
| Event | Detail | Description |
|---|---|---|
change | — | Fired when the selected value changes. Detail: |
input | — | Fired during value input. Detail: |
Slots
| Slot | Description |
|---|---|
default | Slot for native option elements that define the available choices |
expand-icon | Custom dropdown indicator icon (overrides the default chevron) |
clear-icon | Custom clear-button icon (overrides the default close glyph) |
CSS Parts
| Part | Description |
|---|---|
base | The select's base wrapper element |
label | The label element |
container | The select input container |
select | The native select element |
icon | The dropdown indicator icon |
clear-button | The clear affordance (rendered when clearable, a value is set, and the select is neither required nor disabled) |
helper-text | The helper text element |
error-message | The error message element |
CSS Custom Properties
| Property | Description |
|---|---|
--hy-select-focus-ring-width | Focus ring width override |
--hy-select-clear-radius | Clear-button corner radius |
--hy-select-label-column-width | Width of the label column in layout="inline" mode. No default — set on a wrapping container so stacked selects align. |
--hy-select-height-sm | Outer height for small size variant. Per-component override in the form-control height contract (see .claude/rules/control-heights.md). Default: var(--hy-control-height-sm) |
--hy-select-height-md | Outer height for medium size variant. Default: var(--hy-control-height-md) |
--hy-select-height-lg | Outer height for large size variant. Default: var(--hy-control-height-lg) |
--hy-select-hover-duration | Transition duration for hover and focus state feedback |
--hy-select-hover-easing | Transition easing for hover and focus state feedback |
Methods
focus()
Sets focus on the select.
Parameters:
options- Optional focus options
javascript
const select = document.querySelector('hy-select');
select.focus();blur()
Removes focus from the select.
javascript
const select = document.querySelector('hy-select');
select.blur();