Skip to content

Accessibility Conformance Report

This is the accessibility conformance report for @toolbox-web/grid. It follows the structure of a VPAT® 2.5, covering both the WCAG edition — every Level A and Level AA success criterion in WCAG 2.2 — and the EU edition, which maps those onto the EN 301 549 clauses that the European Accessibility Act enforces. Every row carries the test that verifies it.

If you are looking for how to use the accessibility features, read Accessibility instead. This page is the evidence.

Product@toolbox-web/grid — the <tbw-grid> custom element, its bundled features, and its first-party plugins
Also covers@toolbox-web/grid-angular, @toolbox-web/grid-react, @toolbox-web/grid-vue
StandardsWCAG 2.2 Level A and Level AA; EN 301 549 clauses 5, 9, 11 and 12
Report editionsVPAT® 2.5 WCAG edition and EU edition
Conformance claimSupports
Evaluation methodsAutomated (axe-core via Playwright, run against the vanilla demo on every commit), unit and integration tests asserting specific ARIA and interaction behaviour, and manual review with NVDA, JAWS and VoiceOver
Applies fromv3.6.0
Report date31 August 2026

This page is the authoritative copy and is revised with the product. Print it to PDF from your browser if you need a file to attach to a procurement pack — that way the copy you hand over carries the report date above and can never be a stale snapshot of an older release.

A grid is a component, not a page. Several success criteria are about things a component cannot control — the document’s language, the page title, whether there is more than one way to find a page. Those are marked Not Applicable with a note about where the responsibility actually sits.

The Status column carries one of the four VPAT® 2.5 values and nothing else — Supports, Partially Supports, Does Not Support, Not Applicable — so the report can be read straight against the standard’s own checklist.

Where the grid provides a conforming mechanism but your content can still break the criterion, the status stays Supports: the term means the product has at least one method that meets the criterion, and it does. The remark then opens with Author responsibility and says exactly which part is yours. A custom cell renderer that emits an image without alt text is the clearest example.

CriterionStatusHow it is metVerified by
1.1.1 Non-text ContentSupportsEvery icon the grid renders is either labelled or marked aria-hidden with adjacent text. Author responsibility: images you render from your own data need their own alt text.accessibility.spec.ts — axe image-alt, svg-img-alt
1.2.1 Audio-only and Video-onlyNot ApplicableThe grid renders no time-based media.
1.2.2 Captions (Prerecorded)Not ApplicableThe grid renders no time-based media.
1.2.3 Audio Description or Media AlternativeNot ApplicableThe grid renders no time-based media.
1.3.1 Info and RelationshipsSupportsThe WAI-ARIA Grid Pattern throughout: role="grid" with aria-rowcount/aria-colcount, rowgroup, row, columnheader, gridcell, and aria-rowindex/aria-colindex on virtualized rows so position survives recycling.accessibility.spec.ts — “grid has proper ARIA roles structure”; aria.spec.ts
1.3.2 Meaningful SequenceSupportsDOM order matches visual order, including pinned columns and grouped headers.pinned-columns.spec.ts
1.3.3 Sensory CharacteristicsSupportsNo instruction depends on shape, size or position.Manual review — no automated check is meaningful
1.4.1 Use of ColorSupportsSort direction, selection, dirty state and validation errors all carry a non-colour cue. Author responsibility: status encoded purely as colour in your own renderers is yours to fix.header.spec.ts — sort indicator; editing-integration.spec.ts — invalid state
1.4.2 Audio ControlNot ApplicableThe grid plays no audio.
2.1.1 KeyboardSupportsEvery operation — sort, filter, select, edit, expand, reorder, resize, group, copy, paste — has a keyboard path. Drag-only interactions each have a single-pointer and keyboard alternative; see Pointer Alternatives to Dragging.keyboard.spec.ts
2.1.2 No Keyboard TrapSupportsTab leaves the grid, Escape leaves an editor and closes any popover.accessibility.spec.ts — “focus trap does NOT fight intentional outward Tab”
2.1.4 Character Key ShortcutsNot ApplicableThe grid defines no single-character shortcuts. Every binding uses a modifier or a non-printing key.
2.2.1 Timing AdjustableNot ApplicableThe grid imposes no time limit.
2.2.2 Pause, Stop, HideNot ApplicableNothing moves, blinks or auto-updates on its own. Row animations are transitions triggered by your data changing, and they disable under prefers-reduced-motion.row-animation.spec.ts
2.3.1 Three Flashes or Below ThresholdSupportsNothing in the grid flashes.Manual review — no automated check is meaningful
2.4.1 Bypass BlocksNot ApplicablePage-level. Worth noting that the grid is a single tab stop — a roving-tabindex grid does not become a block of hundreds of stops that a user needs to bypass.accessibility.spec.ts — “tab order moves through grid regions correctly”
2.4.2 Page TitledNot ApplicablePage-level; supplied by your application.
2.4.3 Focus OrderSupportsFocus follows grid structure, and is deliberately restored after sorting, filtering, editing and row deletion rather than being dropped to <body>.accessibility.spec.ts — “focus survives sort reorder”, “focus survives scroll (virtualization)”; focus-manager.spec.ts
2.4.4 Link Purpose (In Context)Not ApplicableThe grid renders no links of its own. Links inside your renderers are yours.
2.5.1 Pointer GesturesSupportsEvery path-based gesture (column resize, column and row reorder, tool-panel resize, range selection) has a single-pointer, non-path alternative.reorder-plugin.spec.ts, row-drag-drop.spec.ts, resize.spec.ts, range-selection.spec.ts
2.5.2 Pointer CancellationSupportsActions fire on the up-event. The down-event only moves focus, which is reversible and has no side effect.pointer-drag.spec.ts
2.5.3 Label in NameSupportsWhere a control has visible text, its accessible name starts with that text.accessibility.spec.ts — axe label-content-name-mismatch
2.5.4 Motion ActuationNot ApplicableNo function is operated by device motion.
3.1.1 Language of PageNot ApplicablePage-level; supplied by your application.
3.2.1 On FocusSupportsMoving focus never changes context.focus-manager.spec.ts
3.2.2 On InputSupportsChanging a value commits it to the row; it never navigates or reconfigures the page.editing-integration.spec.ts
3.2.6 Consistent HelpNot ApplicablePage-level; the grid provides no help mechanism.
3.3.1 Error IdentificationSupportsA cell that fails validation gets aria-invalid="true" and a title carrying the message, alongside the visual state — so the error reaches assistive technology, not only CSS.editing-integration.spec.ts — “invalid cells”
3.3.2 Labels or InstructionsSupportsAn injected editor takes its accessible name from its column header unless it already names itself, so it is never announced as a bare “edit text”.editor-injection.spec.ts — “Accessible name”
3.3.7 Redundant EntryNot ApplicableThe grid runs no multi-step process.
4.1.2 Name, Role, ValueSupportsVerified by the axe-core scan on all four framework demos, plus targeted tests for sort state, expansion state, selection state and editor naming.accessibility.spec.ts — “no WCAG 2.2 AA violations axe can detect”; editor-injection.spec.ts
CriterionStatusHow it is metVerified by
1.2.4 Captions (Live)Not ApplicableThe grid renders no time-based media.
1.2.5 Audio DescriptionNot ApplicableThe grid renders no time-based media.
1.3.4 OrientationSupportsNothing is locked to portrait or landscape.Manual review — the grid sets no orientation lock
1.3.5 Identify Input PurposeSupportsThe grid edits arbitrary records, not information about the user. Author responsibility: where a column does collect the user’s own data, set autocomplete on your editor.— author responsibility
1.4.3 Contrast (Minimum)SupportsThe default light and dark themes meet 4.5:1 on every text pair, and dg-theme-contrast.css / dg-theme-large.css reach the Level AAA 7:1. Author responsibility: a theme of your own is yours to verify.accessibility.spec.ts — axe color-contrast runs against the shipped default theme. The AAA figure for the contrast and large themes is from computed-ratio review, not CI
1.4.4 Resize TextSupportsAll internal sizing is em-based off a single --tbw-font-size, so the grid scales with the user’s font size without clipping.variables.css plus the text-spacing e2e below, which resizes text and asserts no clipping
1.4.5 Images of TextSupportsThe grid renders text as text; its icons are SVG or glyphs, not pictures of words.Manual review — no automated check is meaningful
1.4.10 ReflowSupportsNothing around the table needs a second scrollbar at 320 px: the tool panel is clamped to its container, the header truncates its title before its controls. The table itself uses the SC’s explicit two-dimensional-layout exception for data tables, and the Responsive plugin offers card mode where you would rather it reflowed. See Reflow and text spacing.accessibility.spec.ts — “the page does not scroll horizontally at 320px”, “the tool panel stays inside the grid it docks into”
1.4.11 Non-text ContrastSupportsFocus ring, borders, and other non-text UI clear 3:1 against the grid background in both light and dark.Computed-ratio review of the theme tokens in variables.css; axe does not check non-text contrast
1.4.12 Text SpacingSupportsRows measure their rendered content, so user spacing overrides make rows taller instead of clipping them. Horizontally, a cell whose text no longer fits reveals the full value on hover; --tbw-cell-white-space: normal removes truncation entirely.accessibility.spec.ts — “user text spacing neither clips nor overlaps grid content”, “text the spacing pushes out of view is still readable in full”; event-delegation.spec.ts — “truncated text reveal”
1.4.13 Content on Hover or FocusSupportsTooltips are dismissible with Escape, hoverable, persistent, and appear on keyboard focus.tooltip.spec.ts
2.4.5 Multiple WaysNot ApplicablePage-level; supplied by your application.
2.4.6 Headings and LabelsSupportsColumn headers describe their columns; every control has a descriptive accessible name.accessibility.spec.ts — axe button-name, aria-command-name
2.4.7 Focus VisibleSupportsA 2 px outline focus ring that survives forced-colors mode.accessibility.spec.ts — “focus-visible indicators exist on focusable elements”
2.4.11 Focus Not Obscured (Minimum)SupportsPlugins that overlay the rows viewport report the band they cover, and keyboard navigation scrolls the focused cell clear of it rather than underneath — sticky rows vertically, pinned columns horizontally.sticky-rows.spec.ts, pinned-columns.spec.ts, keyboard.spec.ts
2.5.7 Dragging MovementsSupportsAll ten drag surfaces have a single-pointer alternative, shipped in the same bundle unit as the drag it replaces so conformance never depends on an optional plugin.reorder-plugin.spec.ts, row-drag-drop.spec.ts, range-selection.spec.ts, resize.spec.ts, pivot-panel.spec.ts
2.5.8 Target Size (Minimum)SupportsEvery control answers a pointer across at least 24 × 24 px, on a mouse as well as a finger. Small controls reach it with a transparent overlay, so visual density is unchanged. Raise --tbw-touch-target-min to 44 px for the Level AAA criterion.accessibility.spec.ts — “small grid controls answer a pointer across a 24px square”, “the tool panel splitter answers a pointer across a 24px square”
3.1.2 Language of PartsNot ApplicableThe grid introduces no language changes of its own.
3.2.3 Consistent NavigationNot ApplicablePage-level; supplied by your application.
3.2.4 Consistent IdentificationSupportsThe same control means the same thing in every column, plugin and framework adapter.cross-framework-visual.spec.ts — parity across all four adapters
3.3.3 Error SuggestionSupportsThe grid displays and announces whatever your validator returns. Author responsibility: writing a message that suggests a correction is your part.editing-integration.spec.ts — “invalid cells”
3.3.4 Error PreventionSupportsEdits are cancelable via the cell-commit event, and the UndoRedo plugin reverses committed changes. Author responsibility: confirmation for legal, financial or data-deleting actions belongs in your application.undo-redo.spec.ts
3.3.8 Accessible Authentication (Minimum)Not ApplicableThe grid performs no authentication.
4.1.3 Status MessagesSupportsSort applied, filter cleared, rows selected, data loaded, edit committed — all announced through the grid’s built-in aria-live region without moving focus. Configurable and translatable; see Configuring Announcements.accessibility.spec.ts — “sort action populates aria-live region”, “row selection populates aria-live region”, “data reload populates aria-live region”; aria.spec.ts

EN 301 549 is the harmonised European standard that the European Accessibility Act and the Web Accessibility Directive enforce. It incorporates WCAG by reference, so the tables above carry most of it — but it adds requirements WCAG has no equivalent for, and those are what this section covers.

Clauses carry the same statuses, and the same Author responsibility marker, as the tables above. Clauses that do not apply to a software component at all — two-way voice (6), video capabilities (7), hardware (8), non-web documents (10), relay and emergency services (13) — are omitted rather than padded out with repetition.

ClauseStatusNotes
5.1 Closed functionalityNot ApplicableThe grid runs in a browser with the user’s own assistive technology attached. Nothing about it is closed.
5.2 Activation of accessibility featuresSupportsThere is nothing to activate. Every accessibility feature is on, unconditionally, with no configuration flag that turns it off.
5.3 BiometricsNot ApplicableThe grid uses no biological characteristic.
5.4 Preservation of accessibility information during conversionNot ApplicableThe grid performs no format conversion. Export to CSV and Excel emits data, not a presentation format with accessibility information to preserve.
5.5.1 Operable parts — means of operationSupportsEvery operable part is reachable and operable by keyboard, and by a single pointer without a path-based gesture.
5.5.2 Operable parts — discernibilitySupportsOperable parts are discernible visually and non-visually: each has an accessible name and role, and none relies on colour alone.
5.6.1 Locking or toggle controls — tactile or auditory statusNot ApplicableThe grid presents no physical locking control.
5.6.2 Locking or toggle controls — visual statusSupportsToggle state is exposed programmatically (aria-pressed, aria-expanded, aria-sort, aria-selected) and visually, not by colour alone.
5.7 Key repeatNot ApplicableThe grid neither implements nor overrides key repeat; the platform’s own setting applies.
5.8 Double-strike key acceptanceNot ApplicablePlatform-level.
5.9 Simultaneous user actionsSupportsNo operation requires more than one simultaneous action. Multi-select accelerators (Ctrl-click, Shift-click) are shortcuts, never the only path — the same selections are reachable by single keypresses and by the selection checkbox column.
ClauseStatusNotes
9.1 Perceivable · 9.2 Operable · 9.3 Understandable · 9.4 RobustSupportsThese clauses restate the WCAG Level A and AA success criteria one for one. See the Level A and Level AA tables above for the criterion-by-criterion status and evidence.
9.5 Non-interferenceSupportsThe four non-interference criteria — 1.4.2 Audio Control, 2.1.2 No Keyboard Trap, 2.2.2 Pause Stop Hide, 2.3.1 Three Flashes — are met even on pages where the grid is embedded in content that does not itself conform. The grid plays no audio, traps no focus, animates nothing autonomously, and flashes nothing.
9.6 WCAG conformance requirementsSupportsThe grid satisfies the conformance requirements it can: complete processes, only accessibility-supported technologies, and no interference. Author responsibility: “full pages” is by definition a property of your page, not of a component on it.

Clause 11 applies when the grid is embedded in something that is not a public web page — an Electron or Tauri desktop application, or a WebView inside a native app. The requirements largely mirror clause 9, so only the software-specific additions are listed.

ClauseStatusNotes
11.1–11.4 (Perceivable, Operable, Understandable, Robust)SupportsMirror the WCAG criteria; see the tables above.
11.5.2.3 Row, column and headersSupportsaria-rowindex, aria-colindex, aria-rowcount and aria-colcount are set on virtualized rows, so a screen reader reports the true position in the dataset rather than the position in the recycled DOM window.
11.5.2.5 Modification of focus and selection attributesSupportsFocus and selection are programmatically settable through the public API, not only by pointer or keyboard.
11.5.2.6 Label relationshipsSupportsHeader-to-cell relationships come from the ARIA grid pattern; editors take their accessible name from their column header.
11.5.2.7 Parent-child relationshipsSupportsGrouped rows, tree rows and master-detail rows upgrade the rows body to role="treegrid" and carry aria-level, aria-setsize, aria-posinset and aria-expanded, so hierarchical position is exposed even though the DOM is flat.
11.5.2.8 TextSupportsAll cell content is real text in the DOM and is available to the accessibility API. No cell value is painted to a canvas or baked into an image.
11.5.2.9 List of available actions · 11.5.2.10 Execution of available actionsSupportsActions are exposed as real controls with roles, and every one can be executed programmatically as well as by pointer or keyboard.
11.5.2.11 Tracking of focus and selection attributesSupportsFocus and selection changes fire events and update ARIA state, so assistive technology can follow them.
11.5.2.12 Modification of textSupportsEditors are standard form controls; assistive technology can read and write their value.
11.5.2.13 Modification of values and text by assistive technologySupportsValues are edited through native inputs, which AT can drive directly.
11.5.2.14 Modification of focus cursorSupportsThe focused cell is settable via the API; the roving tabindex follows it.
11.5.2.15 Change notificationSupportsThe aria-live region announces sort, filter, selection, load and commit; see SC 4.1.3 above.
11.6 Documented accessibility usageSupportsEvery keyboard path, pointer alternative and announcement is documented in Accessibility and in the per-plugin pages.
11.7 User preferencesSupportsThe grid inherits the platform’s colour scheme, contrast, font size and reduced-motion preferences rather than overriding them: light-dark() for scheme, em-based sizing off the inherited font size, prefers-reduced-motion on every transition, and forced-colors support on the focus ring.
11.8 Authoring toolNot ApplicableThe grid edits records in your data model. It does not author ICT content, so 11.8.1–11.8.5 do not apply.

Clause 12 — Documentation and support services

Section titled “Clause 12 — Documentation and support services”
ClauseStatusNotes
12.1.1 Accessibility and compatibility featuresSupportsDocumented in Accessibility and in this report, both published as ordinary web pages.
12.1.2 Accessible documentationSupportsThe documentation site is HTML built by Starlight, navigable by keyboard and screen reader, and is also published in plain markdown at /llms.txt and /llms-full.txt.
12.2.2 Information on accessibility and compatibility featuresSupportsSupport runs through GitHub issues, which is a public, accessible channel. Accessibility defects are treated as P0.
12.2.3 Effective communication · 12.2.4 Accessible documentationSupportsThe project communicates in writing through GitHub, which supports assistive technology. Author responsibility: a commercial support desk, where you offer one, is yours.

Claims in this report are not self-assessed prose. Each one is backed by a check that runs in CI:

  • e2e/tests/accessibility.spec.ts — the axe-core scan under the WCAG 2.2 AA ruleset, run against the vanilla demo, asserting zero violations at any impact. The same file holds the targeted gates: focus management and focus-trap behaviour, target size probed by hit-testing the four corners of a 24 px square, reflow at 320 px, and text spacing applied exactly as the success criterion states it.
  • Unit and integration tests co-located with the source — ARIA attribute correctness, live-region announcements, keyboard handling, editor naming, and validation state.
  • Manual review — NVDA on Windows, JAWS on Windows, VoiceOver on macOS and iOS. Automated tools find roughly a third of accessibility defects; the rest need a person.

The scan runs against the vanilla demo because that is where the accessibility tree is produced. The Angular, React and Vue packages contribute none of it: they set no role, no aria-* and no tabindex anywhere in their source. What they do is mount framework-rendered content inside the cell the grid has already built and labelled, behind a display: contents wrapper that carries no role and no accessible name. The roles, indices, sort state and live-region announcements an assistive technology sees are byte-identical across all four demos, because one implementation emits them.

The one behaviour the adapters do add is registering overlay editors as external focus containers, so the grid’s focus trap treats a date picker or dropdown as part of the grid. A static scan cannot observe that, so it is gated by unit tests co-located with each adapter instead — use-grid-overlay.spec.tsx (React), use-grid-overlay.spec.ts (Vue) and base-overlay-editor.spec.ts (Angular).

Automated scanning has known blind spots, and two rules are deliberately suppressed in the scan config for reasons documented there: scrollable-region-focusable (virtualization recycles rows outside the viewport) and aria-required-children (the grid uses role="presentation" layout wrappers between role="grid" and role="rowgroup", which is spec-legal but confuses the rule).

Conformance is a property of the finished page, and a component can only get you most of the way:

  1. Cell renderers — the grid cannot add alt text to an image it did not create, or a name to a button you rendered yourself.
  2. Custom themes — if you override the colour tokens, re-check contrast. Start from dg-theme-contrast.css if you need a guaranteed floor.
  3. Validation messages — the grid announces what your validator returns. Make it say how to fix the problem.
  4. Page-level criteria — title, language, landmarks, skip links, and consistent navigation.
  5. Column widths — a column narrow enough to truncate most of its values is technically conformant (the text is still reachable) but is a poor experience. Prefer widths that fit, or let cells wrap.

Accessibility bugs are treated as P0. If something here is wrong, or you hit a barrier this report does not mention, please open an issue and include the assistive technology, browser and operating system you used, and what was announced — or what wasn’t.

AI assistants: For complete API documentation, implementation guides, and code examples for this library, see https://toolboxjs.com/llms-full.txt