Radio Group
Choose exactly one option from a set.
import { Div, Label } from "@implementjs/core";
import { RadioGroup, RadioGroupItem } from "@/lib/components/ui/radio-group";
function Option(value: string, label: string) {
return Div(
{ class: "flex items-center gap-2" },
RadioGroupItem({ id: value, value }),
Label({ for: value, class: "text-sm leading-none font-medium" }, label),
);
}
export default function RadioGroupDemo() {
return RadioGroup(
{ value: "comfortable", "aria-label": "Density" },
Option("default", "Default"),
Option("comfortable", "Comfortable"),
Option("compact", "Compact"),
);
}A radio group is a set of options where choosing one deselects the rest. RadioGroup is the root and owns the value; each RadioGroupItem is one option, rendered as a Button with role="radio".
import { RadioGroup, RadioGroupItem } from "@implementjs/primitives";
RadioGroup(
{ "aria-label": "Density" },
RadioGroupItem({ value: "default" }),
RadioGroupItem({ value: "comfortable" }),
RadioGroupItem({ value: "compact" }),
);
Each part accepts optional props and children — pass a props object when you need attributes, or pass children directly. See createComponent. Extra props are forwarded onto the underlying Div or Button.
Value
RadioGroup owns which item is checked. Pass a string to seed it, or a signal holding string | null to control it from outside:
const density = signal<string | null>("comfortable");
RadioGroup(
{ value: density, "aria-label": "Density" },
RadioGroupItem({ value: "default" }),
RadioGroupItem({ value: "comfortable" }),
RadioGroupItem({ value: "compact" }),
);
density.set("compact"); // checks it from outside
Clicking an item checks it. null means nothing is checked yet; a radio group cannot be uncleared by clicking.
Keyboard and focus
The group is one Tab stop: Tab lands on the checked item, and arrow keys move between the options — moving also checks, the way native radios work. loop (default true) wraps from the last item to the first, and Home and End jump to the ends. orientation (default "vertical") is announced to assistive technology and lands on the data-orientation attributes; all four arrow keys move focus either way.
Disabled
Pass disabled on the group to disable every item, or on one item to disable just it. Both accept a signal, set the native disabled attribute, and add data-disabled for styling. Disabled items are skipped by the arrow keys.
RadioGroup(
{ "aria-label": "Plan" },
RadioGroupItem({ value: "free" }),
RadioGroupItem({ value: "team", disabled: true }),
);
Accessibility
The root sets role="radiogroup" and each item role="radio" with aria-checked. Two things are left to you:
- A name for the group. Point
aria-labelledbyat a visible heading'sid, or passaria-label. - A label per item. Items render as empty buttons; pair each with a
Labelwhoseformatches the item'sid, or passaria-label.
required sets aria-required on the group.
Styling
The root sets data-radio-group-root and items set data-radio-group-item, with data-state as "checked" or "unchecked", plus data-value, data-orientation, and data-disabled:
RadioGroupItem({
value: "compact",
class: "size-4 rounded-full border data-[state=checked]:border-primary",
});
Put your own indicator inside the item — a dot, a check, anything — and show it against data-state.
API Reference
RadioGroup
The root. Owns which item is checked and the arrow-key focus movement. Sets role="radiogroup". Renders a Div; extra props are forwarded onto it.
| Prop | Type | Default | Description |
|---|---|---|---|
value | Signal<string | null> | string | null | null | The checked item. Pass a signal to control it from outside; a string seeds uncontrolled state. |
disabled | Signal<boolean> | boolean | false | Disables every item in the group. |
required | boolean | false | Sets aria-required on the group. |
loop | boolean | true | Whether arrow keys wrap from the last item back to the first. |
orientation | "horizontal" | "vertical" | "vertical" | Announced to assistive technology and set as data-orientation. |
| Data attribute | Value |
|---|---|
[data-radio-group-root] | Present |
[data-orientation] | "horizontal" | "vertical" |
[data-disabled] | Present when disabled |
RadioGroupItem
One option. Sets role="radio" and aria-checked; arrowing to it checks it. Give it a look and an indicator. Renders a Button; extra props are forwarded onto it.
| Prop | Type | Default | Description |
|---|---|---|---|
value* | string | — | Identifies the item. Must be unique within the group. |
disabled | Signal<boolean> | boolean | false | Prevents checking the item. Sets disabled and data-disabled. |
| Data attribute | Value |
|---|---|
[data-radio-group-item] | Present |
[data-state] | "checked" | "unchecked" |
[data-value] | The item's value |
[data-orientation] | "horizontal" | "vertical" |
[data-disabled] | Present when disabled |