implement
Radio Group

Radio Group

One choice out of several.

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"),
	);
}

Installation

npx jsrepo add @implementjs/ui/radio-group

It installs @implementjs/lucide at the same time.

Usage

The group is a vertical grid; each item renders its own dot unless you pass children. Roving focus, arrow-key navigation, and the single-selection invariant are the primitive's.

import { RadioGroup, RadioGroupItem } from "@/lib/components/ui/radio-group";

RadioGroup(
	{ value: "comfortable", "aria-label": "Density" },
	Div(
		{ class: "flex items-center gap-2" },
		RadioGroupItem({ id: "comfortable", value: "comfortable" }),
		Label({ for: "comfortable", class: "text-sm font-medium" }, "Comfortable"),
	),
);

Give each item an id and point a Label at it, the same as a checkbox — the item is a Button, not an input.

Controlled

Pass a signal as the group's value to read or set the choice from outside:

const density = signal<string | null>("comfortable");

RadioGroup({ value: density, "aria-label": "Density" } /* items */);

API Reference

Every prop the styling does not consume is forwarded to the Radio Group primitive, so the tables below are the whole surface — the behavior props and the styling ones together.

RadioGroup

The root. Owns which item is checked and the arrow-key focus movement. Sets role="radiogroup". Styled as a vertical grid with a gap between items. Renders a Div; extra props are forwarded onto it.

PropTypeDefaultDescription
valueSignal<string | null> | string | nullnullThe checked item. Pass a signal to control it from outside; a string seeds uncontrolled state.
disabledSignal<boolean> | booleanfalseDisables every item in the group.
requiredbooleanfalseSets aria-required on the group.
loopbooleantrueWhether 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 attributeValue
[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 its own dot indicator unless you pass children of your own. Renders a Button; extra props are forwarded onto it.

PropTypeDefaultDescription
value*stringIdentifies the item. Must be unique within the group.
disabledSignal<boolean> | booleanfalsePrevents checking the item. Sets disabled and data-disabled.
Data attributeValue
[data-radio-group-item]Present
[data-state]"checked" | "unchecked"
[data-value]The item's value
[data-orientation]"horizontal" | "vertical"
[data-disabled]Present when disabled