Vize

Data Grid

Accessible, unstyled DataGrid (WAI-ARIA APG grid / treegrid): typed column definitions, multi-column sorting, filtering hooks, column resize, reorder, pinning and visibility, row selection, cell navigation and editing, tree rows, and optional row virtualization.

Package @vizejs/ui/data-grid
Maturity stable
Own the source vize lib pull data-grid
Requires context, controllable-state, id, virtualizer
Aliases data table, spreadsheet grid, tree grid, editable table
Covers WAI-ARIA grid pattern, WAI-ARIA treegrid pattern, TanStack Table, AG Grid, React Aria Table

Usage

import { DataGrid, DataGridCell, DataGridCellEditor, DataGridColumnHeader, DataGridResizeHandle, DataGridRow } from "@vizejs/ui/data-grid";

Or copy the source into your project with vize lib pull data-grid (see Source Distribution).

API

DataGrid

Source: src/families/data/data-grid/data-grid.vue

Props

Prop Type Default Description
rows (required) readonly Row[] undefined Source rows. Nested rows come from getSubRows.
columns (required) readonly Column[] undefined Column definitions, usually built with createColumnHelper<Row>().
id string | null undefined Consumer-owned grid id. null and undefined select a deterministic fallback.
getRowId (row: Row, index: number, parentId: string | null) => string undefined Stable row id; defaults to the index path ("3", "3.1").
getSubRows (row: Row) => readonly Row[] | null | undefined undefined Sub rows; providing it renders role="treegrid".
filterRow (row: Row) => boolean undefined Extra row predicate combined with column and global filters.
selectionMode DataGridSelectionMode "none" Row selection policy.
pageSize number 10 Rows moved by PageUp and PageDown.
dir "ltr" | "rtl" "ltr" Reading direction for horizontal arrow keys.
virtualize boolean false Render only the rows in view (the root element is the scroll container).
rowHeight number 36 Fixed row height in CSS pixels used by virtualization.
overscan number 4 Extra virtualized rows rendered above and below the viewport.
initialViewportHeight number 400 Viewport height assumed during SSR and before measurement.
ariaLabel string undefined Accessible name of the grid.
ariaLabelledby string undefined Ids that label the grid.
defaultState Partial<DataGridState> undefined Initial uncontrolled state slices.
sorting readonly DataGridSort[] undefined Controlled sort keys (v-model:sorting).
globalFilter string undefined Controlled global filter text (v-model:global-filter).
columnFilters Readonly<Record<string, unknown>> undefined Controlled per-column filter values (v-model:column-filters).
columnVisibility Readonly<Record<string, boolean>> undefined Controlled column visibility (v-model:column-visibility).
columnOrder readonly string[] undefined Controlled column order (v-model:column-order).
columnPinning DataGridPinning undefined Controlled pinning (v-model:column-pinning).
columnSizing Readonly<Record<string, number>> undefined Controlled widths (v-model:column-sizing).
selection readonly string[] undefined Controlled selected row ids (v-model:selection).
expanded readonly string[] undefined Controlled expanded row ids (v-model:expanded).

Events

Event Payload Description
update:sorting [value: readonly DataGridSort[]] Fired when sorting changes.
update:globalFilter [value: string] Fired when the global filter changes.
update:columnFilters [value: Readonly<Record<string, unknown>>] Fired when a column filter changes.
update:columnVisibility [value: Readonly<Record<string, boolean>>] Fired when column visibility changes.
update:columnOrder [value: readonly string[]] Fired when the column order changes.
update:columnPinning [value: DataGridPinning] Fired when pinning changes.
update:columnSizing [value: Readonly<Record<string, number>>] Fired when a column is resized.
update:selection [value: readonly string[]] Fired when the row selection changes.
update:expanded [value: readonly string[]] Fired when rows expand or collapse.
cell-edit [event: DataGridCellEditEvent<Row>] Fired when a cell edit commits; update rows to apply it.

Slots

Slot Slot props Description
header DataGridHeaderSlotProps<Row, Column> Column header contents. Defaults to the column's header or id.
cell DataGridCellSlotProps<Row, Column> Cell contents, discriminated by columnId. Defaults to the formatted value.
editor DataGridEditorSlotProps<Row> Editor for the cell being edited. Defaults to a text input.
empty — Rendered in the body when no rows remain after filtering.

Exposed

Member Type Description
element Readonly<ShallowRef<HTMLElement | null>> Template ref to the rendered root element.
controller —
focusCell —
scrollToRow —

DataGridCell

Source: src/families/data/data-grid/data-grid-cell.vue

Props

Prop Type Default Description
rowId (required) string undefined Row id this cell belongs to.
columnId (required) string undefined Column id this cell belongs to.
colIndex (required) number undefined One-based aria-colindex.
width number 150 Column width in CSS pixels, published as --vize-ui-data-grid-column-width.
pin DataGridPinSide | null null Pin side, published as data-pin.
pinOffset number 0 Sticky inset from the pinned edge, published as --vize-ui-data-grid-pin-offset.
align DataGridAlign "start" Logical alignment hook.
editable boolean false Whether the cell can be edited (Enter/F2 or double click).

Slots

Slot Slot props Description
default — Cell contents rendered by the grid root.

Exposed

Member Type Description
element Readonly<ShallowRef<HTMLElement | null>> Template ref to the rendered root element.

DataGridCellEditor

Source: src/families/data/data-grid/data-grid-cell-editor.vue

Props

Prop Type Default Description
label string undefined Accessible name of the editor input.

Exposed

Member Type Description
element Readonly<ShallowRef<HTMLElement | null>> Template ref to the rendered root element.

DataGridColumnHeader

Source: src/families/data/data-grid/data-grid-column-header.vue

Props

Prop Type Default Description
columnId (required) string undefined Column id.
colIndex (required) number undefined One-based aria-colindex.
label string undefined Header text, also the resize handle's accessible name.
width number 150 Column width in CSS pixels.
minWidth number 40 Minimum width announced by the resize handle.
maxWidth number Infinity Maximum width announced by the resize handle.
pin DataGridPinSide | null null Pin side.
pinOffset number 0 Sticky inset from the pinned edge.
align DataGridAlign "start" Logical alignment hook.
sortable boolean false Whether clicking, Enter, or Space toggles sorting (Shift adds a sort key).
sortDirection DataGridSortDirection | null null Current sort direction.
sortIndex number | null null One-based priority among sort keys.
resizable boolean false Render a pointer and keyboard resize handle.

Slots

Slot Slot props Description
default — Header contents rendered by the grid root.

DataGridResizeHandle

Source: src/families/data/data-grid/data-grid-resize-handle.vue

Props

Prop Type Default Description
columnId (required) string undefined Column id resized by this handle.
label string undefined Column label used in the handle's accessible name.
width number 150 Current width, published as aria-valuenow.
minWidth number 40 Minimum width, published as aria-valuemin.
maxWidth number Infinity Maximum width, published as aria-valuemax when finite.
step number 10 Pixels per Arrow key press.

DataGridRow

Source: src/families/data/data-grid/data-grid-row.vue

Props

Prop Type Default Description
rowId (required) string undefined Row id.
rowIndex (required) number undefined One-based aria-rowindex (the header row is 1).
selected boolean false Whether the row is selected.
depth number 0 Zero-based tree depth, published as aria-level in tree grids.
expandable boolean false Whether the row has sub rows.
expanded boolean false Whether the sub rows are shown.
start number | null null Virtualized offset in CSS pixels, published as --vize-ui-data-grid-row-start. null means the row is laid out in normal flow.

Slots

Slot Slot props Description
default — Row cells rendered by the grid root.

Behavior

@vizejs/ui/data-grid implements the WAI-ARIA APG data grid and treegrid patterns. data-grid.vue is the generic root (Row, Column); data-grid-row.vue, data-grid-cell.vue, data-grid-column-header.vue, data-grid-resize-handle.vue, and data-grid-cell-editor.vue are value-erased parts. The headless model (useDataGrid) and pure row pipeline are proven in data-grid-model.test.ts; mounted behavior in data-grid.test.ts; SSR in data-grid-ssr.test.ts; column inference in data-grid.types.test-d.ts.

# State Input Outcome Proven by
G1 any render role="grid", aria-rowcount/aria-colcount, header columnheaders with aria-sort, rows with aria-rowindex, typed cell slots renders APG grid roles, counts, indices, and typed cell slots
G2 sortable header click / Shift+click ascending → descending → off; Shift adds lower-priority keys; update:sorting fires header clicks sort ascending, descending, then off; Shift adds sort keys
G3 sorted null/undefined values missing values sort last in both directions missing values sort last in both directions
G4 filters global, column filter, filterRow rows narrow; data-empty and the empty slot render when nothing matches global, column, and custom filters narrow rows and show the empty slot
G5 focus in grid arrows, Home/End, Ctrl+Home/End, Page keys one roving tab stop moves across header and body cells, clamped at edges arrow, Home/End, Ctrl+Home/End, and Page keys move a single roving tab stop
G6 dir="rtl" ArrowLeft/ArrowRight horizontal movement flips rtl flips horizontal cell movement
G7 header focus Enter/Space, Ctrl+Shift+arrows, Alt+arrows toggles sort, moves the column (focus follows), resizes by 10 px header keys sort, reorder with Ctrl+Shift+arrows, and resize with Alt+arrows
G8 resizable column handle pointer drag / arrows role="separator" with value range; width follows the pointer, clamps to minWidth/maxWidth, publishes width CSS variables resize handles are labelled separators driven by pointer and arrows within limits
G9 layout state visibility, order, pinning, sizing hidden columns disappear, order applies, pinned columns group at each edge with sticky offsets and total width variables visibility, order, and pinning props lay out columns with sticky offsets
G10 selectionMode="multiple" click/Ctrl/Shift, Space, Shift+Arrow, Ctrl+A replace, toggle, range, keyboard toggle/extend, select all; aria-selected and aria-multiselectable multiple selection: click replaces, Ctrl toggles, Shift extends, Space and Ctrl+A
G11 single / none click single keeps one row; none publishes no aria-selected single selection keeps one row and none mode publishes no aria-selected
G12 editable cell Enter/F2/double click, typing, Enter/Tab/Escape editor takes focus; validate errors keep it open with aria-invalid; parse converts; cell-edit fires; focus returns to the cell Enter or F2 edits, Enter commits through parse and validate, Escape cancels
G13 read-only cell Enter nothing happens; aria-readonly="true" read-only cells never enter edit mode
G14 getSubRows ArrowRight/ArrowLeft on the first cell role="treegrid" with aria-level/aria-expanded; expand, collapse, move to parent; filters keep ancestors tree rows render a treegrid with levels; arrows expand, collapse, and climb
G15 virtualize render / Ctrl+End only a window of rows renders with absolute aria-rowindex and offset variables; focus scrolls the target row in virtualization renders a window with absolute row indices and scrolls to focus
G16 custom layouts import parts are exported exported parts stay importable for custom layouts
G17 model sort toggles cycle and multi-key priority toggleSorting cycles ascending, descending, off and keeps multi-key priority
G18 model dot paths nullish segments short-circuit readPath short-circuits nullish segments and ignores non-objects
G19 model tree pipeline depth, parents, selection, expansion, stable sort within levels buildRowModels flattens expanded trees with depth, parents, and stable sort
G20 model default compare locale- and numeric-aware ordering custom compare and default string comparison are locale and numeric aware
G21 model, uncontrolled state actions every slice updates and reports through onStateChange; hideable/resizable/display-column rules hold uncontrolled slices update state and report every change
G22 model, controlled state actions controlled slices only change through the owner controlled slices only change through the owner
G23 model edit commit parse errors surface, validation gates, rows are never mutated edits parse, validate, report parse errors, and never mutate rows
G24 SSR two requests byte-identical markup including default sorting and selection renders byte-identical sorted, selected grid markup across SSR requests
G25 SSR hydrate plain/tree/virtual no diagnostics; server root reused hydrates plain, tree, and virtualized grids without diagnostics

Extension hooks

Hook Values
parts root, header, header-row, column-header, resize-handle, body, row, cell, cell-editor, empty
data data-vize-ui, data-row-id, data-column-id, data-sort, data-sort-index, data-pin, data-align, data-active, data-editing, data-selected, data-depth, data-virtualized
CSS vars --vize-ui-data-grid-column-width, --vize-ui-data-grid-pin-offset, --vize-ui-data-grid-total-width, --vize-ui-data-grid-body-height, --vize-ui-data-grid-row-start