Radio

A radio group component for selecting a single option from a list of options.

Anatomy

Import and assemble the component:

1import { Radio } from "@raystack/apsara";
2
3<Radio.Group>
4 <Radio />
5 <Radio />
6</Radio.Group>

Usage

Radios always live in a group. The group owns the value; the radios are the options.

Size

Two sizes. large is the default; small fits dense lists. Set size on Radio.Root and every item follows.

1<Radio.Group defaultValue="1" size="large">
2 <Flex gap={3} align="center">
3 <Radio value="1" id="sl1" />
4 <label htmlFor="sl1">Large Option One</label>
5 </Flex>
6 <Flex gap={3} align="center">
7 <Radio value="2" id="sl2" />
8 <label htmlFor="sl2">Large Option Two</label>
9 </Flex>
10</Radio.Group>

Orientation

vertical (the default) stacks the options, which scans faster for more than three. horizontal suits short binary choices in a row.

1<Radio.Group defaultValue="1" orientation="vertical">
2 <Flex gap={3} align="center">
3 <Radio value="1" id="ov1" />
4 <label htmlFor="ov1">Option One</label>
5 </Flex>
6 <Flex gap={3} align="center">
7 <Radio value="2" id="ov2" />
8 <label htmlFor="ov2">Option Two</label>
9 </Flex>
10 <Flex gap={3} align="center">
11 <Radio value="3" id="ov3" />
12 <label htmlFor="ov3">Option Three</label>
13 </Flex>
14</Radio.Group>

With labels

Radio buttons should always be accompanied by labels for accessibility and usability.

1<Radio.Group defaultValue="1">
2 <Flex gap={3} align="center">
3 <Radio value="1" id="L1" />
4 <label htmlFor="L1">Option One</label>
5 </Flex>
6 <Flex gap={3} align="center">
7 <Radio value="2" id="L2" />
8 <label htmlFor="L2">Option Two</label>
9 </Flex>
10 <Flex gap={3} align="center">
11 <Radio value="3" id="L3" />
12 <label htmlFor="L3">Option Three</label>
13 </Flex>
14</Radio.Group>

State

Radio buttons support different states to indicate interactivity and selection.

1<Radio.Group defaultValue="1">
2 <Flex gap={3} align="center">
3 <Radio value="1" id="d1" />
4 <label htmlFor="d1">Default Option</label>
5 </Flex>
6</Radio.Group>

Form example

Radio buttons can be used in forms with proper validation and submission handling.

1<form
2 onSubmit={(e) => {
3 e.preventDefault();
4 const formData = new FormData(e.target);
5 alert(JSON.stringify(Object.fromEntries(formData)));
6 }}
7>
8 <Flex direction="column" gap={5}>
9 <Radio.Group name="plan" defaultValue="monthly">
10 <Flex gap={3} align="center">
11 <Radio value="monthly" id="mp" />
12 <label htmlFor="mp">Monthly Plan</label>
13 </Flex>
14 <Flex gap={3} align="center">
15 <Radio value="yearly" id="yp" />

Controlled

Pass value with onValueChange on Radio.Group to own the selection — needed when the choice drives something else on the page or is submitted with a form.

1(function ControlledRadio() {
2 const [plan, setPlan] = React.useState("team");
3
4 return (
5 <Flex direction="column" gap={5}>
6 <Radio.Group value={plan} onValueChange={setPlan}>
7 <Flex align="center" gap={3}>
8 <Radio value="solo" id="solo" />
9 <Label htmlFor="solo">Solo</Label>
10 </Flex>
11 <Flex align="center" gap={3}>
12 <Radio value="team" id="team" />
13 <Label htmlFor="team">Team</Label>
14 </Flex>
15 </Radio.Group>

API Reference

The group that holds the value, and the radio itself.

Group

Groups radio buttons and manages their shared state.

Prop

Type

Root

Renders an individual radio button.

Prop

Type

Slots

Every rendered part carries a stable data-slot attribute for styling and testing:

SlotElement
radio-groupThe Radio.Group container
radioThe radio button itself
radio-indicatorThe indicator inside the radio button

Accessibility

  • Follows the WAI-ARIA Radio Group pattern
  • Supports keyboard navigation with arrow keys within the group
  • Uses role="radiogroup" for the group and role="radio" for items
  • Selected state is communicated via aria-checked