Browse docs
Browse docs
A single-selection list. Backed by Radix RadioGroup primitive — keyboard navigation (arrows + Space), role="radiogroup", and focus management come for free. Bridge-integrated so it slots into <DashForm> like every other Dashforge input, and uniquely supports per-option RBAC (each option can hide/disable/readonly independently).
import { RadioGroup } from '@dashforge/tw';
<RadioGroup
name="plan"
label="Plan"
options={[
{ value: 'free', label: 'Free' },
{ value: 'pro', label: 'Pro' },
{ value: 'team', label: 'Team' },
]}
defaultValue="free"
/>Inside <DashForm>:
import { DashForm } from '@dashforge/forms';
import { RadioGroup, Button } from '@dashforge/tw';
<DashForm onSubmit={onSubmit}>
<RadioGroup
name="contactMethod"
label="How should we reach you?"
options={[
{ value: 'email', label: 'Email' },
{ value: 'sms', label: 'SMS' },
{ value: 'phone', label: 'Phone call' },
]}
required
/>
<Button type="submit" color="primary">Continue</Button>
</DashForm>Standalone (no form):
const [value, setValue] = useState('email');
<RadioGroup
name="contactMethod"
options={OPTIONS}
value={value}
onValueChange={setValue}
/>import { RadioGroup } from '@dashforge/tw';
<RadioGroup
name="plan"
label="Choose a plan"
defaultValue="pro"
options={[
{ value: 'free', label: 'Free — 1 workspace, community support' },
{ value: 'pro', label: 'Pro — unlimited workspaces, email support' },
{ value: 'team', label: 'Team — SSO, audit log, priority support' },
]}
/>import { RadioGroup } from '@dashforge/tw';
<RadioGroup
name="size"
label="Size"
layout="row"
defaultValue="m"
options={[
{ value: 's', label: 'S' },
{ value: 'm', label: 'M' },
{ value: 'l', label: 'L' },
{ value: 'xl', label: 'XL' },
]}
/><RadioGroup name="size" layout="stacked" options={SIZES} />
<RadioGroup name="size" layout="row" options={SIZES} />stacked is the default — best for 3+ options with descriptive labels. row works for binary-ish choices (yes/no/maybe) where horizontal density beats per-row readability.
<RadioGroup size="sm" options={OPTIONS} />
<RadioGroup size="md" options={OPTIONS} />
<RadioGroup size="lg" options={OPTIONS} />The killer feature. Each option carries its own access:
<RadioGroup
name="plan"
options={[
{ value: 'free', label: 'Free' },
{ value: 'pro', label: 'Pro' },
{
value: 'team',
label: 'Team (admin only)',
access: { requires: 'workspace.admin', when: 'denied:hide' },
},
]}
/>Non-admin users see only Free + Pro. Group-level access (if also passed) takes precedence — when the whole group is denied, no per-option override resurrects it.
<RadioGroup
name="terms"
label="Do you accept the terms?"
options={[{ value: 'yes', label: 'Yes' }, { value: 'no', label: 'No' }]}
required
rules={{ validate: (v) => v === 'yes' || 'You must accept to continue' }}
/>required adds the asterisk marker + RHF required rule. Custom rules (RHF format) layer on top.
<RadioGroup name="hasAccount" options={[{ value: 'yes', label: 'Yes' }, { value: 'no', label: 'No' }]} />
<TextField
name="email"
label="Email"
visibleWhen={(engine) => engine.getNode('hasAccount')?.value === 'yes'}
/>| Prop | Type | Default | Description |
|---|---|---|---|
name | string | — | Field name. Registers with <DashForm> if present. |
options | RadioGroupOption[] | — | The options. See the RadioGroupOption shape below. |
label | ReactNode | — | Group label. |
required | boolean | false | Marks label + adds RHF rule. |
rules | RegisterOptions | — | RHF validation rules. |
size | 'sm' | 'md' | 'lg' | 'md' | Density. |
layout | 'stacked' | 'row' | 'stacked' | Direction of the option list. |
error | boolean | false | Force error state. |
disabled | boolean | false | Disable the whole group. |
visibleWhen | (engine) => boolean | — | Reactive visibility predicate. |
access | AccessRequirement | — | Group-level RBAC. Wins over per-option access. |
value | string | — | Controlled value. |
defaultValue | string | — | Uncontrolled initial value. |
onValueChange | (v: string) => void | — | Change handler (Radix-style). |
slotProps | RadioGroupSlotProps | — | Per-slot overrides. |
sx | string | — | Utility-class override on root. |
root · label · requiredMark · optionList · option · control · indicator · optionLabel · helperText · errorText
@dashforge/tw exposes it). Use it for plan/role pickers where some choices are admin-only.aria-checked are not hand-rolled.string (the option's value field). Cast at form-submit time if you need numbers.<Switch> (binary toggle) or two separate <Checkbox> — RadioGroup is best from 3 options up.