bo-grid v3.1.0

Styling

.md

Accessibility

Grid and treegrid semantics with true row and column counts, a full keyboard model, visible focus and WCAG 2.1 AA contrast.

bo-grid follows the ARIA grid pattern and targets WCAG 2.1 AA. Rows are virtualized, so only a window of them is in the page at any time; the grid reports the full size and every row’s real position, so a screen reader is not misled by the window.

Try it with the keyboard only: Tab into the grid, move with the arrows, tick a row with Space, and open the column menu with Alt+↓ (its Filter… item filters the column).

accessibility.svelte GitHub ↗

Give the grid a name

Set ariaLabel so the grid has an accessible name (“Watchlist”, “Open orders”):

<Grid {rows} {columns} height={480} ariaLabel="Open orders" />

Roles and states

  • The grid is role="grid" (role="treegrid" with tree data), with aria-rowcount and aria-colcount giving the full size, not the rendered window, and aria-multiselectable while range selection is on. It holds only rows; the toolbar, pager and menus sit beside it.
  • Rows are role="row" with aria-rowindex; cells are role="gridcell" with aria-colindex and aria-selected. Headers are role="columnheader" with aria-sort.
  • The focused cell is announced through aria-activedescendant, so assistive technology follows it as it moves.
  • Tree rows carry aria-level and aria-expanded; the row-number column is made of row headers.
  • Sparkline cells have a text label; copies of rows drawn for sticky headers or while loading are aria-hidden; the selection’s totals bar and the find bar’s match count are live regions.

Keyboard

The grid is a single tab stop with arrow-key navigation inside it. Everything works from the keyboard: editing, selection, copy and paste, the column menu (Alt+↓), the row menu (Shift+F10), and filtering through the column menu’s Filter… item. Menus move focus in when they open and give it back when they close, and there are no keyboard traps. The full map is in Keyboard & hotkeys.

Focus, contrast and motion

  • Every control that takes focus shows a visible :focus-visible ring: headers, menu items, the pager, filter and column panels, tree and detail toggles.
  • The built-in themes meet AA contrast for text and for interface parts; the high-contrast presets go well beyond it. See Theming.
  • Flashes and other animations respect prefers-reduced-motion.
  • Every string the grid writes, accessible names included, can be translated; see Localization.

The full audit (keyboard map, roles, measured contrast ratios and conformance notes) is in ACCESSIBILITY.md.

Reference

Grid props from the types
ariaLabel string Default undefined

Accessible name for the grid (aria-label on the role="grid" root).

labels Partial<GridLabels> Default {}

Override any string the grid renders itself (menus, filter editor, pager, aria labels). Merged over English defaults — pass only what changes. Interpolated entries are functions so translations can reorder the parts. Resolved per grid.

Example
<Grid {rows} {columns} height={480} labels={{ noRows: 'Không có dữ liệu', sortAscending: 'Tăng dần' }} />
hotkeys Hotkeys Default undefined

Keys for the app, run before the grid's own. A binding is a key ('b', 'Delete', 'Space'; a symbol by the character it types: '?', not 'Shift+/'), after any of Shift+, Alt+, Ctrl+, Meta+ and Mod+ (Ctrl or ⌘, either). Case does not matter. The handler is given the focused row and column (null when there is none) and the event; return false to leave the key to the grid. Keys go to the grid, not to a binding, while a cell is edited or an input, button or menu inside the grid has them, and a key a binding took runs it once when held down. A binding that cannot be read, or binds a key twice, throws (BG1001–BG1004).

Example
<Grid {rows} {columns} height={480}
  hotkeys={{ b: ({ row }) => { if (row) buy(row); }, 'Shift+C': cancelAll, Delete: ({ row }) => { if (row) cancel(row); } }} />