Browse docs
Browse docs
Pick several from a short list.
import { CheckboxGroup } from '@dashforge/ui';
<CheckboxGroup
name="channels"
label="How should we reach you?"
options={[
{ value: 'email', label: 'Email' },
{ value: 'sms', label: 'SMS' },
]}
/><Autocomplete multiple> and <Select multiple> earn their dropdown when the
list is long enough that showing it all would drown the form. Below roughly
seven options, a dropdown hides choices behind an interaction for no gain:
the user has to open it to find out what is on offer.
This component is the other shape. Everything is visible, nothing is behind a click, and the group reads as one field rather than a text input that happens to hold chips.
The field stores an array. onChange fires with the next array, not with
the option that was toggled, so you can hand it straight to a useState
setter.
Pick as many as you like.
Stored value: ["email"]
<CheckboxGroup
name="channels"
label="How should we reach you?"
options={[
{ value: 'email', label: 'Email' },
{ value: 'sms', label: 'SMS' },
{ value: 'push', label: 'Push notification' },
{ value: 'postal', label: 'Postal mail', disabled: true },
]}
value={value}
onChange={setValue}
helperText="Pick as many as you like."
/>If the field loads ['email', 'fax'] and fax is no longer in options, the
value stays in the payload. It renders nothing, because there is no option to
render, but toggling something else does not silently drop it.
That is deliberate, and it was a bug first: an early version rebuilt the array
from options on the check path while the uncheck path preserved it, so a form
loading a value the option list no longer contained lost it on the very first
interaction. Caught before release and pinned by a test. Recorded as BUG 38.
The ordering follows from the same rule: values with no option come first, then the declared options in the order you listed them.
access on the group hides, disables or freezes the whole thing. access on
an individual option does the same for one row, with one exception worth
knowing: an option that would be hidden stays visible if it is currently
checked. Hiding a checked box would leave a value in the submitted payload that
the user can neither see nor remove.
Group-level access takes precedence over option-level.
required is presentationalIt renders the asterisk and sets aria-required, matching <RadioGroup>.
Enforcement at submit time still needs rules={{ required: … }}. See BUG 20 for
why the two are separate.
| Prop | Type | Default | Description |
|---|---|---|---|
name | string | — | Field name. Required. |
options | CheckboxGroupOption[] | — | The options to render. Required. |
label | ReactNode | — | Group label displayed above the checkboxes. |
value | string[] | — | Controlled value. [] means nothing checked. |
onChange | (value: string[]) => void | — | Fires with the NEXT array, not with the toggled option. |
required | boolean | false | Renders the asterisk and sets aria-required. Presentational only: see the note above. |
disabled | boolean | false | Disables every option in the group. |
error | boolean | false | Error visual state. |
helperText | string | — | Hint or error text below the group. |
tooltip | FieldTooltipProp | — | Label-help tooltip (ⓘ in the label row). |
access | AccessRequirement | — | RBAC access requirement for the whole group. Combines with an explicit disabled via OR. |
rules | RegisterOptions | — | React Hook Form validation rules. |
visibleWhen | (engine: Engine) => boolean | — | Conditional visibility expression. |
Anything else is forwarded to MUI's <FormGroup>, except name, onChange
and children, which this component owns.
| Field | Type | Default | Description |
|---|---|---|---|
value | string | — | Stored in the array when checked. Required. |
label | ReactNode | — | Rendered next to the box. Required. |
disabled | boolean | false | Disables this option only. |
access | AccessRequirement | — | RBAC access requirement for this option. hide keeps it visible while it is checked; readonly falls back to disabled, since a checkbox has no readonly state. |