Accessibility in Apex Grid
The Apex grid ships ARIA semantics and keyboard affordances that follow the WCAG 2.2 AA grid pattern. Screen readers see the component as a tabular structure (or a tree-grid in tree-data mode); keyboard users can navigate, sort, expand, select, and edit without reaching for a pointer.
ARIA semantics
The grid role sits on an inner element exposed as part table, not on the <apex-grid> host. It holds only the header rows, the pinned rows and the body, so the toolbar, paginator, filter panel and live region are not read as table content. It advertises:
role="grid", orrole="treegrid"whenever rows carry levels or expand: tree data, master-detail with a detail template, and the enterprise row grouping, expandable pivot and server-side grouping.aria-rowcountandaria-colcountreflecting the live shape: counts include the header rows, pinned rows and any auto-added selection or expansion columns.aria-multiselectablewhen multi-row selection is enabled.
Code or tests that read these attributes should query the part:
const table = grid.shadowRoot.querySelector('[part~="table"]');
table.getAttribute('role'); // 'grid' or 'treegrid'
Header and body rows carry role="row" with aria-rowindex. Column headers carry role="columnheader" with aria-colindex plus aria-sort reflecting the per-column sort state. Cells carry role="gridcell" with aria-colindex and aria-current on the active cell. Body rows reflect aria-selected when selection is enabled and aria-expanded when row expansion or tree-data is enabled.
The table part gets a localized accessible name ("Data grid") unless you put your own aria-label or aria-labelledby on the host, and an aria-describedby on the host becomes its description. References are resolved when the grid renders: if the referenced element is added later, set the attribute again. The filter condition trigger advertises aria-haspopup="listbox" with aria-expanded; the sort indicator is a real <button> with a descriptive aria-label and focus-visible styling.
Roving-tabindex focus model
The grid body is a single tab stop, and the column header row is not a tab stop of its own: Tab enters the grid, and the active cell holds real focus (a roving tabindex), so screen readers follow the cursor as it moves cell to cell. A keyboard-driven commit or cancel returns focus to the cell host, so navigation continues from where you were, and pointer exits never steal focus from the click target. Dialogs and menus (the AI panel, context menu) remember the deep-focused element across shadow roots and restore focus on close.
Polite live announcements
The grid renders a polite aria-live region. Sorting, filtering, selection, paging, row pinning, row reorder, expansion, and undo / redo all announce themselves through it, and every announcement (plus the header control labels and sort-state descriptions) is localizable through the announce.* and header.* locale keys. The status bar is itself a polite live region. Custom UI can post messages to the same channel:
grid.announce('Filter applied, 12 rows visible');
announce(message) debounces consecutive messages and prevents duplicates from overlapping the user's own actions.
Keyboard navigation
The grid follows the WCAG 2.2 AA grid keyboard pattern:
- Arrow keys move the active cell.
- Home / End jump to the first / last cell in the row; Ctrl/Cmd+Home / Ctrl/Cmd+End jump to the corner of the grid.
- PageUp / PageDown move by a viewport page.
- Space toggles the focused row's selection; Shift+Space extends from the anchor; Ctrl+A selects all in multiple-selection mode.
- Enter or F2 opens the active cell's inline editor.
- Escape cancels an open editor; Tab commits and moves focus out of the cell.
- Ctrl/Cmd+Z / Ctrl/Cmd+Y undo / redo when editing history is enabled.
- Shift + arrows extend a cell range from the keyboard (enterprise, 0.7.0).
Changed in 3.4.0: Home / End used to jump to the first / last row; they now stay within the row (the common data-grid convention). Use Ctrl/Cmd+Home / Ctrl/Cmd+End for the grid corners. Enter / F2 keyboard editing is new in 3.4.0 (editing was previously pointer-only).
While an input method (IME) is composing Japanese, Chinese or Korean text, the Enter, Escape and Tab that confirm or cancel the conversion belong to the IME: they do not commit or cancel a cell edit, close the filter panel or clear the quick filter.
In a right-to-left grid the left and right arrows map onto previous and next column by inline order, so the key that moves "forward" is the one pointing at the next column on screen.
Touch targets
Sort buttons, expansion chevrons, and filter chip-remove controls are sized to at least 24×24 CSS pixels to satisfy WCAG 2.5.8 (Target Size: Minimum).
As of 3.5.0 this holds across the grid, not just those three. The selection cell forwards its click to the checkbox rather than growing a deliberately small mark, header action buttons reach 24×24 through the invisible chip that already expanded them (so the packed header layout is unchanged), and paginator buttons grew from 22 to 24, which makes the paginator bar 2px taller.
Reduced motion
Every transition in the grid routes through one of the --ag-dur-* tokens, and those zero under prefers-reduced-motion: reduce. Twenty-four transitions across nine stylesheets go instant, with their end states unchanged. Added in 3.5.0. If you override the duration tokens yourself, keep the media query in mind: setting a hard-coded transition on a grid part opts that part out of the user's preference.
Forced colors
Forced-colors modes such as Windows High Contrast paint no box-shadow, and the grid leaned on inset shadows for exactly the indicators that matter most, so a keyboard user previously had no visible cursor and no visible selection there.
As of 3.5.0 the active-cell ring, the invalid-cell ring, the selected-row bar and every toolbar and filter focus ring are restated as outlines, which forced colors recolours rather than drops.
In forced colors, checkboxes are drawn by the browser in system colours, so checkbox styles applied through parts do not show in that mode. In a selected row the cell text, row number, reorder grip and chevrons take the selection text colour, and a keyboard-grabbed row shows an outline.