I9kRadioGroup
Fieldset of mutually exclusive radio options, rendered as a stacked list or a card grid. Unlike I9kInput, I9kTextarea, and I9kSelect, it does not participate in the I9kField composable — it owns its own legend, hint, error, and ids entirely.
ts
import { I9kRadioGroup } from '@9klabs/design';Examples
Default
vue
<I9kRadioGroup v-model="service" legend="Choose a service" :options="options" />Card variant
vue
<I9kRadioGroup
v-model="service"
legend="Choose a service"
variant="card"
:options="options"
/>Required with error
vue
<I9kRadioGroup
v-model="service"
legend="Choose a service"
required
error="Choose the service you need."
:options="options"
/>Watch out
- Never wrap I9kRadioGroup in I9kField — it does not call useI9kField() and will not inherit label, hint, error, or size from it; pass those as its own props instead.
optionsmust match the I9kRadioOption shape exactly: { label, value, description?, disabled? }.- The
cardvariant lays out options in a two-column grid (one column under 640px) with the native input visually hidden;defaultrenders a plain stacked or wrapped list.
API
Props
| Prop | Type | Default | Required |
|---|---|---|---|
modelValue | string | — | yes |
options | readonly I9kRadioOption[] | — | yes |
legend | string | — | yes |
name | string | undefined | no |
hint | string | undefined | no |
error | string | undefined | no |
required | boolean | false | no |
disabled | boolean | false | no |
size | 'sm' | 'md' | 'lg' | 'md' | no |
variant | 'default' | 'card' | 'default' | no |
orientation | 'horizontal' | 'vertical' | 'vertical' | no |
Emits
| Event | Payload |
|---|---|
update:modelValue | [value: string] |
Types
ts
export interface I9kRadioOption {
label: string;
value: string;
description?: string;
disabled?: boolean;
}Agent prompt
Paste this into an agent to have it use the component correctly. It is self-contained.
text
Use I9kRadioGroup from @9klabs/design for a single choice among a small, fully visible set of options.
import { I9kRadioGroup } from '@9klabs/design';
import type { I9kRadioOption } from '@9klabs/design';
Props:
- modelValue: string (required) — the v-model target, matched against each option's value.
- options: readonly I9kRadioOption[] (required) — each is { label: string; value: string; description?: string; disabled?: boolean }.
- legend: string (required) — the fieldset's accessible name; always rendered, there is no slot override.
- name?: string — the radio input group name; defaults to an auto-generated id.
- hint?: string
- error?: string — a defined value renders the error message instead of the hint and marks the group invalid.
- required?: boolean (default false)
- disabled?: boolean (default false) — disables the whole group.
- size?: 'sm' | 'md' | 'lg' (default 'md')
- variant?: 'default' | 'card' (default 'default')
- orientation?: 'horizontal' | 'vertical' (default 'vertical')
Emits: update:modelValue with the selected option's value.
Slots: none.
IMPORTANT: I9kRadioGroup never calls useI9kField() — do NOT wrap it in I9kField expecting it to inherit label, hint, error, or size the way I9kInput/I9kTextarea/I9kSelect do. It renders its own <fieldset><legend> and its own hint/error paragraphs directly from its own props. Wrapping it in I9kField still renders I9kField's separate label/hint/error around the group, producing duplicated, disconnected markup — pass legend, hint, error, required, and size straight to I9kRadioGroup instead, with no I9kField involved.
Usage:
<I9kRadioGroup v-model="service" legend="Choose a service" :options="[{ label: 'Technical audit', value: 'audit' }, { label: 'Design system', value: 'design' }]" />