Skip to content

Simple Table

A basic data table with no pagination - perfect for small datasets.

Open in

The Simple Table is the most basic implementation. It displays your data in a clean, accessible table format without pagination, filtering, or sorting. Perfect for small datasets (< 50 rows) or when you just need to display data.

  1. Add the <Table /> component to your project:
npx shadcn@latest add table
  1. Add tanstack/react-table dependency:
npm install @tanstack/react-table
  1. Copy the DataTable components into your project. See the Installation Guide for detailed instructions.

We are going to build a table to show users. Here’s what our data looks like:

type User = {
id: string
name: string
email: string
status: "active" | "inactive"
}
const data: User[] = [
{ id: "1", name: "John Doe", email: "[email protected]", status: "active" },
{ id: "2", name: "Jane Smith", email: "[email protected]", status: "active" },
{
id: "3",
name: "Bob Johnson",
status: "inactive",
},
]

Let’s start by building a basic table.

First, we’ll define our columns.

columns.tsx
"use client"
import type { DataTableColumnDef } from "@/components/niko-table/types"
export type User = {
id: string
name: string
email: string
status: "active" | "inactive"
}
export const columns: DataTableColumnDef<User>[] = [
{
accessorKey: "name",
header: "Name",
},
{
accessorKey: "email",
header: "Email",
},
{
accessorKey: "status",
header: "Status",
},
]

Next, we’ll create a <DataTable /> component to render our table.

simple-table.tsx
"use client"
import {
DataTableRoot,
DataTable,
DataTableHeader,
DataTableBody,
DataTableSkeleton,
DataTableEmptyBody,
} from "@/components/niko-table/core"
import type { DataTableColumnDef } from "@/components/niko-table/types"
type User = {
id: string
name: string
email: string
status: "active" | "inactive"
}
const columns: DataTableColumnDef<User>[] = [
{
accessorKey: "name",
header: "Name",
},
{
accessorKey: "email",
header: "Email",
},
{
accessorKey: "status",
header: "Status",
},
]
export function SimpleTable({ data }: { data: User[] }) {
return (
<DataTableRoot data={data} columns={columns}>
<DataTable>
<DataTableHeader />
<DataTableBody>
<DataTableSkeleton />
<DataTableEmptyBody />
</DataTableBody>
</DataTable>
</DataTableRoot>
)
}

Let’s format the status cell to display with colors.

columns.tsx
export const columns: DataTableColumnDef<User>[] = [
{
accessorKey: "status",
header: "Status",
cell: ({ row }) => {
const status = row.getValue("status") as string
return (
<span
className={status === "active" ? "text-green-600" : "text-gray-400"}
>
{status}
</span>
)
},
},
]

You can use the same approach to format other cells.

Show a loading skeleton while data is being fetched:

export function SimpleTable({
data,
isLoading,
}: {
data: User[]
isLoading?: boolean
}) {
return (
<DataTableRoot data={data} columns={columns} isLoading={isLoading}>
<DataTable>
<DataTableHeader />
<DataTableBody>
<DataTableSkeleton />
<DataTableEmptyBody />
</DataTableBody>
</DataTable>
</DataTableRoot>
)
}

The DataTableSkeleton component will automatically show when isLoading is true.

The DataTableEmptyBody component automatically shows when there’s no data or when filters return no results.

✅ Use Simple Table when:

  • You have a small dataset (< 50 rows)
  • You don’t need user interactions (sorting, filtering)
  • You want the fastest, simplest implementation
  • You’re building a prototype or MVP

❌ Don’t use Simple Table when:

Once you’re comfortable with the Simple Table, try adding more features: