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 colorSmall: Uses
--hy-body-sm-*tokensMedium: Uses
--hy-body-md-*tokensLarge: Uses
--hy-body-lg-*tokens
Common Use Cases
Examples
Simple Single Selection (Standalone)
<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>Using with Radio Group (Recommended)
<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
<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
<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
<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).
const radio = document.querySelector('hy-radio[required]');
radio.reportValidity(); // Shows native validation message if invalidfocus()
Sets focus on the radio button input element.
const radio = document.querySelector('hy-radio');
radio.focus(); // Focuses the radio button for keyboard interactionblur()
Removes focus from the radio button input element.
const radio = document.querySelector('hy-radio');
radio.blur(); // Removes focus from the radio buttonsetChecked()
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
const radio = document.querySelector('hy-radio');
radio.setChecked(true); // Check this radio and uncheck others in group
radio.setChecked(false); // Uncheck this radio