Skip to content

Radio - Elements ​

Radios allow users to select a single option from a list of choices.

AndroidreleasedElementsreleasediOSreleasedReactreleasedVuereleased

Elements ​

Usage Notes ​

The radio component is a custom element that provides a single radio with built-in form validation and styling support. The radio group component adds labeling, help text, and required validation for a set of radios.

  • <w-radio> - A single radio with required and invalid states
  • <w-radio-group> - A grouping wrapper that manages labeling, help text, roving keyboard focus, and validation for child radios

The components automatically handle:

  • Form integration and constraint validation
  • Required state handling with validation messages
  • Accessibility attributes, keyboard interaction, and labeling

Example ​

html
<w-radio name="plan" value="basic">Basic plan</w-radio>

<script type="module">
  const radio = document.querySelector('w-radio');

  radio.addEventListener('change', (event) => {
    console.log('Checked:', event.target.checked);
  });
</script>

Props ​

Optional Props ​

NameTypeDefaultDescription
checkedbooleanfalseDraws the radio in a checked state.
disabledbooleanfalseDisables the radio.
invalidbooleanfalseDraws the radio in an invalid state.
namestring''The name of the radio, submitted as a name/value pair with form data.
requiredbooleanfalseMakes the radio a required field.
valuestring'on'The value of the radio, submitted as a name/value pair with form data.

Events ​

NameDescription
changeFired when the checked state changes.
invalidFired when the radio fails validation.

Methods ​

NameParametersReturnsDescription
blur-voidRemoves focus from the radio.
checkValidity-booleanChecks whether the radio passes constraint validation.
click-voidSimulates a click on the radio.
focusoptions?voidSets focus on the radio.
reportValidity-booleanChecks validity and shows validation UI behavior if invalid.
resetFormControl-voidResets the radio to its initial checked state.

Validation Properties ​

NameTypeDescription
validationMessagestringReturns the validation message if the radio is invalid, otherwise an empty string.
validityValidityStateReturns the validity state of the radio.

Label (slot) ​

Provide the radio label as default slot content.

html
<w-radio name="contact" value="email">Email</w-radio>

Checked (checked) ​

Sets the radio to a checked state.

Type: boolean

Default: false

html
<w-radio checked name="plan" value="pro">Pro plan</w-radio>

Validation ​

Required (required) ​

When set, the radio must be checked before form submission.

Type: boolean

Default: false

html
<form id="radio-form">
  <w-radio name="terms" required value="agree">I agree to the terms</w-radio>
  <w-radio name="terms" required value="disagree">I do not agree to the terms</w-radio>
  <w-button type="submit" style="margin-top: 8px;">Submit</w-button>
</form>
<script type="module">
  const form = document.querySelector('#radio-form');
  form.addEventListener('submit', (event) => {
    event.preventDefault();
    const radio = form.querySelector('w-radio');
    if (radio.reportValidity()) {
      console.log('Form is valid!');
    }
  });
</script>

Invalid (invalid) ​

Renders the radio in an invalid state. This is useful for external validation flows.

Type: boolean

Default: false

html
<w-radio invalid>There is a problem</w-radio>

Disabled (disabled) ​

Disables the radio.

Type: boolean

Default: false

html
<w-radio disabled>Cannot change</w-radio>

Programmatic Control ​

You can programmatically control the radio value:

html
<w-radio id="controlled-radio" name="choice" value="one">Controlled radio</w-radio>
<w-button id="check-radio" style="margin-top: 8px;">Check</w-button>
<script type="module">
  const radio = document.querySelector('#controlled-radio');
  const button = document.querySelector('#check-radio');

  button.addEventListener('click', () => {
    radio.checked = true;
  });
</script>

Radio Group ​

Use <w-radio-group> to label and validate a set of radios together.

Group Example ​

html
<w-radio-group label="Notification preference" name="notification" help-text="Select one option">
  <w-radio value="email">Email</w-radio>
  <w-radio value="sms">SMS</w-radio>
  <w-radio value="push">Push</w-radio>
</w-radio-group>

Group Props ​

Optional Props ​

NameTypeDefaultDescription
disabledbooleanfalseDisables the radio group and all child radios.
help-textstring-Help text displayed below the group.
invalidbooleanfalseMarks the radio group as invalid.
labelstring-The group label displayed above the radios.
namestring-The name applied to child radios when they do not provide one.
optionalbooleanfalseWhether to show optional text next to the label.
requiredbooleanfalseMakes the radio group required.

Events ​

NameDescription
changeFired when the selected child radio changes.
invalidFired when the radio group fails validation.

Methods ​

NameParametersReturnsDescription
checkValidity-booleanChecks whether the group passes constraint validation.
focusoptions?voidSets focus on the selected radio or first enabled radio.
reportValidity-booleanChecks validity and shows validation UI behavior if invalid.

Group Label (label) ​

A visual label displayed above the radio group.

Type: string

html
<w-radio-group label="Preferred contact">
  <w-radio>Email</w-radio>
</w-radio-group>

Optional (optional) ​

Displays "Optional" next to the group label to indicate the field is not required.

Type: boolean

Default: false

html
<w-radio-group label="Preferred contact" optional>
  <w-radio>Email</w-radio>
</w-radio-group>

Help Text (help-text) ​

Provides additional context below the radio group. When the group is required and no option is selected after interaction, the help text is replaced with a required message.

Type: string

html
<w-radio-group label="Preferred contact" help-text="Choose one">
  <w-radio>Email</w-radio>
  <w-radio>Phone</w-radio>
</w-radio-group>

Group Validation ​

Required (required) ​

When set, one radio in the group must be selected before form submission.

Type: boolean

Default: false

html
<form id="radio-group-form">
  <w-radio-group label="Preferred contact" name="contact" required>
    <w-radio value="email">Email</w-radio>
    <w-radio value="phone">Phone</w-radio>
  </w-radio-group>
  <w-button type="submit" style="margin-top: 8px;">Submit</w-button>
</form>
<script type="module">
  const form = document.querySelector('#radio-group-form');
  form.addEventListener('submit', (event) => {
    event.preventDefault();
    const group = form.querySelector('w-radio-group');
    if (group.reportValidity()) {
      console.log('Form is valid!');
    }
  });
</script>

Invalid (invalid) ​

Marks the group and all child radios as invalid.

Type: boolean

Default: false

html
<w-radio-group label="Preferred contact" invalid help-text="Please select an option">
  <w-radio>Email</w-radio>
  <w-radio>Phone</w-radio>
</w-radio-group>

Form Integration ​

The radio and radio group components work with native HTML forms.

  • Standalone radios with the same name behave like native radio groups (only one can be selected).
  • Inside <w-radio-group>, the group handles validation and applies its name to child radios that do not provide one.
  • The group itself does not submit a value; checked child radios submit values.
html
<form id="group-form">
  <w-radio-group label="Shipping" name="shipping">
    <w-radio value="standard">Standard</w-radio>
    <w-radio value="express">Express</w-radio>
  </w-radio-group>
  <w-button type="submit" style="margin-top: 8px;">Submit</w-button>
</form>
<script type="module">
  const form = document.querySelector('#group-form');
  form.addEventListener('submit', (event) => {
    event.preventDefault();
    const data = new FormData(form);
    console.log('Selected:', data.get('shipping'));
  });
</script>

Styling API ​

This section documents the supported styling hooks for <w-radio>.

Use these hooks to customize appearance without relying on internal structure or selectors.


Parts ​

The radio exposes a small set of parts that can be targeted for last‑mile layout or typography tweaks.

PartTargetsTypical use
controlradio control (circle)minor alignment or sizing tweaks
labellabel contenttypography tweaks

Example:

css
w-radio::part(label) {
  font-weight: 600;
}

w-radio::part(control) {
  margin-top: 1px;
}

Parts are intended as an escape hatch. Prefer component tokens for anything state‑ or size‑related.


Component tokens (--w-c-radio-*) ​

Component tokens act as inputs to the radio styling. They can be set directly on the component or inherited from a parent container.

css
.settings-panel {
  --w-c-radio-gap: 12px;
}

Defaults are defined internally; setting a token is always optional.


Layout & size ​

TokenPurposeDefault
--w-c-radio-gapspace between control and label8px
--w-c-radio-sizewidth/height of the control2rem
--w-c-radio-radiusborder radius of the control50%
--w-c-radio-border-widthborder width1px
--w-c-radio-checked-border-widthborder width when checked0.6rem

Colors ​

TokenPurposeDefault
--w-c-radio-bgcontrol backgroundtheme default
--w-c-radio-border-colorcontrol border colortheme default
--w-c-radio-border-color-checkedborder color when checkedtheme default
--w-c-radio-label-colorlabel text colorcurrentColor

Invalid state ​

TokenPurposeDefault
--w-c-radio-border-color-invalidborder color when invalidtheme default

Disabled state ​

TokenPurposeDefault
--w-c-radio-bg-disabledbackground when disabledtheme default
--w-c-radio-border-color-disabledborder when disabledtheme default
--w-c-radio-label-color-disabledlabel color when disabledtheme default
--w-c-radio-cursor-disabledcursor when disablednot-allowed

Typography ​

TokenPurposeDefault
--w-c-radio-label-font-sizelabel font sizetheme default
--w-c-radio-label-line-heightlabel line heighttheme default

Focus ​

TokenPurposeDefault
--w-c-radio-outline-widthfocus outline width2px
--w-c-radio-outline-colorfocus outline colortheme default
--w-c-radio-outline-offsetfocus outline offsettheme default

Interaction ​

TokenPurposeDefault
--w-c-radio-cursorcursor in enabled statepointer

Motion ​

TokenPurposeDefault
--w-c-radio-transitiontransition for control150ms cubic-bezier(0.4, 0, 0.2, 1)

Transitions are automatically disabled when prefers-reduced-motion: reduce is active.


Examples ​

Compact radio ​

css
.filters w-radio {
  --w-c-radio-gap: 4px;
  --w-c-radio-size: 1.6rem;
}

Emphasized checked state ​

css
w-radio {
  --w-c-radio-border-color-checked: var(--w-s-color-border-selected);
  --w-c-radio-checked-border-width: 0.7rem;
}

Contextual invalid color (advanced) ​

css
.danger-zone w-radio {
  --w-c-radio-border-color-invalid: red;
}

Guidelines ​

  • Before changing the default styles, remember that doing so can result in less consistent experiences for users across the product. Prefer defaults.

  • Prefer component tokens for size, spacing, and state styling

  • Use parts only for small, local tweaks

  • Avoid relying on internal class names or selectors