Skip to content

Radio - Frameworks

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