Skip to content

DataGroup

<DataGroup> is a vertical stack of Collapsible groups, each owning its own DataTable. Use for case-list grouped by collector, team-queue grouped by stage — anywhere groups carry meaning and the user benefits from collapsing by default.

import from "@na/ui/components/DataGroup" ▶ Open in Storybook packages/ui/src/components/DataGroup.tsx

When to use

  • Case lists grouped by owner (“Mine”, “Team”).
  • Queues grouped by stage / status / region.
  • Any list where group membership is the primary scan axis and 5+ groups would be too much for Tabs.

Don’t use DataGroup for: a single homogeneous list (use DataTable directly), 2–5 mutually-exclusive views (Tabs or SegmentedControl), or grouping that the user would re-pick frequently (use a Filter chip instead).

Default

Open and closed groups; click the header to toggle. The chevron rotates with the open state.

NameStageAmount
Acme CorpNegotiation$24,000
GlobexDiscovery$8,500
InitechClosed-Won$42,000
<DataGroup<Case>
columns={columns}
groups={[
{ id: 'mine', label: 'Mine', count: 3, rows: minRows },
{ id: 'team', label: 'Team', count: 2, defaultOpen: false, rows: teamRows },
]}
/>

API

DataGroup

Prop Type Default Description
groups * DataGroupGroup<T>[] One section per group. Each: { id, label, count?, description?, rows, defaultOpen? }.
columns * DataTableColumn<T>[] Forwarded to every group's DataTable.
rowId (row: T) => string Stable row id. Required when selection is enabled.
onRowClick (row: T) => void Whole-row click. Forwarded to every DataTable.
groupEmptyState ReactNode Rendered when a group has zero rows. Pass <EmptyState variant="filtered" />.
className string Forwarded.

DataGroupGroup<T>

Prop Type Default Description
id * string Unique within the group list.
label * ReactNode Section header label.
count number Trailing tabular-num count next to the label.
description ReactNode Optional muted description.
rows * T[] Rows for this group.
defaultOpen boolean true Initial open state.

Design guidelines

✓ Do

  • Order groups by user importance (Mine first, then Team, then Archive). Don't alphabetize.
  • Default-open groups the user expects to act on; default-closed the rest.
  • Pass count prop — the user wants to see "47 in Team" without expanding it.

✗ Don't

  • Use DataGroup for one group only. That's a DataTable.
  • Mix column shapes across groups. Every group renders the same columns.
  • Replace Tabs with DataGroup when the user only ever wants one view at a time. Tabs is correct there.

Accessibility

  • Each section is a Radix Collapsible — trigger is <button aria-expanded aria-controls>, content has role="region".
  • Inner DataTable keeps its own role + sort + selection a11y.
  • Keyboard: Tab reaches each trigger; Enter / Space toggles.
  • DataTable — Single-list base.
  • Collapsible — Underlying primitive.
  • Tabs — When the user wants one group at a time.

▶ Open DataGroup stories in Storybook