Skip to content

Manual Installation

Copy and paste all DataTable components into your project manually.

Before copying the components, make sure you have:

  1. A React project (Next.js, Vite, etc.)
  2. Shadcn UI set up in your project (Installation Guide)
  3. TailwindCSS configured
  4. TypeScript (recommended)

The DataTable components use a two-layer architecture for maximum flexibility:

  • Components (data-table-*.tsx in /components folder) - Context-aware wrapper components that use useDataTable() hook to automatically get the table from DataTableRoot context. These eliminate prop drilling and are the recommended way to use components:
    • DataTableSearchFilter, DataTableFilterMenu, DataTableSortMenu, DataTablePagination, etc.
  • Filters (table-*.tsx in /filters folder) - Core implementation components that accept a table prop directly and use TanStack Table hooks (like table.getState(), table.setGlobalFilter(), etc.). These can be used standalone:
    • TableSearchFilter, TableFilterMenu, TableSortMenu, etc.

Why this architecture?

  • Use DataTable* components from ”@/components/niko-table/components” when you want context-based, zero-config usage
  • Use Table* components from filters when you want to build custom components or manage the table instance yourself
  • All filter components use TanStack Table hooks directly, giving you full control
  1. Install the required dependencies

    pnpm add @tanstack/react-table
  2. Install the required Shadcn UI components

    pnpm dlx npx shadcn@latest add table button input dropdown-menu
  3. Update components/ui/table.tsx

    Replace the entire contents with this updated version:

    components/ui/table.tsx
    "use client"
    import * as React from "react"
    import { cn } from "@/lib/utils"
    function TableComponent({
    className,
    ...props
    }: React.ComponentProps<"table">) {
    return (
    <table
    data-slot="table"
    className={cn("w-full caption-bottom text-sm", className)}
    {...props}
    />
    )
    }
    function Table({ className, ...props }: React.ComponentProps<"table">) {
    return (
    <div
    data-slot="table-container"
    className="relative w-full overflow-x-auto"
    >
    <TableComponent className={className} {...props} />
    </div>
    )
    }
    function TableHeader({
    className,
    ...props
    }: React.ComponentProps<"thead">) {
    return (
    <thead
    data-slot="table-header"
    className={cn("[&_tr]:border-b", className)}
    {...props}
    />
    )
    }
    function TableBody({ className, ...props }: React.ComponentProps<"tbody">) {
    return (
    <tbody
    data-slot="table-body"
    className={cn("[&_tr:last-child]:border-0", className)}
    {...props}
    />
    )
    }
    function TableFooter({
    className,
    ...props
    }: React.ComponentProps<"tfoot">) {
    return (
    <tfoot
    data-slot="table-footer"
    className={cn(
    "border-t bg-muted/50 font-medium [&>tr]:last:border-b-0",
    className,
    )}
    {...props}
    />
    )
    }
    function TableRow({ className, ...props }: React.ComponentProps<"tr">) {
    return (
    <tr
    data-slot="table-row"
    className={cn(
    "border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted",
    className,
    )}
    {...props}
    />
    )
    }
    function TableHead({ className, ...props }: React.ComponentProps<"th">) {
    return (
    <th
    data-slot="table-head"
    className={cn(
    "h-10 px-2 text-left align-middle font-medium whitespace-nowrap text-foreground [&:has([role=checkbox])]:pr-0 *:[[role=checkbox]]:translate-y-[2px]",
    className,
    )}
    {...props}
    />
    )
    }
    function TableCell({ className, ...props }: React.ComponentProps<"td">) {
    return (
    <td
    data-slot="table-cell"
    className={cn(
    "p-2 align-middle whitespace-nowrap [&:has([role=checkbox])]:pr-0 *:[[role=checkbox]]:translate-y-[2px]",
    className,
    )}
    {...props}
    />
    )
    }
    function TableCaption({
    className,
    ...props
    }: React.ComponentProps<"caption">) {
    return (
    <caption
    data-slot="table-caption"
    className={cn("mt-4 text-sm text-muted-foreground", className)}
    {...props}
    />
    )
    }
    export {
    TableComponent,
    Table,
    TableHeader,
    TableBody,
    TableFooter,
    TableHead,
    TableRow,
    TableCell,
    TableCaption,
    }

    What changed?

    • Added TableComponent export (used internally by DataTable)
    • Added data-slot attributes to all elements
    • Wrapped table in a container div for overflow handling

    Note: These changes are 100% backward compatible - your existing Shadcn tables will continue to work exactly as before.

  4. Copy all DataTable components

    Copy all the files below into your project, maintaining the directory structure shown.

  5. Update import paths

    Update the import paths in the copied files to match your project structure. The components use:

    • @/components/ui/ for Shadcn UI components
    • @/components/niko-table/ for DataTable components
    • @/lib/ for utility functions
  6. Verify installation

    Create a simple test to verify everything is working:

    import {
    DataTableRoot,
    DataTable,
    DataTableHeader,
    DataTableBody,
    } from "@/components/niko-table/core"
    const columns = [
    { accessorKey: "name", header: "Name" },
    { accessorKey: "email", header: "Email" },
    ]
    const data = [
    { id: "1", name: "John Doe", email: "[email protected]" },
    { id: "2", name: "Jane Smith", email: "[email protected]" },
    ]
    export function TestTable() {
    return (
    <DataTableRoot data={data} columns={columns}>
    <DataTable>
    <DataTableHeader />
    <DataTableBody />
    </DataTable>
    </DataTableRoot>
    )
    }

After copying all files, your project structure should look like this:

your-project/
├── src/
│ ├── components/
│ │ ├── ui/
│ │ │ ├── table.tsx # Updated Shadcn table component
│ │ │ ├── button.tsx
│ │ │ ├── input.tsx
│ │ │ ├── dropdown-menu.tsx
│ │ │ └── ... # Other Shadcn components
│ │ │
│ │ └── niko-table/
│ │ ├── index.tsx # Main exports
│ │ │
│ │ ├── core/ # Core table components
│ │ │ ├── data-table-root.tsx
│ │ │ ├── data-table.tsx
│ │ │ ├── data-table-context.tsx
│ │ │ ├── data-table-structure.tsx # Header, Body, EmptyBody, Skeleton, Loading (consolidated)
│ │ │ ├── data-table-virtualized-structure.tsx # VirtualizedHeader, VirtualizedBody, VirtualizedEmptyBody, VirtualizedSkeleton, VirtualizedLoading (consolidated)
│ │ │ └── index.tsx
│ │ │
│ │ ├── components/ # All user-facing components
│ │ │ ├── data-table-search-filter.tsx # Context-aware components
│ │ │ ├── data-table-view-menu.tsx
│ │ │ ├── data-table-filter-menu.tsx
│ │ │ ├── data-table-sort-menu.tsx
│ │ │ ├── data-table-clear-filter.tsx
│ │ │ ├── data-table-faceted-filter.tsx
│ │ │ ├── data-table-slider-filter.tsx
│ │ │ ├── data-table-date-filter.tsx
│ │ │ ├── data-table-inline-filter.tsx
│ │ │ ├── data-table-pagination.tsx
│ │ │ ├── data-table-export-button.tsx
│ │ │ ├── table-column-header.tsx # Reusable UI components
│ │ │ ├── data-table-aside.tsx
│ │ │ ├── data-table-selection-bar.tsx
│ │ │ ├── data-table-toolbar-section.tsx
│ │ │ ├── data-table-empty-state.tsx
│ │ │ └── index.tsx
│ │ │
│ │ ├── filters/ # Core implementation components
│ │ │ ├── table-search-filter.tsx
│ │ │ ├── table-faceted-filter.tsx
│ │ │ ├── table-slider-filter.tsx
│ │ │ ├── table-date-filter.tsx
│ │ │ ├── table-inline-filter.tsx
│ │ │ ├── table-filter-menu.tsx
│ │ │ ├── table-view-menu.tsx
│ │ │ ├── table-sort-menu.tsx
│ │ │ ├── table-range-filter.tsx
│ │ │ ├── table-pagination.tsx
│ │ │ ├── table-export-button.tsx
│ │ │ └── index.tsx
│ │ │
│ │ ├── config/ # Configuration
│ │ │ ├── data-table.ts
│ │ │ ├── feature-detection.ts
│ │ │ └── index.tsx
│ │ │
│ │ ├── hooks/ # Custom React hooks
│ │ │ ├── use-derived-column-title.ts
│ │ │ ├── use-keyboard-shortcut.ts
│ │ │ └── index.ts
│ │ │
│ │ ├── lib/ # Utility functions
│ │ │ ├── constants.ts
│ │ │ ├── data-table.ts
│ │ │ ├── filter-functions.ts
│ │ │ ├── format.ts
│ │ │ └── index.ts
│ │ │
│ │ └── types/ # TypeScript types
│ │ └── index.ts
│ │
│ └── lib/
│ └── utils.ts # cn() utility (already in your project)
└── package.json

Browse and copy individual files below:

For advanced features, you may need additional dependencies:

For URL state persistence in tables:

pnpm add nuqs

For virtualized tables:

pnpm add @tanstack/react-virtual

For drag-and-drop row reordering, follow the DiceUI Sortable installation guide.

Now that you have all the components installed, check out the examples: