Data Table

Configurable data table with optional column freeze (left/right), customizable header and body colors and backgrounds, optional borders, and optional sortable columns.

UniqueUI CLI

npx uniqueui add data-table

shadcn CLI

npx shadcn@latest add https://uniqueui.com/r/data-table.json -y

shadcn path expects @/lib/utils (run shadcn init first). Same source file is installed to components/ui/.

Default

Variant 1 of 8
NameRoleEmailDepartmentLocationStatusJoined
Alex KimEngineeralex@example.comPlatformSan FranciscoActive2023-01
Sara ChenDesignersara@example.comProductNew YorkActive2023-03
Jordan LeePMjordan@example.comGrowthChicagoAway2023-06
Maya PatelEngineermaya@example.comPlatformSeattleActive2024-01
Ryan WuDesignerryan@example.comProductAustinAway2024-02
import { DataTable } from "@/components/ui/data-table";

const columns = [
  { key: "name", label: "Name" },
  { key: "role", label: "Role" },
  { key: "email", label: "Email" },
  { key: "department", label: "Department" },
  { key: "status", label: "Status" },
  { key: "joined", label: "Joined" },
];
const data = [
  { name: "Alex Kim", role: "Engineer", email: "alex@example.com", department: "Platform", status: "Active", joined: "2023-01" },
  { name: "Sara Chen", role: "Designer", email: "sara@example.com", department: "Product", status: "Active", joined: "2023-03" },
  { name: "Jordan Lee", role: "PM", email: "jordan@example.com", department: "Growth", status: "Away", joined: "2023-06" },
  { name: "Maya Patel", role: "Engineer", email: "maya@example.com", department: "Platform", status: "Active", joined: "2024-01" },
  { name: "Ryan Wu", role: "Designer", email: "ryan@example.com", department: "Product", status: "Away", joined: "2024-02" },
  { name: "Priya Shah", role: "PM", email: "priya@example.com", department: "Growth", status: "Active", joined: "2024-04" },
  { name: "Sam Rivera", role: "Engineer", email: "sam@example.com", department: "Platform", status: "Active", joined: "2024-05" },
  { name: "Jess Taylor", role: "Designer", email: "jess@example.com", department: "Product", status: "Active", joined: "2024-06" },
];

export default function Example() {
  return (
    <div className="w-full p-6">
      <DataTable columns={columns} data={data} paginated pageSize={5} theme="dark" />
    </div>
  );
}

Freeze left

Variant 2 of 8
IDNameEmailRoleDepartmentRegionLocationProjectDivisionSiteTZCost ctrJoinedStatusActions
1Alex Kimalex@example.comEngineerPlatformWestSan FranciscoOrionPlatform coreSF-01PTCC-41002023-01ActiveEdit · View
2Sara Chensara@example.comDesignerProductEastNew YorkNovaProduct designNYC-04ETCC-22002023-03ActiveEdit · View
3Jordan Leejordan@example.comPMGrowthCentralChicagoAtlasGrowth GTMCHI-02CTCC-18002023-06AwayEdit · View
4Maya Patelmaya@example.comEngineerPlatformWestSeattlePulsePlatform coreSEA-01PTCC-41002024-01ActiveEdit · View
5Ryan Wuryan@example.comDesignerProductEastAustinVertexProduct designAUS-01CTCC-33002024-02AwayEdit · View
import { DataTable } from "@/components/ui/data-table";

const columns = [
  { key: "id", label: "ID" },
  { key: "name", label: "Name" },
  { key: "email", label: "Email" },
  { key: "role", label: "Role" },
  { key: "department", label: "Department" },
  { key: "region", label: "Region" },
  { key: "joined", label: "Joined" },
  { key: "status", label: "Status" },
  { key: "actions", label: "Actions" },
];
const data = [
  { id: "1", name: "Alex Kim", email: "alex@example.com", role: "Engineer", department: "Platform", region: "West", joined: "2023-01", status: "Active", actions: "Edit · View" },
  { id: "2", name: "Sara Chen", email: "sara@example.com", role: "Designer", department: "Product", region: "East", joined: "2023-03", status: "Active", actions: "Edit · View" },
  { id: "3", name: "Jordan Lee", email: "jordan@example.com", role: "PM", department: "Growth", region: "Central", joined: "2023-06", status: "Away", actions: "Edit · View" },
  { id: "4", name: "Maya Patel", email: "maya@example.com", role: "Engineer", department: "Platform", region: "West", joined: "2024-01", status: "Active", actions: "Edit · View" },
  { id: "5", name: "Ryan Wu", email: "ryan@example.com", role: "Designer", department: "Product", region: "East", joined: "2024-02", status: "Away", actions: "Edit · View" },
  { id: "6", name: "Priya Shah", email: "priya@example.com", role: "PM", department: "Growth", region: "Central", joined: "2024-04", status: "Active", actions: "Edit · View" },
  { id: "7", name: "Sam Rivera", email: "sam@example.com", role: "Engineer", department: "Platform", region: "West", joined: "2024-05", status: "Active", actions: "Edit · View" },
  { id: "8", name: "Jess Taylor", email: "jess@example.com", role: "Designer", department: "Product", region: "East", joined: "2024-06", status: "Active", actions: "Edit · View" },
];

export default function Example() {
  return (
    <div className="w-full p-6">
        <DataTable
          columns={columns}
          data={data}
          freezeColumns="left"
          freezeLeftCount={2}
        paginated
        pageSize={5}
        theme="dark"
      />
    </div>
  );
}

Freeze right

Variant 3 of 8
NameRoleDepartmentRegionProjectDivisionSiteTZCost ctrLocationStatusEmailJoinedLast activeActions
Alex KimEngineerPlatformWestOrionPlatform coreSF-01PTCC-4100San FranciscoActivealex@example.com2023-012024-03Edit · View
Sara ChenDesignerProductEastNovaProduct designNYC-04ETCC-2200New YorkActivesara@example.com2023-032024-03Edit · View
Jordan LeePMGrowthCentralAtlasGrowth GTMCHI-02CTCC-1800ChicagoAwayjordan@example.com2023-062024-02Edit · View
Maya PatelEngineerPlatformWestPulsePlatform coreSEA-01PTCC-4100SeattleActivemaya@example.com2024-012024-03Edit · View
Ryan WuDesignerProductEastVertexProduct designAUS-01CTCC-3300AustinAwayryan@example.com2024-022024-01Edit · View
import { DataTable } from "@/components/ui/data-table";

const columns = [
  { key: "name", label: "Name" },
  { key: "role", label: "Role" },
  { key: "department", label: "Department" },
  { key: "region", label: "Region" },
  { key: "status", label: "Status" },
  { key: "email", label: "Email" },
  { key: "joined", label: "Joined" },
  { key: "lastActive", label: "Last active" },
  { key: "actions", label: "Actions" },
];
const data = [
  { name: "Alex Kim", role: "Engineer", department: "Platform", region: "West", status: "Active", email: "alex@example.com", joined: "2023-01", lastActive: "2024-03", actions: "Edit · View" },
  { name: "Sara Chen", role: "Designer", department: "Product", region: "East", status: "Active", email: "sara@example.com", joined: "2023-03", lastActive: "2024-03", actions: "Edit · View" },
  { name: "Jordan Lee", role: "PM", department: "Growth", region: "Central", status: "Away", email: "jordan@example.com", joined: "2023-06", lastActive: "2024-02", actions: "Edit · View" },
  { name: "Maya Patel", role: "Engineer", department: "Platform", region: "West", status: "Active", email: "maya@example.com", joined: "2024-01", lastActive: "2024-03", actions: "Edit · View" },
  { name: "Ryan Wu", role: "Designer", department: "Product", region: "East", status: "Away", email: "ryan@example.com", joined: "2024-02", lastActive: "2024-01", actions: "Edit · View" },
  { name: "Priya Shah", role: "PM", department: "Growth", region: "Central", status: "Active", email: "priya@example.com", joined: "2024-04", lastActive: "2024-03", actions: "Edit · View" },
  { name: "Sam Rivera", role: "Engineer", department: "Platform", region: "West", status: "Active", email: "sam@example.com", joined: "2024-05", lastActive: "2024-03", actions: "Edit · View" },
  { name: "Jess Taylor", role: "Designer", department: "Product", region: "East", status: "Active", email: "jess@example.com", joined: "2024-06", lastActive: "2024-03", actions: "Edit · View" },
];

export default function Example() {
  return (
    <div className="w-full p-6">
        <DataTable
          columns={columns}
          data={data}
          freezeColumns="right"
          freezeRightCount={1}
        paginated
        pageSize={5}
        theme="dark"
      />
    </div>
  );
}

Freeze both

Variant 4 of 8
IDNameEmailRoleDepartmentRegionLocationProjectDivisionSiteTZCost ctrJoinedStatusActions
1Alex Kimalex@example.comEngineerPlatformWestSan FranciscoOrionPlatform coreSF-01PTCC-41002023-01ActiveEdit · View
2Sara Chensara@example.comDesignerProductEastNew YorkNovaProduct designNYC-04ETCC-22002023-03ActiveEdit · View
3Jordan Leejordan@example.comPMGrowthCentralChicagoAtlasGrowth GTMCHI-02CTCC-18002023-06AwayEdit · View
4Maya Patelmaya@example.comEngineerPlatformWestSeattlePulsePlatform coreSEA-01PTCC-41002024-01ActiveEdit · View
5Ryan Wuryan@example.comDesignerProductEastAustinVertexProduct designAUS-01CTCC-33002024-02AwayEdit · View
import { DataTable } from "@/components/ui/data-table";

const columns = [
  { key: "id", label: "ID" },
  { key: "name", label: "Name" },
  { key: "email", label: "Email" },
  { key: "role", label: "Role" },
  { key: "department", label: "Department" },
  { key: "region", label: "Region" },
  { key: "joined", label: "Joined" },
  { key: "status", label: "Status" },
  { key: "actions", label: "Actions" },
];
const data = [
  { id: "1", name: "Alex Kim", email: "alex@example.com", role: "Engineer", department: "Platform", region: "West", joined: "2023-01", status: "Active", actions: "Edit · View" },
  { id: "2", name: "Sara Chen", email: "sara@example.com", role: "Designer", department: "Product", region: "East", joined: "2023-03", status: "Active", actions: "Edit · View" },
  { id: "3", name: "Jordan Lee", email: "jordan@example.com", role: "PM", department: "Growth", region: "Central", joined: "2023-06", status: "Away", actions: "Edit · View" },
  { id: "4", name: "Maya Patel", email: "maya@example.com", role: "Engineer", department: "Platform", region: "West", joined: "2024-01", status: "Active", actions: "Edit · View" },
  { id: "5", name: "Ryan Wu", email: "ryan@example.com", role: "Designer", department: "Product", region: "East", joined: "2024-02", status: "Away", actions: "Edit · View" },
  { id: "6", name: "Priya Shah", email: "priya@example.com", role: "PM", department: "Growth", region: "Central", joined: "2024-04", status: "Active", actions: "Edit · View" },
  { id: "7", name: "Sam Rivera", email: "sam@example.com", role: "Engineer", department: "Platform", region: "West", joined: "2024-05", status: "Active", actions: "Edit · View" },
  { id: "8", name: "Jess Taylor", email: "jess@example.com", role: "Designer", department: "Product", region: "East", joined: "2024-06", status: "Active", actions: "Edit · View" },
];

export default function Example() {
  return (
    <div className="w-full p-6">
        <DataTable
          columns={columns}
          data={data}
          freezeColumns="both"
          freezeLeftCount={2}
          freezeRightCount={1}
        paginated
        pageSize={5}
        theme="dark"
      />
    </div>
  );
}

Bordered

Variant 5 of 8
NameRoleEmailDepartmentLocationStatusJoined
Alex KimEngineeralex@example.comPlatformSan FranciscoActive2023-01
Sara ChenDesignersara@example.comProductNew YorkActive2023-03
Jordan LeePMjordan@example.comGrowthChicagoAway2023-06
Maya PatelEngineermaya@example.comPlatformSeattleActive2024-01
Ryan WuDesignerryan@example.comProductAustinAway2024-02
import { DataTable } from "@/components/ui/data-table";

const columns = [
  { key: "name", label: "Name" },
  { key: "role", label: "Role" },
  { key: "email", label: "Email" },
  { key: "department", label: "Department" },
  { key: "status", label: "Status" },
  { key: "joined", label: "Joined" },
];
const data = [
  { name: "Alex Kim", role: "Engineer", email: "alex@example.com", department: "Platform", status: "Active", joined: "2023-01" },
  { name: "Sara Chen", role: "Designer", email: "sara@example.com", department: "Product", status: "Active", joined: "2023-03" },
  { name: "Jordan Lee", role: "PM", email: "jordan@example.com", department: "Growth", status: "Away", joined: "2023-06" },
  { name: "Maya Patel", role: "Engineer", email: "maya@example.com", department: "Platform", status: "Active", joined: "2024-01" },
  { name: "Ryan Wu", role: "Designer", email: "ryan@example.com", department: "Product", status: "Away", joined: "2024-02" },
  { name: "Priya Shah", role: "PM", email: "priya@example.com", department: "Growth", status: "Active", joined: "2024-04" },
  { name: "Sam Rivera", role: "Engineer", email: "sam@example.com", department: "Platform", status: "Active", joined: "2024-05" },
  { name: "Jess Taylor", role: "Designer", email: "jess@example.com", department: "Product", status: "Active", joined: "2024-06" },
];

export default function Example() {
  return (
    <div className="w-full p-6">
      <DataTable columns={columns} data={data} border paginated pageSize={5} theme="dark" />
    </div>
  );
}

Sortable

Variant 6 of 8
Jordan LeePMGrowthSan Francisco2024-03Away
Alex KimEngineerPlatformNew York2024-01Active
Sara ChenDesignerProductChicago2024-02Active
Maya PatelEngineerPlatformSeattle2023-11Active
Ryan WuDesignerProductAustin2024-05Away
import { DataTable } from "@/components/ui/data-table";

const columns = [
  { key: "name", label: "Name", sortKey: "name" },
  { key: "role", label: "Role", sortKey: "role" },
  { key: "department", label: "Department", sortKey: "department" },
  { key: "joined", label: "Joined", sortKey: "joined" },
  { key: "status", label: "Status", sortKey: "status" },
];
const data = [
  { name: "Jordan Lee", role: "PM", department: "Growth", joined: "2024-03", status: "Away" },
  { name: "Alex Kim", role: "Engineer", department: "Platform", joined: "2024-01", status: "Active" },
  { name: "Sara Chen", role: "Designer", department: "Product", joined: "2024-02", status: "Active" },
  { name: "Maya Patel", role: "Engineer", department: "Platform", joined: "2023-11", status: "Active" },
  { name: "Ryan Wu", role: "Designer", department: "Product", joined: "2024-05", status: "Away" },
  { name: "Priya Shah", role: "PM", department: "Growth", joined: "2023-08", status: "Active" },
  { name: "Sam Rivera", role: "Engineer", department: "Platform", joined: "2024-06", status: "Active" },
  { name: "Jess Taylor", role: "Designer", department: "Product", joined: "2023-09", status: "Active" },
];

export default function Example() {
  return (
    <div className="w-full p-6">
      <DataTable columns={columns} data={data} sortable paginated pageSize={5} theme="dark" />
    </div>
  );
}

Custom colors

Variant 7 of 8
NameRoleEmailDepartmentLocationStatusJoined
Alex KimEngineeralex@example.comPlatformSan FranciscoActive2023-01
Sara ChenDesignersara@example.comProductNew YorkActive2023-03
Jordan LeePMjordan@example.comGrowthChicagoAway2023-06
Maya PatelEngineermaya@example.comPlatformSeattleActive2024-01
Ryan WuDesignerryan@example.comProductAustinAway2024-02
import { DataTable } from "@/components/ui/data-table";

const columns = [
  { key: "name", label: "Name" },
  { key: "role", label: "Role" },
  { key: "email", label: "Email" },
  { key: "department", label: "Department" },
  { key: "status", label: "Status" },
  { key: "joined", label: "Joined" },
];
const data = [
  { name: "Alex Kim", role: "Engineer", email: "alex@example.com", department: "Platform", status: "Active", joined: "2023-01" },
  { name: "Sara Chen", role: "Designer", email: "sara@example.com", department: "Product", status: "Active", joined: "2023-03" },
  { name: "Jordan Lee", role: "PM", email: "jordan@example.com", department: "Growth", status: "Away", joined: "2023-06" },
  { name: "Maya Patel", role: "Engineer", email: "maya@example.com", department: "Platform", status: "Active", joined: "2024-01" },
  { name: "Ryan Wu", role: "Designer", email: "ryan@example.com", department: "Product", status: "Away", joined: "2024-02" },
  { name: "Priya Shah", role: "PM", email: "priya@example.com", department: "Growth", status: "Active", joined: "2024-04" },
  { name: "Sam Rivera", role: "Engineer", email: "sam@example.com", department: "Platform", status: "Active", joined: "2024-05" },
  { name: "Jess Taylor", role: "Designer", email: "jess@example.com", department: "Product", status: "Active", joined: "2024-06" },
];

export default function Example() {
  return (
    <div className="w-full p-6">
      <DataTable
        columns={columns}
        data={data}
        headerTextColor="text-purple-900"
        bodyTextColor="text-neutral-800"
        headerBackground="bg-purple-100"
        bodyBackground="bg-purple-50/50"
        paginated
        pageSize={5}
        border
        theme="dark"
      />
    </div>
  );
}

Full options

Variant 8 of 8
IDDeptRegionLocationProjectDivisionSiteTZCost ctrJoinedActions
1Jordan LeePMGrowthCentralSan FranciscoOrionPlatform coreSF-01PTCC-41002023-06Edit
2Alex KimEngineerPlatformWestNew YorkNovaProduct designNYC-04ETCC-22002023-01Edit
3Sara ChenDesignerProductEastChicagoAtlasGrowth GTMCHI-02CTCC-18002023-03Edit
4Maya PatelEngineerPlatformWestSeattlePulsePlatform coreSEA-01PTCC-41002024-01Edit
5Ryan WuDesignerProductEastAustinVertexProduct designAUS-01CTCC-33002024-02Edit
import { DataTable } from "@/components/ui/data-table";

const columns = [
  { key: "id", label: "ID" },
  { key: "name", label: "Name", sortKey: "name" },
  { key: "role", label: "Role", sortKey: "role" },
  { key: "department", label: "Dept" },
  { key: "region", label: "Region" },
  { key: "joined", label: "Joined" },
  { key: "actions", label: "Actions" },
];
const data = [
  { id: "1", name: "Jordan Lee", role: "PM", department: "Growth", region: "Central", joined: "2023-06", actions: "Edit" },
  { id: "2", name: "Alex Kim", role: "Engineer", department: "Platform", region: "West", joined: "2023-01", actions: "Edit" },
  { id: "3", name: "Sara Chen", role: "Designer", department: "Product", region: "East", joined: "2023-03", actions: "Edit" },
  { id: "4", name: "Maya Patel", role: "Engineer", department: "Platform", region: "West", joined: "2024-01", actions: "Edit" },
  { id: "5", name: "Ryan Wu", role: "Designer", department: "Product", region: "East", joined: "2024-02", actions: "Edit" },
  { id: "6", name: "Priya Shah", role: "PM", department: "Growth", region: "Central", joined: "2024-04", actions: "Edit" },
  { id: "7", name: "Sam Rivera", role: "Engineer", department: "Platform", region: "West", joined: "2024-05", actions: "Edit" },
  { id: "8", name: "Jess Taylor", role: "Designer", department: "Product", region: "East", joined: "2024-06", actions: "Edit" },
];

export default function Example() {
  return (
    <div className="w-full p-6">
        <DataTable
          columns={columns}
          data={data}
          freezeColumns="left"
          freezeLeftCount={1}
        headerTextColor="text-neutral-100"
        bodyTextColor="text-neutral-300"
        headerBackground="bg-neutral-800"
        bodyBackground="bg-neutral-950"
        border
        sortable
        paginated
        pageSize={5}
        pageSizeOptions={[5, 10, 20]}
        onPageChange={(page, pageSize) =>
          console.log("page changed", page, "pageSize", pageSize)
        }
        theme="dark"
      />
    </div>
  );
}

Props

PropTypeDescription
columnsDataTableColumn[]Column definitions: key, label, and optional sortKey for sortable columns.
dataRecord<string, React.ReactNode>[]Row data; each row is an object keyed by column key.
freezeColumns"none" | "left" | "right" | "both"Which columns to freeze when horizontally scrolling: none, left, right, or both sides.
freezeCountnumberLegacy fallback count used only when freezeLeftCount or freezeRightCount are not provided.
freezeLeftCountnumberHow many columns to freeze on the left when freezeColumns is "left" or "both".
freezeRightCountnumberHow many columns to freeze on the right when freezeColumns is "right" or "both".
paginatedbooleanEnable built-in pagination controls.
pageSizenumberNumber of rows per page when paginated is true.
pageSizeOptionsnumber[]Optional list of page sizes to show in a selector.
initialPagenumberInitial page index (1-based) when paginated is true.
onPageChange(page: number, pageSize: number) => voidCalled when the current page or page size changes.
paginationPreviousLabelReact.ReactNodePrevious-page control content; defaults to a left chevron icon.
paginationNextLabelReact.ReactNodeNext-page control content; defaults to a right chevron icon.
getRowKey(row, index) => React.KeyOptional stable key per row for React reconciliation (sort, pagination). Defaults to row.id / row.key when string or number, else a generated key.
headerTextColorstringTailwind class for header text, e.g. text-neutral-900.
bodyTextColorstringTailwind class for body cell text.
headerBackgroundstringTailwind class for header background, e.g. bg-neutral-100.
bodyBackgroundstringTailwind class for body background.
borderbooleanWhether to show table and cell borders.
sortablebooleanWhether column headers with sortKey are clickable to sort.
onSort(key: string, direction: "asc" | "desc") => voidCallback when sort changes (for controlled use).
classNamestringAdditional classes on the root wrapper.
theme"light" | "dark"Theme for default header/body colors when not overridden.