Use cases
- Selecting many items from a long, flat list — designations, job categories, payroll schemes, modules.
- Any flow where the user needs to scan "what's on" vs "what's off", filter the list, and bulk-toggle.
When NOT to use
- For a small fixed number of toggles → multiple Switch rows.
- For a transfer between two pools (assigned ↔ unassigned) → use TransferList.
- For a single binary choice → use Checkbox.
Platform support
Web: multi-column grid with view tabs (All/Selected/Unselected).
Native: single-column FlatList with touch-friendly checkbox rows. View tabs are omitted; filter, select-all, and clear are retained. The columns prop is accepted but ignored on native.
Anatomy
┌────────────────────────────────────────────────────────┐
│ 3 selected · 9 remaining [All|Selected|Unselected] │ ← summary bar
│ [Select All] [Clear] │
├────────────────────────────────────────────────────────┤
│ [🔍 Filter items…] │ ← search
├────────────────────────────────────────────────────────┤
│ ☑ Engineering ☑ Product ☐ Design │ ← grid
│ ☑ Marketing ☐ Sales ☐ Support │
│ ☐ Finance ☐ Ops ☐ HR │
└────────────────────────────────────────────────────────┘
Columns
| Setting | Mobile | Tablet | Desktop |
|---|---|---|---|
columns={1} | 1 | 1 | 1 |
columns={2} | 1 | 2 | 2 |
columns={3} (default) | 1 | 2 | 3 |
Controlled state
selected is a Record<string, boolean>. Missing keys count as false:
const [selected, setSelected] = useState<Record<string, boolean>>({});
<CheckboxGrid
items={['A', 'B', 'C']}
selected={selected}
onSelectedChange={setSelected}
/>The component never mutates your state — onSelectedChange always receives a new object.
Scroll containment
The grid scrolls inside its own bounded region (maxHeight={240} default). For very long lists (60+ items) the search filter does the heavy lifting — bump maxHeight only when there's no good filter axis.
Responsive and customization props
layout="auto"creates responsive cards withauto-fit, useful when the same grid must work from mobile to desktop.layout="list"forces one column for dense review screens.density="compact"reduces row height for administrative permission matrices.showToolbar={false}hides count tabs and bulk actions when the grid is embedded inside a larger form.emptyStateandgetItemClassNamelet consumers render domain-specific empty copy and tokenized item styling.
Composition
- Use
columnsto control grid density. 2 columns is default; 3 works for short labels. - Pair with a SectionHeader above the grid for context.
selectedis aRecord<string, boolean>— missing keys count asfalse.
Related
- Checkbox — individual checkbox for single boolean fields.
- TransferList — dual-list picker with move-between semantics.
- RadioGroup — single selection from a list.