GrCheckboxGroup
Collects checkboxes into one multi-select field with a shared model and states.
Overview
When to take it
- several values out of a short set — permissions, tags, days of the week, notification channels;
- every option has to be visible — the selection is seen as a whole, without opening a panel;
- the group is part of a form — a shared
string[]model, shareddisabled,readonlyandinvalid; - there are up to a dozen options — beyond that the list grows longer than the screen.
When to take something else
| Need | Take |
|---|---|
| There are many options | GrSelect with multiple |
| There are many options and they are searched by typing | GrAutocomplete |
| Only one can be selected | GrRadioGroup |
| There is a single checkbox | GrCheckbox |
| The options are nested | GrTreeSelect |
Playground controls come from the API, not from hand
Loading…
0 changed· state is in the URL
<GrCheckboxGroup :options="options" v-model="value" />Examples 4 each with a live demo and its code
Permissions of a role, area by area
Each area is a group with its own
string[], and the group hands the selection,nameand states down to its checkboxes — none of them needs av-model. An option’sdisabledbeats an enabled group: voiding issued invoices stays with the owner, and the label says so.Role · Accountant3 members · 5 of 7 permissionsInvoicesView invoicesCreate and edit draftsSend to customersVoid issued invoices · owner onlyPaymentsView paymentsMatch bank transfersIssue refundsA filter with counts
When a row needs more than a label, the default slot replaces
options: eachGrCheckboxgets only avalue, and the group gives it the rest. Here every status carries its count, and the total under the list follows the selection.Status71 tickets in the queueOpen48Waiting on customer23On hold6Solved this week131A review that turns into an edit
readonlyon the group keeps the choice visible and in the form, but not switchable — the renewal is reviewed, not edited, until «Change». The state belongs to the group and reaches every checkbox; nothing moves when it flips.Renewal · add-onsBusiness plan renews on 1 NovemberSingle sign-on€120 a monthAudit log export€60 a monthSandbox workspace€45 a monthPriority support€200 a monthAdd-ons on the next invoice€320 a monthDays of the week in a row
direction="horizontal"suits seven short labels.requiredannounces the rule, andinvalidmarks the group as a whole — «at least one day» is broken by the set, not by a single box, so the error is announced once, not seven times.Café Lumen · deliveriesBread arrives before 7:00 on the chosen days Delivery days3 deliveries a weekMonTueWedThuFriSatSun
API generated from the package · cannot drift
Props
| Prop | Type | default | Description |
|---|---|---|---|
disabled | boolean | undefined | false | Disable the whole group. Combined with `disabled` of `GrFormField`. |
options | GrCheckboxGroupOption[] | undefined | undefined | The options from which the group builds the checkboxes. Not needed if the checkboxes are laid out in the slot. |
readonly | boolean | undefined | false | Read-only: the selection is visible but does not change. |
invalid | boolean | undefined | false | The visual and ARIA state of an error for the whole group. |
required | boolean | undefined | false | A required group: `aria-required` is announced by the checkboxes themselves. |
size | "xs" | "sm" | "md" | "lg" | undefined | undefined | The size step of the checkboxes in the group. `md` by default; taken from `GrConfigProvider`. |
ariaLabel | string | undefined | undefined | The accessible name of the group. If not set, the name is taken from the label of `GrFormField`. |
name | string | undefined | undefined | A shared name for a native form: the values leave as repeated fields. |
direction | GrCheckboxGroupDirection | undefined | "vertical" | The layout: `vertical` — in a column, `horizontal` — in a row with wrapping. `vertical` by default. |
modelValuerequiredv-model | string[] | — | The checked values (`v-model`): every checkbox in the group has its own `value`. |
Slots
| Slot | Type | Description |
|---|---|---|
default | any | Markup of your own for the checkboxes instead of generating them from `options`. |
Events
| Event | Signature | Description |
|---|---|---|
update:modelValue | (event: "update:modelValue", value: string[]): void | — |
change | (event: "change", value: string[]): void | — |
focus | (event: "focus", event: FocusEvent): void | — |
blur | (event: "blur", event: FocusEvent): void | — |
Methods
| Methods | Signature | Description |
|---|---|---|
focus | () => void | Put focus on the first available checkbox of the group. |
blur | () => void | Remove focus from the first available checkbox — the counterpart of `focus`. |
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 { GrCheckboxGroupConfigurableProps, GrCheckboxGroupDirection, GrCheckboxGroupOption } from '@feugene/granularity/components/GrCheckboxGroup'Filedist/types/components/GrCheckboxGroup/config.d.ts
const grCheckboxGroupConfig: import("@feugene/granum/contract").GranumComponentDescriptor<"GrCheckboxGroup">;Filedist/types/components/GrCheckboxGroup/defaults.d.ts
interface GrCheckboxGroupConfigurableProps {
size: GrCheckboxSize;
}Filedist/types/components/GrCheckboxGroup/GrCheckboxGroup.vue.d.ts
type GrCheckboxGroupDirection = 'vertical' | 'horizontal';interface GrCheckboxGroupOption {
value: string;
label: string;
disabled?: boolean;
}interface GrCheckboxGroupProps {
modelValue: string[];
options?: GrCheckboxGroupOption[];
name?: string;
disabled?: boolean;
readonly?: boolean;
invalid?: boolean;
required?: boolean;
direction?: GrCheckboxGroupDirection;
size?: GrCheckboxSize;
ariaLabel?: string;
}interface GrCheckboxGroupEmits {
(e: 'update:modelValue', value: string[]): void;
(e: 'change', value: string[]): void;
(e: 'focus', event: FocusEvent): void;
(e: 'blur', event: FocusEvent): void;
}Filedist/types/components/GrCheckboxGroup/index.d.ts
type GrCheckboxGroupInstance = ComponentExposed<typeof GrCheckboxGroupComponent>;Accessibility
APG pattern
group
Full contract of the package: docs/keyboard.md ↗
Usage from the library prose
The model and the context
The group hands the nested checkboxes the selected values, name, size and the
disabled/readonly/invalid states, so they need no v-model of their own —
value is enough:
<GrCheckboxGroup v-model="channels" name="channels" :options="options" />
<GrCheckboxGroup v-model="channels" direction="horizontal">
<GrCheckbox value="sms">SMS</GrCheckbox>
<GrCheckbox value="email">Email</GrCheckbox>
</GrCheckboxGroup>name goes to every checked checkbox, so a native form gets a repeated field:
new FormData(form).getAll('channels').
The disabled of an individual option beats an enabled group. A value in the model
that is not among the options is not lost by the group: unchecking a neighbouring
checkbox keeps it.
The role and ARIA
role="group", not radiogroup: checkboxes have no roving tabindex and no moving
of the selection with the arrows — each stays a Tab stop of its own, exactly like
a set of native <input type="checkbox">.
role="group" does not support aria-required and aria-readonly (axe reports that
as a critical aria-allowed-attr), so both states are declared by the checkboxes
themselves. aria-invalid, on the contrary, hangs on the group alone: duplicated on
every item, it would make a screen reader repeat “invalid value” as many times as
there are checkboxes in the group — on an error the items are merely recoloured.
Being required
As with a single checkbox, required is a declaration; a form rule does the
checking. For a group the built-in required works: an empty array counts as an
empty value.
const rules: GrFormRules = {
channels: [{ required: true, message: 'Choose at least one channel' }],
}Props in this example