Radio Group

A native input-backed radio group primitive for single-choice decisions. It includes orb, command-row, segmented, and tile styles, labels, descriptions, disabled and error states, controlled/uncontrolled state, sizes, keyboard-friendly native behavior, and light/dark compatible surfaces.

Loading preview...

Examples

Practical examples and common states for the same installable component.

Orb

Minimal radio rows for normal form choices.

examples/radio-group-orb.tsx
import { RadioGroup, RadioOption } from "@/components/wensity/radio-group";
export function RadioGroupOrb() {
return (
<RadioGroup label="Workspace visibility" defaultValue="private">
<RadioOption
value="private"
label="Private"
description="Only invited members can view this workspace."
/>
<RadioOption
value="team"
label="Team-visible"
description="Every teammate in the organization can discover it."
/>
<RadioOption
value="public"
label="Public"
description="Anyone with the link can view the overview."
/>
</RadioGroup>
);
}

Command rows

Rich rows for setup flows where descriptions and metadata matter.

examples/radio-group-command.tsx
import { IconBrandGithub, IconCloud, IconCode } from "@tabler/icons-react";
import { RadioGroup, RadioOption } from "@/components/wensity/radio-group";
export function RadioGroupCommand() {
return (
<RadioGroup label="Source provider" defaultValue="github" variant="command">
<RadioOption
value="github"
label="GitHub"
description="Import repositories and sync preview deployments."
leading={<IconBrandGithub stroke={1.75} />}
trailing="OAuth"
/>
<RadioOption
value="cli"
label="CLI upload"
description="Ship a local component package from your terminal."
leading={<IconCode stroke={1.75} />}
/>
<RadioOption
value="cloud"
label="Cloud storage"
description="Reference an existing source bundle."
leading={<IconCloud stroke={1.75} />}
/>
</RadioGroup>
);
}

Segment

Compact single-choice control for filters, toolbars, and form headers.

examples/radio-group-segment.tsx
import { RadioGroup, RadioOption } from "@/components/wensity/radio-group";
export function RadioGroupSegment() {
return (
<RadioGroup defaultValue="annual" variant="segment" orientation="horizontal">
<RadioOption value="monthly" label="Monthly" />
<RadioOption value="annual" label="Annual" />
<RadioOption value="custom" label="Custom" />
</RadioGroup>
);
}

Tiles

Selection cards for pricing, onboarding, and high-value decisions.

examples/radio-group-tiles.tsx
import {
IconBuildingSkyscraper,
IconRocket,
IconSparkles,
} from "@tabler/icons-react";
import { RadioCard, RadioGroup } from "@/components/wensity/radio-group";
export function RadioGroupTiles() {
return (
<RadioGroup defaultValue="pro" variant="tile">
<div className="grid gap-3 sm:grid-cols-3">
<RadioCard
value="free"
label="Free"
description="Explore primitives and docs."
eyebrow="$0"
leading={<IconSparkles stroke={1.75} />}
/>
<RadioCard
value="pro"
label="Pro"
description="Use source files in production."
eyebrow="$19"
leading={<IconRocket stroke={1.75} />}
/>
<RadioCard
value="team"
label="Team"
description="Seats, billing, and shared tokens."
eyebrow="Custom"
leading={<IconBuildingSkyscraper stroke={1.75} />}
/>
</div>
</RadioGroup>
);
}

Controlled

Controlled value for app state and live summaries.

examples/radio-group-controlled.tsx
"use client";
import * as React from "react";
import { IconBuildingSkyscraper, IconCreditCard } from "@tabler/icons-react";
import { RadioGroup, RadioOption } from "@/components/wensity/radio-group";
export function RadioGroupControlled() {
const [value, setValue] = React.useState("card");
return (
<RadioGroup value={value} onValueChange={setValue} variant="command">
<RadioOption
value="card"
label="Card"
description="Charge the saved company card today."
leading={<IconCreditCard stroke={1.75} />}
/>
<RadioOption
value="invoice"
label="Invoice"
description="Send a net-30 invoice to billing."
leading={<IconBuildingSkyscraper stroke={1.75} />}
/>
</RadioGroup>
);
}

Error

Validation messaging for required single-choice fields.

examples/radio-group-error.tsx
import { IconShieldLock } from "@tabler/icons-react";
import { RadioGroup, RadioOption } from "@/components/wensity/radio-group";
export function RadioGroupError() {
return (
<RadioGroup
label="Security policy"
error="Choose a policy before saving this workspace."
variant="command"
>
<RadioOption
value="standard"
label="Standard"
description="Balanced defaults for most teams."
leading={<IconShieldLock stroke={1.75} />}
/>
<RadioOption
value="strict"
label="Strict"
description="Require 2FA, SSO, and token approvals."
leading={<IconShieldLock stroke={1.75} />}
/>
</RadioGroup>
);
}

Disabled

Disabled choices stay readable without accepting input.

examples/radio-group-disabled.tsx
import { IconDeviceLaptop, IconShieldLock } from "@tabler/icons-react";
import { RadioGroup, RadioOption } from "@/components/wensity/radio-group";
export function RadioGroupDisabled() {
return (
<RadioGroup defaultValue="desktop" variant="command">
<RadioOption
value="desktop"
label="Desktop"
description="Sync settings on this device."
leading={<IconDeviceLaptop stroke={1.75} />}
/>
<RadioOption
value="managed"
label="Managed device"
description="Controlled by your organization."
disabled
leading={<IconShieldLock stroke={1.75} />}
/>
</RadioGroup>
);
}