Grid

A headless, accessible grid primitive with roving tabindex, cell selection, and full keyboard navigation following the WAI-ARIA Grid pattern.

Features

  • Full keyboard navigation
  • Roving tabindex focus management
  • Cell, row, column, and multi-cell selection
  • Semantic ARIA roles
  • Structural validation
  • Foundation for calendars and data tables

Installation

npm install @ariaui/grid

Examples

Roving-tabindex grid with cell selection following the WAI-ARIA Grid pattern. The sample is a small "team members" table built from Grid.Root, Head/Body, Row, Header, and Cell.

Styling uses semantic tokens from @ariaui/tokens (border-border, bg-muted, text-foreground, etc.).

Uncontrolled

Seed selected cells with defaultValue and mirror value changes for display.

Preview

No preview output yet.

live.tsxReady

Controlled

Control selected cells with value and onValueChange.

Preview

No preview output yet.

live.tsxReady

Anatomy

tsx
import * as Grid from "@ariaui/grid";

export default function Example() {
  return (
    <Grid.Root>
      <Grid.Head>
        <Grid.Row>
          <Grid.Header />
        </Grid.Row>
      </Grid.Head>
      <Grid.Body>
        <Grid.Row>
          <Grid.Cell />
        </Grid.Row>
      </Grid.Body>
    </Grid.Root>
  );
}

API Reference

Root

Top-level grid container. Renders role="grid" and manages focus and selection state for all descendant cells.

PropTypeDefault
aria-label
string
aria-labelledby
string
value
string[]
defaultValue
string[][]
onValueChange
(value: string[]) => void
AttributeValues
rolegrid

Body

Optional body section container, analogous to <tbody>. Groups data rows.

Row

A single row in the grid. Renders role="row". Must be a direct child of Root, Head, or Body.

AttributeValues
rolerow

Cell

A data cell in the grid. Renders role="gridcell". Participates in roving tabindex focus management and selection.

PropTypeDefault
onClick
(event: React.MouseEvent) => void
value
stringrow:col
AttributeValues
rolegridcell
aria-selectedtrue when selected
[data-selected]Present when selected
[data-value]Resolved selection value

Keyboard

ShortcutAction
Move focus to the next cell in the current row without changing selection.
Move focus to the previous cell in the current row without changing selection.
Move focus to the cell below in the same column without changing selection.
Move focus to the cell above in the same column without changing selection.
HomeMove focus to the first cell in the current row without changing selection.
EndMove focus to the last cell in the current row without changing selection.
Ctrl+HomeMove focus to the first cell in the grid without changing selection.
Ctrl+EndMove focus to the last cell in the grid without changing selection.
TabMove focus out of the grid to the next focusable element.
EnterToggle selection for the focused cell.
SpaceToggle selection for the focused cell.
Ctrl+ASelect all cells in the grid.
Shift+SpaceToggle the current row in the current selection.
Ctrl+SpaceToggle the current column in the current selection.
Shift+ArrowToggle selection for the cell in the arrow direction.
EscClear the current selection.

Accessibility

The Grid component implements the WAI-ARIA Grid pattern:

  • Root renders as role="grid" and requires an accessible name via aria-label or aria-labelledby.
  • Row renders as role="row".
  • Cell renders as role="gridcell" with roving tabindex for focus management and aria-selected for selection state.
  • Header renders as role="columnheader" and is not focusable by default.
  • Arrow key navigation moves focus between cells; Home/End navigate within rows; Ctrl+Home/End navigate to grid boundaries.
  • Selection supports single-cell click, row (Shift+Space), column (Ctrl+Space), multi-cell (Shift+Arrow), and select-all (Ctrl+A).
  • Escape clears the current selection.
Previous
Form