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

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

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