RadioGroup
Client leafA set of mutually exclusive options.
Live preview
Rendered from the installed VEXA source — the same files you receive.
Installation
Adds the component source to your project. Registry dependencies are pulled in automatically.
npx shadcn@latest add https://vexa.valfiguer.com/r/radio-group.jsonInstalls to components/vexa/radio-group.tsx
npm dependencies
- @radix-ui/react-radio-group
Registry dependencies
- @vexa/utils
Other VEXA items this component needs. Install them first — they are resolved automatically by the CLI.
Source
Copy this into its target path, or install it with the command above.
components/vexa/radio-group.tsx
"use client";
import type * as React from "react";
import * as RadioGroupPrimitive from "@radix-ui/react-radio-group";
import { cn } from "@/lib/utils";
/**
* RadioGroup — a set of mutually exclusive options.
*
* Client leaf. Radix provides the `radiogroup`/`radio` roles and the APG roving
* focus model: Arrow keys move between and select options, Tab moves in and out
* of the group. Give the group an accessible name with `aria-label` or
* `aria-labelledby`, and associate each item with a `<Label htmlFor>`.
*/
export function RadioGroup({
className,
...props
}: React.ComponentProps<typeof RadioGroupPrimitive.Root>) {
return (
<RadioGroupPrimitive.Root
data-slot="radio-group"
className={cn("grid gap-2.5", className)}
{...props}
/>
);
}
export function RadioGroupItem({
className,
...props
}: React.ComponentProps<typeof RadioGroupPrimitive.Item>) {
return (
<RadioGroupPrimitive.Item
data-slot="radio-group-item"
className={cn(
"aspect-square size-5 shrink-0 rounded-full border border-vexa-input bg-vexa-surface-raised shadow-vexa-sm",
"transition-[color,border-color,box-shadow] duration-[var(--vexa-duration-fast)] ease-[var(--vexa-ease-standard)]",
"outline-none focus-visible:ring-2 focus-visible:ring-vexa-ring focus-visible:ring-offset-2 focus-visible:ring-offset-vexa-background",
"disabled:cursor-not-allowed disabled:opacity-50",
"data-[state=checked]:border-vexa-primary",
"aria-[invalid=true]:border-vexa-danger",
className,
)}
{...props}
>
<RadioGroupPrimitive.Indicator
data-slot="radio-group-indicator"
className="flex items-center justify-center"
>
<span className="size-2.5 rounded-full bg-vexa-primary" />
</RadioGroupPrimitive.Indicator>
</RadioGroupPrimitive.Item>
);
}
Details
Example
tsx
<RadioGroup defaultValue="a" aria-label="Plan"><div className="flex items-center gap-2"><RadioGroupItem value="a" id="a" /><Label htmlFor="a">Starter</Label></div></RadioGroup>Accessibility
APG radiogroup model: Arrow keys move and select, Tab enters/exits the group. Give the group a name via aria-label/aria-labelledby and label each item.