Select
On this page
Importing
Add rh-select to your page with this import statement:
<script type="module">
import '@rhds/elements/rh-select/rh-select.js';
</script>
Copy to Clipboard
Copied!
Wrap lines
Overflow lines
To learn more about installing RHDS elements on your site using an import map read our getting started docs.
Lightdom CSS
This element requires you to load "Lightdom CSS" stylesheets for styling deeply slotted elements.
Note
Replace /path/to/ with path to the CSS file, whether local or CDN.
<link rel="stylesheet" href="/path/to/rh-select/rh-select-lightdom.css">
Lightdom CSS shim
Warning
Lightdom CSS shims are an optional, temporary solution for reducing CLS. Learn more about lightdom CSS shims .
<link rel="stylesheet" href="/path/to/rh-select/rh-select-lightdom-shim.css">
Note
Replace /path/to/ with path to the CSS file, whether local or CDN.
Usage
<label for="my-select">
Products
</label>
<rh-select id="my-select" placeholder="Select an item">
<rh-option>Device Edge</rh-option>
<rh-option>JBoss Web Server</rh-option>
<rh-option>OpenShift</rh-option>
<rh-option disabled="">Red Hat Lightspeed</rh-option>
<rh-option>Quay</rh-option>
</rh-select>
<link rel="stylesheet" href="../rh-select-lightdom-shim.css">
<script type="module">
import '@rhds/elements/rh-select/rh-select.js';
</script>
<style>
label,
rh-select {
margin-inline: 20px;
max-inline-size: 320px;
}
label {
display: block;
font-family: var(--rh-font-family-body-text);
font-weight: var(--rh-font-weight-body-text-medium, 500);
margin-block: var(--rh-space-md, 8px);
}
</style>
Copy to Clipboard
Copied!
Wrap lines
Overflow lines
Validation and error state
Built-in validation
When users set the required property and the no option is selected, the component participates in the Constraint Validation API. It sets an internal validity state (valueMissing), so the browser can show "Please fill out this field" when the user submits the form or when you call reportValidity(). Use checkValidity() or reportValidity() on the <rh-select> element to validate before submit.
See the Required demo for an example of this functionality.
Custom validation and error state
This component does not set aria-invalid when setting state="danger". For custom errors, you should:
- Visual state: Set
state="danger"andhelp-text="My error message"with the error message. - Semantic state for assistive tech: Set
aria-invalid="true"on the<rh-select>so screen readers announce the invalid state. - Blocking form submit: The component only sets validity for
requiredwith an empty value. For custom rules, handle submit yourself:- In your submit handler, run your custom check.
- If the check fails: call
preventDefault()so the form does not submit then setstate="danger",help-text, andaria-invalid="true"so the user sees and hears the error. - If the check passes: clear the error state and allow the form to submit.
Example: validate on submit and show a custom error state when the selected option fails a rule.
<form id="my-form">
<label for="region">Region</label>
<rh-select id="region" name="region" placeholder="Select a region">
<rh-option value="us">United States</rh-option>
<rh-option value="eu">European Union</rh-option>
<rh-option value="deprecated">Legacy (deprecated)</rh-option>
</rh-select>
<button type="submit">Submit</button>
</form>
<script type="module">
import '@rhds/elements/rh-select/rh-select.js';
const form = document.getElementById('my-form');
const select = document.getElementById('region');
form.addEventListener('submit', (e) => {
const value = select.value;
if (value === 'deprecated') {
e.preventDefault();
select.setAttribute('state', 'danger');
select.setAttribute('help-text', 'This option is no longer available.');
select.setAttribute('aria-invalid', 'true');
select.focus();
} else {
select.removeAttribute('state');
select.setAttribute('help-text', '');
select.removeAttribute('aria-invalid');
}
});
</script>
For accessibility implications and why the component does not set aria-invalid from state, see Validation and error state in the Select accessibility documentation.
rh-select
A select element allows users to Select from an expandable list.
Slots
3
| Slot Name | Summary | Description |
|---|---|---|
placeholder
|
Placeholder inline text for the select. Overrides the |
|
[default]
|
Insert |
|
help-text
|
Insert a block element (e.g. |
Attributes
9
| Attribute | DOM Property | Description | Type | Default |
|---|---|---|---|---|
accessible-label
|
accessibleLabel |
Accessible label text for screen readers and assistive technologies.
Should be used when the select lacks an associated |
|
|
disabled
|
disabled |
Whether the select control is disabled and non-interactive. When true, prevents user interaction and excludes the value from form submission. |
|
|
expanded
|
expanded |
Whether the dropdown listbox is currently expanded and visible. Automatically managed by keyboard and mouse interactions. Should not be manually set in most cases. |
|
|
required
|
required |
When true, the user must select an option with a non-empty value before the form can be submitted. Syncs to aria-required and constraint validation so the browser can show "Please fill out this field" when the value is empty. |
|
|
value
|
value |
Current form value representing the selected option's value attribute. Updates automatically when selection changes. Use for form submission and programmatic value access. |
|
|
name
|
name |
Form control name. Submitted with the form as the key for this control's value in FormData. Reflects to the name attribute. |
|
|
placeholder
|
placeholder |
Placeholder text displayed when no option is selected. Should provide guidance about expected input. Overridden by the placeholder slot if provided. Used as fallback accessible label when no accessible-label or associated label is present. |
|
|
help-text
|
helpText |
Help text displayed below the control. Content slotted into the help-text slot overrides this attribute. |
|
|
state
|
state |
Visual and semantic state of the form control for user feedback. Use 'danger' for blocking errors that prevent form submission, 'warning' for non-blocking issues requiring attention, and 'success' for valid selections. Affects styling. |
|
|
Methods
5
| Method Name | Description |
|---|---|
checkValidity()
|
Returns true if the element's value passes constraint validation. Participates in the Constraint Validation API; updates validity state before checking. |
reportValidity()
|
Returns true if the element's value passes constraint validation. If invalid, reports the problem (e.g. browser "Please fill out this field") and returns false. Participates in the Constraint Validation API. |
show()
|
Opens the dropdown |
hide()
|
Closes the dropdown |
toggle()
|
Toggles the dropdown based on current state |
Events
3
| Event Name | Description |
|---|---|
open
|
Fires when the dropdown listbox opens. Does not bubble. The event has no |
close
|
Fires when the dropdown listbox closes. Does not bubble. The event has no |
change
|
Fires when the selected value changes. Bubbles. The event has no |
CSS Shadow Parts
0
None
CSS Custom Properties
4
| CSS Property | Description | Default |
|---|---|---|
--rh-color-status-disabled |
light-dark(
var(--rh-color-gray-30, #c7c7c7),
var(--rh-color-gray-40, #a3a3a3))
|
|
--rh-color-text-status-disabled |
light-dark(
var(--rh-color-gray-50, #707070),
var(--rh-color-gray-60, #4d4d4d))
|
|
--rh-color-icon-status-disabled |
light-dark(
var(--rh-color-gray-40, #a3a3a3),
var(--rh-color-gray-60, #4d4d4d))
|
|
--rh-select-icon-size |
14px
|
Design Tokens
26
| Token | Description | Copy |
|---|---|---|
--rh-font-weight-body-text-regular
|
Regular font weight design token Regular font weight |
|
--rh-line-height-body-text
|
Body text line height design token Line height for body text |
|
--rh-box-shadow-sm
|
Small shadow design token for dropdown elevation Small box shadow |
|
--rh-color-surface-lightest
|
Primary surface (light theme) |
|
--rh-color-surface-darkest
|
Primary surface (dark theme) |
|
--rh-border-radius-default
|
Default border radius design token 3px border radius; Example: Card |
|
--rh-color-gray-30
|
Subtle borders (light theme) |
|
--rh-color-text-primary
|
Primary text color design token for the select control Primary text color for the toggle button label |
|
--rh-font-family-body-text
|
Body text font family design token Body text font stack for the toggle button Body text font family |
|
--rh-space-lg
|
16px spacer |
|
--rh-color-gray-50
|
Subtle icon |
|
--rh-border-width-md
|
2px border width: Example: Alert |
|
--rh-color-border-interactive
|
|
|
--rh-color-gray-40
|
Subtle icon (hover state) |
|
--rh-color-gray-60
|
Secondary text (light theme) |
|
--rh-border-width-sm
|
1px border width; Example: Secondary CTA or Button |
|
--rh-color-border-subtle
|
|
|
--rh-space-md
|
Medium spacing design token for vertical padding Medium spacing between toggle text and icons 8px spacer |
|
--rh-font-size-body-text-sm
|
Small body text size design token Small body text size for the toggle button 14px font size |
|
--rh-font-weight-body-text-medium
|
Medium font weight |
|
--rh-color-border-status-success
|
|
|
--rh-color-border-status-warning
|
|
|
--rh-color-border-status-danger
|
|
|
--rh-color-icon-status-success
|
|
|
--rh-color-icon-status-warning
|
|
|
--rh-color-icon-status-danger
|
|
rh-option-group
Groups related rh-option elements within an rh-select for organizing
options into categories. Provides visual separation when used with <hr>.
Should include a label for screen readers (ARIA group role). When
disabled, all child options are disabled. Arrow keys and Tab navigate
through grouped options the same way as ungrouped options.
Slots
2
| Slot Name | Summary | Description |
|---|---|---|
label
|
Group label as inline text. Overrides the |
|
[default]
|
Insert |
Attributes
2
| Attribute | DOM Property | Description | Type | Default |
|---|---|---|---|---|
label
|
label |
Group label text displayed above the option group for identification. Should be used to describe the category or purpose of grouped options. Overridden by the label slot if provided. Required for accessibility. |
|
|
disabled
|
disabled |
Whether the option group and all its child options are disabled. When true, automatically disables all rh-option children, preventing selection of any options within this group. |
|
|
Methods
1
| Method Name | Description |
|---|---|
firstUpdated()
|
Events
0
None
CSS Shadow Parts
0
None
CSS Custom Properties
1
| CSS Property | Description | Default |
|---|---|---|
--rh-color-text-status-disabled |
—
|
Design Tokens
6
| Token | Description | Copy |
|---|---|---|
--rh-color-gray-50
|
Subtle icon |
|
--rh-color-gray-60
|
Secondary text (light theme) |
|
--rh-color-text-secondary
|
Secondary text color design token for the group label |
|
--rh-font-size-body-text-xs
|
Extra-small text size design token for the group label 12px font size |
|
--rh-space-md
|
Medium spacing design token for vertical padding 8px spacer |
|
--rh-space-lg
|
16px spacer |
|
rh-option
An option within an rh-select dropdown. Must be a child of rh-select
or rh-option-group. Should include a value attribute for form data.
Must have text content or label for screen readers (ARIA option role).
Press Enter/Space to select; Arrow keys to navigate between options.
Slots
2
| Slot Name | Summary | Description |
|---|---|---|
[default]
|
Option label as inline text. Screen readers use this content as the accessible name. Falls back to the |
|
description
|
Optional inline or block description text displayed below the option label. Overrides the |
Attributes
7
| Attribute | DOM Property | Description | Type | Default |
|---|---|---|---|---|
disabled
|
disabled |
Whether the option is disabled and cannot be selected. Defaults to |
|
|
value
|
value |
Form value for this option. Priority: value attr -> displayLabel -> '' |
|
|
selected
|
selected |
Whether the option is currently selected. Defaults to |
|
|
icon-set
|
iconSet |
Icon set for the optional rh-icon to precede the option text - 'ui' by default |
|
|
icon
|
icon |
The icon name of an rh-icon |
|
|
description
|
description |
Optional option description; overridden by description slot. |
|
|
label
|
label |
Display text for this option; overridden by slotted text content |
|
|
Methods
1
| Method Name | Description |
|---|---|
firstUpdated(changedProperties: PropertyValues
|
Initialize cached display label on first client-side render |
Events
0
None
CSS Shadow Parts
0
None
CSS Custom Properties
2
| CSS Property | Description | Default |
|---|---|---|
--rh-color-text-status-disabled |
light-dark(
var(--rh-color-gray-50, #707070),
var(--rh-color-gray-60, #4d4d4d))
|
|
--rh-select-icon-size |
14px
|
Design Tokens
11
| Token | Description | Copy |
|---|---|---|
--rh-color-surface-lighter
|
Tertiary surface (light theme) |
|
--rh-color-surface-darker
|
Secondary surface (dark theme) |
|
--rh-space-lg
|
16px spacer |
|
--rh-border-radius-default
|
3px border radius; Example: Card |
|
--rh-color-border-interactive
|
|
|
--rh-border-width-lg
|
3px border width: Example: Expanded Accordion panel |
|
--rh-color-gray-50
|
Subtle icon |
|
--rh-color-gray-60
|
Secondary text (light theme) |
|
--rh-color-interactive-primary-default
|
Primary interactive color design token for selected checkmark |
|
--rh-font-size-body-text-xs
|
Extra-small text size design token for option descriptions 12px font size |
|
--rh-space-md
|
Medium spacing design token between icon and label 8px spacer |
|
Other libraries
To learn more about our other libraries, visit this page.
Feedback
To give feedback about anything on this page, contact us.