Radio
One choice of a set. Put several in a zeno-radio-group, or give them the same name.
import '@usezeno/tokens/css';
import '@usezeno/core/web-components';
Examples
Radios that share a name
Radios with the same name uncheck each other. For a set with a legend, arrow keys and one error, put the radios in a zeno-radio-group.
<zeno-radio name="delivery" value="standard" label="Standard delivery" checked></zeno-radio>
<zeno-radio name="delivery" value="express" label="Express delivery"></zeno-radio>
<zeno-radio name="delivery" value="pickup" label="Pick up in store"></zeno-radio>
Sizes
<zeno-radio name="size" size="sm" label="Small" checked></zeno-radio>
<zeno-radio name="size" size="md" label="Medium"></zeno-radio>
<zeno-radio name="size" size="lg" label="Large"></zeno-radio>
States
loading shows a spinner in the circle and disables the radio. An error marks the radio invalid and shows the text under it.
<zeno-radio label="Disabled" disabled></zeno-radio>
<zeno-radio label="Disabled and checked" disabled checked></zeno-radio>
<zeno-radio label="Loading" loading></zeno-radio>
<zeno-radio label="With an error" error="This option is no longer available."></zeno-radio>
In a form
Only the checked radio is sent, under name. A reset brings back the radio that was checked at the start.
<form>
<zeno-radio name="contact" value="email" label="Email" checked></zeno-radio>
<zeno-radio name="contact" value="phone" label="Phone"></zeno-radio>
<zeno-radio name="contact" value="post" label="Post"></zeno-radio>
<zeno-button type="submit">Save changes</zeno-button>
<zeno-button type="reset" variant="ghost">Reset</zeno-button>
<p data-result>Nothing submitted yet.</p>
</form>
const form = document.querySelector('form');
form.addEventListener('submit', event => {
event.preventDefault();
const sent = [...new FormData(form)].map(([name, value]) => name + '=' + value);
document.querySelector('[data-result]').textContent = 'Submitted: ' + sent.join('&');
});
Attributes and properties
| Property | Attribute | Type | Default | Description |
|---|---|---|---|---|
checked | checkedreflects | boolean | false | |
size | sizereflects | 'sm' | 'md' | 'lg' | 'md' | |
loading | loadingreflects | boolean | false | |
defaultChecked | boolean | false | Whether it is checked when its form is reset. | |
value | value | FormValue | 'on' | From FormFieldMixin. |
name | namereflects | string | From FormFieldMixin. | |
required | requiredreflects | boolean | false | From FormFieldMixin. |
disabled | disabledreflects | boolean | false | From FormFieldMixin. |
readonly | readonlyreflects | boolean | false | From FormFieldMixin. |
error | error | string | An error to show, for example one a server returned. From FormFieldMixin. | |
label | label | string | A visible label. An outside <label for> works as well. From FormFieldMixin. | |
hideRequiredIndicator | hide-required-indicator | boolean | false | From FormFieldMixin. |
touched | boolean | false | True once the user has left the control or a submit was refused. From FormFieldMixin. | |
dirty | boolean | false | True once the user has changed the value. From FormFieldMixin. | |
defaultValue | FormValue | '' | The value the control goes back to when its form is reset. From FormFieldMixin. | |
formread only | HTMLFormElement | null | From FormFieldMixin. | ||
labelsread only | NodeList | From FormFieldMixin. | ||
validityread only | ValidityState | From FormFieldMixin. | ||
validationMessageread only | string | From FormFieldMixin. | ||
willValidateread only | boolean | From FormFieldMixin. | ||
isDisabledread only | boolean | True when the element or an ancestor fieldset disables it. From FormFieldMixin. | ||
invalidread only | boolean | True when the control should look invalid. From FormFieldMixin. | ||
testId | string | Test ID for automated testing From ZenoElement. |
Methods
| Method | Description |
|---|---|
focus(options?: FocusOptions): void | Focus the component or its first focusable element From ZenoElement. |
blur(): void | Blur the component or its focused element From ZenoElement. |
checkValidity(): boolean | Reports whether the value is valid without showing anything. Use reportValidity() or validate() to show the result as well. From FormFieldMixin. |
reportValidity(): boolean | From FormFieldMixin. |
setCustomValidity(message: string): void | From FormFieldMixin. |
validate(): boolean | Checks validity and shows the result on the control. From FormFieldMixin. |
Events
| Event | Detail | Description |
|---|---|---|
input | { checked: boolean; value: FormValue } | The user selected the radio. |
change | { checked: boolean; value: FormValue } | The user selected the radio. |
Slots
This element has no slots.
CSS parts
| Part |
|---|
base |
button |
dot |
error |
label |
loading |
required |
CSS custom properties
This element documents no custom properties of its own. Style it through its parts and through the tokens it reads.
The element's own source reads no tokens.
Types
type FormValue = string | number | boolean | Date | null | undefined;
Accessibility
Keyboard
| Key | What it does |
|---|---|
| Tab | Moves focus to the radio. Outside a zeno-radio-group every radio is a Tab stop. |
| Space | Checks the focused radio. |
Forms
- With a
name, the element adds its value to the data of the form it is in, and is left out while it is disabled. - It is labelled by its
labelattribute or by a<label for>that points at itsid. - It takes part in validation:
checkValidity(),reportValidity()andsetCustomValidity()work, and an invalid element blocks the submit and matches:invalid. - It follows a
<fieldset disabled>around it and goes back to its first value when the form is reset. - The messages it writes itself, such as “Please fill out this field.”, are in English only.
Notes
- Renders a native
<input type="radio">in its shadow root, inside a<label>that holds thelabeltext. A click on the text checks the radio. - Without
label, the name comes fromaria-labelon the element or from an outside<label for>. - The input always carries
aria-invalid. When an error shows,aria-describedbypoints at the error text. - The native input is invisible but still focusable. The focus ring is drawn on the circle.
- The required star is hidden from assistive technology.
Tests and known gaps
- Tested in a real browser by
radio.test.ts. - Checked with axe-core in the light and the dark theme.
- Has no Storybook story.
23 of the 38 properties, methods, events, slots and parts above have no description in the source
- the property
checked - the property
size - the property
loading - the property
value - the property
name - the property
required - the property
disabled - the property
readonly - the property
hideRequiredIndicator - the property
form - the property
labels - the property
validity - the property
validationMessage - the property
willValidate - the method
reportValidity() - the method
setCustomValidity() - the part
base - the part
button - the part
dot - the part
error - the part
label - the part
loading - the part
required
Known gaps:
- Outside a
zeno-radio-group, radios with onenameare not a keyboard group. Every radio is a Tab stop and the arrow keys do not move between them. Assistive technology does not announce “1 of 3”. - There is no slot. The label is plain text from
label, and content placed inside the element is not shown. readonlyis declared but does nothing. A read-only radio can still be changed.- Outside a group,
requiredworks for each radio alone. Every required radio shows its own star, and after a refused submit every one of them shows the same error text. - Inside a
zeno-radio-grouptheerrorof a single radio is not shown. loadingdisables the inner input, so the radio cannot take focus while it loads. The spinner is announced as “Loading”, in English, and the input has noaria-busy.- The required message “Please select one of these options.” is English only. An
errortext replaces it. - The error text is not a live region. An error that appears while the user is elsewhere is not announced.
- The gap before the required star uses
margin-left, so it is on the wrong side in a right-to-left page.