Row Stagger Table
A free animated data table with staggered row reveals for React and Next.js.
- Automated axe check
- Reduced-motion tested
- SSR build verified
- GSAP
- 2 runtime packages
Row Stagger Table is a free React animated table component for Next.js, built with GSAP ScrollTrigger and styled with Tailwind. It renders a real table element and, as it scrolls into view, cascades the body rows in one after another: each row rises 12 pixels and fades from transparent to opaque, separated by a configurable stagger. The header row never animates.
You author the thead and tbody yourself and pass them as children, so the table semantics reach the browser untouched; the component only wraps them in a table, renders an optional visible caption and owns the reveal choreography. The authored HTML is the final visible state, which means crawlers, no-JS visitors and reduced-motion users always see every row immediately, with no ScrollTriggers created under reduced motion.
| Service | Region | Version | p95 latency | Status |
|---|---|---|---|---|
| edge-gateway | eu-west-1 | v2.14.0 | 38 ms | Healthy |
| api-core | us-east-1 | v5.3.2 | 61 ms | Healthy |
| billing-worker | us-east-1 | v1.9.4 | 112 ms | Degraded |
| search-index | ap-south-1 | v3.0.1 | 74 ms | Healthy |
| media-transcode | eu-west-1 | v0.27.8 | 215 ms | Deploying |
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-row-staggerUsage
import { TableRowStagger } from "@/components/table-row-stagger";
export default function Page() {
return (
<TableRowStagger caption="Invoices issued this quarter" stagger={0.05}>
<thead>
<tr>
<th scope="col">Invoice</th>
<th scope="col">Client</th>
<th scope="col">Amount</th>
</tr>
</thead>
<tbody>
<tr>
<td>INV-0041</td>
<td>Acme Ltd</td>
<td>1,200.00</td>
</tr>
<tr>
<td>INV-0042</td>
<td>Northwind</td>
<td>860.00</td>
</tr>
</tbody>
</TableRowStagger>
);
}Props
| Prop | Type | Default | Description |
|---|---|---|---|
| children | ReactNode | required | The table content: a thead and tbody authored by the consumer. Semantics pass through untouched; only tbody rows animate. |
| caption | string | undefined | Rendered as a visible caption at the top of the table. |
| stagger | number | 0.05 | Seconds between row reveals. |
| className | string | undefined | Additional classes merged onto the table. |
Customisation
Row Stagger Table declares no tokens of its own; it is a semantic frame that consumes the global semantic tokens through the Tailwind utilities on the table and caption, and your thead and tbody markup owns the cell styling. Space the reveals further apart with the stagger prop, restyle the table from the className prop, and retheme your rows through the same semantic tokens the rest of the library uses:
<TableRowStagger stagger={0.1} className="text-sm">
{rows}
</TableRowStagger>
/* rows styled with semantic tokens */
:root {
--border: oklch(from var(--color-neutral-50) l c h / 0.16);
}Frequently asked questions
- Is Row Stagger Table free for commercial use?
- Yes. Row Stagger Table is MIT licensed, so you can use it in personal and commercial projects without attribution.
- Does Row Stagger Table affect performance or accessibility?
- The reveal animates transform and opacity only, inside space the table has already reserved, so layout shift is zero. You author the thead and tbody yourself and the component passes them through untouched, keeping real table semantics, and animation never changes the DOM order. The from-state is applied only when the single run-once ScrollTrigger fires, so keyboard users, crawlers and no-JS visitors always see every row, and with reduced motion enabled no triggers are created at all.
- Can I change the speed of the row cascade?
- Yes. The stagger prop sets the gap in seconds between one row starting and the next, and defaults to 0.05. Raise it for a slower, more deliberate cascade or lower it for a quicker one. Each row's own rise and fade uses the shared library timing, and the header row is never part of the cascade.