GrRadioGroup

  • core
  • forms
  • API · 11 props
  • ⌨ keys

Combines radio options into a single-choice selection flow.

import { GrRadioGroup } from '@feugene/granularity/components/GrRadioGroup'

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, disabled and readonly are handed out through the context;
  • an option looks like a button — variant="button" without losing the semantics of a radiogroup.

When to take something else

NeedTake
There are more than seven optionsGrSelect
There are 2–5 options and they switch a view rather than a valueGrSegmented
Several can be selectedGrCheckboxGroup
There is one switch and it is about “on/off”GrSwitch
A single switch outside a groupGrRadio

Variants every tone and view, rendered by the real component

variant

  • radiobox
  • button

Sizes

  • xs
  • sm
  • md
  • lg

States

  • normal
  • disabled
  • readonly
  • invalid

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

Stage

Loading…

0 changed· state is in the URL

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, and invalid marks 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
  • Appearance 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 computer
    Table densityCompact fits 40% more rows
    Week starts onCalendars and weekly reports
  • A digest schedule in one row

    Four short answers fit a row — orientation="horizontal". One option is disabled on 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

API generated from the package · cannot drift

Props

PropTypedefaultDescription
disabledboolean | undefinedfalseDisable the whole group. It adds up with the `disabled` of `GrFormField`.
variantGrRadioGroupVariant | undefined"radiobox"The look: `radiobox` — circles with labels, `button` — a row of joined buttons. `radiobox` by default.
optionsGrRadioGroupOption[] | undefinedundefinedThe options from which the group builds its radios. Not needed if they are laid out in the slot.
readonlyboolean | undefinedfalseRead only: the choice is visible but does not change.
invalidboolean | undefinedfalseThe visual and ARIA state of an error.
requiredboolean | undefinedfalseA mandatory field (`aria-required`).
size"xs" | "sm" | "md" | "lg" | undefinedundefinedThe size step of the radios. `md` by default; taken from `GrConfigProvider`.
ariaLabelstring | undefinedundefinedThe accessible name of the group. Unset — the name is taken from the label of `GrFormField`.
namestring | undefinedundefinedThe name for a native form: the selected value goes out in a hidden field. Without a name it does not go out.
orientationGrRadioGroupOrientation | undefined"vertical"The layout of the `radiobox` variant. The button variant is always horizontal — it is assembled by `GrButtonGroup`.
modelValuerequiredv-modelGrRadioValue—The selected value (`v-model`): it matches the `value` of one of the radios.

Slots

SlotTypeDescription
defaultanyMarkup of your own for the radios instead of generating them from `options`.

Events

EventSignatureDescription
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

MethodsSignatureDescription
focus() => voidPut the focus on the `Tab` stop of the group — usually the selected radio, not the first one.
blur() => voidRemove 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
import type { GrRadioGroupConfigurableProps, GrRadioGroupVariant, GrRadioGroupOrientation } from '@feugene/granularity/components/GrRadioGroup'

Filedist/types/components/GrRadioGroup/config.d.ts

grRadioGroupConfigconst
const grRadioGroupConfig: import("@feugene/granum/contract").GranumComponentDescriptor<"GrRadioGroup">;

Filedist/types/components/GrRadioGroup/defaults.d.ts

GrRadioGroupConfigurablePropsinterface
interface GrRadioGroupConfigurableProps {
    size: GrButtonSize;
}

Filedist/types/components/GrRadioGroup/GrRadioGroup.vue.d.ts

GrRadioGroupVarianttype
type GrRadioGroupVariant = 'radiobox' | 'button';
GrRadioGroupOrientationtype
type GrRadioGroupOrientation = 'vertical' | 'horizontal';
GrRadioGroupOptioninterface
interface GrRadioGroupOption {
    value: GrRadioValue;
    label: string;
    disabled?: boolean;
    description?: string;
}
GrRadioGroupPropsinterface
interface GrRadioGroupProps {
    modelValue: GrRadioValue;
    options?: GrRadioGroupOption[];
    name?: string;
    disabled?: boolean;
    readonly?: boolean;
    invalid?: boolean;
    required?: boolean;
    variant?: GrRadioGroupVariant;
    orientation?: GrRadioGroupOrientation;
    size?: GrButtonSize;
    ariaLabel?: string;
}
GrRadioGroupEmitsinterface
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

GrRadioGroupInstancetype
type GrRadioGroupInstance = ComponentExposed<typeof GrRadioGroupComponent>;

Accessibility

APG pattern

radio

Keys

Enter↑ / ←

Usage from the library prose

Two modes
vue
<!-- 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
ts
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.