Skip to content
Template Empire
Browse components

Row Stagger Table

A free animated data table with staggered row reveals for React and Next.js.

Service status across production regions
ServiceRegionVersionp95 latencyStatus
edge-gatewayeu-west-1v2.14.038 msHealthy
api-coreus-east-1v5.3.261 msHealthy
billing-workerus-east-1v1.9.4112 msDegraded
search-indexap-south-1v3.0.174 msHealthy
media-transcodeeu-west-1v0.27.8215 msDeploying

Customise

0.05s

Code

<TableRowStagger
  caption="Service status across production regions"
>
  {/* your thead and tbody */}
</TableRowStagger>

Row Stagger Table is a free React animated table component for Next.js, built with Motion 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, and under reduced motion nothing is animated or observed.

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-stagger

Usage

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

PropTypeDefaultDescription
childrenReactNoderequiredThe table content: a thead and tbody authored by the consumer. Semantics pass through untouched; only tbody rows animate.
captionstringundefinedRendered as a visible caption at the top of the table.
staggernumber0.05Seconds between row reveals.
classNamestringundefinedAdditional 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. Rows waiting below the fold are set to their starting state before the page first paints, so no row is ever seen visible and then hidden; they fade with opacity only and stay in the accessibility tree, and if focus lands in the table before the cascade has finished, every row comes to rest at once so a focused link is never transparent. Crawlers and no-JS visitors get the server HTML with every row visible, and with reduced motion enabled nothing is animated or observed.
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.

Related components

Want the full page this belongs to?Template Empire builds complete Next.js templates with this motion system throughout. Browse the paid templates that pair with these free components.Explore Template Empire templates