Data Grid
A performant, accessible data table with column sorting, loading skeletons, sticky header,
and empty state. Pair with the Pagination component for page navigation —
filtering and pagination are intentionally outside the component's scope.
Basic
Define columns with a key and label, then pass
rows as plain objects. Each row value is coerced to a string for display.
| Ada Lovelace | Engineer | 36 |
| Alan Turing | Researcher | 41 |
| Grace Hopper | Admiral | 85 |
| Linus Torvalds | Engineer | 54 |
| Margaret Hamilton | Director | 87 |
import { DataGrid } from "@usevyre/react";
const columns = [
{ key: "name", label: "Name", sortable: true },
{ key: "email", label: "Email", sortable: true },
{ key: "status", label: "Status", width: "120px" },
];
const rows = [
{ name: "Alice Chen", email: "alice@example.com", status: "Active" },
{ name: "Bob Martinez", email: "bob@example.com", status: "Inactive" },
{ name: "Carol Smith", email: "carol@example.com", status: "Active" },
];
<DataGrid columns={columns} rows={rows} /> <script setup>
import { DataGrid } from "@usevyre/vue";
const columns = [
{ key: "name", label: "Name", sortable: true },
{ key: "email", label: "Email", sortable: true },
{ key: "status", label: "Status", width: "120px" },
];
const rows = [
{ name: "Alice Chen", email: "alice@example.com", status: "Active" },
{ name: "Bob Martinez", email: "bob@example.com", status: "Inactive" },
{ name: "Carol Smith", email: "carol@example.com", status: "Active" },
];
</script>
<template>
<DataGrid :columns="columns" :rows="rows" />
</template> Sorting
Mark columns with sortable: true to show sort toggle buttons. The grid is
fully controlled — manage sortKey and sortDir in your own
state and pass them back. Sort icons cycle: unsorted ↕ → ascending ↑ → descending ↓.
| Ada Lovelace | Engineer | 36 |
| Alan Turing | Researcher | 41 |
| Grace Hopper | Admiral | 85 |
| Linus Torvalds | Engineer | 54 |
| Margaret Hamilton | Director | 87 |
import { DataGrid } from "@usevyre/react";
import { useState } from "react";
const [sortKey, setSortKey] = useState<string | undefined>();
const [sortDir, setSortDir] = useState<"asc" | "desc">("asc");
<DataGrid
columns={columns}
rows={rows}
sortKey={sortKey}
sortDir={sortDir}
onSort={(key, dir) => {
setSortKey(key);
setSortDir(dir);
}}
/> <script setup>
import { DataGrid } from "@usevyre/vue";
const sortKey = ref(undefined);
const sortDir = ref("asc");
</script>
<template>
<DataGrid
:columns="columns"
:rows="rows"
v-model:sortKey="sortKey"
v-model:sortDir="sortDir"
@sort="({ key, dir }) => { sortKey = key; sortDir = dir; }"
/>
</template> Sticky header
Set stickyHeader and constrain the wrapper height to enable vertical
scrolling with a fixed header row.
| Ada Lovelace | Engineer | 36 |
| Alan Turing | Researcher | 41 |
| Grace Hopper | Admiral | 85 |
| Linus Torvalds | Engineer | 54 |
| Margaret Hamilton | Director | 87 |
| Katherine Johnson | Mathematician | 101 |
| Dennis Ritchie | Engineer | 70 |
| Barbara Liskov | Researcher | 84 |
| Tim Berners-Lee | Inventor | 69 |
| Donald Knuth | Author | 86 |
| Vint Cerf | Engineer | 81 |
| Radia Perlman | Engineer | 73 |
Scroll the table — the header row stays pinned to the top.
<DataGrid
columns={columns}
rows={rows}
stickyHeader
style={{ maxHeight: "300px" }}
/> <DataGrid
:columns="columns"
:rows="rows"
:sticky-header="true"
style="max-height: 300px"
/> Loading state
Set loading to show 5 animated skeleton rows while data is fetching.
Pass an empty rows array alongside it to avoid rendering stale data.
// Shows 5 skeleton rows while data is fetching
<DataGrid columns={columns} rows={[]} loading={isLoading} /> <DataGrid :columns="columns" :rows="[]" :loading="isLoading" /> Pagination
DataGrid does not handle pagination internally — slice your rows array
to the current page and pair with the Pagination component.
Vue bindings
In Vue, use v-model:sortKey and v-model:sortDir for two-way
binding, or listen to the @sort event which receives { key, dir }.
Props
Props
| Prop | Type | Default | Description |
|---|---|---|---|
columns | { key: string; label: string; sortable?: boolean; width?: string }[] | — | Column definitions. Set sortable: true to enable sort toggle on that column. |
rows | Record<string, unknown>[] | — | Array of row objects. Each key maps to a column key. |
sortKey | string | — | Controlled sort column key. |
sortDir | "asc" | "desc" | — | Controlled sort direction. |
onSort | (key: string, dir: "asc" | "desc") => void | — | React only. Called when a sortable column header is clicked. |
loading | boolean | false | Displays 5 skeleton placeholder rows while data is loading. |
emptyText | string | "No data" | Message shown when rows is an empty array. |
stickyHeader | boolean | false | Fixes the header row when the grid container scrolls vertically. |
className | string | — | Additional CSS class on the grid wrapper. |
Valid props
| Prop | Values | Default |
|---|---|---|
sortDir | "asc"|"desc" | — |
loading | true|false | false |
stickyHeader | true|false | false |
Common AI mistakes
- DataGrid expecting built-in pagination→ Slice rows yourself and use the Pagination component
- DataGrid expecting built-in filtering→ Filter the rows array before passing it in
- sortable without onSort→ Handle onSort and sort the rows array in your state
Quick examples
const cols = [{ key: "name", label: "Name", sortable: true }];
<DataGrid
columns={cols}
rows={people}
sortKey={sortKey}
sortDir={sortDir}
onSort={(k, d) => { setSortKey(k); setSortDir(d); }}
/><DataGrid columns={cols} rows={[]} loading />