Expandable Rows
Free expandable table rows for React and Next.js, animated with pure CSS.
- Automated axe check
- Reduced-motion tested
- SSR build verified
- CSS and React
- 1 runtime package
Expandable Rows is a free React table component for Next.js that adds expandable detail rows to a real HTML table, styled with Tailwind and animated with zero JavaScript animation code. Each data row carries a trailing toggle button; activating it unfolds a full width detail panel beneath the row by interpolating a CSS grid wrapper's grid-template-rows from 0fr to 1fr while the chevron rotates ninety degrees in sync.
Semantics stay pure table throughout: detail panels are real tr and td elements with colSpan, never divs pretending to be rows, so screen readers and crawlers see an ordinary table. Any number of rows can be open at once, each one independent, and a required stable row id keeps expansion attached to the same record through inserts, removals, and reordering. Closing panels become inert immediately, then transition visibility to hidden after the fold completes; with reduced motion enabled every toggle is instant.
| Order | Customer | Total | Status | Details |
|---|---|---|---|---|
| TE-1042 | Aurora Studio | $1,240.00 | Shipped | |
| ||||
| TE-1041 | Northwind Labs | $386.50 | Processing | |
| ||||
| TE-1040 | Halbon Systems | $2,980.00 | Delivered | |
| ||||
| TE-1039 | Fieldline Co | $149.00 | Refunded | |
| ||||
| TE-1038 | Meridian Press | $720.00 | Shipped | |
| ||||
Install
Add the @te registry to your components.json once:
{
"registries": {
"@te": "https://templateempire.io/r/{name}.json"
}
}Then install the component:
npx shadcn@latest add @te/table-expand-rowsUsage
import { TableExpandRows } from "@/components/table-expand-rows";
const columns = [
{ key: "order", label: "Order" },
{ key: "customer", label: "Customer" },
{ key: "total", label: "Total" },
];
const rows = [
{
id: "TE-1042",
cells: { order: "TE-1042", customer: "Aurora Studio", total: "$1,240.00" },
detail: <p>3 x Studio Display Arm, shipped via DHL Express.</p>,
},
{
id: "TE-1041",
cells: { order: "TE-1041", customer: "Northwind Labs", total: "$386.50" },
detail: <p>2 x Mechanical Keyboard, picking in Rotterdam.</p>,
},
];
export default function Page() {
return (
<TableExpandRows caption="Recent orders" columns={columns} rows={rows} />
);
}Props
| Prop | Type | Default | Description |
|---|---|---|---|
| columns | { key: string; label: string }[] | required | Column definitions; each key indexes into every row's cells record and each label renders as a column header. |
| rows | { id: string; cells: Record<string, ReactNode>; detail: ReactNode }[] | required | Row data with a unique stable id plus the detail panel content. The id keeps expansion attached to its record when rows reorder. |
| caption | string | undefined | Rendered as a visible caption at the top of the table. |
| className | string | undefined | Additional classes merged onto the table. |
Customisation
Expandable Rows declares no tokens of its own; it consumes the shared motion tokens for the unfold and the global semantic colour tokens through its Tailwind utilities, with the docs/03 values baked in as fallbacks for fresh installs. Slow the unfold or change its curve by overriding the motion tokens, and restyle the table through the className prop and your semantic tokens:
<TableExpandRows columns={columns} rows={rows} className="text-sm" />
/* slower, softer unfold everywhere the tokens are consumed */
:root {
--dur-3: 800ms;
--ease-out-quart: cubic-bezier(0.22, 1, 0.36, 1);
}Frequently asked questions
- Is Expandable Rows free for commercial use?
- Yes. Expandable Rows is MIT licensed, so you can use it in personal and commercial projects without attribution.
- Does Expandable Rows stay accessible while rows are collapsed?
- Yes. Every toggle is a real button with aria-expanded and a name that references its row, and detail panels are real table rows with a single spanned cell, so table semantics are never faked. A closing panel becomes inert immediately, removing its content from focus and accessibility navigation while its visibility waits for the visual fold to finish. The animation interpolates grid-template-rows in pure CSS, and with reduced motion enabled both directions toggle instantly.
- Can several rows be open at the same time?
- Yes. Each row's required id owns its expanded state, so any number of detail panels can be open at once, reordering the rows keeps the right record open, and toggling one row never closes another. IDs must be unique and stable for the lifetime of each record. There is no accordion mode or controlled expansion API.