Radio
Standalone radio buttons and radio group for single-select options — built with Tailwind CSS.
Preview
Basic radio group
import { RadioGroup } from '@/registry/ui-kit/tailwind-radio/react'
function Example() {
return (
<RadioGroup
name="color"
options={[
{ value: 'red', label: 'Red' },
{ value: 'blue', label: 'Blue' },
{ value: 'green', label: 'Green' },
]}
/>
)
}With descriptions
import { RadioGroup } from '@/registry/ui-kit/tailwind-radio/react'
function Example() {
return (
<RadioGroup
name="plan"
options={[
{ value: 'free', label: 'Free', description: 'Up to 5 projects.' },
{ value: 'pro', label: 'Pro', description: 'Unlimited projects.' },
]}
/>
)
}Component API
| Prop | Default | Description |
|---|---|---|
name | — | HTML name attribute shared by all radios in the group. |
options | — | Array of radio options for RadioGroup. |
value | — | Currently selected value (controlled). |
onChange | — | Callback when selection changes. |
label | — | Text label for a single Radio input. |
description | — | Optional helper text for a single Radio input. |
Source Code
"use client";
import { forwardRef } from "react";
/* ── Radio ── */
interface RadioProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, "type"> {
label: string;
description?: string;
className?: string;
}
const Radio = forwardRef<HTMLInputElement, RadioProps>(
({ label, description, className = "", ...props }, ref) => {
return (
<label className={`flex items-start gap-3 ${className}`}>
<input
ref={ref}
type="radio"
className="h-4 w-4 shrink-0 cursor-pointer border-zinc-300 text-indigo-600 focus:ring-indigo-500/20 dark:border-zinc-600 dark:bg-zinc-900"
{...props}
/>
<span className="select-none">
<span className="block text-sm font-medium text-zinc-900 dark:text-zinc-100">
{label}
</span>
{description && (
<span className="block text-sm text-zinc-500 dark:text-zinc-400">
{description}
</span>
)}
</span>
</label>
);
}
);
Radio.displayName = "Radio";
/* ── RadioGroup ── */
interface RadioOption {
value: string;
label: string;
description?: string;
}
interface RadioGroupProps {
name: string;
options: RadioOption[];
value?: string;
onChange?: (value: string) => void;
className?: string;
}
function RadioGroup({ name, options, value, onChange, className = "" }: RadioGroupProps) {
return (
<div className={`space-y-3 ${className}`} role="radiogroup">
{options.map((option) => (
<Radio
key={option.value}
name={name}
value={option.value}
label={option.label}
description={option.description}
checked={value === option.value}
onChange={() => onChange?.(option.value)}
/>
))}
</div>
);
}
export { Radio, RadioGroup };
export type { RadioOption, RadioGroupProps };
export default Radio;