The m3e-radio-group and m3e-radio components enable single-choice selection within a
set of mutually exclusive options.
import "@m3e/web/radio-group";
This section outlines usage examples and configuration guidance for the components in this package.
Radios are typically placed inside a m3e-radio-group.
<m3e-radio-group> <label><m3e-radio value="1"></m3e-radio> Option 1</label> <label><m3e-radio value="2"></m3e-radio> Option 2</label> <label><m3e-radio value="3"></m3e-radio> Option 3</label> <label><m3e-radio value="4"></m3e-radio> Option 4</label> </m3e-radio-group>
Associate a label with a radio using the label element. In addition, radio groups can also be
labelled using a label.
<label for="radio-group">Select an option</label> <m3e-radio-group id="radio-group"> <label><m3e-radio value="1"></m3e-radio> Option 1</label> <!-- Additional radios omitted for brevity --> </m3e-radio-group>
Radios participate in form submission as a
form-associated custom element
(FACE), contributing its state to the form data. The name attribute defines the key under which
the radio's value is submitted in a form. When checked and not disabled, value (defaults to
"on") is submitted.
Radios honor the disabled state as a property-only control. When disabled at
runtime, it does not sprout a disabled attribute into the DOM.
When using a radio group, the group's name is propagated to all nested radios.
Use the disabled attribute to disable an individual radio or a entire radio group. Associated
labels are automatically styled to show disabled.
The following example illustrates disabling individual radios in a group.
<label for="radio-group">Select an option</label> <m3e-radio-group id="radio-group"> <label><m3e-radio disabled value="1"></m3e-radio> Option 1</label> <!-- Additional radios omitted for brevity --> </m3e-radio-group>
The next example illustrates disabling an entire group.
<label for="radio-group">Select an option</label> <m3e-radio-group id="radio-group" disabled> <label><m3e-radio value="1"></m3e-radio> Option 1</label> <!-- Additional radios omitted for brevity --> </m3e-radio-group>
Use the required attribute of a radio group to require an option to be checked. Associated labels
are automatically styled to show the validity state.
In the example below, press TAB to enter the radio group, then TAB again to exit without making a selection to see how validation is trigger. Selecting a radio will revalidate.
<label for="radio-group">Select an option</label> <m3e-radio-group id="radio-group" required> <label><m3e-radio value="1"></m3e-radio> Option 1</label> <!-- Additional radios omitted for brevity --> </m3e-radio-group>
Radios are density-aware and adjust their vertical spacing based on the
--md-sys-density-scale and --md-sys-density-size custom CSS properties. The default
density size is 4dp (0.25rem). Radios support negative density scales down to -3, with each step reducing the
visual height by one density unit. Regardless of visual size, radios maintain a 48x48dp minimum touch target
to ensure reliable accessibility.
The following illustrates applying density to a radio. Interact with each radio to see how density impacts its state layer.
<label> <m3e-radio class="density-3"></m3e-radio> Density -3 </label> <!-- Additional radios omitted for brevity -->
.density-3 {
--md-sys-density-scale: -3;
}
/* Additional classes omitted for brevity */
Each radio group is assigned role="radiogroup" to signal a related set of options, while
individual radios receive role="radio" to indicate their participation in the group. This ensures
screen readers can convey the correct context and selection state to users.
The aria-checked attribute reflects whether a radio is currently selected within its group. When
a radio is checked, aria-checked="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 the radio is disabled. When disabled at runtime, it does not sprout a
disabled attribute into the DOM.
When a radio group is disabled, aria-disabled is not applied to the group. Instead, the disabled
state is reflected by applying aria-disabled="true" to each nested radio, ensuring assistive
technologies correctly interpret the non-interactive status of individual options.
When a radio group is marked as required using the required attribute,
aria-required="true"is applied to the group. This communicates to assistive technologies that a
selection is mandatory. The aria-required="true" attribute is not propagated to individual
radios, as the requirement applies to the group as a whole, not each option.
Always provide an accessible label via aria-label or aria-labelledby for radios and
radio groups without descriptive text content
The @m3e/web 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/web/dist/radio-group.js"></script>
In addition, you must use an import map to include dependencies.
<script type="importmap">
{
"imports": {
"tslib": "https://cdn.jsdelivr.net/npm/tslib@2.8.1/+esm",
"lit": "https://cdn.jsdelivr.net/npm/lit@3.3.0/+esm",
"lit/": "https://cdn.jsdelivr.net/npm/lit@3.3.0/",
"lit-html": "https://cdn.jsdelivr.net/npm/lit-html@3.3.0/+esm",
"lit-html/directive.js": "https://cdn.jsdelivr.net/npm/lit-html@3.3.0/directive.js",
"lit-html/directives/if-defined.js": "https://cdn.jsdelivr.net/npm/lit-html@3.3.0/directives/if-defined.js",
"lit-html/directives/class-map.js": "https://cdn.jsdelivr.net/npm/lit-html@3.3.0/directives/class-map.js",
"@lit/reactive-element": "https://cdn.jsdelivr.net/npm/@lit/reactive-element@2.0.4/+esm",
"@lit/reactive-element/": "https://cdn.jsdelivr.net/npm/@lit/reactive-element@2.0.4/",
"@m3e/web/core": "/node_modules/@m3e/web/dist/core.js",
"@m3e/web/core/a11y": "/node_modules/@m3e/web/dist/core-a11y.js",
"@m3e/web/core/bidi": "/node_modules/@m3e/web/dist/core-bidi.js"
}
}
</script>
For production builds, use the minified files to ensure optimal load performance.
The @m3e/web 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.