Radio
StableMutually exclusive option selection. Arrow keys navigate between items — correct ARIA roving tabindex behavior. Supports vertical and horizontal layouts.
Form elementInteractiveVhyxSeal
Interactive example
Selected: starter
Plan selection
Import
tsx
import { RadioGroup, RadioItem } from '@vhyxui/react'Orientation
Vertical (default)
Horizontal
Sizes
sm, md, lg
States
With disabled item
Entire group disabled
Props
RadioGroup
| Prop | Type | Default | Description |
|---|---|---|---|
value | string | — | Controlled selected value. |
defaultValue | string | — | Default value for uncontrolled usage. |
onValueChange | (value: string) => void | — | Called when the selected value changes. |
disabled | boolean | false | Disables all items in the group. |
orientation | 'horizontal' | 'vertical' | 'vertical' | Layout direction of the radio group. |
size | 'sm' | 'md' | 'lg' | 'md' | Size of all radio items. |
contract | Partial<ComponentContract> | — | VhyxSeal contract override. |
RadioItem
| Prop | Type | Default | Description |
|---|---|---|---|
value * | string | — | The value this item represents. |
disabled | boolean | false | Disables this specific item independently of the group. |
children | React.ReactNode | — | Label content for this option. |
Accessibility
- Uses roving
tabIndex— only the selected (or first) item is in the tab order. -
role="radiogroup"on the group.role="radio"andaria-checkedon each item. - Arrow keys navigate between options without leaving the group — Tab exits entirely.
- Disabled items have
aria-disabled="true"and are skipped during arrow key navigation. - Always provide
aria-labelonRadioGroupto name the group for screen readers. - Focus ring via
:focus-visible— visible on keyboard, hidden on mouse click.
Keyboard navigation
| Key | Action |
|---|---|
| Arrow DownorArrow Right | Move focus to the next radio item (wraps around). |
| Arrow UporArrow Left | Move focus to the previous radio item (wraps around). |
| Space | Select the currently focused item. |
| Tab | Move focus out of the radio group entirely. |
| Shift + Tab | Move focus to the previous focusable element. |
Agent contract
Default VhyxSeal contract shipped with every RadioGroup.
Default contract
{
"type": "input",
"intent": "select-option",
"description": "Captures a single mutually exclusive selection from a set of radio options",
"requires": [],
"requiredPermissions": [],
"consequence": "Updates the selected radio value in the parent form context",
"affects": [
"form"
],
"reversible": true,
"safetyLevel": "low",
"requiresConfirmation": false,
"destructive": false,
"contractVersion": "0.0.1",
"fingerprint": "vhyxs_65a21959"
}Theming
Override these CSS tokens to theme RadioGroup.
--vhyx-color-accentSelected indicator fill color
--vhyx-color-accent-hoverIndicator hover color
--vhyx-color-border-strongUnselected border color
--vhyx-color-surfaceUnselected background
--vhyx-radius-fullCircular shape of the radio button
--vhyx-duration-fastSelection animation duration
--vhyx-easing-springSelection animation easing
--vhyx-shadow-focusFocus ring
Examples
T-shirt size selector
Selected: MD
Horizontal size picker
Inside a Field
tsx
<Field name="theme" label="Appearance">
<RadioGroup
value={theme}
onValueChange={setTheme}
aria-label="Appearance theme"
>
<RadioItem value="light">Light</RadioItem>
<RadioItem value="dark">Dark</RadioItem>
<RadioItem value="system">System</RadioItem>
</RadioGroup>
</Field>Theme picker (live)
Active: system
Appearance setting