Accessibility
@toolbox-web/grid follows the WAI-ARIA Grid Pattern to provide an accessible data grid experience. This page documents the ARIA attributes, keyboard interactions, and best practices.
ARIA Roles & Attributes
Section titled “ARIA Roles & Attributes”The grid applies the following ARIA roles and attributes automatically:
Grid Structure
Section titled “Grid Structure”| Element | Role | Attributes |
|---|---|---|
<tbw-grid> | grid | aria-rowcount, aria-colcount, aria-multiselectable |
| Header container | rowgroup | — |
| Header row | row | aria-rowindex="1" |
| Header cell | columnheader | aria-sort, aria-colindex |
| Body container | rowgroup | — |
| Data row | row | aria-rowindex, aria-selected, aria-expanded |
| Data cell | gridcell | aria-colindex, aria-selected, aria-readonly |
Dynamic Attributes
Section titled “Dynamic Attributes”| Attribute | Applied When | Values |
|---|---|---|
aria-sort | Column is sorted | ascending, descending, none |
aria-selected | Row or cell is selected | true, false |
aria-expanded | Row grouping/tree is active | true, false |
aria-multiselectable | Selection plugin allows multi-select | true |
aria-readonly | Cell is not editable | true |
aria-rowindex | Always (1-based) | Row position in full dataset |
aria-colindex | Always (1-based) | Column position |
Keyboard Navigation
Section titled “Keyboard Navigation”The grid implements full keyboard navigation following the WAI-ARIA grid pattern:
Basic Navigation
Section titled “Basic Navigation”| Key | Action |
|---|---|
| ↑ / ↓ | Move focus between rows |
| ← / → | Move focus between cells |
| Home | Move to first cell in row |
| End | Move to last cell in row |
| Ctrl + Home | Move to first cell in grid |
| Ctrl + End | Move to last cell in grid |
| PgUp | Scroll up one viewport |
| PgDn | Scroll down one viewport |
| ⇥ Tab | Move to next cell (wraps to next row) |
| ⇧ Shift + ⇥ Tab | Move to previous cell (wraps to previous row) |
Plugin-Specific Shortcuts
Section titled “Plugin-Specific Shortcuts”Keyboard shortcuts that depend on a plugin being installed are documented on each plugin’s own page — that’s the source of truth and stays in sync with the implementation:
- Selection — Space, Shift + arrows / PgUp / PgDn / Ctrl + Home/End, Ctrl + A, Esc
- Editing — Enter (start row edit / commit), F2 (single-cell edit), Tab / Shift + Tab, Esc (cancel)
- Clipboard — Ctrl/Cmd + C / X / V
- Context Menu — Shift + F10 or the dedicated ☰ Menu key opens the menu at the focused cell; ↑/↓ navigates, Enter/Space activates, Esc closes
- Row Grouping — Space toggles expand/collapse on a group or tree node
Focus Management
Section titled “Focus Management”Focus Indicators
Section titled “Focus Indicators”The grid uses visible focus indicators that meet WCAG 2.1 Level AA requirements:
tbw-grid { /* Customize focus ring */ --tbw-color-focus-ring: #2563eb;}The focus ring is 2px solid and uses outline (not border) so it doesn’t affect layout.
Focus Trapping
Section titled “Focus Trapping”When editing a cell, focus is trapped within the editor until the user commits (Enter/Tab) or cancels (Escape). Overlay editors (date pickers, dropdowns) use registerExternalFocusContainer() to extend the focus trap.
Roving Tabindex
Section titled “Roving Tabindex”The grid uses a roving tabindex pattern:
- Only the currently focused cell has
tabindex="0" - All other cells have
tabindex="-1" - This means Tab moves focus out of the grid, and Shift+Tab moves focus back to the last focused cell
Screen Reader Support
Section titled “Screen Reader Support”Labels and Descriptions
Section titled “Labels and Descriptions”Provide accessible labels for screen readers:
<tbw-grid aria-label="Employee directory">Or reference a visible heading:
<h2 id="grid-heading">Employees</h2><tbw-grid aria-labelledby="grid-heading">Live Regions
Section titled “Live Regions”The grid uses aria-live regions to announce dynamic changes to screen readers:
- Sort changes (“Sorted by Name, ascending”)
- Filter changes (“Filter applied on Name”, “All filters cleared”)
- Group expand/collapse (“Group Engineering expanded, 5 rows”)
- Selection changes (“3 rows selected”)
- Editing lifecycle (“Editing row 1”, “Row 1 saved”)
Configuring Announcements
Section titled “Configuring Announcements”You can disable or customize live region announcements via the a11y config — see A11yMessages for the full list of overridable messages and their signatures:
// Disable all announcementsgrid.gridConfig = { a11y: { announcements: false },};
// Override messages for internationalizationgrid.gridConfig = { a11y: { messages: { sortApplied: (col, dir) => `Trié par ${col}, ${dir}`, sortCleared: () => 'Tri effacé', filterApplied: (col) => `Filtre appliqué sur ${col}`, filterCleared: (col) => `Filtre effacé de ${col}`, allFiltersCleared: () => 'Tous les filtres effacés', groupExpanded: (name, count) => `Groupe ${name} développé, ${count} lignes`, groupCollapsed: (name) => `Groupe ${name} réduit`, selectionChanged: (count) => `${count} lignes sélectionnées`, editingStarted: (rowIndex) => `Édition de la ligne ${rowIndex + 1}`, editingCommitted: (rowIndex) => `Ligne ${rowIndex + 1} enregistrée`, dataLoaded: (count) => `${count} lignes chargées`, }, },};Only override the messages you need — defaults (English) are used for the rest.
Column Headers
Section titled “Column Headers”Column headers include:
- Column name via text content
- Sort direction via
aria-sort - Filter state via
aria-description(“Filtered”)
High Contrast Mode
Section titled “High Contrast Mode”Using CSS Custom Properties
Section titled “Using CSS Custom Properties”The grid’s CSS variable system makes high contrast easy:
/* High contrast theme */tbw-grid.high-contrast { --tbw-color-bg: #000; --tbw-color-fg: #fff; --tbw-color-border: #fff; --tbw-color-header-bg: #1a1a1a; --tbw-color-row-hover: #333; --tbw-color-focus-ring: #ffff00; --tbw-color-accent: #00ffff;}Pre-built Contrast Theme
Section titled “Pre-built Contrast Theme”import '@toolbox-web/grid/themes/dg-theme-contrast.css';Windows High Contrast Mode
Section titled “Windows High Contrast Mode”The grid ships with a built-in @media (forced-colors: active) block that remaps all theming variables to Windows system colors (CanvasText, Canvas, Highlight, HighlightText). Focus rings and selected rows are also overridden to use Highlight. No extra configuration needed — it works automatically.
WCAG Compliance Checklist
Section titled “WCAG Compliance Checklist”| Criterion | Level | Status | Notes |
|---|---|---|---|
| 1.1.1 Non-text Content | A | ✅ | Icons have text alternatives |
| 1.3.1 Info and Relationships | A | ✅ | ARIA roles convey structure |
| 1.3.2 Meaningful Sequence | A | ✅ | DOM order matches visual order |
| 1.4.1 Use of Color | A | ✅ | Status not conveyed by color alone |
| 1.4.3 Contrast (Min) | AA | ✅ | Default theme meets 4.5:1 ratio |
| 1.4.11 Non-text Contrast | AA | ✅ | Focus indicators visible at 3:1 |
| 2.1.1 Keyboard | A | ✅ | All functions accessible via keyboard |
| 2.1.2 No Keyboard Trap | A | ✅ | Tab exits the grid; Escape exits editors |
| 2.4.3 Focus Order | A | ✅ | Logical focus order follows grid structure |
| 2.4.7 Focus Visible | AA | ✅ | Clear focus indicators |
| 4.1.2 Name, Role, Value | A | ✅ | ARIA attributes on all interactive elements |
What’s Automatic
Section titled “What’s Automatic”The grid handles most accessibility concerns out of the box:
- ARIA roles & attributes —
role="grid",role="row",role="gridcell",aria-rowcount,aria-colcount,aria-rowindex,aria-colindexare always set - Keyboard navigation — Arrow keys, Tab, Enter, Home/End, PgUp/PgDn all work by default (core feature, not a plugin)
- Column headers — Always rendered with
role="columnheader"; cannot be hidden - Column type inference — Types (
number,date,boolean) are auto-detected from the first data row - Grid label — Auto-derived from the shell title (
<tbw-grid-header title="...">orshell.header.titleconfig) - Windows High Contrast —
forced-colorsmedia query is built into core CSS - Live announcements — Sort, filter, selection, grouping, and editing changes are announced via
aria-liveregions (configurable viaa11yconfig) - Plugin ARIA — Selection, editing, filtering, tree, and grouping plugins manage their own ARIA attributes (
aria-selected,aria-readonly,aria-expanded,aria-multiselectable,aria-description)
Developer Responsibilities
Section titled “Developer Responsibilities”These require explicit action:
- Provide a grid label when not using a shell — Without
<tbw-grid-header title="...">, setgridAriaLabelin config or addaria-labelon the element - Test with screen readers — NVDA (Windows), VoiceOver (macOS), Orca (Linux)
- Don’t override keyboard handling — The grid follows WAI-ARIA patterns; custom key listeners may conflict
- Use the contrast theme for additional a11y — Import
dg-theme-contrast.cssfor higher contrast beyond the built-in forced-colors support