Tuimorphic

Radio

Terminal-style radio button group for single selection from multiple options.

Import

import { RadioGroup, Radio } from 'tuimorphic';

Basic Usage

<RadioGroup defaultValue="option1">
  <Radio value="option1" label="Option 1" />
  <Radio value="option2" label="Option 2" />
  <Radio value="option3" label="Option 3" />
</RadioGroup>

Props

RadioGroup Props

PropTypeDefaultDescription
valuestringSelected value (controlled)
defaultValuestringDefault selected value (uncontrolled)
onValueChange(value: string) => voidCallback when value changes
namestringName attribute for forms
disabledbooleanfalseWhether the entire group is disabled
children*React.ReactNodeRadio components
classNamestringAdditional CSS class names
refReact.Ref<HTMLDivElement>Forwarded ref to the container

Radio Props

PropTypeDefaultDescription
value*stringValue of this radio option
labelstringLabel text displayed next to radio
disabledbooleanfalseWhether this option is disabled
classNamestringAdditional CSS class names
refReact.Ref<HTMLButtonElement>Forwarded ref to the button

Horizontal Layout

<RadioGroup defaultValue="medium" className="flex gap-4">
  <Radio value="small" label="Small" />
  <Radio value="medium" label="Medium" />
  <Radio value="large" label="Large" />
</RadioGroup>

Disabled Options

<RadioGroup defaultValue="enabled">
  <Radio value="enabled" label="Enabled option" />
  <Radio value="disabled" label="Disabled option" disabled />
  <Radio value="another" label="Another enabled" />
</RadioGroup>

Controlled RadioGroup

Selected: option1
const [value, setValue] = useState('medium');
 
<RadioGroup value={value} onValueChange={setValue}>
  <Radio value="small" label="Small" />
  <Radio value="medium" label="Medium" />
  <Radio value="large" label="Large" />
</RadioGroup>

Pricing Plans Example

const [plan, setPlan] = useState('pro');
 
const plans = [
  { value: 'free', label: 'Free', price: '$0/month' },
  { value: 'basic', label: 'Basic', price: '$9/month' },
  { value: 'pro', label: 'Pro', price: '$29/month' },
  { value: 'enterprise', label: 'Enterprise', price: '$99/month' },
];
 
<RadioGroup value={plan} onValueChange={setPlan}>
  {plans.map((p) => (
    <Radio key={p.value} value={p.value} label={`${p.label} - ${p.price}`} />
  ))}
</RadioGroup>

Visual Design

The radio uses a terminal-style indicator:

  • Unselected: ( )
  • Selected: (*)

Keyboard Navigation

KeyAction
Arrow Down / Arrow RightSelect next option
Arrow Up / Arrow LeftSelect previous option
TabMove focus to/from radio group

Accessibility

  • Built on Base UI's accessible radio primitive
  • Proper ARIA attributes for screen readers
  • Keyboard navigable within group
  • Labels properly associated with radio buttons

Styling

VariableDescription
--theme-borderRadio border color
--theme-textIndicator and label color
--theme-focused-borderBorder color when focused

On this page