Skip to content

BbCheckboxGroup

Several boxes inside one set, with your data as the options and one array as the model.

import { BbCheckboxGroup } from 'bitboss-ui';

On this page

Use it for

Reach for BbCheckboxGroup when the answer is several choices out of one set: which teams get the alert, which scopes the token carries. You hand it your rows, it renders one box per row.

Use something else when

  • BbCheckbox: it is one yes/no standing alone
  • BbRadioGroup: exactly one choice out of the set
  • BbSwitchGroup: they are on/off states, not answers
  • BbSelect: the set is long, searchable or paged. Forty checkboxes are a scroll, not a control

Also see: Options and items, Fetching data, Coherence.

Do not hand-stack BbCheckbox. The group adds a fieldset, shared validation, item mapping, and selection limits.

Passthrough

Hover or tap a part to outline it. The toggles turn on loading, errors and warnings where the component has them; only parts get a row.

Shown under the label as lasting context.
Guidance while the control is focused.

Options from your data

Pass your domain objects as they are, and name the two fields that matter: the one the user reads, and the one you want in the model.

Notify on failed deploysThey get an email whenever a deploy fails.

Model: [2, 5]

Objects with a label (or text) and a value key need no accessors. For any other shape use item-text and item-value; without item-text each label is the object as JSON. Give every option a unique item-value, ideally a primitive id: each value appears once in the list.

item-props adds a muted second line to each option, and list-layout="vertical" stacks the options once they carry one.

The default model is an array. For one exclusive value, use BbRadioGroup instead of :multiple="false".

The group renders a real <fieldset>, and legend is required: it names the set for assistive technology. Use hide-legend when a nearby heading already shows the same name. hide-label instead hides every option label. The group takes one description and one hint; use separate checkboxes when individual options need different explanations.

Locked and capped options

An option that exists but cannot be chosen is a predicate over the item, not a flag inside it.

On-call rotationDeactivated members cannot take a shift.

1 on the rotation

selectable takes a boolean for the whole set or a predicate per item. Rejected options stay visible and disabled, so give them a reason on screen: here the second line comes from item-props.

To freeze a group that already carries a selection, use readonly: the options stay focusable and the values still submit. disabled locks every option, ticked ones included, and keeps them out of a native post.

max caps how many options may be on at once.

Topics in your digestPick up to three. Untick one to make room for another.

2 of 3 selected

At the cap, unchecked options disable while checked ones stay removable. State the limit in description and show a count; the component renders neither. The cap works alongside a selectable predicate: the predicate locks the options it rejects, and max caps the rest.

Coming from v2disabled on an item → selectable

v2's groups honoured a disabled field on the item object. In v3 it is ordinary domain data with no UI meaning, so options that used to render locked become tickable until you move the rule into selectable. Grep the code that builds your items for disabled: and move each one into selectable:

diff
- :items="channels.map((c) => ({ ...c, disabled: !c.configured }))"
+ :items="channels"
+ :selectable="(c) => c.configured"

Validating the whole set

Inside a BbForm the group joins the form under its name, and rules validates the whole array as one field. Without a name it joins under a slug of the legend, so pass one for a clean key.

Teams this alert reachesEach team gets the alert in its on-call channel.

There is no required prop here: "at least one" is a rule, and rules="required" (a rule you register once) fails on an empty array. It also marks the legend (the asterisk). Submit with nothing ticked: the message shows once focus leaves the group or on submit, then clears as soon as a box is ticked (validation-mode changes when).

Outside a form, compute the one errors message for the set yourself:

vue
<BbCheckboxGroup
    v-model="scopes"
    :errors="submitted && !scopes.length ? 'Choose at least one scope.' : []"
    :items="available"
    legend="Token scopes"
/>

When the options change

Give items a function instead of an array and the group loads its own options. dependencies says what makes it load them again.

Country
Distribution hubs

Model: [milan]

The provider runs on mount and when dependencies change. deps-debounce-time groups rapid changes. Add enforce-coherence when stale selections must be removed after options reload. loading-text and empty-text (or the #loading and #empty slots) cover the wait and an empty result.

Decorating an option

The label slot replaces the text of every option, and receives enough to decide what each one looks like.

Items in the starter bundle

1 item in the bundle

The scope is { item, text, checked, description }. Keep text in the rendered label so the option retains an accessible name. Use separate checkboxes when only one option needs unique markup.

Coming from v2

#option:prepend and #option:append are gone. Everything they did moves into #label, which can put content on either side of the text. Note that #prepend and #append still exist and are unrelated. Those inject once into the options container, before the first option and after the last.

Pick values with the tabs look

variant="pill" or variant="line" gives the group a tab strip's look, for a multi-pick that reads as a strip: opening days, channels, filters. pill draws one pill per run of adjacent picks, so Mon–Wed reads as one block: ticking a neighbour stretches it, unticking a middle option splits it. line draws a bar under each pick across a baseline, and adjacent bars join.

Open on
Notify by

It is still a checkbox group: native checkboxes, max, forms and validation work. The box is hidden (an icon slot shows before the label) and the strip never wraps: it scrolls. list-layout="vertical" stacks it into a column and "vertical-stretch" spans the field. pt:indicator reaches every pill or bar, and a registered checkboxVariants: ['brand'] sets the strip's tokens on .bb-checkbox-group__list--brand, drawing pills per run as pill does.

Layout and CSS

list-layout arranges the options; layout splits the legend from them.

Teams
Include in the export

list-layout takes horizontal (the default, a wrapping row), vertical, vertical-stretch (every row as wide as the list) and tiles. compact tightens the label spacing. reverse, legend-position and input-position arrange the legend against the options, and legend-mode="inside" draws the fieldset border with the legend on it.

To align the box, put a class on pt:icon: self-start pins it to the first line of a label that wraps.

Style the rows through each group's own classes, and list all three when a rule applies to every group:

css
.bb-checkbox-group__label,
.bb-radio-group__label,
.bb-switch-group__label {
    font-weight: 500;
}

For control colours and geometry, use the box variables documented on BbCheckbox.

Coming from v2bb-cr-container → one block per group

labelPosition is now legendPosition, with no behaviour change. A leftover label-position falls through to the DOM and the alignment stops applying; a development build warns about the rename, and npx bitboss-ui check --fix rewrites it.

In v2 one CSS block, bb-cr-container, served all three groups, so a rule written for checkboxes hit radios too. Each group now has its own block, and nothing in v3 renders the old prefix. Search styles and test selectors:

v2v3
.bb-cr-container.bb-checkbox-group__list, .bb-radio-group__list, .bb-switch-group__list
.bb-cr-container--horizontal.bb-…-group__list--horizontal
.bb-cr-container--vertical.bb-…-group__list--vertical-stretch (--vertical rows keep their own width)
.bb-cr-container--errors.bb-…-group__list--errors
.bb-cr-container__containermerged into .bb-…-group__list
.bb-cr-container__loading-container.bb-…-group__loading
.bb-cr-container__no-data-container.bb-…-group__empty
.bb-cr-container-option.bb-…-group__item
.bb-cr-container-option__text.bb-…-group__label
—.bb-…-group__list--tiles, --warnings and .bb-…-group__item--selected, all new