Skip to content

HyRadio

A form-associated radio button component that provides single-choice selection within a group. Supports comprehensive form integration via the ElementInternals API, accessibility features, and customizable styling. Automatically manages mutual exclusivity when radio buttons share the same name attribute.

Key Behavioral Model

Radio buttons implement mutually exclusive selection within groups:

  • Single selection: Checking one radio unchecks others in the same group

  • Click to select: Once selected, clicking again has no effect

  • Keyboard navigation: Space/Enter to select, Arrow keys to move between group members (when inside hy-radio-group)

  • No deselection: Users cannot uncheck a radio button directly (use setChecked(false) programmatically)

  • setChecked(): Programmatically select a radio and uncheck others in group

  • Group management: Automatic handling of name-based grouping

  • Form integration: Works seamlessly with native form submission via ElementInternals

Form Integration

This component implements the Form-Associated Custom Elements API. When used standalone (not inside hy-radio-group), each radio participates in form submission via ElementInternals. When used inside hy-radio-group, the group component handles form submission and individual radios become presentational.

Styling and Theming

The component uses design tokens from your design system:

  • small: 16px radio button, 8px inner dot

  • medium: 20px radio button, 12px inner dot (default)

  • large: 24px radio button, 16px inner dot

  • --hy-background-surface-base: Background color when unchecked

  • --hy-foreground-default-rest: Color of inner dot

  • --hy-foreground-default-rest: Label text color

  • --hy-foreground-subtle-rest: Top label and help text color

  • --hy-foreground-danger-rest: Error variant text color

  • --hy-foreground-default-disabled: Disabled state color

  • Small: Uses --hy-body-sm-* tokens

  • Medium: Uses --hy-body-md-* tokens

  • Large: Uses --hy-body-lg-* tokens

Common Use Cases

Examples

Simple Single Selection (Standalone)

html
<form>
  <hy-radio name="size" value="small" label="Small"></hy-radio>
  <hy-radio name="size" value="medium" label="Medium" state="on"></hy-radio>
  <hy-radio name="size" value="large" label="Large"></hy-radio>
  <button type="submit">Submit</button>
</form>
html
<form>
  <hy-radio-group name="size" label="Select Size" value="medium">
    <hy-radio value="small" label="Small"></hy-radio>
    <hy-radio value="medium" label="Medium"></hy-radio>
    <hy-radio value="large" label="Large"></hy-radio>
  </hy-radio-group>
  <button type="submit">Submit</button>
</form>

Radio with Different Sizes

html
<hy-radio name="size-demo" value="small" label="Small Radio" size="small"> </hy-radio>
<hy-radio name="size-demo" value="medium" label="Medium Radio" size="medium"> </hy-radio>
<hy-radio name="size-demo" value="large" label="Large Radio" size="large"> </hy-radio>

Error State for Validation Feedback

html
<hy-radio
  name="terms"
  value="agree"
  label="I agree to the terms and conditions"
  variant="error"
  help-text="You must agree to continue"
  required
>
</hy-radio>

Using Slots for Rich Content

html
<hy-radio name="plan" value="premium">
  <span slot="top-label">Select Plan</span>
  <span slot="help-text"> <strong>Premium</strong> includes all features </span>
</hy-radio>

Event Handling

Programmatic Methods

Accessibility Features

  • Full keyboard navigation support (Space/Enter to check, Arrow keys via hy-radio-group)
  • Proper ARIA attributes (role, aria-checked, aria-describedby)
  • Screen reader announcements for state changes
  • High contrast mode support with system color keywords
  • Minimum 44x44px touch targets on mobile devices
  • Semantic form integration with native validation via ElementInternals
  • Focus visible indicators (outline only on keyboard focus)

Design Token Requirements

This component requires the following design tokens to be defined:

Size tokens:

  • --hy-radio-size-sm, --hy-radio-size-md, --hy-radio-size-lg
  • --hy-radio-padding-size-sm, --hy-radio-padding-size-md, --hy-radio-padding-size-lg

Color tokens:

  • --hy-background-surface-base
  • --hy-foreground-default-rest, --hy-foreground-subtle-rest
  • --hy-foreground-danger-rest, --hy-foreground-default-disabled

Typography tokens (per size):

  • --hy-body-sm-*, --hy-body-md-*, --hy-body-lg-*

## Events

- **change** - Fired when state changes. Detail: { state: RadioState, checked: boolean, value: string, name: string, reason: 'user' }
- **input** - Standard form input event for compatibility

## Slots

- **default** - The radio label content (alternative to label attribute)
- **top-label** - Content to display above the radio button as a group label
- **help-text** - Content to display below the radio button as help or error text

## Methods

### willUpdate()

Generates unique IDs before the first render to prevent update-after-update warnings.
IDs are generated client-side only to prevent SSR/client hydration mismatches.

### checkValidity()

Checks the validity of the radio button against any validation constraints.
Integrates with native HTML form validation via ElementInternals.
Only applicable when radio is standalone (not in radio-group).

```javascript
const radio = document.querySelector('hy-radio[required]');
if (!radio.checkValidity()) {
console.log('Required radio button is not selected');
}

reportValidity()

Checks the validity of the radio button and shows validation messages if invalid. Triggers the browser's built-in validation UI via ElementInternals. Only applicable when radio is standalone (not in radio-group).

javascript
const radio = document.querySelector('hy-radio[required]');
radio.reportValidity(); // Shows native validation message if invalid

focus()

Sets focus on the radio button input element.

javascript
const radio = document.querySelector('hy-radio');
radio.focus(); // Focuses the radio button for keyboard interaction

blur()

Removes focus from the radio button input element.

javascript
const radio = document.querySelector('hy-radio');
radio.blur(); // Removes focus from the radio button

setChecked()

Programmatically sets the checked state of the radio button. When setting to true and radio is standalone (not in radio-group), automatically unchecks other radio buttons in the same group and updates the form value via ElementInternals. When setting to false, clears the form value.

Parameters:

  • checked - Whether the radio button should be checked
javascript
const radio = document.querySelector('hy-radio');
radio.setChecked(true); // Check this radio and uncheck others in group
radio.setChecked(false); // Uncheck this radio

Built with Lit. Documented with VitePress.