Skip to main content

Checkboxes

Overview

The Checkboxes component wraps multiple Checkbox components in a Bulma-styled group.

Use for lists of boolean choices, such as preference lists or to-do checklists.


Import

import { Checkboxes, Checkbox } from '@allxsmith/bestax-bulma';

Usage

Grouped Checkboxes

This example demonstrates the Checkboxes component wrapping multiple Checkbox children. Use this pattern for lists of boolean options, such as to-do lists or preference selections. Each Checkbox receives its own label via the children prop.

<Checkboxes>
  <Checkbox> Make the bed </Checkbox>
  <Checkbox> Brush teeth </Checkbox>
  <Checkbox> Do homework </Checkbox>
  <Checkbox> Feed the pet </Checkbox>
  <Checkbox> Take out the trash </Checkbox>
  <Checkbox> Clean your room </Checkbox>
  <Checkbox> Set the table </Checkbox>
  <Checkbox> Help with dishes </Checkbox>
  <Checkbox> Water the plants </Checkbox>
  <Checkbox> Put away toys </Checkbox>
</Checkboxes>


Context-Aware Rendering

The Checkboxes component is context-aware: it detects whether it is already inside a Field or Control and adjusts its rendering accordingly. This means you can use it standalone with a label prop (it wraps itself in Field+Control), inside a Field (it skips its own Field), or inside both Field and Control (it renders only the raw checkbox group).

Default (with label)

The simplest usage — the component automatically renders its own Field and Control wrappers.

<Checkboxes label="Chores">
  <Checkbox> Make the bed </Checkbox>
  <Checkbox> Brush teeth </Checkbox>
  <Checkbox> Do homework </Checkbox>
</Checkboxes>


With Field Wrapper

When you need manual control over the Field layout (e.g., horizontal forms), wrap the component in Field. The component detects it's inside a Field and skips rendering its own.

function example() {
  return (
    <Field horizontal label="Chores">
      <Field.Body>
        <Field>
          <Checkboxes>
            <Checkbox> Make the bed </Checkbox>
            <Checkbox> Brush teeth </Checkbox>
            <Checkbox> Do homework </Checkbox>
          </Checkboxes>
        </Field>
      </Field.Body>
    </Field>
  );
}


With Field and Control Wrappers

For full manual control, wrap in both Field and Control. The component detects both and renders only the raw checkbox group.

function example() {
  return (
    <Field horizontal label="Chores">
      <Field.Body>
        <Field>
          <Control>
            <Checkboxes>
              <Checkbox> Make the bed </Checkbox>
              <Checkbox> Brush teeth </Checkbox>
              <Checkbox> Do homework </Checkbox>
            </Checkboxes>
          </Control>
        </Field>
      </Field.Body>
    </Field>
  );
}


Compound (dot-notation) usage

Checkbox is also available as Checkboxes.Checkbox, so a checkbox group can be composed from the single Checkboxes import.

<Checkboxes name="frameworks" label="Frameworks">
  <Checkboxes.Checkbox value="react">React</Checkboxes.Checkbox>
  <Checkboxes.Checkbox value="vue">Vue</Checkboxes.Checkbox>
</Checkboxes>


Group State

Checkboxes can manage the selected-values array for the entire group, matching the pattern used by React Aria's CheckboxGroup. Three usage modes:

  1. Name-only — pass just name. Each child Checkbox manages its own checked state. Backwards compatible.
  2. Controlled — pass value (an array of selected values) and onChange. The parent owns selection; each Checkbox derives checked from value.includes(my.value).
  3. Uncontrolled — pass defaultValue (an array) and optionally onChange. The group manages internal state; onChange fires with the new array.

Local props (checked, onChange) on individual Checkbox children always win over the group context.

Controlled

function ControlledCheckboxes() {
  const [tags, setTags] = React.useState(['react']);
  return (
    <div>
      <Checkboxes name="tags" value={tags} onChange={setTags}>
        <Checkbox value="react">React</Checkbox>
        <Checkbox value="vue">Vue</Checkbox>
        <Checkbox value="angular">Angular</Checkbox>
        <Checkbox value="svelte">Svelte</Checkbox>
      </Checkboxes>
      <p style={{ marginTop: '1rem' }}>
        Selected: <strong>{tags.length ? tags.join(', ') : '(none)'}</strong>
      </p>
    </div>
  );
}

Uncontrolled

function UncontrolledCheckboxes() {
  const [latest, setLatest] = React.useState([]);
  return (
    <div>
      <Checkboxes
        name="features"
        defaultValue={['darkmode']}
        onChange={setLatest}
      >
        <Checkbox value="darkmode">Dark mode</Checkbox>
        <Checkbox value="notifications">Notifications</Checkbox>
        <Checkbox value="analytics">Analytics</Checkbox>
      </Checkboxes>
      {latest.length > 0 && (
        <p style={{ marginTop: '1rem' }}>
          Latest: <strong>{latest.join(', ')}</strong>
        </p>
      )}
    </div>
  );
}


Form Submission

Checkboxes is HTML-form-compatible. Pass a name prop on the group and every child Checkbox inherits it via React context (works at any nesting depth). Each checked box submits as name=value, producing a standard form-encoded array (e.g., tags=react&tags=vue) that server-side parsers handle natively.

PropDescription
nameForm field name shared by every child Checkbox. Children with their own name prop keep theirs (explicit > implicit).
function CheckboxesFormDemo() {
  const [submitted, setSubmitted] = React.useState('');
  return (
    <form
      onSubmit={e => {
        e.preventDefault();
        const fd = new FormData(e.currentTarget);
        setSubmitted(JSON.stringify(Array.from(fd.entries()), null, 2));
      }}
    >
      <Checkboxes name="tags">
        <Checkbox value="react" defaultChecked>
          React
        </Checkbox>
        <Checkbox value="vue" defaultChecked>
          Vue
        </Checkbox>
        <Checkbox value="angular">Angular</Checkbox>
        <Checkbox value="svelte">Svelte</Checkbox>
      </Checkboxes>
      <div style={{ marginTop: '1rem' }}>
        <button type="submit" className="button is-primary">
          Submit
        </button>
      </div>
      {submitted && <pre style={{ marginTop: '1rem' }}>{submitted}</pre>}
    </form>
  );
}


Accessibility

  • The group is rendered as a <div class="checkboxes" role="group"> containing labeled checkboxes.
  • The label prop names the whole group: the rendered <label> gets an id (yours via labelProps.id, or a generated one) and the group points at it with aria-labelledby.
  • Each child should be a Checkbox for proper labeling and accessibility.

  • Checkbox: Individual checkbox.
  • Field: For labeled/grouped form fields.

Additional Resources


Props

PropTypeDefaultDescription
labelReact.ReactNodeField label naming the whole group. Automatically associated via aria-labelledby on the role="group" wrapper — uses your labelProps.id when provided, otherwise a generated one. Dropped inside an outer Field (label that Field yourself).
labelPropsReact.LabelHTMLAttributes<HTMLLabelElement> & { [key: string]: unknown; }Props for the label element. An explicit id here is used as the aria-labelledby target instead of a generated one; any htmlFor is ignored (a group label names the group, never a single control).
classNamestringAdditional CSS classes to apply.
namestringForm field name shared by every Checkbox in the group (via context).
valuestring[]Currently-selected values (controlled mode).
defaultValuestring[]Initial selected values (uncontrolled mode).
onChange(values: string[]) => voidFires when the selection changes; receives the new array.
childrenReact.ReactNodeCheckbox elements to render in the group.
labelSize'small' | 'normal' | 'medium' | 'large'Size for the label (used in horizontal layouts).
horizontalbooleanfalseHorizontal field layout.
messageReact.ReactNodeHelp/validation message below the input.
messageColor'primary' | 'link' | 'info' | 'success' | 'warning' | 'danger'Bulma color for the message.
fieldClassNamestringAdditional CSS classes for the Field wrapper.
...Bulma helper propsSee Helper Props

Subcomponents: