Data Table
Feature-rich table wrapper with search, sorting, pagination, selection, and column controls.
pnpm dlx @glinui/cli@latest add data-tableMK Maya Kovacsmaya@northwind.io | Owner | Active | 12 | |
JO Jonas Okaforjonas@northwind.io | Admin | Active | 8 | |
PN Priya Nairpriya@fabrikam.dev | Editor | Invited | 4 | |
DA Diego Alvarezdiego@contoso.com | Viewer | Suspended | 1 | |
HS Hana Satohana@tailspin.jp | Editor | Active | 6 |
Showing 1-5 of 7
Page 1 of 2
Installation
pnpm dlx @glinui/cli@latest add data-tablePrefer the package?
Usage
Grid and sticky header
| Glin UI | Active | 18400 | |
| Glin Docs | Monitoring | 7920 | |
| Registry | Active | 12340 |
Showing 1-3 of 4
Page 1 of 2
import { Badge, DataTable } from "@glinui/ui"
const columns = [ { id: "project", header: "Project", accessor: "project" }, { id: "status", header: "Status", accessor: "status", cell: ({ value }) => <Badge variant={value === "Active" ? "soft" : "outline"}>{String(value)}</Badge> }, { id: "mrr", header: "MRR", accessor: "mrr", align: "right" }]
const data = [ { id: "p1", project: "Glin UI", status: "Active", mrr: 18400 }, { id: "p2", project: "Glin Docs", status: "Monitoring", mrr: 7920 }, { id: "p3", project: "Registry", status: "Active", mrr: 12340 }, { id: "p4", project: "CLI", status: "Paused", mrr: 2310 }]
export function Demo() { return ( <DataTable columns={columns} data={data} selectable striped stickyHeader grid variant="soft" pageSize={3} getRowId={(row) => row.id} /> )}Compact Board With Sticky Header
import { DataTable } from "@glinui/ui"
export function DataTableCompactDemo() {
return (
<DataTable
columns={[
{ id: "account", header: "Account", accessor: "account", sortable: true },
{ id: "stage", header: "Stage", accessor: "stage", sortable: true },
{ id: "owner", header: "Owner", accessor: "owner", sortable: true },
{ id: "arr", header: "ARR", accessor: "arr", sortable: true, align: "right" },
]}
data={[
{ id: "op-4012", account: "Northwind", stage: "Qualified", owner: "Maya", arr: "$42,000" },
{ id: "op-4015", account: "Stellar Forge", stage: "Proposal", owner: "Ilya", arr: "$18,500" },
{ id: "op-4018", account: "Blue Harbor", stage: "Won", owner: "Rae", arr: "$63,200" },
{ id: "op-4021", account: "Arcadia Labs", stage: "Discovery", owner: "Nico", arr: "$11,900" },
{ id: "op-4022", account: "Halcyon", stage: "Qualified", owner: "Leah", arr: "$27,600" },
]}
getRowId={(row) => row.id}
variant="matte"
size="sm"
stickyHeader
containerClassName="max-h-72"
pageSize={5}
searchable
/>
)
}Selection + Column Controls
Enable `selectable` and hide low-priority columns with `hidden`/`canHide` to keep dense dashboards readable.
import { DataTable } from "@glinui/ui"
export function DataTableSelectionDemo() {
return (
<DataTable
columns={[
{ id: "account", header: "Account", accessor: "account", sortable: true },
{ id: "stage", header: "Stage", accessor: "stage", sortable: true },
{ id: "owner", header: "Owner", accessor: "owner", sortable: true, hidden: true, canHide: true },
{ id: "arr", header: "ARR", accessor: "arr", sortable: true, align: "right" },
]}
data={[
{ id: "op-4012", account: "Northwind", stage: "Qualified", owner: "Maya", arr: "$42,000" },
{ id: "op-4015", account: "Stellar Forge", stage: "Proposal", owner: "Ilya", arr: "$18,500" },
{ id: "op-4018", account: "Blue Harbor", stage: "Won", owner: "Rae", arr: "$63,200" },
{ id: "op-4021", account: "Arcadia Labs", stage: "Discovery", owner: "Nico", arr: "$11,900" },
]}
selectable
variant="outline"
pageSize={4}
/>
)
}Server Data Pattern
For large datasets, fetch and paginate on the server, then pass only the current page to `DataTable`. Use this pattern when your API owns filtering, sorting, and pagination.
"use client"
import * as React from "react"
import { DataTable } from "@glinui/ui"
const columns = [
{ id: "account", header: "Account", accessor: "account", sortable: true },
{ id: "stage", header: "Stage", accessor: "stage", sortable: true },
{ id: "arr", header: "ARR", accessor: "arr", sortable: true, align: "right" }
]
export function DataTableServerPattern() {
const [rows, setRows] = React.useState([])
const [query, setQuery] = React.useState("")
const [page, setPage] = React.useState(1)
React.useEffect(() => {
const params = new URLSearchParams({ q: query, page: String(page) })
fetch(`/api/pipeline?${params.toString()}`)
.then((res) => res.json())
.then((payload) => setRows(payload.items))
}, [query, page])
return (
<DataTable
columns={columns}
data={rows}
searchable={false}
pageSize={20}
variant="glass"
emptyMessage="No matching records."
/>
)
}Accessibility
- Built on semantic table primitives for screen reader compatibility.
- Sorting controls are keyboard-focusable buttons in header cells.
- Selection checkboxes provide explicit labels.
- Built on semantic table elements (`table`, `thead`, `tbody`, `th`, and `td`) for screen-reader compatibility.
- Keep column names concise and unique so assistive tech announces context clearly.
Keyboard Interactions
| Key | Action |
|---|---|
| Tab | Move across toolbar, headers, and pagination controls. |
| Enter / Space | Activate sort, selection, and pagination controls. |
ARIA Attributes
- `aria-label` for search and selection controls
- `role="checkbox"` for selectable rows
- Native table semantics from the base table primitive
Reduced Motion
Inherits reduced-motion behavior from Table and action/input primitives.
DataTable inherits reduced-motion behavior from `Table`, `Input`, `Select`, and `Button`. Hover/focus transitions are non-essential and respect user preference settings.
Affected properties
background-coloropacityAPI Reference
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
columns | DataTableColumn<TData>[] | Yes | - | Column schema with accessor, sorting, visibility, and custom cell rendering. |
data | TData[] | Yes | - | Array of row objects. |
searchable | boolean | No | true | Enable built-in text filtering. |
selectable | boolean | No | false | Adds row-selection checkboxes. |
pageSize | number | No | 10 | Initial page size. |
pageSizeOptions | number[] | No | [10, 20, 50] | Page-size choices shown in toolbar. |
variant | "glinr" | "solid" | "plain" | "soft" | "outline" | "ghost" | "gradient" | "glass" | - | ambient (glinr) | Surface variant. Omit to follow the ambient design style (glinr by default, plain for minimal, glass for glass). |
className | string | No | - | Auto-generated from TypeScript source. |
emptyMessage | string | No | "No results." | Auto-generated from TypeScript source. |
getRowId | (row: TData, index: number) => string | No | - | Auto-generated from TypeScript source. |
onRowClick | (row: TData) => void | No | - | Auto-generated from TypeScript source. |
onSelectionChange | (rows: TData[]) => void | No | - | Auto-generated from TypeScript source. |
rowTone | (row: TData) => TableRowTone | No | - | Auto-generated from TypeScript source. |
searchPlaceholder | string | No | "Search rows..." | Auto-generated from TypeScript source. |
Source
Import directly from the package or browse the source on GitHub. Click any file to view it.
Import
import { DataTable } from "@glinui/ui"Source Files
Dependencies
@glinui/uiGenerated API Snapshot
Beta
Generated API Snapshot
BetaAuto-extracted from TypeScript source in packages/ui/src/components/data-table.tsx. This section is in beta and may lag behind hand-curated docs. Regenerate with pnpm --filter @glinui/docs api:generate.
Generated: 2026-10-08T01:41:21.546Z · Full index: /docs/api-metadata
Primary Props Type
DataTableProps
DataTableProps
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
className | string | No | - | - |
columns | DataTableColumn<TData>[] | Yes | - | - |
data | TData[] | Yes | - | - |
emptyMessage | string | No | "No results." | - |
getRowId | (row: TData, index: number) => string | No | - | - |
onRowClick | (row: TData) => void | No | - | - |
onSelectionChange | (rows: TData[]) => void | No | - | - |
pageSize | number | No | 10 | - |
pageSizeOptions | number[] | No | [10, 20, 50] | - |
rowTone | (row: TData) => TableRowTone | No | - | - |
searchable | boolean | No | true | - |
searchPlaceholder | string | No | "Search rows..." | - |
selectable | boolean | No | false | - |