Radio
freeRadio lets users pick a single option from a short, mutually exclusive set.
Preview
Dark
Billing plan
Choose the plan applied to this workspace.
import { useState } from 'react';
import Radio from '@/components/ui/Radio';
const plans = [
{ label: 'Starter', value: 'starter', hint: 'For solo projects' },
{ label: 'Team', value: 'team', hint: 'Shared workspaces' },
{ label: 'Business', value: 'business', hint: 'SSO and audit logs' },
];
export default function UsageDemo() {
const [plan, setPlan] = useState('team');
return (
<div className="flex flex-col gap-4">
<div>
<div className="text-base font-semibold text-foreground">
Billing plan
</div>
<p className="text-muted-foreground">
Choose the plan applied to this workspace.
</p>
</div>
<Radio.Group value={plan} onChange={setPlan} vertical>
{plans.map((item) => (
<Radio
key={item.value}
value={item.value}
className="items-start"
radioClass="mt-1"
>
<span className="flex flex-col">
<span>{item.label}</span>
<span className="text-xs text-muted-foreground">
{item.hint}
</span>
</span>
</Radio>
))}
</Radio.Group>
</div>
);
}Installation
Add this component with the NateUI CLI.
npx nateui@latest add RadioExamples
Basic
Preview
Dark
import Radio from '@/components/ui/Radio';
export default function BasicDemo() {
return (
<div className="flex flex-wrap items-center gap-4">
<Radio name="basic-demo" value="off">
Unselected
</Radio>
<Radio name="basic-demo" value="on" defaultChecked>
Selected by default
</Radio>
</div>
);
}Group
Preview
Dark
import { useState } from 'react';
import Radio from '@/components/ui/Radio';
const speeds = [
{ label: 'Standard', value: 'standard' },
{ label: 'Priority', value: 'priority' },
{ label: 'Overnight', value: 'overnight' },
];
export default function GroupDemo() {
const [speed, setSpeed] = useState('priority');
return (
<Radio.Group value={speed} onChange={setSpeed}>
{speeds.map((item) => (
<Radio key={item.value} value={item.value}>
{item.label}
</Radio>
))}
</Radio.Group>
);
}Vertical
Preview
Dark
import { useState } from 'react';
import Radio from '@/components/ui/Radio';
export default function VerticalDemo() {
const [visibility, setVisibility] = useState('team');
return (
<Radio.Group vertical value={visibility} onChange={setVisibility}>
<Radio value="private">Only me</Radio>
<Radio value="team">Everyone on the team</Radio>
<Radio value="public">Anyone with the link</Radio>
</Radio.Group>
);
}States
Preview
Dark
import Radio from '@/components/ui/Radio';
export default function StatesDemo() {
return (
<div className="flex flex-col gap-4">
<Radio name="states-demo" value="selected" defaultChecked>
Active selection
</Radio>
<Radio name="states-demo" value="disabled" disabled>
Disabled unselected
</Radio>
<Radio value="locked" checked disabled>
Disabled selected
</Radio>
<Radio value="readonly" checked readOnly>
Read-only selected
</Radio>
</div>
);
}Custom Color
Preview
Dark
import Radio from '@/components/ui/Radio';
export default function CustomColorDemo() {
return (
<div className="flex flex-col gap-4">
<Radio value="healthy" defaultChecked radioClass="text-success">
Healthy status
</Radio>
<Radio value="review" defaultChecked radioClass="text-warning">
Needs attention
</Radio>
<Radio value="blocked" defaultChecked radioClass="text-destructive">
Blocked deployment
</Radio>
</div>
);
}Controlled
Preview
Dark
Current access: write
import { useState } from 'react';
import Radio from '@/components/ui/Radio';
const levels = [
{ label: 'Read', value: 'read' },
{ label: 'Write', value: 'write' },
{ label: 'Admin', value: 'admin' },
];
export default function ControlledDemo() {
const [access, setAccess] = useState('write');
return (
<div className="flex flex-col gap-4">
<Radio.Group value={access} onChange={setAccess}>
{levels.map((item) => (
<Radio key={item.value} value={item.value}>
{item.label}
</Radio>
))}
</Radio.Group>
<p className="text-xs text-muted-foreground">
Current access: <span className="font-medium">{access}</span>
</p>
</div>
);
}API
Radio exposes a single radio input and a compound Radio.Group for single-selection sets.
Radio
Radio accepts the props below plus native props for the underlying input.
| Prop | Description | Type | Default |
|---|---|---|---|
checked | Controls the selected state for standalone usage. | boolean | - |
defaultChecked | Initial selected state for uncontrolled usage. | boolean | - |
value | Value used by Radio.Group to match the selected option and passed through to the input. | RadioValue | - |
radioClass | Class names applied to the radio control, used for custom color or local styling. | string | - |
children | Label content rendered beside the radio control. | ReactNode | - |
className | Class names applied to the root label. | string | - |
disabled | Prevents interaction and applies disabled styling. Inherited from the group when set there. | boolean | Group disabled |
readOnly | Prevents the radio from changing state on interaction. | boolean | - |
name | Name passed to the input, or inherited from the group. | string | Group name |
onChange | Called with this radio value and the input change event when it becomes selected. | RadioChangeHandler | - |
labelRef | Ref forwarded to the root label element. | Ref<HTMLLabelElement> | - |
ref | Ref forwarded to the underlying radio input. | Ref<HTMLInputElement> | - |
...nativeInputProps | Native props for the underlying radio input. | NativeRadioInputProps | - |
Radio.Group
Radio.Group accepts the props below plus native props for the root div.
| Prop | Description | Type | Default |
|---|---|---|---|
value | Selected value shared by the group; the matching radio is selected. | RadioValue | - |
onChange | Called with the next selected value and the source change event. | RadioGroupChangeHandler | - |
radioClass | Class names applied to every radio control in the group. | string | - |
disabled | Disables every radio in the group. | boolean | - |
name | Name shared by radio inputs inside the group. | string | - |
vertical | Stacks group items vertically. | boolean | false |
children | Radio items rendered inside the group. | ReactNode | - |
className | Class names applied to the group root. | string | - |
ref | Ref forwarded to the group root. | Ref<HTMLDivElement> | - |
...nativeDivProps | Native props for the group root div. | NativeRadioGroupDivProps | - |
Types
type RadioValue = string;
type RadioChangeHandler = (
value: RadioValue,
event: ChangeEvent<HTMLInputElement>,
) => void;
type RadioGroupChangeHandler = (
value: RadioValue,
event: ChangeEvent<HTMLInputElement>,
) => void;
type NativeRadioInputProps = ComponentProps<'input'>;
type NativeRadioGroupDivProps = ComponentProps<'div'>;