Grouped Rows Table React component
A deals table grouped by stage or owner: sticky group headers with a count, total, weighted value and share bar, groups that fold away smoothly, a Group by switch and collapse all.
About the Grouped Rows Table component
Grouped Rows Table organises a long list into sections: deals grouped by pipeline stage or by owner, each group with a header that shows how many deals it holds, their total value, the probability-weighted value and its share of the pipeline.
Group headers stay stuck to the top while their rows scroll past, groups fold away with a click, and the Group by switch reshuffles everything instantly.
When to use it
Use it for sales pipelines, tasks by status or assignee, expenses by category, tickets by priority, inventory by warehouse: any list people slice by one field.
For two-level breakdowns that need to be compared visually, a treemap or stacked bar chart may say more.
Installation
Add the Grouped Rows Table component to your project with the shadcn CLI. It lands in components/grouped-rows-table.tsx as plain React + Tailwind CSS source you own and can edit.
npx shadcn@latest add @reactframe/grouped-rows-tableOr copy the source by hand and install its dependencies:
npm install clsx tailwind-mergeProps
<GroupedRowsTable /> accepts 7 props, all optional. It also accepts the usual <div> attributes, like className, style, id and aria-*, and passes them to its root element.
| Prop | Type | Default |
|---|---|---|
| theme | "dark" | "light" | "dark" |
| title | string | "Pipeline" |
| subtitle | string | "Group deals by stage or owner, fold groups you don't need" |
| deals | { company: string; owner: string; stage: DealStage; value: number; probability: number; close: string }[] | DEFAULT_DEALS |
| groupBy Field to group by at first. | "stage" | "owner" | "none" | "stage" |
| height Height of the scroll area, in px. | number | 440 |
| currency | string | "$" |
- theme"dark" | "light"Default: "dark"
- titlestringDefault: "Pipeline"
- subtitlestringDefault: "Group deals by stage or owner, fold groups you don't need"
- deals{ company: string; owner: string; stage: DealStage; value: number; probability: number; close: string }[]Default: DEFAULT_DEALS
- groupBy
Field to group by at first.
"stage" | "owner" | "none"Default: "stage" - height
Height of the scroll area, in px.
numberDefault: 440 - currencystringDefault: "$"
npm dependencies
Installed for you by the shadcn CLI.
Grouped Rows Table FAQ
- What data does it take?
- deals is { company, owner, stage, value, probability, close }[]. probability is 0–1 and is used for the weighted totals.
- Can I start grouped by owner?
- Yes, groupBy="owner" (or "none" for a flat list). Visitors can switch with the Group by control.
- Do group headers stay visible?
- Yes, each group header sticks just under the column header while its rows scroll past, so you always know which group you're in.
- Is it accessible?
- It uses table roles; each group header is a button with aria-expanded, and folded groups are inert so their rows aren't tabbable. With reduced motion groups fold instantly.