For AI agents: the complete documentation index is available at /ooui-react/en/llms.txt, the full documentation bundle is available at /ooui-react/en/llms-full.txt, and this page is available as Markdown at /ooui-react/en/components/checkbox-multiselect/index.md.
  • English
  • CheckboxMultiselect

    Source | Original component

    A checkbox group: several checkbox items in one group, multiple selections allowed.

    Basic usage

    The selected value is an array, driven by the value / defaultValue / onChange channels; onChange carries the full value array. With name, every option's checkbox shares it and the checked ones submit as multiple same-name fields.

    Current selection: banana
    import { useState } from "react";
    import { CheckboxMultiselect } from "ooui-react";
    
    const options = [
      { value: "apple", children: "Apple" },
      { value: "banana", children: "Banana" },
      { value: "cherry", children: "Cherry" },
    ];
    
    function App() {
      const [value, setValue] = useState<Array<string | number>>(["banana"]);
    
      return (
        <div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
          <CheckboxMultiselect options={options} value={value} onChange={setValue} name="fruits" />
          <div>Current selection: {value.join(", ") || "(none)"}</div>
          <CheckboxMultiselect options={options} defaultValue={["apple", "cherry"]} />
        </div>
      );
    }
    
    export default App;

    Shift+click range selection

    Click one item, then click another with Shift held: the range between the two clicks (both ends included) is set to the state the second item just flipped to; disabled items in the range keep their state. This mirrors bulk-checking in list tables.

    Current selection: (none)
    Click one item, then Shift+click another to see range selection
    import { useState } from "react";
    import { CheckboxMultiselect } from "ooui-react";
    
    const options = [1, 2, 3, 4, 5].map((number) => ({
      value: number,
      children: `Item ${number}`,
    }));
    
    function App() {
      const [value, setValue] = useState<Array<string | number>>([]);
    
      return (
        <div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
          <CheckboxMultiselect options={options} value={value} onChange={setValue} />
          <div style={{ fontSize: 13 }}>
            Current selection: {value.join(", ") || "(none)"}
          </div>
          <div style={{ color: "#54595d", fontSize: 13 }}>
            Click one item, then Shift+click another to see range selection
          </div>
        </div>
      );
    }
    
    export default App;

    Using it with FieldLayout

    To give the whole group a field label, wrap it with FieldLayout. Clicking the field label moves focus to the first enabled option's checkbox (it does not toggle anything — a group has no "one value for the whole group" semantics like a single checkbox does).

    import { CheckboxMultiselect, FieldLayout } from "ooui-react";
    
    function App() {
      return (
        <div style={{ maxWidth: 320 }}>
          <FieldLayout label="Subscribed sections">
            <CheckboxMultiselect
              defaultValue={["news"]}
              options={[
                { value: "news", children: "News" },
                { value: "sports", children: "Sports" },
                { value: "tech", children: "Tech" },
              ]}
            />
          </FieldLayout>
        </div>
      );
    }
    
    export default App;

    Disabled

    • An option's own disabled skips that item (not checkable).
    • Component-level disabled disables every option in the group, and the group state wins. See Selection and options · Disabled.
    import { CheckboxMultiselect } from "ooui-react";
    
    function App() {
      return (
        <CheckboxMultiselect
          defaultValue={["a"]}
          options={[
            { value: "a", children: "Enabled" },
            { value: "b", children: "Disabled item", disabled: true },
            { value: "c", children: "Also enabled" },
          ]}
        />
      );
    }
    
    export default App;

    Keyboard and focus

    • Every option's native <input type="checkbox"> is in the Tab order; ↑↓←→ are an in-group shortcut — they move focus cyclically between non-disabled items (unlike RadioSelect, they only move focus and do not select directly), and Space toggles the current item.
    • A Shift+click range starts from the item last clicked (or last toggled with Space).
    • onChange's second argument is the native change event that triggered this change.
    • Option roots carry role='checkbox' and aria-checked (the original's option roots have no role and express selection only via a class), so screen readers can read each option's state directly.

    API

    PropDescriptionTypeDefault
    optionsThe option set, rendered in display order; each item has value and children (the option text) and supports option fields such as disabledCheckboxMultiselectOptionProps[]—
    valueCurrent selected values (controlled; passing it enables controlled mode)(string | number)[]—
    defaultValueInitial selected values for uncontrolled use(string | number)[][]
    onChangeSelected-values change callback with the full value array and the native eventChangeHandler<(string | number)[], HTMLInputElement>—
    nameForm field name, passed to every option's checkboxstring—
    disabledWhether disabled (also disables every option in the group)booleanfalse
    ...restNative div props (className, id, aria-*, etc.) passed straight to the group containerHTMLAttributes<HTMLDivElement>—

    See also

    • Option data and the keyboard focus model: Selection and options
    • A single checkbox: CheckboxInput
    • The checkbox group field that submits with a form: CheckboxMultiselectInput