import { FieldItem, FieldLabel, FieldLegend, FieldSet } from "@/components/ui/field";
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
export default function RadioGroupBasic() {
return (
<FieldSet>
<FieldLegend variant="label">Density</FieldLegend>
<RadioGroup defaultValue="comfortable">
<FieldItem>
<RadioGroupItem value="compact" />
<FieldLabel>Compact</FieldLabel>
</FieldItem>
<FieldItem>
<RadioGroupItem value="comfortable" />
<FieldLabel>Comfortable</FieldLabel>
</FieldItem>
<FieldItem>
<RadioGroupItem value="spacious" />
<FieldLabel>Spacious</FieldLabel>
</FieldItem>
</RadioGroup>
</FieldSet>
);
}- Add the registryOnce per project
pnpm dlx shadcn@latest registry add @jarvis=https://ui.jarv.is/r/{name}.json - Add radio-group
pnpm dlx shadcn@latest add @jarvis/radio-group
Usage
Pair each item with a label in a FieldItem, and name the group with a FieldSet and
FieldLegend.
import { FieldItem, FieldLabel, FieldLegend, FieldSet } from "@/components/ui/field";
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
export function ThemePicker() {
return (
<FieldSet>
<FieldLegend variant="label">Theme</FieldLegend>
<RadioGroup defaultValue="system">
<FieldItem>
<RadioGroupItem value="light" />
<FieldLabel>Light</FieldLabel>
</FieldItem>
<FieldItem>
<RadioGroupItem value="dark" />
<FieldLabel>Dark</FieldLabel>
</FieldItem>
<FieldItem>
<RadioGroupItem value="system" />
<FieldLabel>System</FieldLabel>
</FieldItem>
</RadioGroup>
</FieldSet>
);
}Without a visible legend, give the RadioGroup an aria-label instead.
Composition
Examples
With descriptions
Wrap the label in a FieldContent with a FieldDescription when an option needs explaining.
import {
FieldContent,
FieldDescription,
FieldItem,
FieldLabel,
FieldLegend,
FieldSet,
} from "@/components/ui/field";
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
export default function RadioGroupWithDescriptions() {
return (
<FieldSet className="w-full max-w-sm">
<FieldLegend variant="label">Visibility</FieldLegend>
<RadioGroup defaultValue="private">
<FieldItem>
<RadioGroupItem value="public" />
<FieldContent>
<FieldLabel>Public</FieldLabel>
<FieldDescription>Anyone with the link can view it.</FieldDescription>
</FieldContent>
</FieldItem>
<FieldItem>
<RadioGroupItem value="private" />
<FieldContent>
<FieldLabel>Private</FieldLabel>
<FieldDescription>Only people you invite can view it.</FieldDescription>
</FieldContent>
</FieldItem>
</RadioGroup>
</FieldSet>
);
}Disabled
Set disabled on an item, or on the RadioGroup to disable all of them.
import {
FieldContent,
FieldDescription,
FieldItem,
FieldLabel,
FieldLegend,
FieldSet,
} from "@/components/ui/field";
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
export default function RadioGroupDisabled() {
return (
<FieldSet>
<FieldLegend variant="label">Layout</FieldLegend>
<RadioGroup defaultValue="list">
<FieldItem>
<RadioGroupItem value="list" />
<FieldLabel>List</FieldLabel>
</FieldItem>
<FieldItem>
<RadioGroupItem value="board" />
<FieldLabel>Board</FieldLabel>
</FieldItem>
<FieldItem>
<RadioGroupItem value="timeline" disabled />
<FieldContent>
<FieldLabel>Timeline</FieldLabel>
<FieldDescription>Not available on small screens.</FieldDescription>
</FieldContent>
</FieldItem>
</RadioGroup>
</FieldSet>
);
}Choice cards
Put the item and its FieldContent inside the FieldLabel to make the whole card clickable.
import {
FieldContent,
FieldDescription,
FieldItem,
FieldLabel,
FieldLegend,
FieldSet,
FieldTitle,
} from "@/components/ui/field";
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
const plans = [
{ value: "starter", name: "Starter", description: "Up to 3 projects and 5 members." },
{ value: "team", name: "Team", description: "Unlimited projects and 25 members." },
{ value: "enterprise", name: "Enterprise", description: "SSO, audit logs and priority support." },
];
export default function RadioGroupChoiceCards() {
return (
<FieldSet className="w-full max-w-sm">
<FieldLegend variant="label">Plan</FieldLegend>
<RadioGroup defaultValue="team">
{plans.map((plan) => (
<FieldItem key={plan.value}>
<FieldLabel>
<FieldContent>
<FieldTitle>{plan.name}</FieldTitle>
<FieldDescription>{plan.description}</FieldDescription>
</FieldContent>
<RadioGroupItem value={plan.value} />
</FieldLabel>
</FieldItem>
))}
</RadioGroup>
</FieldSet>
);
}Invalid
Wrap the group in a Field, set invalid on it, and explain the problem with a FieldError.
import {
Field,
FieldError,
FieldItem,
FieldLabel,
FieldLegend,
FieldSet,
} from "@/components/ui/field";
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
export default function RadioGroupInvalid() {
return (
<Field invalid className="w-fit">
<FieldSet>
<FieldLegend variant="label">Shipping speed</FieldLegend>
<RadioGroup>
<FieldItem>
<RadioGroupItem value="standard" />
<FieldLabel>Standard</FieldLabel>
</FieldItem>
<FieldItem>
<RadioGroupItem value="express" />
<FieldLabel>Express</FieldLabel>
</FieldItem>
</RadioGroup>
</FieldSet>
<FieldError>Choose a shipping speed.</FieldError>
</Field>
);
}Props
The tables leave out className, style and render. Parts built on Base UI take them as its styling and composition guides describe.
RadioGroup
| Prop | Type | Default |
|---|---|---|
disabledWhether the component should ignore user interaction. | boolean | false |
readOnlyWhether the user should be unable to select a different radio button in the group. | boolean | false |
requiredWhether the user must choose a value before submitting a form. | boolean | false |
nameIdentifies the field when a form is submitted. | string | — |
formIdentifies the form that owns the radio inputs. Useful when the radio group is rendered outside the form. | string | — |
valueThe controlled value of the radio item that should be currently selected. To render an uncontrolled radio group, use the | any | — |
defaultValueThe uncontrolled value of the radio button that should be initially selected. To render a controlled radio group, use the | any | — |
onValueChangeCallback fired when the value changes. | ((value: any, eventDetails: RadioGroup.ChangeEventDetails) => void) | — |
inputRefA ref to access the hidden input element. | React.Ref<HTMLInputElement> | — |
RadioGroupItem
| Prop | Type | Default |
|---|---|---|
valueThe unique identifying value of the radio in a group. | any | — |
disabledWhether the component should ignore user interaction. | boolean | — |
requiredWhether the user must choose a value before submitting a form. | boolean | — |
readOnlyWhether the user should be unable to select the radio button. | boolean | — |
inputRefA ref to access the hidden input element. | React.Ref<HTMLInputElement> | — |
nativeButtonWhether the component renders a native | boolean | false |