Radio
Single-choice picker with `RadioGroup` compound API and roving tabindex.
Preview
Switch the framework picker (top-right of the panel) to render the same demo live in React, Vue, or Angular — same class names, ARIA, and visual output across all three.
Installation
Sisyphos UI ships unified packages for React, Vue, and Angular. Pick the one that matches your stack — every framework exports the same component classes, ARIA semantics, and CSS tokens.
$ pnpm add @sisyphos-ui/reactThen import the bundled stylesheet once at app entry: import "@sisyphos-ui/react/styles.css";
Usage
import { useState } from "react";
import { RadioGroup, Radio } from "@sisyphos-ui/react";
export const Plan = () => {
const [plan, setPlan] = useState<string | number>("pro");
return (
<RadioGroup label="Plan" value={plan} onChange={setPlan} variant="card">
<Radio value="free" label="Free" />
<Radio value="pro" label="Pro" />
</RadioGroup>
);
};Card variant
Card variant turns each option into a large, clickable surface.
Sizes
`size` on `RadioGroup` cascades to every `Radio` inside.
API
| Prop | Type | Default | Description |
|---|---|---|---|
| value | string | number | — | Selected value (controlled). Use `defaultValue` for uncontrolled. |
| defaultValue | string | number | — | Initial selected value (uncontrolled). |
| onChange | (value: string | number) => void | — | Called with the new value when the selection changes. |
| options | RadioOption[] | — | Flat option array (`value`, `label`, `description`, `icon`, `disabled`) — alternative to composing `<Radio>` children. |
| label | string | — | Group label rendered above the options and used as the group's accessible name. |
| direction | "horizontal" | "vertical" | "vertical" | Layout direction for the options. |
| variant | "standard" | "card" | "list" | "standard" | Visual style applied to each option. |
| size | "xs" | "sm" | "md" | "lg" | "xl" | "md" | Control size shared by all options. |
| color | "primary" | "success" | "error" | "warning" | "info" | "primary" | Semantic color for the selected state. |
| error | boolean | false | Marks the group as invalid for styling and ARIA. |
| errorMessage | string | — | Message shown below the group when `error` is true. |
| allowAddOption | boolean | false | Shows a trailing add-option button; pair with `onAddOption`. |
The full API including refs, ARIA attributes, and HTML passthroughs lives in the package README on npm.
Accessibility
Adheres to the Radio Group WAI-ARIA design pattern.
- Options are wrapped in a
role="radiogroup"container labeled by the grouplabelviaaria-label. aria-requiredandaria-invalidmirrorrequired/erroron the group; the error message is announced withrole="alert".- Each option is a native
<input type="radio">sharing an auto-generatedname, so browser and AT semantics come for free. - Each radio is nested inside its
<label>, so clicking the label (or card/list row) activates the option. - The custom radio visual is
aria-hidden; only the native input is exposed to assistive tech.
Keyboard interactions
| Key | Action |
|---|---|
| Tab | Moves focus into the group (onto the checked option, or the first option when none is checked). |
| ArrowDownthenArrowRight | Moves selection to the next option (native radio behavior). |
| ArrowUpthenArrowLeft | Moves selection to the previous option (native radio behavior). |
| Space | Selects the focused option. |