The m3e-select component provides a form control for selecting a value from a set of predefined
options.
npm i @m3e/select
This section outlines usage examples and configuration guidance for the components in this package.
The following example illustrates use of a m3e-select in conjunction with the
m3e-form-field. See Form Field for more information.
To define selectable options within a m3e-select, include one or more
m3e-option elements as its children. Each m3e-option may specify a
value attribute, which determines the programmatic value submitted when the option is selected. The
textual content of the m3e-option element represents the label presented to the user in the
dropdown interface.
<m3e-form-field>
<label slot="label" for="select">Favorite fruit</label>
<m3e-select id="select">
<m3e-option>Apples</m3e-option>
<m3e-option>Oranges</m3e-option>
<m3e-option>Bananas</m3e-option>
<m3e-option>Grapes</m3e-option>
</m3e-select>
</m3e-form-field>
To define an empty option, include a m3e-option without a value or content. Alternately, set the
value attribute to "" and include descriptive content such as "None". This signals
that no meaningful value has been selected. Empty options are commonly used to represent a placeholder or
default state prior to user interaction.
<m3e-form-field>
<label slot="label" for="select">Favorite fruit</label>
<m3e-select id="select">
<m3e-option value="">None</m3e-option>
<m3e-option>Apples</m3e-option>
<m3e-option>Oranges</m3e-option>
<m3e-option>Bananas</m3e-option>
<m3e-option>Grapes</m3e-option>
</m3e-select>
</m3e-form-field>
The m3e-optgroup component can be used to group common options under a subheading. The name of the
group can be set using the label slot.
Nested groups are not supported—only a single level of grouping is permitted.
<m3e-form-field>
<label slot="label" for="select">Pokemon</label>
<m3e-select id="select">
<m3e-optgroup>
<span slot="label">Grass</span>
<m3e-option>Bulbasaur</m3e-option>
<m3e-option>Oddish</m3e-option>
<m3e-option>Bellsprout</m3e-option>
</m3e-optgroup>
<!-- Additional option groups omitted for brevity -->
</m3e-select>
</m3e-form-field>
Selects support both single-select and multi-select modes. Use the
multi attribute to allow multiple options to be selected simultaneously.
Use the selected attribute to control the selected state of a m3e-option. When
clicked, a cancellable input event is emitted by the m3e-select followed by a
change event. To cancel selection change, call preventDefault during
input.
<m3e-form-field>
<label slot="label" for="select">Toppings</label>
<m3e-select id="select" multi>
<m3e-option selected>Extra cheese</m3e-option>
<m3e-option selected>Mushroom</m3e-option>
<!-- Additional option groups omitted for brevity -->
</m3e-select>
</m3e-form-field>
You can disable the entire select component or individual options by applying the
disabled attribute to m3e-select or m3e-option, respectively.
<m3e-form-field>
<label slot="label" for="select">Favorite fruit</label>
<m3e-select id="select" disabled>
<m3e-option selected>Apples</m3e-option>
<!-- Additional option groups omitted for brevity -->
</m3e-select>
</m3e-form-field>
<m3e-form-field>
<label slot="label" for="select">Favorite fruit</label>
<m3e-select id="select">
<m3e-option disabled>Apples</m3e-option>
<!-- Additional option groups omitted for brevity -->
</m3e-select>
</m3e-form-field>
Apply the required attribute to enforce selection. This ensures that users must choose at least one
option before the field is considered valid. For multi-select configurations, at least one selected option
satisfies the requirement.
<m3e-form-field>
<label slot="label" for="select">Favorite fruit</label>
<m3e-select id="select" required>
<m3e-option value="">None</m3e-option>
<m3e-option>Apples</m3e-option>
<!-- Additional option groups omitted for brevity -->
</m3e-select>
</m3e-form-field>
The m3e-select component follows the ARIA combobox interaction pattern. Selects are
given the ARIA role="combobox", while the dropdown panel applies role="listbox" to
convey its structure to assistive technologies.
Options are given ARIA role="option", indicating that each item represents a selectable choice
within a listbox context. This role enables assistive technologies to interpret and announce the options
appropriately, supporting accessible navigation and selection behavior.
Option groups are given ARIA role="group", indicating that the grouped options form a semantically
related set within the listbox. This role helps assistive technologies convey structural relationships between
options, enhancing navigability and contextual understanding for screen reader users.
The aria-selected attribute reflects whether an option is currently selected. When an option is
selected, aria-selected="true" is exposed to assistive technologies; otherwise, it is
"false".
When disabled using the disabled attribute, aria-disabled="true" is used to convey to
assistive technologies that an option or select is disabled. When a m3e-select is disabled at
runtime, it does not sprout a disabled attribute into the DOM.
The aria-activedescendant attribute is applied to the m3e-select element to indicate
which option is currently active within the listbox. Instead of moving DOM focus to each option, the select
retains focus while updating aria-activedescendant to reference the id of the focused
m3e-option. This approach preserves focus management and enables assistive technologies to announce
the active option during keyboard navigation, ensuring accessible and predictable interaction.
The aria-owns and aria-controls attributes are applied to the
m3e-select element to establish an explicit relationship with the listbox popup. Both attributes
reference the id of the listbox container, ensuring assistive technologies recognize the connection
between the trigger and the controlled content. While aria-controls indicates that the select
governs the visibility and behavior of the listbox, aria-owns asserts DOM ownership when the
listbox is rendered outside the select's subtree.
The aria-expanded attribute reflects the current state of the listbox popup. When the listbox is
open, aria-expanded="true" is set on the m3e-select element; when collapsed, it is set
to false. This dynamic state enables screen readers to announce whether the listbox is expanded or
collapsed, supporting accessible navigation and interaction.
Because listbox is designed for single-item selection, you should avoid placing additional
interactive elements—such as buttons, checkboxes, or toggles—inside m3e-option. Nesting interactive
controls within options disrupts expected navigation and interferes with screen reader behavior.
This package uses JavaScript Modules. To use it directly in a browser without a bundler, use a module script similar to the following.
<script type="module" src="/node_modules/@m3e/select/dist/index.js"></script>
You also need a module script for @m3e/option due to it being a dependency.
<script type="module" src="/node_modules/@m3e/option/dist/index.js"></script>
In addition, you must use an import map to include additional dependencies.
<script type="importmap">
{
"imports": {
"lit": "https://cdn.jsdelivr.net/npm/lit@3.3.0/+esm",
"@m3e/core": "/node_modules/@m3e/core/dist/index.js",
"@m3e/core/a11y": "/node_modules/@m3e/core/dist/a11y.js",
"@m3e/core/anchoring": "/node_modules/@m3e/core/dist/anchoring.js",
"@m3e/core/bidi": "/node_modules/@m3e/core/dist/bidi.js"
}
}
</script>
For production, use index.min.js, a11y.min.js, anchoring.min.js, and bidi.min.js for faster load times.
This package includes a Custom Elements Manifest (custom-elements.json), which
documents the properties, attributes, slots, events and CSS custom properties of each component.
You can explore the API below, or integrate the manifest into your own tooling.