Skip to main content
Copy for LLM

Radio

A form control for single-select lists. Multiple radios sharing the same name form a mutually exclusive group.

Basic Usage

Radio group

With Hint

Radios with helper text per option

€9 billed each month

€90 per year — save 2 months

Card Variant

variant="card" turns each option into a bordered, fully-clickable card that highlights when selected — perfect for pricing tiers and plan pickers. The card reacts to its own input via CSS :has(), no JavaScript needed.

Pricing-tier cards

Sizes

sm, md (default), and lg scale the circle and its inner dot together, matching the size prop on Checkbox and Toggle.

Radio sizes

Disabled

Disabled options

With Error

Radio group with a group-level error message
Choose a plan:

Please select a plan.

When validation fails, apply the error prop to one of the radios (usually the last) so the message appears under the group. Wrap the group in a native <fieldset> + <legend> for the WCAG-standard group-label semantics — screen readers announce the legend before each radio in the set.

Livewire Integration

Bind every radio in the group to the same Livewire property via wire:model.live. The radios share a name so the browser already groups them; wire:model synchronizes the chosen value back to the component.

<x-wirekit::radio name="plan" value="free" label="Free" wire:model.live="selectedPlan" />
<x-wirekit::radio name="plan" value="pro"  label="Pro"  wire:model.live="selectedPlan" />

Bound to a property declared int, float or an enum backed by int, each radio is read as a number: wire:model.live goes out as wire:model.number.live. A radio gives its value as text, and Livewire would take the server's typed answer for a change made on the server and set the group back to an earlier choice while a newer one is on its way. A property without a type, or a string one, gets the text.

Props

Prop Type Default Description
label string|null null Text next to the radio
hint string|null null Helper text below
help string|null null An explanation of the field, shown in a tooltip from a question mark beside the label and read as the field's description. Needs a label to stand beside. See Help beside the label
error string|null null Error message (also triggers aria-invalid)
groupError bool true Take the surrounding field.set's group error, or decline it with :group-error="false". A control that belongs to the group but neither causes the rejection nor can resolve it is then neither marked aria-invalid by the group nor described by its message; its own error, its own hint and the set's hint are unaffected
value string|null null Value submitted when selected (required for grouping)
size string 'md' Circle size — sm, md, or lg
variant string 'default' default (inline) or card (the whole bordered card is the selectable target)
scope string|null null Scoped personalization name
announceError bool|null null Render the error message in an aria-live="polite" region so a validation error that appears after render reaches a screen reader. Precedence: this prop, then the parent <x-wirekit::form :announce-errors>, then config('wirekit.a11y.announce_error'). Set false when the page runs its own live region.

The id is auto-generated as {name}-{value} when both are given, ensuring unique IDs within a radio group.

Slots

Slot Description
labelAfter Markup after the label and its help question mark, in the same row and outside both, such as a badge that says a setting is not decided yet. See A Mark After the Label.

Accessibility

  • Native <input type="radio"> — browser provides full keyboard support:
    • Arrow keys navigate between options within the same name group
    • Space selects the focused radio
    • Tab moves focus to the first/checked radio of the next group
  • The focus ring follows the arrow keys in every browser. Safari, and every browser on iOS, does not count the focus an arrow key moves as keyboard focus, so WireKit's scripts note when an arrow key brings the focus to a radio, and the ring follows it there too, on the circle and on a card. Without @wirekitScripts on the page, Safari draws the ring after Tab and not after an arrow key.
  • The visual circle and inner dot are decorative (aria-hidden="true").
  • For a screen-reader-announced group label, wrap related radios in <x-wirekit::field.set>. It renders a native <fieldset> with its <legend> as the first child, the WCAG-recommended pattern for grouped form controls that is announced before each radio in the set, and it resets the fieldset's default border and spacing:
<x-wirekit::field.set legend="Choose a plan" name="plan">
    <x-wirekit::radio name="plan" value="free" label="Free" />
    <x-wirekit::radio name="plan" value="pro" label="Pro" />
</x-wirekit::field.set>

With name, the set shows a validation error for plan once, above the options, and every radio points at it. Radios outside a set each render that message under themselves.

  • A label in another language than the page, such as a language's own name, takes lang. It goes on the label, which holds the words and the radio, so a screen reader says them in that language's voice:
<x-wirekit::field.set legend="Language" name="language">
    <x-wirekit::radio name="language" value="de" label="Deutsch" lang="de" />
    <x-wirekit::radio name="language" value="fr" label="Français" lang="fr" />
</x-wirekit::field.set>

Keyboard Interaction

Key Action
Tab Move focus into the radio group
ArrowUp / ArrowLeft Move focus and selection to the previous radio in the group
ArrowDown / ArrowRight Move focus and selection to the next radio in the group
Space Select the focused radio (when entering the group with Tab)

Pitfalls

  • Don't omit name="..." on a radio group. All radios in the same group MUST share name — otherwise multi-selection is possible and the form posts unexpected data.
  • Don't use a radio group for binary on/off. A <x-wirekit::toggle> is the right pattern; radios are for ≥3 mutually exclusive choices.

Design Tokens

Token Purpose
--color-wk-accent Inner dot + active border
--color-wk-bg-input Circle background
--color-wk-border-strong / --color-wk-border-error Circle border
--color-wk-ring Focus ring

Personalization blocks

Three visual zones are resolvable through WireKit::personalize() / WireKit::scope(), and a config override under components.radio.classes.{block} reaches the same keys:

Block key Applies to
radio.base The visible circle — its border, fill and focus ring
radio.label The wrapping <label> — its display mode, gap and padding (both variants)
radio.text The visible label text

The label is inline-flex, so it is as wide as its content. To make a radio a full-width row with a code or a count at its edge, swap the display mode through the label block and let the text take the rest of the row through the text block, as on a checkbox.

Further Reading

Updated in WireKit v2.66.0 (2026-10-13)

Was this page helpful?

Thank you for your feedback!

Voting requires cookies or local storage. What we store