Skip to content
Template Empire
Browse components

FLIP Sort Table

A free sortable data table with FLIP row animation for React and Next.js.

Cot Field, pressed this season
DabinettLong Meadow41.2688
Yarlington MillLong Meadow27.6671
Harry Masters JerseyHedgerow22.1659
Kingston BlackHedgerow18.4642
Browns AppleCot Field12.9705
Somerset RedstreakCot Field9.7618

FLIP Sort Table is a free React data table component for Next.js, built with Motion and styled with Tailwind. Clicking a column header sorts the rows, and instead of snapping into place each row glides to its new position with a FLIP layout animation on a soft spring, transform only, settling in about half a second.

Sort controls are real buttons inside each th, aria-sort stays in sync on the header cell, and the active column's arrow rotates 180 degrees when the direction changes. Sorting re-orders the DOM itself, so the accessible reading order always matches the visual order at rest, and with reduced motion enabled rows swap to their new order instantly.

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-sort-flip

Usage

import { TableSortFlip } from "@/components/table-sort-flip";

const columns = [
  { key: "client", label: "Client" },
  { key: "invoices", label: "Invoices", numeric: true },
  { key: "revenue", label: "Revenue", numeric: true },
];

const rows = [
  { client: "Acme Ltd", invoices: 14, revenue: 12400 },
  { client: "Northwind", invoices: 9, revenue: 8600 },
  { client: "Globex", invoices: 21, revenue: 19750 },
];

export default function Page() {
  return (
    <TableSortFlip
      columns={columns}
      rows={rows}
      defaultSort={{ key: "revenue", dir: "desc" }}
      caption="Revenue by client this quarter"
    />
  );
}

Props

PropTypeDefaultDescription
columns{ key: string; label: string; numeric?: boolean }[]requiredSortable column definitions in display order. numeric right-aligns the column and compares values numerically.
rowsRecord<string, string | number>[]requiredRow data keyed by column key. Row identity follows the array index, so each row FLIPs as the same element across sorts.
defaultSort{ key: string; dir: "asc" | "desc" }undefinedInitial sort column and direction. Omit to render rows in their authored order until a header is clicked.
captionstringundefinedRendered as a visible caption at the top of the table.
classNamestringundefinedAdditional classes merged onto the table.

Customisation

FLIP Sort Table declares no tokens of its own; it consumes the global semantic tokens through the Tailwind utilities on the table, headers and cells. Restyle it from the className prop and retheme the borders, muted header text and foreground cells through the same semantic tokens the rest of the library uses:

<TableSortFlip
  columns={columns}
  rows={rows}
  className="text-sm"
/>

/* retheme through semantic tokens */
:root {
  --border: oklch(from var(--color-neutral-50) l c h / 0.16);
}

Frequently asked questions

Is FLIP Sort Table free for commercial use?
Yes. FLIP Sort Table is MIT licensed, so you can use it in personal and commercial projects without attribution.
Does FLIP Sort Table affect performance or accessibility?
The re-order animates transforms only: each row FLIPs to its new slot at a fixed height, so there is no layout thrash and no layout shift while rows are in flight. Sort controls are real buttons with visible focus, the header cells keep aria-sort in sync, and sorting re-orders the DOM so screen readers always read the order that is on screen. With reduced motion enabled rows swap instantly and the arrow flips without rotation.
Can I control how columns sort?
Mark a column with numeric: true to right-align it and compare its values as numbers; other columns compare as natural-order, case-insensitive strings. Set the initial column and direction with defaultSort, and clicking the active header toggles between ascending and descending. Ties fall back to the authored row order, so repeat sorts are deterministic.

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