<Radio.Group
name="playground-plan"
defaultValue="pro"
ariaLabel="Plan"
>
<Stack
direction="row"
gap={4}
>
<Radio.Item
value="starter"
>
Starter
</Radio.Item>
<Radio.Item
value="pro"
>
Pro
</Radio.Item>
<Radio.Item
value="team"
>
Team
</Radio.Item>
</Stack>
</Radio.Group>Features
- Groups options with a shared label and description.
- Supports controlled and uncontrolled selection.
- Shows helper text under each option.
- Extends the click area to a container with
stretched. - Supports responsive sizes, disabled and error states.
Anatomy
<Radio.Group name="delivery">
<Radio.GroupLabel>Delivery method</Radio.GroupLabel>
<Radio.GroupDescription>Choose how the order ships.</Radio.GroupDescription>
<Radio.Item value="standard">Standard delivery</Radio.Item>
<Radio.Item value="express">Express delivery</Radio.Item>
</Radio.Group>value.Initial Value
Set defaultValue to choose the initial option. A selected radio can't be cleared by clicking it, so use a Checkbox for a single on/off choice.
import { Radio, Stack, Text } from "@vortexlabs/vortex";
<Radio.Group name="delivery" defaultValue="standard">
<Stack gap={4}>
<Radio.GroupLabel>
<Text size="body-md-desktop" weight="medium">Delivery method</Text>
</Radio.GroupLabel>
<Stack gap={3}>
<Radio.Item value="standard">Standard delivery</Radio.Item>
<Radio.Item value="express">Express delivery</Radio.Item>
</Stack>
</Stack>
</Radio.Group>Group Description
Use Radio.GroupDescription for text that applies to every option.
<Radio.Group name="billing" defaultValue="monthly">
<Stack gap={4}>
<Stack gap={1}>
<Radio.GroupLabel>
<Text size="body-md-desktop" weight="medium">Billing interval</Text>
</Radio.GroupLabel>
<Radio.GroupDescription>
<Text size="body-sm-desktop" color="subtle">You can change this at any time.</Text>
</Radio.GroupDescription>
</Stack>
<Stack gap={3}>
<Radio.Item value="monthly">Monthly</Radio.Item>
<Radio.Item value="yearly">Yearly</Radio.Item>
</Stack>
</Stack>
</Radio.Group>Sizes
Radio comes in sm and md; the default is md. Pass a breakpoint object to change size by screen width.
<Radio.Group name="size" defaultValue="small" ariaLabel="Radio sizes">
<Stack gap={4}>
<Radio.Item value="small" size="sm">Small</Radio.Item>
<Radio.Item value="medium" size="md">Medium</Radio.Item>
<Radio.Item value="responsive" size={{ xs: "sm", md: "md" }}>Responsive</Radio.Item>
</Stack>
</Radio.Group>Helper Text
Use children for the label and helperText for supporting information.
<Radio.Group name="access" defaultValue="invite">
<Stack gap={4}>
<Radio.GroupLabel>
<Text size="body-md-desktop" weight="medium">Workspace access</Text>
</Radio.GroupLabel>
<Stack gap={3}>
<Radio.Item value="invite" helperText="Only people you invite can join.">Invite only</Radio.Item>
<Radio.Item value="domain" helperText="Anyone with a company email address can join.">Company domain</Radio.Item>
</Stack>
</Stack>
</Radio.Group>Controlled Selection
Pass value to Radio.Group and update it in onChange. Use null to clear the selection.
"use client";
import { Button, Radio, Stack, Text } from "@vortexlabs/vortex";
import React from "react";
export const RadioControlledExample = () => {
const [value, setValue] = React.useState<string | null>("monthly");
return (
<Stack gap={4}>
<Radio.Group
name="billing-controlled"
value={value}
onChange={({ value }) => setValue(value)}
>
<Stack gap={4}>
<Radio.GroupLabel>
<Text size="body-md-desktop" weight="medium">Billing interval</Text>
</Radio.GroupLabel>
<Stack gap={3}>
<Radio.Item value="monthly">Monthly</Radio.Item>
<Radio.Item value="yearly">Yearly</Radio.Item>
</Stack>
</Stack>
</Radio.Group>
<Text size="body-sm-desktop">Selected: {value ?? "None"}</Text>
<Button variant="secondary" onClick={() => setValue(null)}>
Clear selection
</Button>
</Stack>
);
};Stretched Click Area
Set stretched to make the whole container clickable, such as a card. Place the item directly inside it; other links or buttons in the container need position: relative; z-index: 1.
<Radio.Group name="plan" defaultValue="team" ariaLabel="Plan">
<Stack direction="row" gap={3}>
<Stack padding={4} borderRadius="md" borderColor="default">
<Radio.Item stretched value="starter" helperText="Up to 3 projects">Starter</Radio.Item>
</Stack>
<Stack padding={4} borderRadius="md" borderColor="default">
<Radio.Item stretched value="team" helperText="Unlimited projects">Team</Radio.Item>
</Stack>
</Stack>
</Radio.Group>Disabled Items
Set disabled on an item to make that option unavailable, or on Radio.Group to disable all options.
<Radio.Group name="export-format" defaultValue="csv">
<Stack gap={4}>
<Radio.GroupLabel>
<Text size="body-md-desktop" weight="medium">Export format</Text>
</Radio.GroupLabel>
<Stack gap={3}>
<Radio.Item value="csv">CSV</Radio.Item>
<Radio.Item value="pdf" disabled helperText="PDF export is unavailable for this report.">PDF</Radio.Item>
</Stack>
</Stack>
</Radio.Group>Error State
Set error on the group and explain the fix in Radio.GroupDescription. Pass native attributes like required through inputAttributes.
<Radio.Group name="region" error>
<Stack gap={4}>
<Stack gap={1}>
<Radio.GroupLabel>
<Text size="body-md-desktop" weight="medium">Data storage region</Text>
</Radio.GroupLabel>
<Radio.GroupDescription>
<Text size="body-sm-desktop" color="critical">Choose a region to continue.</Text>
</Radio.GroupDescription>
</Stack>
<Stack gap={3}>
<Radio.Item value="au" inputAttributes={{ required: true }}>Australia</Radio.Item>
<Radio.Item value="eu">Europe</Radio.Item>
</Stack>
</Stack>
</Radio.Group>Accessibility
Space while a radio is focused selects it.ArrowDown or ArrowRight selects the next option, and ArrowUp or ArrowLeft the previous one. Selection wraps and skips disabled options.Radio.GroupLabel or ariaLabel, and provide ariaLabel for items without visible text.