Velora UI

Data Grid

Sortable, searchable, filterable table with selection, column toggles and pagination, built on TanStack Table.

  • 5.4 KB gzipped
  • Deps: @tanstack/react-table, lucide-react
  • Reduced-motion safe
  • Base UI & Radix compatible
Open in v0

Preview

ORD-7940
Ana Whitfield
PaidCard2026-10-28$12.00
ORD-7939
Samuel Okafor
PaidBank transfer2026-10-28$91.00
ORD-7938PaidPayPal2026-10-27$170.00
ORD-7937PendingCard2026-10-27$250.00
ORD-7936RefundedCard2026-10-26$329.00
ORD-7935
Felix Lindqvist
PaidBank transfer2026-10-26$408.00
ORD-7934FailedPayPal2026-10-25$487.00
ORD-7933
Marcus Oyelaran
PendingCard2026-10-25$566.00
ORD-7932PaidCard2026-10-24$646.00
ORD-7931PaidBank transfer2026-10-24$725.00

1–10 of 48

Page 1 of 5

Installation

pnpm dlx shadcn@latest add https://velora.colorlib.com/r/data-grid.json

Adds components/velora/data-grid.tsx, installs @tanstack/react-table@^8.21.3, lucide-react.

Examples

Compact, read-only

/api/searchGET5082.1
/api/ordersPOST3411.4
/api/invoicesGET2140.6
/api/ordersGET1820.2
/api/webhooks/stripePOST1270.3

1–5 of 7

Page 1 of 2

Props

PropTypeDefault
data*

Rows to display

TData[]—
columns*

TanStack Table column definitions; set `meta.label` for a readable name in menus

ColumnDef<TData, TValue>[]—
getRowId

Stable row id, so selection survives sorting and new data. Defaults to the row index

(row: TData, index: number) => string—
searchable

Show a search box that matches text in every column

booleantrue
searchPlaceholderstring"Search…"
filters

Multi-select filter buttons, one per column

DataGridFilter[][]
selectable

Add a checkbox column

booleanfalse
onSelectionChange

Called with the selected rows' data whenever the selection changes

(rows: TData[]) => void—
bulkActions

Actions shown in a bar while rows are selected

(rows: TData[], clearSelection: () => void) => React.ReactNode—
columnToggle

Show the column visibility menu

booleantrue
pageSizenumber10
pageSizes

Options in the rows-per-page menu

number[][10, 20, 50]
defaultSort

Initial sort, e.g. `[{ id: "date", desc: true }]`

SortingState[]
loading

Show skeleton rows instead of data

booleanfalse
empty

Shown when no row matches

React.ReactNode"No results."
density

Row height

"compact" | "comfortable""comfortable"
label

Accessible name for the table

string"Data table"
classNamestring—

DataGridFilter

interface DataGridFilter {
  /** Column id (usually the accessorKey) to filter */
  column: string;
  /** Label on the filter button */
  title: string;
  /** Choices; read from the data when omitted */
  options?: { label: string; value: string }[];
}

Accessibility

Reduced motion
Nothing in the table animates. The selection bar fades in only when reduced motion is off.
Keyboard
Sortable headers are buttons: Tab reaches them and Enter or Space cycles ascending, descending and unsorted. Search, filter and column menus, row checkboxes and pagination are all native or Radix controls reachable with Tab; menus use arrow keys.
Screen readers
A named table whose sortable headers report aria-sort. Every checkbox and icon button has a label, and the result range ("1–10 of 48") is a polite live region, so filtering announces how many rows match.