Skip to content
HHydro UIdocs
Navigate
ComponentsRadio Group
ImplementedForms / selection

Radio Group

Offer mutually exclusive choices with roving keyboard navigation.

Interactive

Try it

value, loop, required
BasicStandardProfessional
Live previewReady
MarkupStateEvents
<hui-radio-group id="playground-radio-group" name="plan" value="standard" aria-label="Plan">
  <hui-radio value="basic">Basic</hui-radio>
  <hui-radio value="standard">Standard</hui-radio>
  <hui-radio value="pro">Professional</hui-radio>
</hui-radio-group>
data-state
Waiting for enhancement

No component events yet.

Usage

Use hui-radio-group for a set of mutually exclusive choices. Each hui-radio has a stable value; the group exposes the selected value through its value attribute and emits hui-value-change when selection changes.

The default radio presentation is native-first: every item renders a real radio input. Set as="button" on an item when a button-based presentation is required; that variant keeps form submission through a visually hidden native radio input.

Do not use a radio group for independent choices (use a checkbox group), a binary setting (use a switch), or a command (use a button).

Anatomy

  • Group host: hui-radio-group with role="radiogroup"
  • Item host: hui-radio
  • Native variant: labelled input[type="radio"]
  • Button variant: button[role="radio"] plus a visually hidden native radio input
  • Label content: default slot
  • State mirror: item host data-state="checked|unchecked"

Examples

Fixture exampleSource-backed
<section aria-labelledby="plans-h">
    <h2 id="plans-h">Plan</h2>
    <form id="plans-form">
      <hui-radio-group id="plans" name="plan" value="standard" aria-labelledby="plans-h" loop>
        <hui-radio value="basic">Basic</hui-radio>
        <hui-radio value="standard"><b>Standard</b></hui-radio>
        <hui-radio value="pro" disabled>Pro</hui-radio>
        <hui-radio value="enterprise" as="button">Enterprise</hui-radio>
      </hui-radio-group>
    </form>
  </section>

API reference

Group attributes

AttributeMeaning
valueSelected item value; source of truth for group selection.
nameName applied to items that do not provide their own native form name.
loopWhen present, arrow navigation wraps from the last enabled item to the first.
allow-emptyWhen present, a selected button item may be cleared by activating it again.
requiredMarks the group required and applies native required validation to its items.
aria-label / aria-labelledbyAccessible group name.
aria-describedbyAccessible group description.

Item attributes

AttributeMeaning
valueStable submitted and selected value.
checkedItem selection mirror; normally managed by the group.
disabledRemoves the item from keyboard navigation and prevents activation.
requiredNative form validation requirement.
name, formNative form association; name falls back to the group name.
asnative (default) or button. Rendering mode is chosen at connection time.

Events:

  • hui-value-change: emitted by the group with { value: string | undefined }.
  • hui-checked-change: emitted by each item with { checked: boolean }.

States and styling

StateContract and styling guidance
Default / uncheckeddata-state="unchecked"; use neutral surface and border aliases.
HoverUse --hui-color-interactive-hover without changing selection.
ActiveUse --hui-color-interactive-active.
FocusKeep a visible focus ring using --hui-color-focus-ring. Only the selected enabled item is in the tab order.
Checkeddata-state="checked" and aria-checked="true"; use --hui-color-interactive.
DisabledNative disabled or aria-disabled="true"; skip disabled items during roving navigation.
ErrorNo built-in error state. Consumers may use aria-invalid="true" with associated error text.
State channel

Attributes are the source of truth. Style derived state with data-state, ARIA attributes, and the --hui-* token aliases.

Accessibility and keyboard support

  • ArrowUp / ArrowLeft moves to the previous enabled item and selects it.
  • ArrowDown / ArrowRight moves to the next enabled item and selects it.
  • Horizontal arrow direction is inverted when the group is in RTL.
  • Home and End select the first and last enabled items.
  • Arrow navigation wraps only when loop is present.
  • Space activates the focused item. Tab leaves the group; the selected enabled item is the single tab stop.
  • Checked native radios submit their name/value; unchecked radios submit nothing.

SSR and forms

SSR writes role="radiogroup", item ARIA state, checked attributes, native form attributes, and deterministic selected state. The checked attribute is written explicitly so it survives happy-dom serialization and client adoption. Without JavaScript, the native presentation remains visible and native radio inputs remain selectable; group-level arrow coordination and button-mode selection are unavailable.

Code

<link rel="stylesheet" href="./styles/tokens.css" />
<link rel="stylesheet" href="./styles/a11y.css" />
<link rel="stylesheet" href="./styles/components.css" />

<hui-radio-group name="plan" value="standard" aria-labelledby="plan-label">
  <span id="plan-label">Plan</span>
  <hui-radio value="basic">Basic</hui-radio>
  <hui-radio value="standard">Standard</hui-radio>
  <hui-radio value="pro" disabled>Pro</hui-radio>
</hui-radio-group>
<hui-radio-group id="playground-radio-group" name="plan" value="standard" aria-label="Plan">
  <hui-radio value="basic">Basic</hui-radio>
  <hui-radio value="standard">Standard</hui-radio>
  <hui-radio value="pro">Professional</hui-radio>
</hui-radio-group>