Lattice Grid Buy a licence

developer guide

Accessibility and keyboard

Built to WCAG 2.2 level AA: the full keyboard map, roving focus over a virtualised body, the ARIA the grid writes, and forced-colours support.

Developer guide › Accessibility and keyboard

Accessibility

The grid is built to WCAG 2.2 level AA. What follows is what it does, where the standard's own allowances apply, and the keyboard map in full: stated plainly, because a conformance claim that overstates is worth less than one that admits its edges.

Keyboard

Every operation is reachable without a pointer. Resizing and reordering a column were once drag-only; both now have key bindings and menu items, so nothing depends on dragging.

KeysDoes
In the data
ArrowUp/Down/Left/RightMove the focused cell
Home or EndFirst / last cell of the row
Ctrl+Home or Ctrl+EndFirst cell of the first row / last cell of the last row
PageUp or PageDownMove one viewport of rows
Tab or Shift+TabNext / previous cell, wrapping across rows
EnterStart editing the focused cell
SpaceToggle selection of the focused row
EscapeCancel the current edit or drag
Alt+ArrowRight or Alt+ArrowLeftExpand / collapse a group or tree row
Ctrl+Alt+HMove focus to the column header
Ctrl+Alt+PMove focus to the tool panel
Shift+F10 or ContextMenuOpen the context menu for the focused cell
Alt+Shift+ArrowUp or Alt+Shift+ArrowDownMove the focused row, when row reorder is enabled
On a column heading
ArrowLeft or ArrowRightMove between headings
Ctrl+ArrowLeft or Ctrl+ArrowRightFirst / last heading
Enter or SpaceSort by the column, Shift to add to the sort
Alt+ArrowLeft or Alt+ArrowRightResize the column, Ctrl for a coarse step
Shift+ArrowLeft or Shift+ArrowRightMove the column
Alt+ArrowDownOpen the column menu
ArrowDown or EscapeReturn focus to the data
In the tool panel's column list
GGroup by the column, or stop grouping by it
VAdd the column to values, or take it out
PPivot by the column, or stop pivoting by it
Shift+ArrowUp or Shift+ArrowDownMove the column

This table is generated from the bindings the build ships and checked on every build, so it cannot drift from what the grid actually does.

What a screen reader is told

The grid reports itself as a grid, or a treegrid when it holds a hierarchy, and the role follows the configuration rather than being fixed when the grid is created. Rows and cells carry their position in the dataset, not in the rendered window: a reader on row 500,000 of a virtualised grid is told exactly that, which is the point most grids get wrong. Rows in a hierarchy also carry their position among their siblings, since a reader cannot count siblings that were never rendered.

Focus is real focus, moved onto the cell, rather than aria-activedescendant. It is restored after a row is recycled or scrolled out and back, and the grid holds a single tab stop, so tabbing in and out crosses it once.

State changes are announced: sorting, filtering, selection, grouping, expanding and collapsing, paging, undo and redo, pasting, and rows arriving or leaving on a live feed. A feed is summarised on an interval rather than narrated, because a reader queues what it is given and a fast feed would leave someone listening to counts that are no longer true. A rejected edit is announced with the value that was put back, which is the change users most need to hear about and the one a visual marker alone cannot convey.

Colour and contrast

No information is carried by hue alone. The high-contrast theme runs text at 21:1 and borders at 6.1:1. In Windows High Contrast Mode the grid translates its state into borders and system colours rather than fighting the palette: see theming for what that means in detail.

How this is checked

The grid carries its own accessibility rules, and they run on every build against each configuration that differs structurally: flat, grouped, tree, pinned, editing, paginated and with a tool panel: rather than against one sample grid. The same rules are available live from the devtools panel, where they can also read colour and measure targets.

Be clear about what that proves. These are our own rules covering what a data grid gets wrong, not a general-purpose engine, and automated checking of any kind catches a minority of real problems. They are a regression net (they stop a fix being undone silently) and not evidence of conformance.

Bigger targets for touch

The grid meets the minimum target size on its own. That minimum is a conformance floor, not a comfortable size for a finger: both mobile platforms recommend nearer 44 pixels.

targetSize: 'large'

This raises the hit areas and leaves the type where it is, which is the distinction that matters: a touch user wants a larger target, and a low-vision user wants larger text. Density is the control for the second, and the two combine, a compact grid with large targets is a reasonable thing to want on a tablet.

It applies by itself under a coarse pointer, since the person holding one is both who the criterion is for and the least likely to go looking for a setting. Pass targetSize: 'default' to opt out of that.

Density alone does not do this. It scales the header, the rows and the type, and leaves the affordances inside them exactly as they were: measured at every preset, the menu button stays 24 pixels, the filter 16 and the resize grip 10. A spacious grid has the room going spare and controls no larger than a compact one, which is the gap this fills.

Edge cases at narrow widths

Stated because a report that claims everything invites the one question it cannot answer.

  • Two-dimensional scrolling. A grid scrolls horizontally at narrow widths. WCAG 1.4.10 Reflow explicitly permits this for data tables, so it is conforming rather than a gap, but it is worth knowing before you meet it.
  • Pinning is honoured at every width. At around 320 pixels, two pinned columns of ordinary width can leave under 60 pixels for the scrolling middle. The grid stays operable and nothing is lost, but a layout that pins columns is worth reviewing if you expect it to be used at that size.
  • The filter icon is a small target, deliberately. It is 16 × 16, below the 24-pixel minimum of WCAG 2.5.8, and conforms under that criterion's equivalent allowance: filtering is also a column-menu item, and the menu button meets the size on its own. Worth knowing if you are pointing at it on a touch screen, the menu is the larger route to the same thing.

Keyboard

Press ? in the grid to see this list in the product. The overlay is generated from the same bindings the grid implements, so it cannot drift from them, and it shows Cmd rather than Ctrl on a Mac, the grid reads either, so that is what you will actually press. Escape closes it and focus returns where it was. Set shortcuts: false if you want ? for something else.

KeysDoes
ArrowsMove the focused cell.
Shift + arrowsExtend the range.
Ctrl/Cmd + Shift + arrowsOpen a second range at the focused cell, keeping the first; further presses extend it.
Ctrl/Cmd + C, V, DCopy, paste, fill down.
Delete / BackspaceClear the selected cells.
EnterStart editing; commit and step down.
TabCommit and step across.
EscapeCancel the edit; restore a maximised grid once nothing else wants it.
SpaceToggle the row's selection.
Home / End, Page Up / DownJump; with Ctrl, to the ends of the grid.

None of these fire while you are typing into an input, a filter box, an open editor, the view-name field. The grid checks where the keystroke came from before claiming it, which sounds obvious and is the sort of thing that is usually wrong.