Skip to content

Radio Group

Lets the user pick exactly one option from a small, visible set. Use with Radio children.

Inputv0.1.1experimentalWCAG 2.2 AAView spec
Plan
import { Radio, RadioGroup } from "@rdloom/react";

export default function RadioGroupBasicExample() {
  return (
    <RadioGroup label="Plan" defaultValue="pro">
      <Radio value="free">Free</Radio>
      <Radio value="pro">Pro</Radio>
      <Radio value="team">Team</Radio>
    </RadioGroup>
  );
}

Installation

npx rdloom add radio-group

Copies the source into src/components/rdloom. Edit it freely: rdloom upgrade merges later versions into your changes. It needs react-aria-components; add --install to install them.

Use another registry client
npx shadcn@latest add https://rdloom.vimalbhatt.com/r/radio-group.json

Works, but without upgrade tracking.

Usage

import { Radio, RadioGroup } from "@rdloom/react";

<RadioGroup label="Plan" defaultValue="pro">
  <Radio value="free">Free</Radio>
  <Radio value="pro">Pro</Radio>
  <Radio value="team">Team</Radio>
</RadioGroup>

Horizontal

Billing
import { Radio, RadioGroup } from "@rdloom/react";

export default function RadioGroupHorizontalExample() {
  return (
    <RadioGroup label="Billing" orientation="horizontal" defaultValue="monthly">
      <Radio value="monthly">Monthly</Radio>
      <Radio value="yearly">Yearly</Radio>
    </RadioGroup>
  );
}

Invalid

Shipping
import { Button, Radio, RadioGroup } from "@rdloom/react";

export default function RadioGroupInvalidExample() {
  return (
    <form className="flex flex-col items-start gap-3" onSubmit={(e) => e.preventDefault()}>
      {/* Submit without choosing to see the error. */}
      <RadioGroup label="Shipping" isRequired>
        <Radio value="standard">Standard</Radio>
        <Radio value="express">Express</Radio>
      </RadioGroup>
      <Button type="submit">Continue</Button>
    </form>
  );
}

Disabled

Region
import { Radio, RadioGroup } from "@rdloom/react";

export default function RadioGroupDisabledExample() {
  return (
    <RadioGroup label="Region" defaultValue="eu" isDisabled>
      <Radio value="eu">Europe</Radio>
      <Radio value="us">United States</Radio>
    </RadioGroup>
  );
}

API Reference

Defined by the spec. Components also accept the props of the React Aria component they wrap.

PropTypeDefault
labelrequired

Visible group label.

stringnone
description

Help text shown under the options.

stringnone
errorMessage

Shown when the group is invalid.

stringnone
orientation

Layout direction of the options.

"vertical" | "horizontal""vertical"
value

Controlled selected value.

stringnone
defaultValue

Initial value when uncontrolled.

stringnone
isDisabled

Disables every option.

booleanfalse
isInvalid

Marks the group as invalid and shows errorMessage.

booleanfalse
isRequired

Requires a selection for form submission.

booleanfalse
childrenrequired

Radio options.

nodenone
onChange

Called with the newly selected value.

(value: string) => voidnone

Accessibility

Role radiogroup, WCAG 2.2 AA. Tested with axe and keyboard tests; screen reader checks are in the audit checklist.

Keyboard

  • Arrow keys move and select
  • Tab enters and leaves the group

Screen readers announce

  • Entering the group announces the group label
  • Each option: radio button, its label, checked state and position (2 of 3)
  • Arrow keys announce the newly selected option

What your code must do

  • Group has a visible label
  • Only the selected radio is in the tab order

Guidelines

Use it when

  • 2 to 6 mutually exclusive options that should all be visible

Avoid it when

  • Many options: use Select
  • Independent options: use Checkbox

Don't

  • A single radio on its own
  • No option selected when a sensible default exists
  • Passing isInvalid for required or format checks (even isInvalid={false}): any defined value takes over validity and hides the built-in errors. Use isRequired and validate; pass isInvalid only for errors the app finds itself, such as from the server

Design tokens

The semantic tokens this component uses. Change them once and every component follows; see Design tokens.

  • --rd-color-action-primary
  • --rd-color-border-strong
  • --rd-color-surface-default
  • --rd-color-text-default
  • --rd-color-text-muted
  • --rd-color-feedback-danger
  • --rd-color-focus-ring