GrRadioGroup
Combines radio options into a single-choice selection flow.
Overview
When to take it
- there are up to seven options and all are visible — a delivery method, a payment type, a role: a choice without an extra click on a panel;
- the options have a description — a line of explanation under the label, which a select does not give;
- the group is part of a form — a shared
name,disabledandreadonlyare handed out through the context; - an option looks like a button —
variant="button"without losing the semantics of aradiogroup.
When to take something else
| Need | Take |
|---|---|
| There are more than seven options | GrSelect |
| There are 2–5 options and they switch a view rather than a value | GrSegmented |
| Several can be selected | GrCheckboxGroup |
| There is one switch and it is about “on/off” | GrSwitch |
| A single switch outside a group | GrRadio |
Variants every tone and view, rendered by the real component
variant
radioboxbutton
Sizes
xssmmdlg
States
normaldisabledreadonlyinvalid
The grid is live: hover and press it. Hover, focus and active states are not drawn here — they belong to the browser, not to a prop.
Playground controls come from the API, not from hand
Loading…
0 changed· state is in the URL
<GrRadioGroup :options="options" v-model="value" />Examples 3 each with a live demo and its code
How to pay an invoice
Three payment methods are compared by eye, so they all stay in sight — a dropdown would hide two of them behind a click. Each option carries its
description, andinvalidmarks the group, not one option: the rule is broken by the choice as a whole.Pay invoice INV-0418€1,284.50 · due 30 September Visa ending 4242 Charged now · receipt by emailSEPA direct debit AIB ·· 3456 · takes 2 working daysBank transfer Use INV-0418 as the referenceAppearance settings as segments
variant="button"turns the same options into a row of segments: short choices read at a glance — theme, density, the first day of the week — take less room and stay a radio group for the keyboard and the screen reader.ThemeSystem follows your computerTable densityCompact fits 40% more rowsWeek starts onCalendars and weekly reportsA digest schedule in one row
Four short answers fit a row —
orientation="horizontal". One option isdisabledon its own because daily digests come with the Team plan, and its description says so instead of hiding the option.Revenue digestAn email with revenue, churn and overdue invoices Daily Team planWeekly Mondays, 9:00Monthly On the 1stNever
API generated from the package · cannot drift
Props
| Prop | Type | default | Description |
|---|---|---|---|
disabled | boolean | undefined | false | Disable the whole group. It adds up with the `disabled` of `GrFormField`. |
variant | GrRadioGroupVariant | undefined | "radiobox" | The look: `radiobox` — circles with labels, `button` — a row of joined buttons. `radiobox` by default. |
options | GrRadioGroupOption[] | undefined | undefined | The options from which the group builds its radios. Not needed if they are laid out in the slot. |
readonly | boolean | undefined | false | Read only: the choice is visible but does not change. |
invalid | boolean | undefined | false | The visual and ARIA state of an error. |
required | boolean | undefined | false | A mandatory field (`aria-required`). |
size | "xs" | "sm" | "md" | "lg" | undefined | undefined | The size step of the radios. `md` by default; taken from `GrConfigProvider`. |
ariaLabel | string | undefined | undefined | The accessible name of the group. Unset — the name is taken from the label of `GrFormField`. |
name | string | undefined | undefined | The name for a native form: the selected value goes out in a hidden field. Without a name it does not go out. |
orientation | GrRadioGroupOrientation | undefined | "vertical" | The layout of the `radiobox` variant. The button variant is always horizontal — it is assembled by `GrButtonGroup`. |
modelValuerequiredv-model | GrRadioValue | — | The selected value (`v-model`): it matches the `value` of one of the radios. |
Slots
| Slot | Type | Description |
|---|---|---|
default | any | Markup of your own for the radios instead of generating them from `options`. |
Events
| Event | Signature | Description |
|---|---|---|
update:modelValue | (event: "update:modelValue", value: GrRadioValue): void | — |
change | (event: "change", value: GrRadioValue): void | — |
focus | (event: "focus", event: FocusEvent): void | — |
blur | (event: "blur", event: FocusEvent): void | — |
Methods
| Methods | Signature | Description |
|---|---|---|
focus | () => void | Put the focus on the `Tab` stop of the group — usually the selected radio, not the first one. |
blur | () => void | Remove the focus from the `Tab` stop of the group. |
Types
Every exported type of the subpath, grouped by the file it lives in. Names, generics and bodies come from the package’s declaration files and cannot drift.
import type { GrRadioGroupConfigurableProps, GrRadioGroupVariant, GrRadioGroupOrientation } from '@feugene/granularity/components/GrRadioGroup'Filedist/types/components/GrRadioGroup/config.d.ts
const grRadioGroupConfig: import("@feugene/granum/contract").GranumComponentDescriptor<"GrRadioGroup">;Filedist/types/components/GrRadioGroup/defaults.d.ts
interface GrRadioGroupConfigurableProps {
size: GrButtonSize;
}Filedist/types/components/GrRadioGroup/GrRadioGroup.vue.d.ts
type GrRadioGroupVariant = 'radiobox' | 'button';type GrRadioGroupOrientation = 'vertical' | 'horizontal';interface GrRadioGroupOption {
value: GrRadioValue;
label: string;
disabled?: boolean;
description?: string;
}interface GrRadioGroupProps {
modelValue: GrRadioValue;
options?: GrRadioGroupOption[];
name?: string;
disabled?: boolean;
readonly?: boolean;
invalid?: boolean;
required?: boolean;
variant?: GrRadioGroupVariant;
orientation?: GrRadioGroupOrientation;
size?: GrButtonSize;
ariaLabel?: string;
}interface GrRadioGroupEmits {
(e: 'update:modelValue', value: GrRadioValue): void;
(e: 'change', value: GrRadioValue): void;
(e: 'focus', event: FocusEvent): void;
(e: 'blur', event: FocusEvent): void;
}Filedist/types/components/GrRadioGroup/index.d.ts
type GrRadioGroupInstance = ComponentExposed<typeof GrRadioGroupComponent>;Accessibility
APG pattern
radio
Keys
Enter↑ / ←
Full contract of the package: docs/keyboard.md ↗
Usage from the library prose
Two modes
<!-- With a prop: the short path for a flat list. -->
<GrRadioGroup v-model="status" :options="options" />
<!-- With a slot: when the options need markup of their own. -->
<GrRadioGroup v-model="status">
<GrRadio value="draft">Draft</GrRadio>
<GrRadio value="review">In review</GrRadio>
</GrRadioGroup>Both modes get one and the same keyboard and one and the same context: the composition of the group is assembled by the registration of the children rather than by a walk over the DOM, so it works on the server as well.
The options
interface GrRadioGroupOption {
value: string | number | boolean
label: string
disabled?: boolean
description?: string
}disabled switches off a single option without moving the whole group onto a slot — that used to
be the only way. description is drawn under the label and only in the radiobox variant: in a
button chip a description has nowhere to live.
The layout
orientation is vertical (the default) or horizontal. The button variant is always
horizontal: it is assembled by GrButtonGroup, and orientation affects nothing there.
The states
disabled dims the whole group, and readonly leaves the selection visible but unchangeable:
aria-readonly is announced by the group itself (the radio role has no such attribute), and the
switches stop promising a click to the cursor.
invalid and required reach both the group and the look of the switches. Inside GrFormField
the same arrives from the context of the field: the name through aria-labelledby, the hint and
the text of the error through aria-describedby, and the error through aria-invalid. A group is
not a labelable element, so <label for> is not applicable to it.
The keyboard
The whole layout is described in the card of GrRadio: the group is one Tab stop, and inside it
↑/↓/←/→ walk in a ring and Home/End go to the edges. Disabled options are skipped
everywhere — both in the roving tabindex and in the walk with the arrows.
Props in this example