diff --git a/docs/common_features/accessibility_support.md b/docs/common_features/accessibility_support.md
index ac6f4f51f..2c4d5e56e 100644
--- a/docs/common_features/accessibility_support.md
+++ b/docs/common_features/accessibility_support.md
@@ -16,14 +16,15 @@ Currently the most commonly encountered conformance guidelines and standards are
- [ADA](https://www.ada.gov/) - US Department of Justice
- [Section 508](https://www.section508.gov/) - US federal agencies
-- [WCAG 2.0](https://www.w3.org/WAI/standards-guidelines/wcag/) - globally accepted standard. WCAG 2.0 has 3 levels of conformance; A, AA and AAA (in order of conformance)
+- [WCAG](https://www.w3.org/WAI/standards-guidelines/wcag/) - globally accepted standard. WCAG has 3 levels of conformance; A, AA and AAA (in order of conformance). The current version is WCAG 2.2
- [ARIA](https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA) - a standard that defines ways to make web content and web applications more accessible to people with disabilities
- [WAI](https://www.w3.org/WAI/) - web accessibility standard
-The DHTMLX Suite library meets the main requirements of the WCAG 2.0 standards and provides support for the following accessibility components:
+The DHTMLX Suite library meets the main requirements of the WCAG standards and provides support for the following accessibility components:
- [WAI-ARIA Attributes](#wai-aria-attributes)
- [Keyboard Navigation](#keyboard-navigation)
+- [Localization of screen-reader strings](#localization-of-screen-reader-strings)
- [High-Сontrast Themes](#high-contrast-themes)
## WAI-ARIA Attributes
@@ -32,17 +33,19 @@ There are special attributes used in the markup of DHTMLX Suite widgets that mak
### Grid
-There are **roles** and **attributes** for elements of grid, sorting, filters, editable cells to enable screen readers to interpret and navigate the columns and rows of the grid (enabled by default). The semantics are always present and there is no flag to disable them. Custom content should be marked manually.
+There are **roles** and **attributes** for elements of grid, sorting, filters, editable cells to enable screen readers to interpret and navigate the columns and rows of the grid (enabled by default). Custom content should be marked manually.
You can find the following **roles** and **attributes** in the DOM:
-- role: *grid* (or *treegrid* in the `type: "tree"` mode), *rowgroup*, *row*, *columnheader*, *gridcell*, *button*
-- aria attributes: *label*, *rowcount*, *colcount*, *rowindex*, *colindex*, *aria-sort*, *aria-selected*, *aria-readonly*, *aria-multiselectable*, and — for tree rows — *aria-level* and *aria-expanded*.
+- role: *grid* (or *treegrid* in the `type: "tree"` mode), *rowgroup*, *row*, *columnheader*, *gridcell*, *button* (the sort control and the tree expand/collapse toggle)
+- aria attributes: *label*, *rowcount*, *colcount*, *rowindex*, *colindex*, *aria-sort* (on sortable columns), *aria-selected*, *aria-readonly*, *aria-multiselectable*, *aria-colspan* and *aria-rowspan* (on merged cells), and — for tree rows — *aria-level* and *aria-expanded*.
-In-place editors and header/footer filters get an accessible name derived from the column header text. Role presentation and aria-hidden are used to hide redundant content (resizers, sort icons, drag ghosts, the selection overlay) from the accessibility tree.
+The cell surface is a single tab stop, and the arrow keys move the active cell inside it, whether or not a selection module is enabled.
+
+In-place editors and header/footer filters get an accessible name derived from the column header text. Role presentation and aria-hidden are used to hide redundant content (resizers, sort icons, drag ghosts, the selection overlay) from the accessibility tree. Dynamic changes - sorting, filtering, data loading - are read out through a visually hidden polite live region, which the application can write to itself; all the built-in screen-reader strings are stored in the `aria_*` locale keys and can be translated.
:::info
-For the complete picture — the ARIA model, the keyboard zones (header/body/footer), the focus model, and configuration recipes — see the dedicated [Grid accessibility](grid/accessibility.md) guide.
+For the complete picture — the ARIA model, the keyboard zones (header/body/footer), the focus model, and configuration recipes — see the dedicated [Grid accessibility](grid/accessibility.md) guide. Criterion-by-criterion conformance with WCAG 2.2 AA, Section 508 and EN 301 549 is documented in the [Accessibility Conformance Report](grid/accessibility_conformance_report.md).
:::
### Chart
@@ -63,32 +66,130 @@ There are general description of the component, items and their states. All the
Role presentation and aria-hidden are used to hide redundant markup from the accessibility tree.
-### Toolbar
+### Toolbar, Menu, Sidebar and Ribbon
-There are general description of the component, items and their states. All the **roles** and **attributes** are enabled by default You can find the following **roles** and **attributes** in the DOM:
+These widgets are built on the same navigation bar and share one accessibility model. All the **roles** and **attributes** are enabled by default. You can find the following **roles** and **attributes** in the DOM:
+
+- role: *toolbar* (Toolbar, Ribbon, and Sidebar with the vertical orientation), *menubar* (Menu), *menu*, *menuitem*, *menuitemcheckbox*, *menuitemradio*, *button*, *combobox*
+- aria attributes: *label*, *orientation*, *haspopup*, *expanded*, *disabled*, *pressed*, *checked*.
+
+A few details worth knowing:
-- role: *toolbar*, *button*, *combobox*, *menu*, *menuitem*
-- aria attributes: *label*, *labeledby*, *orientation*, *haspopup*, *expanded*, *disabled*, *pressed*.
+- a button reports its pressed state (`aria-pressed`) in both positions when the item is declared as a toggle, with `twoState: true`, or as a member of a set, with `group`. Inside a menu, such items are exposed as `menuitemcheckbox` / `menuitemradio` with `aria-checked`;
+- a menu is named after the text (or the tooltip) of the control that opens it;
+- a button built from custom HTML takes its accessible name from its `tooltip`, so give icon-only custom buttons a tooltip;
+- the toolbar is not a navigation landmark.
+
+The accessible name of a Toolbar is set with the `ariaLabel` configuration option. Set it whenever a page has more than one toolbar, so that users can tell them apart. Without it, the name falls back to the `aria_toolbar` locale string (`"Toolbar"`):
+
+~~~jsx
+const formatting = new dhx.Toolbar("formatting", {
+ ariaLabel: "Formatting",
+ data: formattingItems
+});
+~~~
Role presentation and aria-hidden are used to hide redundant markup from the accessibility tree.
+### Window
+
+A window is exposed with `role="dialog"`. Its accessible name is taken from the `ariaLabel` configuration option, then from `title`, and, when there is neither, from the `aria_dialog` locale string (`"Dialog"`). Use `ariaLabel` for a window without a visible title:
+
+~~~jsx
+const search = new dhx.Window({
+ ariaLabel: "Search",
+ width: 405,
+ height: 56
+});
+~~~
+
+`aria-modal="true"` is set only on a modal window (`modal: true`). The window container is focusable from script, but it is not a stop in the tab order of the page, so opening a window does not change the tab order of the host page.
+
+### Colorpicker
+
+The color palette is exposed as a list of options. You can find the following **roles** and **attributes** in the DOM:
+
+- role: *listbox* (the palette), *option* (each swatch and the "Add new color" control), *group* (the custom colors)
+- aria attributes: *label*, *labelledby*, *selected*.
+
+Each swatch is named by its color name, for example "dark green", rather than by its HEX value, and the selected swatch reports `aria-selected="true"`.
+
+### Message
+
+The buttons of alert and confirmation dialogs take their accessible names from the `message` locale: `aria_confirm`, `aria_reject` and `aria_apply`.
+
## Keyboard Navigation
All DHTMLX Suite widgets are provided with a keyboard navigation support. It allows using a Suite-based app without a mouse pointer. Basic rules include:
-- the Tab key is used to navigate between widgets and clickable areas of the widgets
-- the Esc key closes windows and editors
-- the Enter is used to open and hide drop-down lists of select controls
+- the Tab key is used to navigate between widgets and clickable areas of the widgets. A group of controls - a grid, a toolbar, a menu bar, a sidebar, a ribbon, a color palette - is a single tab stop
- the Arrow keys are used to move selection or change active elements within widgets
+- the Esc key closes windows, menus and editors
+- the Enter is used to open and hide drop-down lists of select controls
+
+The focus indicator stays visible during the whole keyboard interaction, including arrow-key navigation, and is removed when the user switches to a pointer.
+
+### Toolbar, Menu, Sidebar and Ribbon
+
+| Keys | Action |
+| ---- | ------ |
+| Tab / Shift + Tab | Enter or leave the bar. Returning to the bar puts focus on the control that was used last |
+| ← / → (Toolbar, Menu, Ribbon), ↑ / ↓ (Sidebar) | Move between the controls of the bar, wrapping at both ends. Separators, spacers and disabled controls are skipped |
+| Home / End | Move to the first / last control |
+| ↓ (Toolbar, Menu, Ribbon), → (Sidebar), Enter / Space | Open the menu of the focused control and move focus into it |
+
+A text field inside a bar keeps the arrow keys while the caret can move, and passes them to the bar when the caret is at the matching end of the text and nothing is selected.
+
+Inside an open menu:
+
+| Keys | Action |
+| ---- | ------ |
+| ↑ / ↓ | Move between the menu entries, wrapping at both ends |
+| Home / End | Move to the first / last entry |
+| → | Open a submenu and move focus into it |
+| ← | Go one level back: to the entry that opened the submenu, or to the control of the bar |
+| Enter / Space | Activate the entry, close the menu and return focus to the control that opened it |
+| Esc | Close the menu and return focus to the control that opened it |
+| Tab | Close the menu and leave the bar |
+
+### Colorpicker
+
+| Keys | Action |
+| ---- | ------ |
+| Tab | Enter the palette on the selected color, or on the first swatch when nothing is selected |
+| ↑ / ↓ / ← / → | Move between swatches in the order they are shown on the screen. Movement stops at the edges of the palette |
+| Home / End | Move to the first / last swatch |
+| Enter | Select the focused color |
+
+Focus moves into the custom color view when it opens, and back to the palette when the view is closed.
:::info
For the full list of built-in hotkeys, refer to the **Keyboard Navigation** articles of the following widgets:
-- [Grid](grid/configuration.md#keyboard-navigation)
+- [Grid](grid/configuration.md#keyboard-navigation) and the [Grid accessibility](grid/accessibility.md#keyboard-navigation) guide
- [List](list/configuration.md#arrow-keys-navigation)
- [Tree](tree/configuration.md#key-navigation)
- [DataView](dataview/configuration.md#arrow-keys-navigation)
:::
+## Localization of screen-reader strings
+
+The accessible names and announcements that the widgets generate are stored in the locale of each widget as keys with the `aria_` prefix, for example `aria_toolbar` in the `toolbar` locale, `aria_dialog` in the `window` locale, `aria_palette` and the color names in the `colorpicker` locale, and `aria_confirm` in the `message` locale. Translate them with the `dhx.i18n.setLocale()` method before the widget is initialized:
+
+~~~jsx
+dhx.i18n.setLocale("toolbar", {
+ aria_toolbar: "Symbolleiste"
+});
+dhx.i18n.setLocale("window", {
+ aria_dialog: "Dialogfeld"
+});
+dhx.i18n.setLocale("colorpicker", {
+ aria_palette: "Farbpalette",
+ aria_colorDarkGray: "dunkelgrau"
+});
+~~~
+
+The locale keys are flat: pass each key at the top level of the object, not inside a nested object.
+
## High-Contrast Themes
For users that are visually impaired due to color deficiencies, care should be taken when using colors to provide information.
diff --git a/docs/grid/accessibility.md b/docs/grid/accessibility.md
index afa742ac3..6a89c52a4 100644
--- a/docs/grid/accessibility.md
+++ b/docs/grid/accessibility.md
@@ -6,21 +6,36 @@ description: You can learn about accessibility and keyboard navigation in DHTMLX
# Accessibility in DHTMLX Grid
-DHTMLX Grid is built to be operated entirely from the keyboard and to expose its structure and state to assistive technology. WAI-ARIA semantics are part of the rendered markup, and a single, coherent focus model spans the header, body, and footer. The semantics are always present — there is **no** configuration flag to disable them.
+DHTMLX Grid is built to be usable by everyone, including people who rely on keyboards, screen readers, screen magnification, or high-contrast display modes. WAI-ARIA semantics are part of the rendered markup, and a single, coherent focus model spans the header, body, and footer.
-## Capabilities
+:::info Target conformance
+DHTMLX Grid is designed to meet **WCAG 2.2 Level AA**, **Section 508** of the U.S. Rehabilitation Act, and **EN 301 549** (the technical baseline of the European Accessibility Act). Because WCAG 2.2 AA also satisfies ADA and Section 508 expectations, a single conformance target covers the major regulatory requirements.
+
+Conformance is reported criterion by criterion rather than as a blanket claim. The detailed **Accessibility Conformance Report (VPAT® 2.5)** is available: [Accessibility Conformance Report](grid/accessibility_conformance_report.md).
+:::
+
+## At a glance
| Area | Support |
| ---- | ------- |
-| Keyboard operation | Full: cell navigation, editing, sorting, range selection, tree expand/collapse, and clipboard all have keyboard equivalents |
-| WAI-ARIA semantics | Built-in (`grid` / `treegrid` model), enabled always — no opt-in flag |
-| Focus model | A single tab stop per zone; focus moves between header, body, and footer |
-| Selection model | Two modes: single-cell/row (`selection`) and spreadsheet-style range (`blockSelection`) |
-| High-contrast display | Light and dark high-contrast themes (`contrast-light` / `contrast-dark`) |
+| Keyboard operation | Full: cell navigation, editing, sorting, range selection, tree expand/collapse, and clipboard all have keyboard equivalents. Cell navigation works in every configuration, with or without a selection module |
+| WAI-ARIA semantics | Built-in (`grid` / `treegrid` model), enabled by default |
+| Focus model | A single tab stop for the whole cell surface; focus moves between header, body, and footer |
+| Selection model | Optional: single-cell/row (`selection`) or spreadsheet-style range (`blockSelection`), for selecting cells and ranges |
+| Screen readers | Tested with NVDA, JAWS and VoiceOver |
+| Visual accessibility | Dedicated light and dark high-contrast themes — colour-blind friendly, AA contrast, 16px base — and non-colour cues |
+| Text resize / zoom | Layout remains operable up to 400% zoom / text spacing overrides |
+| Customization | Public `announce()` API for dynamic messages, and localizable `aria_*` strings for every built-in screen-reader description |
+| Standards | WCAG 2.2 AA, Section 508, EN 301 549 |
+
+Use this page to verify the component against your own accessibility checklist, and to learn how to configure the Grid for an accessible deployment.
+
+
-## Covered areas
+## Scope
-This documentation covers the Grid widget:
+This guide covers the Grid widget itself:
- the **data body** — cells and rows, including tree mode (`type: "tree"`)
- the **column header** — sortable headers and in-header filters
@@ -30,22 +45,127 @@ This documentation covers the Grid widget:
As with any embeddable component, the accessibility of the final page also depends on the host application (see [Host-page responsibilities](#host-page-responsibilities)).
-## WAI-ARIA support
+## Setting up an accessible Grid {#recommendedconfiguration}
+
+The Grid ships accessible by default: WAI-ARIA output is emitted automatically, and keyboard navigation is on ([`keyNavigation: true`](grid/api/grid_keynavigation_config.md)), so the whole cell surface can be reached and walked with the keyboard in any configuration. For a fully WCAG 2.2 AA-compliant deployment, the only other thing you need is an AA-contrast theme. The recommended configuration is:
+
+~~~jsx
+// 1. WAI-ARIA output and keyboard navigation are enabled by default - no action needed
+const grid = new dhx.Grid("grid_container", {
+ columns: [/* ... */],
+ data: dataset,
+ keyNavigation: true // true - by default
+});
+
+// 2. Select an AA-conformant theme
+dhx.setTheme("contrast-light"); // or "contrast-dark"
+~~~
+
+The theme can also be applied through the `data-dhx-theme` attribute of the container or of the root element; see the [Themes overview](/themes/) for all the options.
+
+Add a selection module only when users need to select cells or ranges; see the next section.
+
+### Keyboard navigation with and without selection {#selectionmodules}
+
+#### Without a selection module
+
+A grid configured without `selection` and `blockSelection` is still fully navigable. The active cell moves with the arrow keys, Home / End, Ctrl + Home / End, Page Up / Page Down and Tab, and it is scrolled into view, including next to frozen columns and rows. Moving it selects nothing: `aria-selected` is not set, no selection event fires, and no selection styling is painted. This is the configuration to use for a read-only table:
+
+~~~jsx
+// A read-only grid that can still be walked cell by cell
+const grid = new dhx.Grid("grid_container", {
+ columns: [/* ... */],
+ data: dataset
+});
+~~~
+
+:::note
+Opening an editor from the keyboard (Enter, F2, Space) requires only `editable: true`; no selection module is needed.
+:::
+
+#### With a selection module
+
+When a selection module is enabled, the selection moves together with the active cell and is exposed through `aria-selected`. The two modules are independent and drive different ARIA output and shortcut semantics.
+
+##### 1. Cell / row selection — selection
+
+A single active cell (or row) moves with the arrow keys. This populates `aria-selected` on the focused cell or row. Extending the selection with Shift is enabled only when `multiselection: true`; without it, Shift+arrow moves the active cell.
+
+~~~jsx
+// Single active cell, navigable with arrows / Tab / Home / End / Page Up·Down
+const grid = new dhx.Grid("grid_container", {
+ columns: [/* ... */],
+ data: dataset,
+ selection: "complex", // "cell" | "row" | "complex"
+ multiselection: true, // enables Shift+Arrow multi-select
+ keyNavigation: true, // default
+ sortable: true // default — keyboard sort in headers
+});
+~~~
+
+| `selection` value | Meaning |
+| --- | --- |
+| `"cell"` | One active cell; Shift+arrow extends when `multiselection: true` |
+| `"row"` | One active row; arrows move the whole row, `aria-selected` is on the row |
+| `"complex"` | Cell- and row-style selection combined |
+| `true` | Equivalent to cell selection |
+| *falsy / unset* | Selection (and `aria-selected`) disabled; keyboard navigation still works |
+
+##### 2. Range / block selection — blockSelection
+
+Spreadsheet-style rectangular ranges. The arrow keys move the range anchor; Shift+arrows grow or shrink the rectangle; Delete clears the range (when editing is enabled). This applies in **"range"** mode.
+
+~~~jsx
+// Google-Sheets-style range selection
+const grid = new dhx.Grid("grid_container", {
+ columns: [/* ... */],
+ data: dataset,
+ blockSelection: true, // range mode (Shift+Arrow grows the rectangle)
+ editable: true, // allows Delete to clear the range
+ keyNavigation: true
+});
+~~~
+
+| `blockSelection` value | Mode | Keyboard effect |
+| ---------------------- | ---- | --------------- |
+| `true` | range | Arrows move the range; Shift+arrows extend the rectangle; Delete clears it |
+
+Both modules use the same navigation keys; the Grid responds to whichever module is active.
+
+#### TreeGrid
+
+TreeGrid mode (`type: "tree"`) adds `role="treegrid"`, `aria-level` and `aria-expanded`, and enables arrow-key expand/collapse:
+
+~~~jsx
+const grid = new dhx.Grid("grid_container", {
+ columns: [/* ... */],
+ data: dataset,
+ type: "tree",
+ selection: "complex"
+});
+~~~
+
+
+
+The sections below describe each capability in detail.
-WAI-ARIA roles and attributes are added to the component markup automatically and are **on by default** — there is no flag to turn them off. The Grid exposes itself to assistive technology as an interactive grid (or treegrid) of rows and cells, with a separate group for the header and footer. The semantics are applied per structural part of the widget, so each part is announced with the correct role and state.
+## WAI-ARIA Attributes
+
+WAI-ARIA roles and attributes are added to the component markup automatically and are **enabled by default**. The Grid exposes itself to assistive technology as an interactive grid (or treegrid) of rows and cells, with a separate group for the header and footer. The semantics are applied per structural part of the widget, so each part is announced with the correct role and state.
### Grid container
-The following table lists the container role and the grid-wide attributes applied to the root grid element, which describe the grid as a whole:
+The following table lists the container role and the grid-wide attributes, which describe the grid as a whole. They are applied to the content element of the grid, which holds the header, body, footer and frozen zones:
| Selector | Role / attribute | Purpose |
| -------- | ---------------- | ------- |
-| `.dhx_grid` | `role="grid"` | Standard grid |
-| `.dhx_grid` | `role="treegrid"` | TreeGrid (`type: "tree"`) |
-| `.dhx_grid` | `aria-rowcount` | Total number of data rows |
-| `.dhx_grid` | `aria-colcount` | Number of visible columns |
-| `.dhx_grid` | `aria-readonly` | `"true"` when the grid is not editable |
-| `.dhx_grid` | `aria-multiselectable` | `"true"` when multi-selection is enabled |
+| `.dhx_grid-content` | `role="grid"` | Standard grid |
+| `.dhx_grid-content` | `role="treegrid"` | TreeGrid (`type: "tree"`) |
+| `.dhx_grid-content` | `aria-rowcount` | Total number of data rows |
+| `.dhx_grid-content` | `aria-colcount` | Number of visible columns |
+| `.dhx_grid-content` | `aria-readonly` | `"true"` when the grid is not editable |
+| `.dhx_grid-content` | `aria-multiselectable` | `"true"` when multi-selection is enabled |
### Rows and cells
@@ -58,7 +178,9 @@ The following table lists the roles and the position and state attributes applie
| Data cell | `role="gridcell"` | A data cell |
| Data cell | `aria-colindex` | 1-based column position |
| Data cell | `aria-readonly` | `"true"` when the cell is not editable |
-| Data cell | `aria-selected` | Selection state of the cell |
+| Data cell | `aria-selected` | Selection state of the cell, when a selection module is enabled |
+| Data cell | `tabindex` | `"0"` on exactly one cell (the active cell), `"-1"` on the rest, so the cell surface is a single tab stop |
+| Merged cell | `aria-colspan` / `aria-rowspan` | Number of columns / rows the merged cell covers |
### Tree (TreeGrid) rows
@@ -77,9 +199,9 @@ The following table lists the roles and attributes applied to the header and foo
| Selector | Role / attribute | Purpose |
| -------- | ---------------- | ------- |
-| Header/footer group | `role="rowgroup"` + `aria-rowcount` | Groups the header or footer rows |
+| Header/footer group | `role="rowgroup"` | Groups the header or footer rows |
| Header/footer row | `role="row"` + `aria-rowindex` | A header or footer row |
-| Header cell | `role="columnheader"` + `aria-sort` | Column header; `aria-sort` is `none` / `ascending` / `descending` |
+| Header cell | `role="columnheader"` + `aria-sort` | Column header; `aria-sort` is `none` / `ascending` / `descending` and is present only on sortable columns |
| Footer cell | `role="gridcell"` + `aria-colindex` | A footer (summary) cell |
| Content (filter) cell | `role="gridcell"` | Header/footer cell hosting a filter control |
| Sort affordance | `role="button"` + `aria-label="Sort by …"` | Keyboard- and pointer-activatable sort trigger |
@@ -90,81 +212,98 @@ In-place editor inputs and header/footer filters receive an accessible name deri
### Hidden and decorative elements
-Resizer grips, sort icons, sort-order counters, drag ghosts, drop indicators, and the selection overlay are removed from the accessibility tree with `aria-hidden="true"` / `role="presentation"`, so screen readers are not cluttered with redundant markup.
+Resizer grips, sort icons, sort-order counters, drag ghosts, drop indicators, and the selection overlay are removed from the accessibility tree with `aria-hidden="true"` / `role="presentation"`, so screen readers are not cluttered with redundant markup. The hidden focus sentinels that let the keyboard enter and leave the widget are placed outside the grid role and are not exposed as controls.
-## Selection modes
+## Screen reader support
-The keyboard behavior of the body depends on which selection system is enabled. The two are independent and drive different ARIA output and shortcut semantics.
+DHTMLX Grid is tested against the most widely used assistive technologies:
-### 1. Cell / row selection — selection
+| Screen reader | Browser | Platform |
+| ------------- | ------- | -------- |
+| NVDA | Firefox | Windows |
+| JAWS | Chrome | Windows |
+| VoiceOver | Safari | macOS |
-A single active cell (or row) moves with the arrow keys. This populates `aria-selected` on the focused cell or row. Extending the selection with Shift is enabled only when `multiselection: true`; without it, Shift+arrow moves the active cell.
+Rows and cells carry their position (`aria-rowindex` / `aria-colindex`) against the grid totals (`aria-rowcount` / `aria-colcount`). Because these are absolute positions in the dataset rather than positions in the DOM, they stay correct while rows and columns are virtualized: a screen reader announces "row 4,812 of 50,000" even though only the visible window exists in the markup.
+
+The rest of the state travels the same way, on the element it belongs to:
+
+| State | Exposed through | Read on |
+| ------ | --------------- | ------- |
+| Selection | `aria-selected` | The selected cell, or the row in `selection: "row"` mode, when a selection module is enabled |
+| Editability | `aria-readonly` | The grid container and each cell |
+| Sort direction | `aria-sort` (`none` / `ascending` / `descending`) | The header of a sortable column |
+| Hierarchy | `aria-level`, `aria-expanded` | Tree rows (`type: "tree"`) |
+| Merged cells | `aria-colspan`, `aria-rowspan` | The merged cell |
+| Multi-selection capability | `aria-multiselectable` | The grid container |
+
+Editors and filters take their accessible name from the column header text, so the user always hears which column is in play. Decorative markup — resizer grips, sort icons, drag ghosts, drop indicators, the selection overlay — is hidden from the accessibility tree, so nothing redundant is announced.
+
+### Announcing dynamic changes
+
+For things that *happen* and have no permanent element to label — a completed load, a filter result, a corrected value — the Grid writes text into a visually hidden live region (`role="status"`, `aria-live="polite"`, `aria-atomic="true"`) that the screen reader reads aloud without moving focus. The region is available to your own code through the [`announce()`](grid/api/grid_announce_method.md) method:
~~~jsx
-// Single active cell, navigable with arrows / Tab / Home / End / Page Up·Down
-const grid = new dhx.Grid("grid_container", {
- columns: [/* ... */],
- data: dataset,
- selection: "complex", // "cell" | "row" | "complex"
- multiselection: true, // enables Shift+Arrow multi-select
- keyNavigation: true // default
-});
+grid.announce("5 rows imported");
~~~
-| `selection` value | Meaning |
-| --- | --- |
-| `"cell"` | One active cell; Shift+arrow extends when `multiselection: true` |
-| `"row"` | One active row; arrows move the whole row, `aria-selected` is on the row |
-| `"complex"` | Cell- and row-style selection combined |
-| `true` | Equivalent to cell selection |
-| *falsy / unset* | Selection (and `aria-selected`) disabled |
+The message is always **polite**: the screen reader finishes its current sentence first, so an announcement never interrupts the user.
-### 2. Range / block selection — blockSelection
+The Grid already announces the following out of the box:
-Spreadsheet-style rectangular ranges. The arrow keys move the range anchor; Shift+arrows grow or shrink the rectangle; Delete clears the range (when editing is enabled). This applies in **"range"** mode.
+| Event | Announced text |
+| ----- | -------------- |
+| Sorting by a column | `Sorted by {column}, ascending` / `Sorted by {column}, descending` |
+| Applying a filter | `{count} rows match the filter` |
+| Clearing the filter | `Filter cleared, {count} rows` |
+| Loading data | `{count} rows loaded` |
+| Entering an out-of-range number in an editor | `Value must be between {min} and {max}` and, once it is fixed, `Value corrected to {value}` |
+
+### Translatable screen-reader names
+
+The strings the screen reader hears live in the Grid locale, so they translate with the rest of the UI. They fall into two groups:
+
+- **announcements** — `aria_sortedAscending`, `aria_sortedDescending`, `aria_filterApplied`, `aria_filterCleared`, `aria_rowsLoaded`, `aria_valueOutOfRange`, `aria_valueBelowMin`, `aria_valueAboveMax`, `aria_valueClamped`;
+- **accessible names** — `aria_sortBy`, `aria_filter`, `aria_filterByDate`, `aria_expandGroup`, `aria_collapseGroup`, `aria_expandRow`, `aria_collapseRow`, `aria_editContent`, `aria_subRow`, `aria_rowId`, and the drag-panel names.
+
+Override them like any other locale label, before the Grid is initialized:
~~~jsx
-// Google-Sheets-style range selection
-const grid = new dhx.Grid("grid_container", {
- columns: [/* ... */],
- data: dataset,
- blockSelection: true, // range mode (Shift+Arrow grows the rectangle)
- editable: true, // allows Delete to clear the range
- keyNavigation: true
+dhx.i18n.setLocale("grid", {
+ aria_sortBy: "Sortieren nach {column}",
+ aria_rowsLoaded: "{count} Zeilen geladen"
});
-~~~
-| `blockSelection` value | Mode | Keyboard effect |
-| ---------------------- | ---- | --------------- |
-| `true` | range | Arrows move the range; Shift+arrows extend the rectangle; Delete clears it |
+const grid = new dhx.Grid("grid_container", config);
+~~~
-Both systems coexist with the same navigation keys; the Grid responds to whichever selection system is active.
+Placeholders in curly braces (`{column}`, `{count}`, `{min}`, `{max}`, `{value}`, `{id}`) are substituted at runtime and must be kept in the translated string. See the [Localization](grid/localization.md) article for the full locale workflow.
## Keyboard navigation
-Keyboard navigation is on by default (`keyNavigation: true`); set `keyNavigation: false` to opt out. Focus enters the Grid through hidden focus sentinels placed before the header and after the footer, which direct it into the correct zone. Within each zone a single cell is the tab stop, and the arrow keys move between cells from there.
+Keyboard navigation is on by default (`keyNavigation: true`); set `keyNavigation: false` to opt out. It works in every configuration: without a selection module the keys move the active cell, and with one they move the selection as well — see [Keyboard navigation with and without selection](#selectionmodules). Focus enters the Grid through hidden focus sentinels placed before the header and after the footer, which direct it into the correct zone. Within each zone a single cell is the tab stop, and the arrow keys move between cells from there. Tab at the first or the last cell leaves the Grid in every configuration, including one with frozen columns (`leftSplit` / `rightSplit`).
Shortcuts are organized into **zones** — body, header, footer — and resolved by where focus currently is. The full reference is in the [Keyboard navigation](grid/configuration.md#keyboard-navigation) article; the tables below summarize it.
### Grid body
-| Keys | Action | Selection mode |
-| ---- | ------ | -------------- |
-| ↑ / ↓ / ← / → | Move the selected cell one row/column (↑ from the first row enters the header; ↓ from the last row enters the footer when a footer exists) | both |
-| Ctrl + arrow | Jump the selection to the first/last cell in that direction | both |
+| Keys | Action | Requires |
+| ---- | ------ | -------- |
+| ↑ / ↓ / ← / → | Move the active cell one row/column (↑ from the first row enters the header; ↓ from the last row enters the footer when a footer exists) | — |
+| Ctrl + arrow | Jump the active cell to the first/last cell in that direction | — |
| Shift + arrow | Extend the selection by one cell | `selection` with `multiselection: true`, or `blockSelection` range |
| Ctrl + Shift + arrow | Extend the selection to the edge | as above |
-| Home / End | Move to the first / last column of the current row | both |
-| Ctrl + Home / Ctrl + End | Move to the first / last cell of the grid | both |
+| Home / End | Move to the first / last column of the current row | — |
+| Ctrl + Home / Ctrl + End | Move to the first / last cell of the grid | — |
| Shift + Home / End, Ctrl + Shift + Home / End | Extend the selection to the row/grid extent | extend-capable modes |
-| Page Up / Page Down | Move the selected cell up / down by one page of visible rows | both |
+| Page Up / Page Down | Move the active cell up / down by one page of visible rows | — |
| Shift + Page Up / Page Down | Extend the selection by one page | extend-capable modes |
-| Enter | Open the editor (or toggle a boolean cell); when editing, commit and close | requires `editable` |
-| F2 | Open the editor of the selected cell (non-boolean) | requires `editable` |
-| Space | Toggle a boolean cell | requires `editable` |
-| Escape | Cancel editing without saving | requires `editable` |
-| Tab / Shift + Tab | Move to the next / previous cell, wrapping rows; exits to the footer / header at the ends | both |
-| Delete | Clear the selected range | `blockSelection` range mode + `editable` |
+| Enter | Open the editor (or toggle a boolean cell); when editing, commit and close | `editable` |
+| F2 | Open the editor of the active cell (non-boolean) | `editable` |
+| Space | Toggle a boolean cell | `editable` |
+| Escape | Cancel editing without saving | `editable` |
+| Tab / Shift + Tab | Move to the next / previous cell, wrapping rows; exits to the footer / header at the ends | — |
+| Delete | Clear the selected range | `blockSelection` range mode and `editable` |
| Ctrl + Z / Ctrl + Shift + Z | Undo / Redo | History module |
| Ctrl + Enter | Expand / collapse the row (`type: "tree"`) | TreeGrid |
| → / ← (tree column) | Expand / collapse a branch, or move to first child / parent | TreeGrid |
@@ -194,52 +333,22 @@ Shortcuts are organized into **zones** — body, header, footer — and resolved
Navigation is **span-aware**: movement across merged (colspan/rowspan) header and footer cells stays predictable, and the logical navigation row is preserved. When focus reaches an off-screen (virtualized) column, the Grid scrolls it into view automatically.
:::
-## Assistive technology
+## Low vision and colour
-What the Grid exposes to assistive technology is driven entirely by the ARIA markup above. Rows and cells carry their position (`aria-rowindex` / `aria-colindex`) against the grid totals (`aria-rowcount` / `aria-colcount`), so position is announced even when rows are virtualized. Selection is exposed through `aria-selected`, editability through `aria-readonly`, sort state through `aria-sort`, and — in tree mode (`type: "tree"`) — hierarchy through `aria-level` and `aria-expanded`.
+### High-contrast themes {#highcontrastthemes}
-## High contrast and focus
+Light and dark high-contrast themes ship with the library — `contrast-light` and `contrast-dark` — activated by `dhx.setTheme("contrast-light")` / `dhx.setTheme("contrast-dark")` or by setting `data-dhx-theme="contrast-light"` / `data-dhx-theme="contrast-dark"` on the container or the root element. Both meet WCAG AA contrast, are colour-blind friendly, and raise the base font size to 16px. See the [Themes](/themes/) guide and the [Light High Contrast](themes/contrast_light_theme.md) / [Dark High Contrast](themes/contrast_dark_theme.md) pages for details.
-- **High-contrast themes.** Light and dark high-contrast themes ship with the library (`contrast-light` and `contrast-dark`), activated by setting `data-dhx-theme="contrast-light"` or `data-dhx-theme="contrast-dark"`. See the [Themes](/themes/) guide and the [Light High Contrast](themes/contrast_light_theme.md) / [Dark High Contrast](themes/contrast_dark_theme.md) pages for details.
-- **Visible focus.** Focus is tracked per zone by the roving-tabindex model, so the active cell is the single tab stop and moves predictably with the arrow keys.
+
-## Configuration recipes
+### Other low-vision support
-~~~jsx
-// A. Cell navigation (single active cell)
-new dhx.Grid("grid_container", {
- columns, data,
- selection: "complex",
- multiselection: true, // Shift+Arrow multi-select
- keyNavigation: true, // default
- sortable: true // default — keyboard sort in headers
-});
-
-// B. Spreadsheet-style range selection
-new dhx.Grid("grid_container", {
- columns, data,
- blockSelection: true, // range mode: Shift+Arrow grows the rectangle, Delete clears
- editable: true
-});
-
-// C. TreeGrid (adds role="treegrid", aria-level, aria-expanded,
-// and arrow-key expand/collapse)
-new dhx.Grid("grid_container", {
- columns, data,
- type: "tree",
- selection: "complex"
-});
-
-// WAI-ARIA semantics are always emitted — there is no flag to toggle them.
-~~~
-
-Related articles:
-
-- [Keyboard navigation](grid/configuration.md#keyboard-navigation)
-- [keyNavigation](grid/api/grid_keynavigation_config.md)
-- [selection](grid/api/grid_selection_config.md)
-- [blockSelection](grid/api/grid_blockselection_config.md)
-- [TreeGrid mode](grid/treegrid_mode.md)
+- **Colour is never the only signal.** Sort direction is carried by an arrow glyph and by `aria-sort`, selection by `aria-selected` alongside the highlight, editability by `aria-readonly`, and hierarchy by `aria-level` and `aria-expanded`.
+- **Zoom and reflow.** The grid layout remains operable when the page is zoomed up to 400%.
+- **Text spacing.** Applying WCAG text-spacing overrides does not clip or overlap text in grid cells, column headers or footer summaries.
+- **Visible focus.** Focus is tracked per zone by the roving-tabindex model, so the active cell is the single tab stop and moves predictably with the arrow keys. With `selection: "cell"` / `"complex"` or `blockSelection`, the active cell is marked by a persistent 2px solid selection border in the theme primary colour, and no second focus outline is drawn over it. With `selection: "row"`, and in a grid without a selection module, the focused cell is marked by a dashed focus outline. Header and footer cells show a 2px focus ring, and filter inputs and open editors an inset ring.
+- **Scrolling into view.** When focus reaches an off-screen row or column, the Grid scrolls it into view and compensates for frozen columns and rows and for the header and footer height, so the focused cell is never left behind a frozen zone.
## Host-page responsibilities
@@ -249,6 +358,26 @@ A few accessibility requirements live at the page level, not inside the componen
- provides a page `
` and wraps the grid in an appropriate landmark (e.g. ``);
- gives the grid container an accessible name where multiple widgets share a page.
-## Reference
+## Testing and methodology
+
+Accessibility is validated continuously, and against the component source rather than a single demo page, so the results hold for every configuration the Grid can be put into:
+
+1. **Automated testing** with [axe-core](https://github.com/dequelabs/axe-core) across representative configurations, among them the plain grid, TreeGrid mode, header and footer filters, inline editing, frozen columns and rows, and the high-contrast themes.
+2. **Manual review** of the source: the roles, states and accessible names emitted per part of the widget; the shortcut registry and focus model — zones, the roving tab stop, the sentinels that enter and leave the widget, and the behavior of each binding in each selection mode; and the theme tokens, with contrast ratios computed for the default light, dark, `contrast-light` and `contrast-dark` themes.
+3. **Manual testing**: keyboard-only walkthroughs of every zone, screen-reader passes with NVDA, JAWS and VoiceOver, and checks under color-vision-deficiency emulation, 200% / 400% zoom and WCAG text-spacing overrides.
+4. **Conformance reporting**: results are published openly, criterion by criterion, in the [Accessibility Conformance Report](grid/accessibility_conformance_report.md) — including the criteria the Grid only partially meets.
+## Resources
+
+- [Accessibility Conformance Report (VPAT 2.5)](grid/accessibility_conformance_report.md)
+- [Keyboard navigation](grid/configuration.md#keyboard-navigation)
+- [keyNavigation](grid/api/grid_keynavigation_config.md)
+- [selection](grid/api/grid_selection_config.md)
+- [blockSelection](grid/api/grid_blockselection_config.md)
+- [announce()](grid/api/grid_announce_method.md)
+- [Localization](grid/localization.md)
+- [TreeGrid mode](grid/treegrid_mode.md)
+- [Themes overview](/themes/)
+- [Accessibility support across DHTMLX Suite](common_features/accessibility_support.md)
+- [WCAG 2.2](https://www.w3.org/TR/WCAG22/)
- [WAI-ARIA Authoring Practices: Grid / Treegrid](https://www.w3.org/WAI/ARIA/apg/patterns/)
diff --git a/docs/grid/accessibility_conformance_report.md b/docs/grid/accessibility_conformance_report.md
new file mode 100644
index 000000000..eea060ebf
--- /dev/null
+++ b/docs/grid/accessibility_conformance_report.md
@@ -0,0 +1,215 @@
+---
+sidebar_label: Conformance report (VPAT)
+title: JavaScript Grid - Accessibility Conformance Report
+description: You can explore the accessibility conformance report (VPAT 2.5) for DHTMLX Grid in the documentation of the DHTMLX JavaScript UI library. Browse developer guides and API reference, try out code examples and live demos, and download a free 30-day evaluation version of DHTMLX Suite.
+---
+
+# Accessibility Conformance Report
+
+This report documents how DHTMLX Grid conforms to the major accessibility standards. It follows the **VPAT® 2.5 (International Edition)** structure, so you can map it directly against your own procurement or compliance checklist. For a task-oriented overview of the accessibility features and how to configure them, see the [Accessibility](grid/accessibility.md) guide.
+
+**Name of Product/Version:** DHTMLX Grid v9.3.12
+
+**Report Date:** September 2026
+
+**Product Description:** DHTMLX Grid is an interactive JavaScript data grid component for building tabular interfaces in a web browser. It renders a column header, a virtualized data body and a footer, and supports sorting, filtering, inline editing, cell and range selection, frozen columns and rows, merged cells, and a hierarchical TreeGrid mode. It is embedded by a host web application.
+
+**Contact Information:** [info@dhtmlx.com](mailto:info@dhtmlx.com)
+
+## Notes
+
+- This report evaluates DHTMLX Grid in its **recommended accessibility configuration**: keyboard navigation enabled (`keyNavigation: true`, the default), WAI-ARIA output active (enabled by default), and an AA-conformant colour scheme selected through `dhx.setTheme("contrast-light")` / `dhx.setTheme("contrast-dark")` or the equivalent `data-dhx-theme` attribute. Where a conformance level depends on this configuration, the Remarks say so. See the [Accessibility](grid/accessibility.md) guide for setup instructions.
+- DHTMLX Grid is **web content** rendered by a host application. Page-level responsibilities - the page title, ``, skip/bypass mechanisms, and site-wide navigation - belong to the host application and are reported as *Not Applicable* with an explanation.
+- In the WCAG tables, only the **Web** response is populated. The *Electronic Docs*, *Software*, *Closed*, and *Authoring Tool* rows are *Not Applicable*: the product is not standalone (non-web) software, closed functionality, an authoring tool, or a piece of electronic documentation.
+
+**Evaluation Methods Used:** Testing was performed using a combination of automated testing (axe-core in a headless browser), manual code review of the component source and stylesheets (the roles and ARIA attributes emitted per structural part, the keyboard shortcut registry and focus model, the editor and filter naming, and the theme colour tokens, with contrast ratios computed from those tokens for the default, dark, `contrast-light` and `contrast-dark` themes), assistive-technology testing (manual passes with **NVDA + Firefox** and **JAWS + Chrome** on Windows and **VoiceOver + Safari** on macOS), and browser overrides (colour-vision-deficiency emulation, 200% / 400% zoom, and WCAG text-spacing overrides).
+
+## Applicable standards / guidelines
+
+| Standard / Guideline | Included in report |
+|---|---|
+| Web Content Accessibility Guidelines 2.0 | Level A (No) · Level AA (No) · Level AAA (No) |
+| Web Content Accessibility Guidelines 2.1 | Level A (No) · Level AA (No) · Level AAA (No) |
+| Web Content Accessibility Guidelines 2.2 | Level A (**Yes**) · Level AA (**Yes**) · Level AAA (No) |
+| Revised Section 508 standards (published Jan 18, 2017; corrected Jan 22, 2018) | (**Yes**) |
+| EN 301 549 - V3.1.1 (2019-11) and V3.2.1 (2021-03) | (**Yes**) |
+
+*WCAG 2.0 and 2.1 are not reported separately. Criteria that WCAG marks "2.1 and 2.2" are answered because
+they are part of WCAG 2.2 and are referenced by EN 301 549.*
+
+## Terms
+
+- **Supports:** The functionality of the product has at least one method that meets the criterion without
+ known defects, or meets with equivalent facilitation.
+- **Partially Supports:** Some functionality of the product does not meet the criterion.
+- **Does Not Support:** The majority of product functionality does not meet the criterion.
+- **Not Applicable:** The criterion is not relevant to the product.
+
+## WCAG 2.x report
+
+DHTMLX Grid is web content, so only the **Web** response is populated below. "Requires an AA-conformant
+theme" and "requires `keyNavigation`, on by default" are configuration dependencies, not defects.
+
+### Table 1: Success Criteria, Level A
+
+| Criteria | Conformance level | Remarks and explanations |
+|---|---|---|
+| **1.1.1** Non-text Content | Supports | Icons are rendered as font glyphs, not images of text. Interactive icons carry accessible names: the tree expand/collapse toggle is `role="button"` with `aria-label`, and the sort affordance is `role="button"` with `aria-label="Sort by "`. Decorative parts - resizer grips, sort icons, sort-order counters, drag ghosts, drop indicators and the selection overlay - are removed from the accessibility tree with `aria-hidden="true"` or `role="presentation"`. |
+| **1.2.1** Audio-only and Video-only (Prerecorded) | Not Applicable | The product contains no audio or video content. |
+| **1.2.2** Captions (Prerecorded) | Not Applicable | No prerecorded multimedia. |
+| **1.2.3** Audio Description or Media Alternative (Prerecorded) | Not Applicable | No prerecorded multimedia. |
+| **1.3.1** Info and Relationships | Supports | The grid uses `grid` → `rowgroup` → `row` → `gridcell`/`columnheader` roles, and `treegrid` in tree mode; the grid role owns only row groups and rows, and the focus sentinels are placed outside it. Position is exposed with `aria-rowindex`/`aria-colindex` against `aria-rowcount`/`aria-colcount`; the extent of a merged cell with `aria-colspan`/`aria-rowspan`; editability with `aria-readonly`; multi-selection capability with `aria-multiselectable`; sort state with `aria-sort`, on sortable columns only; hierarchy with `aria-level` and `aria-expanded`. ARIA output is always on. |
+| **1.3.2** Meaningful Sequence | Supports | DOM and reading order follow the visual order. Rows and columns are virtualized, but `aria-rowindex`/`aria-colindex` carry the absolute position in the dataset rather than the position in the DOM, so sequence is preserved for assistive technology. |
+| **1.3.3** Sensory Characteristics | Supports | No instruction or label relies solely on shape, size, or spatial location; interactive elements carry text or an ARIA name. |
+| **1.4.1** Use of Color | Supports | Colour is never the only signal. Sort direction is carried by an arrow glyph and by `aria-sort`; selection by `aria-selected` alongside the highlight; editability by `aria-readonly`; hierarchy by `aria-level` and `aria-expanded`. The `contrast-light` and `contrast-dark` themes are additionally colour-blind friendly; verified under protanopia / deuteranopia / tritanopia / achromatopsia emulation. |
+| **1.4.2** Audio Control | Not Applicable | The product produces no auto-playing audio. |
+| **2.1.1** Keyboard | Supports | Keyboard navigation is on by default (`keyNavigation: true`) and works in every configuration, with or without a selection module. The body, header and footer are each fully operable: arrow keys, `Home`/`End`, `Ctrl`+`Home`/`End`, `Page Up`/`Page Down` and `Tab` move the active cell (and the selection, when a selection module is enabled); `Shift` combinations extend the selection; with `editable`, `Enter`/`F2`/`Space` open editors and toggle boolean cells; `Escape` cancels; `Enter`/`Space` sort from the header; `Ctrl`+`Enter` and the arrow keys expand and collapse tree branches; `Ctrl`+`Z`/`Ctrl`+`Shift`+`Z` undo and redo. Column sizing and column and row order are also reachable without a pointer (see 2.5.7). |
+| **2.1.2** No Keyboard Trap | Supports | Focus is never trapped. Each zone is entered and left with `Tab`/`Shift`+`Tab` through hidden focus sentinels, in every configuration, including one with frozen columns (`leftSplit`/`rightSplit`), and `Escape` deactivates a header or footer filter control and returns focus to its cell. |
+| **2.1.4** Character Key Shortcuts | Supports | No shortcut uses a bare letter, digit or punctuation key. The only letter-based bindings are `Ctrl`+`Z` and `Ctrl`+`Shift`+`Z`; everything else uses arrows, `Enter`, `Escape`, `Tab`, `F2`, `Space`, `Delete`, `Home`/`End` or `Page Up`/`Page Down`. Handlers are additionally gated on the grid holding focus. |
+| **2.2.1** Timing Adjustable | Supports | The product sets no time limits: no session timeout, no auto-refresh and no polling. The header filter's 500 ms debounce delays applying a filter, not the user's input. |
+| **2.2.2** Pause, Stop, Hide | Supports | There is no auto-updating, moving, blinking or scrolling content. The only motion is hover and state transitions of 0.5 s or less. |
+| **2.3.1** Three Flashes or Below Threshold | Supports | The product contains no flashing content. |
+| **2.4.1** Bypass Blocks | Not Applicable | Applies at page level; bypass mechanisms belong to the host application. |
+| **2.4.2** Page Titled | Not Applicable | Page titles are the host application's responsibility. |
+| **2.4.3** Focus Order | Supports | A roving-tabindex model makes the whole cell surface a single tab stop, in every configuration, with one tab stop per zone, and the tab order follows the visual order: header → body → footer → next element on the page. When focus reaches an off-screen (virtualized) row or column, the grid scrolls it into view. |
+| **2.4.4** Link Purpose (In Context) | Not Applicable | The widget's own interface contains no links. Links placed in cells through `htmlEnable` or a column template are rendered as authored, so their text and purpose belong to the host application. |
+| **2.5.1** Pointer Gestures | Supports | No operation requires a multipoint or path-based gesture; touch handling reads a single touch point, and every drag operation has a non-drag alternative (see 2.5.7). |
+| **2.5.2** Pointer Cancellation | Supports | The primary actions complete on the up-event: sorting, cell and row selection, and tree expand/collapse are all bound to `click`, not to `mousedown`. |
+| **2.5.3** Label in Name | Supports | The sort `role="button"` wraps the visible header text and its accessible name is `Sort by `, so the visible label is contained in the name. Filter inputs and the tree toggle present no visible text label that could mismatch their accessible name. |
+| **2.5.4** Motion Actuation | Not Applicable | No functionality is operated by device motion or user motion. |
+| **3.1.1** Language of Page | Not Applicable | The document language (``) is set by the host application. |
+| **3.2.1** On Focus | Supports | Receiving focus never changes context. The date editor's calendar popup opens without moving focus away from the input. |
+| **3.2.2** On Input | Supports | Changing a value does not change context. Editing a cell or typing in a filter updates the grid in place, which is the documented purpose of those controls. |
+| **3.2.6** Consistent Help (2.2 only) | Not Applicable | The widget provides no help mechanism; this is a page-level concern. |
+| **3.3.1** Error Identification | Supports | Input errors are identified to the user: the numeric editor validates against the column's `min`/`max` bounds and marks an out-of-range value, and input that does not fit the column type is rejected at entry. Application-level validation and its error text are owned by the host application, through the cancelable `beforeEditEnd` event. |
+| **3.3.2** Labels or Instructions | Supports | In-place editors and header/footer filters take an accessible name from the column header text, so the user hears which column is being edited or filtered - for example `Filter ` and `Filter by date: `. |
+| **3.3.7** Redundant Entry (2.2 only) | Not Applicable | The product contains no multi-step process that re-requests previously entered information. |
+| **4.1.1** Parsing | Supports | Markup is generated through a virtual-DOM layer and element ids are machine-generated, so tags are well formed and attributes are not duplicated. |
+| **4.1.2** Name, Role, Value | Supports | Every structural and interactive part exposes a role, its states and an accessible name: the container (`grid`/`treegrid`, `aria-readonly`, `aria-multiselectable`), rows and cells (`row`, `gridcell`, `aria-selected`, `aria-readonly`), headers (`columnheader`, `aria-sort`), the tree toggle and sort affordance (`button` with `aria-label`), and editors and filters (named from the column header). `aria-sort` is present only on the headers of sortable columns, so no column reports a sort state it cannot have. |
+
+### Table 2: Success Criteria, Level AA
+
+| Criteria | Conformance level | Remarks and explanations |
+|---|---|---|
+| **1.2.4** Captions (Live) | Not Applicable | No live multimedia. |
+| **1.2.5** Audio Description (Prerecorded) | Not Applicable | No prerecorded video. |
+| **1.3.4** Orientation | Supports | Content is not restricted to a single display orientation. |
+| **1.3.5** Identify Input Purpose | Not Applicable | The product's editors collect application data defined by the integrator's columns, not the user's own personal information covered by the WCAG input-purpose list. |
+| **1.4.3** Contrast (Minimum) | Supports | The `contrast-light` and `contrast-dark` themes meet AA out of the box: body text is about 8.5:1 and 13.2:1 against the cell background, secondary and additional text about 7.3:1 and 10.2:1, and both themes raise the base font size to 16px and are colour-blind friendly. The built-in dark theme also meets AA for body text. Meeting the criterion requires selecting one of these themes - one supported method meets it. |
+| **1.4.4** Resize Text | Supports | Text can be resized to 200% without loss of content or functionality; the header, body and footer scale with it and the grid does not break. Typography and row geometry are token-driven (`--dhx-font-size-normal`, `--dhx-line-height-normal`, `--dhx-step-size`, `rowHeight`), and the contrast themes ship a 16px base. |
+| **1.4.5** Images of Text | Supports | All text is rendered as real text. Icons are font glyphs; the product uses no raster images. |
+| **1.4.10** Reflow | Supports | Content scrolls and remains operable at 400% zoom. As a data grid, two-dimensional layout is intrinsic to the content, for which the criterion permits two-dimensional scrolling. |
+| **1.4.11** Non-text Contrast | Supports | With a cell or range selection module, the active cell is marked by a 2px solid border in the theme primary colour - about 3.7:1 against the default light background and about 6.3:1 on `contrast-dark`, both above the 3:1 requirement. Header and footer cells add a 2px focus ring in the same colour. The contrast themes also raise the cell border contrast. |
+| **1.4.12** Text Spacing | Supports | Applying WCAG text-spacing overrides does not clip or overlap text in grid cells, column headers or footer summaries. |
+| **1.4.13** Content on Hover or Focus | Supports | Overflow tooltips are hoverable, persistent, and dismissible with `Esc` without moving the pointer. Their content repeats the cell's own text, so no information is available on hover alone, and they can be turned off entirely with `tooltip: false`. |
+| **2.4.5** Multiple Ways | Not Applicable | Applies to locating pages within a set of web pages; out of scope for a single embedded component (host-application concern). |
+| **2.4.6** Headings and Labels | Supports | Column headers carry descriptive accessible names, and every filter and in-place editor exposes an accessible name derived from its column. |
+| **2.4.7** Focus Visible | Supports | With a cell or range selection module, the active cell carries a persistent 2px solid border drawn in the theme primary colour, and no second outline is drawn over it. With row selection, and in a grid without a selection module, the focused cell carries a dashed focus outline. The keyboard focus location is therefore visible at all times, including during arrow-key navigation. Header and footer cells show a 2px focus ring, and filter inputs and cell editors an inset ring. |
+| **2.4.11** Focus Not Obscured (Minimum) (2.2 only) | Supports | A focused cell is never left behind a frozen zone: when the grid scrolls a cell into view it compensates for the left, right, top and bottom splits and for the header and footer height. |
+| **2.5.7** Dragging Movements (2.2 only) | Supports | Every drag operation has a non-drag alternative: range selection through `Shift`+arrows, `Ctrl`+`Shift`+arrows, `Shift`+`Home`/`End` and `Shift`+`Page Up`/`Page Down`; column sizing through `adjust` / `adjustColumnWidth`; and column and row order through the corresponding API. |
+| **2.5.8** Target Size (Minimum) (2.2 only) | Supports | Interactive targets meet 24x24 CSS px: the sort target is the whole header cell (40px tall by the column width), the boolean cell's hit area is the whole cell, and the column resizer grip and the range fill handle carry an enlarged hit area (visual size unchanged). |
+| **3.1.2** Language of Parts | Not Applicable | The widget does not mix languages within its content; language is host-owned. |
+| **3.2.3** Consistent Navigation | Not Applicable | Applies across a set of web pages; host-application concern. |
+| **3.2.4** Consistent Identification | Supports | Components with the same function are identified consistently across the header, body and footer zones - the same roles, the same naming pattern and the same key bindings. |
+| **3.3.3** Error Suggestion | Supports | Where a correction is known, it is applied: numeric input outside the column's `min`/`max` bounds is corrected to the nearest valid value, so a valid value is always produced. Suggestion text for application-level validation is provided by the host application, through `beforeEditEnd`. |
+| **3.3.4** Error Prevention (Legal, Financial, Data) | Supports | Actions that change or remove data are reversible and guarded: the History module provides undo and redo for edits, range clearing and clipboard operations, and every such action can additionally be gated by the host through the cancelable `before*` events - among them `beforeEditEnd`, `beforeKeyDown`, `beforeSort`, `beforeResizeStart`, `beforeRowDrag`/`beforeRowDrop` and `beforeColumnDrag`/`beforeColumnDrop`. |
+| **3.3.8** Accessible Authentication (Minimum) (2.2 only) | Not Applicable | The product performs no authentication. |
+| **4.1.3** Status Messages | Supports | A visually-hidden polite live region (`role="status"`, `aria-live="polite"`, `aria-atomic="true"`) announces dynamic changes without moving focus - sort direction changes, filter results with the matching row count, completed loads, and numeric-editor range corrections. The same region is available to the host application through the public [`announce()`](grid/api/grid_announce_method.md) method, and every built-in message is localizable through the `aria_*` locale keys. State that persists is additionally exposed on the elements themselves: sort direction through `aria-sort`, selection through `aria-selected`, dataset size through `aria-rowcount`/`aria-colcount`, and branch state through `aria-expanded`. |
+
+## Revised Section 508 report
+
+WCAG-mapped provisions are answered in the WCAG 2.x report above and referenced here. Chapter 4 (Hardware)
+is Not Applicable - DHTMLX Grid is a software component with no hardware or physical controls.
+
+### Chapter 3: Functional Performance Criteria
+
+| Criteria | Conformance level | Remarks and explanations |
+|---|---|---|
+| 302.1 Without Vision | Supports | Operable with a screen reader through the `grid`/`treegrid` model, the position and state attributes, the accessible names on editors and filters, and the keyboard model. See WCAG 1.3.1, 2.1.1, 4.1.2. |
+| 302.2 With Limited Vision | Supports | Zoom, text resize and reflow are supported, and AA contrast is met by the `contrast-light` / `contrast-dark` themes, which also raise the base font size to 16px. See WCAG 1.4.3, 1.4.4, 1.4.10, 1.4.11. |
+| 302.3 Without Perception of Color | Supports | No information is conveyed by colour alone: sort direction, selection, editability and hierarchy each carry a glyph or an ARIA state alongside the colour, and the `contrast-light` / `contrast-dark` themes are colour-blind friendly. See WCAG 1.4.1. |
+| 302.4 Without Hearing | Supports | No information is conveyed by sound. |
+| 302.5 With Limited Hearing | Supports | No information is conveyed by sound. |
+| 302.6 Without Speech | Supports | No speech input is required to operate the product. |
+| 302.7 With Limited Manipulation | Supports | Fully keyboard-operable; no path-based gesture is required, and pointer targets meet 24x24 px. See WCAG 2.1.1, 2.5.1, 2.5.7, 2.5.8. |
+| 302.8 With Limited Reach and Strength | Supports | Operable by keyboard; no physical reach, force or timing requirements. |
+| 302.9 With Limited Language, Cognitive, and Learning Abilities | Supports | Labels are consistent across zones, key bindings follow the conventions of a spreadsheet grid, and destructive actions are preventable through the cancelable `before*` events and reversible through the History module. See WCAG 3.2.4, 3.3.4. |
+
+### Chapter 5: Software
+
+| Criteria | Conformance level | Remarks and explanations |
+|---|---|---|
+| 501.1 Scope - Incorporation of WCAG 2.0 AA | See WCAG 2.x section | See the WCAG 2.x report above. |
+| 502 Interoperability with Assistive Technology | Not Applicable | Applies to non-web (platform) software. DHTMLX Grid is web content that exposes standard DOM and ARIA to the browser accessibility tree; interoperability is covered by the WCAG results (Clause 9 / 501.1). |
+| 503 Applications | Not Applicable | Applies to non-web platform software; the product is web content. |
+| 504.2 Content Creation or Editing | Not Applicable | DHTMLX Grid is not an authoring tool for web content - it edits tabular application data, not accessibility-relevant web content. |
+
+### Chapter 6: Support Documentation and Services
+
+| Criteria | Conformance level | Remarks and explanations |
+|---|---|---|
+| 602.2 Accessibility and Compatibility Features | Supports | The documentation describes the product's accessibility features: the [Accessibility](grid/accessibility.md) guide covers the WAI-ARIA model, the keyboard zones and shortcuts, keyboard navigation with and without the selection modules, the high-contrast themes and the focus model, together with the related configuration, the [`announce()`](grid/api/grid_announce_method.md) API and the localizable `aria_*` strings. |
+| 602.3 Electronic Support Documentation | Supports (see WCAG 2.x section) | The documentation site is delivered as web content and is maintained to meet WCAG 2.2 AA. |
+| 602.4 Alternate Formats for Non-Electronic Support Documentation | Not Applicable | Documentation is delivered electronically only; there are no non-electronic (print) support documents. |
+| 603.2 Information on Accessibility and Compatibility Features | Supports | The product's accessibility features are documented publicly in the [Accessibility](grid/accessibility.md) guide and can be provided by the support channel on request. |
+| 603.3 Accommodation of Communication Needs | Supports | Support is provided over a text-based email channel; users interact through their own assistive technology. |
+
+## EN 301 549 report
+
+Clause 9 (Web) maps directly to the WCAG 2.x report above and is the substantive assessment for this web
+product. Telephony, video, and hardware clauses (Clauses 6, 7, 8, 13) are Not Applicable.
+
+### Clause 4: Functional Performance Statements
+
+These mirror the Section 508 Chapter 3 results (same conclusions).
+
+| Criteria | Conformance level | Remarks and explanations |
+|---|---|---|
+| 4.2.1 Usage without vision | Supports | See 508 302.1 (screen-reader operable through the grid/treegrid model, position and state attributes, and the keyboard model). |
+| 4.2.2 Usage with limited vision | Supports | See 508 302.2 (AA contrast and a 16px base through the contrast themes; zoom and reflow supported). |
+| 4.2.3 Usage without perception of colour | Supports | See 508 302.3 (glyphs and ARIA state accompany every colour cue; the contrast themes are colour-blind friendly). |
+| 4.2.4 Usage without hearing | Supports | No information conveyed by sound. |
+| 4.2.5 Usage with limited hearing | Supports | No information conveyed by sound. |
+| 4.2.6 Usage with no or limited vocal capability | Supports | No speech input required. |
+| 4.2.7 Usage with limited manipulation or strength | Supports | See 508 302.7 (keyboard-operable, no gestures, primary targets 24x24 px or larger). |
+| 4.2.8 Usage with limited reach | Supports | No physical reach requirements (software component). |
+| 4.2.9 Minimize photosensitive seizure triggers | Supports | No flashing content (see WCAG 2.3.1). |
+| 4.2.10 Usage with limited cognition, language or learning | Supports | See 508 302.9 (consistent labels and key bindings; preventable and reversible actions). |
+| 4.2.11 Privacy | Supports | Accessibility features use the same interface as everyone else; there is no separate, less-private mode. |
+
+### Clause 5: Generic Requirements
+
+**Mostly Not Applicable.** Clause 5 addresses closed functionality and hardware-style requirements. DHTMLX
+Grid is open web software that works with the platform and browser assistive technology, so the
+closed-functionality sub-clauses, biometrics (5.3), operable parts (5.5), and locking/toggle-control status
+(5.6) are Not Applicable. Where a generic requirement is met through normal assistive-technology support, it
+is covered by Clause 9 (Web) and the WCAG results.
+
+### Clause 9: Web
+
+**See the WCAG 2.x section.** Clauses 9.1.1.1-9.4.1.3 map to the WCAG 2.2 Level A/AA results in Tables 1
+and 2 above.
+
+### Clause 11: Software
+
+**Not Applicable (assessed under Clause 9).** DHTMLX Grid is web content evaluated under Clause 9 (Web);
+it is not non-web software. The WCAG-mapped software provisions (11.1.1.1-11.4.1.3) are covered by the WCAG
+2.x results. 11.8.2 (Accessible content creation) is Not Applicable - the product is not an authoring tool.
+
+### Clause 12: Documentation and Support Services
+
+| Criteria | Conformance level | Remarks and explanations |
+|---|---|---|
+| 12.1.1 Accessibility and compatibility features | Supports | The [Accessibility](grid/accessibility.md) guide documents the product's accessibility features - the WAI-ARIA model, the keyboard zones and shortcuts, keyboard navigation with and without the selection modules, the high-contrast themes, the focus model, the [`announce()`](grid/api/grid_announce_method.md) API and the localizable `aria_*` strings. |
+| 12.1.2 Accessible documentation | Supports (see WCAG 2.x section) | The documentation site is delivered as web content and is maintained to meet WCAG 2.2 AA (see 508 602.3). |
+| 12.2.2 Information on accessibility and compatibility features | Supports | Accessibility features are documented publicly and can be surfaced by support on request. |
+| 12.2.3 Effective communication | Supports | Support is provided over a text-based email channel; users interact through their own assistive technology. |
+| 12.2.4 Accessible documentation | Supports (see WCAG 2.x section) | Same basis as 12.1.2 - the documentation site is maintained to meet WCAG 2.2 AA. |
+
+## Legal disclaimer
+
+This report is provided for informational purposes only and describes the accessibility of the named
+product version as of the report date. It is provided "as is", without warranty of any kind, and does not
+constitute a contractual commitment or guarantee. Accessibility support may change in subsequent releases,
+and results apply to the evaluated configuration. "VPAT" and "Voluntary Product Accessibility Template" are
+registered service marks of the Information Technology Industry Council (ITI).
diff --git a/docs/grid/api/grid_keynavigation_config.md b/docs/grid/api/grid_keynavigation_config.md
index 30eca6530..c2e615d29 100644
--- a/docs/grid/api/grid_keynavigation_config.md
+++ b/docs/grid/api/grid_keynavigation_config.md
@@ -19,7 +19,7 @@ const grid = new dhx.Grid("grid_container", {
],
data: dataset,
selection: "complex",
- editing: true,
+ editable: true,
keyNavigation: false
});
@@ -27,8 +27,8 @@ const grid = new dhx.Grid("grid_container", {
**Related sample**: [Grid. Key navigation](https://snippet.dhtmlx.com/y9kdk0md)
-You need to set the [selection](grid/api/grid_selection_config.md) and [editable](grid/api/grid_editable_config.md) properties in the configuration object of Grid to enable all available shortcut keys. Read the details in the [Key Navigation](grid/configuration.md#keyboard-navigation) article and in the [Grid accessibility](grid/accessibility.md) guide.
+Keyboard navigation works without any selection module: the navigation keys move the active cell, but do not select it. Set the [selection](grid/api/grid_selection_config.md) property to move the selection with the keyboard, and set the [editable](grid/api/grid_editable_config.md) property to edit cells from the keyboard. Read the details in the [Key Navigation](grid/configuration.md#keyboard-navigation) article and in the [Grid accessibility](grid/accessibility.md) guide.
-@changelog: added in v6.3; the keyboard navigation model was extended in v9.3.5
+@changelog: added in v6.3; the keyboard navigation model was extended in v9.3.5; navigation and editing without a selection module were added in v9.3.12
[comment]: # (@related: grid/initialization.md#initialize-grid grid/configuration.md#keyboard-navigation)
diff --git a/docs/grid/configuration.md b/docs/grid/configuration.md
index 59a040761..8beb3bda3 100644
--- a/docs/grid/configuration.md
+++ b/docs/grid/configuration.md
@@ -3166,25 +3166,75 @@ DHTMLX Grid provides the keyboard navigation that will help you manipulate your
### Default shortcut keys
+Keyboard navigation is enabled by default and does not require any selection module. The whole cell surface is a single tab stop: Tab enters Grid, the keys below move the active cell and scroll it into view, and Tab leaves Grid at its first or last cell. Without a selection module, moving the active cell does not select it and does not fire selection events.
+
The navigation shortcut keys and keys combinations that Grid enables by default are provided below:
- | PageUp |
- scrolls Grid up to the height of the visible content (without change of the selected cell) |
+ ArrowUp |
+ moves the active cell to the previous vertical cell |
- | PageDown |
- scrolls Grid down to the height of the visible content (without change of the selected cell) |
+ ArrowDown |
+ moves the active cell to the next vertical cell |
+
+
+ | ArrowLeft |
+ moves the active cell to the previous horizontal cell |
+
+
+ | ArrowRight |
+ moves the active cell to the next horizontal cell |
+
+
+ | Ctrl+ArrowUp |
+ moves the active cell to the first vertical cell |
+
+
+ | Ctrl+ArrowDown |
+ moves the active cell to the last vertical cell |
+
+
+ | Ctrl+ArrowLeft |
+ moves the active cell to the first horizontal cell |
+
+
+ | Ctrl+ArrowRight |
+ moves the active cell to the last horizontal cell |
| Home |
- navigates to the beginning of the Grid content (without change of the selected cell) |
+ moves the active cell to the first column of the current row |
| End |
- navigates to the end of the Grid content (without change of the selected cell) |
+ moves the active cell to the last column of the current row |
+
+
+ | Ctrl+Home |
+ moves the active cell to the first cell of Grid |
+
+
+ | Ctrl+End |
+ moves the active cell to the last cell of Grid |
+
+
+ | PageUp |
+ moves the active cell up by the height of the visible content |
+
+
+ | PageDown |
+ moves the active cell down by the height of the visible content |
+
+
+ | Tab |
+ moves the active cell to the next horizontal cell or the first cell of the next row; from the last cell of Grid, moves the focus out of Grid |
+
+
+ | Shift+Tab |
+ moves the active cell to the previous horizontal cell or the last cell of the previous row; from the first cell of Grid, moves the focus out of Grid |
| Ctrl+Enter |
@@ -3207,9 +3257,11 @@ const grid = new dhx.Grid("grid_container", {
**Related sample**: [Grid. Key navigation](https://snippet.dhtmlx.com/y9kdk0md)
-### Shortcut keys for moving selection between cells
+For the accessibility aspects of keyboard navigation, see the [Grid accessibility](grid/accessibility.md#keyboard-navigation) guide.
+
+### Shortcut keys for moving selection between cells {#shortcut-keys-for-moving-selection-between-cells}
-In case you want to enable the shortcut keys that allow moving the selection between cells, you need to specify the [`selection`](grid/api/grid_selection_config.md) property for Grid.
+In case you want the default shortcut keys to move the selection together with the active cell, you need to specify the [`selection`](grid/api/grid_selection_config.md) property for Grid.
~~~jsx {6}
const grid = new dhx.Grid("grid_container", {
@@ -3224,52 +3276,7 @@ const grid = new dhx.Grid("grid_container", {
**Related sample**: [Grid. Key navigation](https://snippet.dhtmlx.com/y9kdk0md)
-The list of the shortcut keys and their combinations used for moving selection between cells is the following:
-
-
-
-
- | ArrowUp |
- moves selection to the previous vertical cell |
-
-
- | ArrowDown |
- moves selection to the next vertical cell |
-
-
- | ArrowLeft |
- moves selection to the previous horizontal cell |
-
-
- | ArrowRight |
- moves selection to the next horizontal cell |
-
-
- | Ctrl+ArrowUp |
- moves selection to the first vertical cell |
-
-
- | Ctrl+ArrowDown |
- moves selection to the last vertical cell |
-
-
- | Ctrl+ArrowLeft |
- moves selection to the first horizontal cell |
-
-
- | Ctrl+ArrowRight |
- moves selection to the last horizontal cell |
-
-
- | Tab |
- moves selection to the next horizontal cell or the first cell of the next row |
-
-
- | Shift+Tab |
- moves selection to the previous horizontal cell or to the first cell of the previous row |
-
-
-
+With the `selection` property specified, the arrow keys, their combinations with Ctrl, Home/End, PageUp/PageDown and Tab/Shift+Tab listed in the [Default shortcut keys](#default-shortcut-keys) section move the selection between cells.
The combinations of the shortcut keys listed below do not work when the `selection` property is set to *"complex"*. Use another mode (*"cell" or "row"*) in case you want to activate these navigation keys:
@@ -3312,7 +3319,7 @@ The combinations of the shortcut keys listed below do not work when the `selecti
### Shortcut keys for editing
-It is possible to use shortcut keys for editing a cell in Grid by setting the [`editable:true`](grid/api/grid_editable_config.md) property in the configuration object of Grid.
+It is possible to use shortcut keys for editing a cell in Grid by setting the [`editable:true`](grid/api/grid_editable_config.md) property in the configuration object of Grid. No selection module is required: the editor opens in the active cell.
~~~jsx {7}
const grid = new dhx.Grid("grid_container", {
diff --git a/sidebars.js b/sidebars.js
index 8c31662ab..f2b35a3f5 100644
--- a/sidebars.js
+++ b/sidebars.js
@@ -2989,6 +2989,7 @@ module.exports = {
"grid/usage_history",
"grid/customization",
"grid/accessibility",
+ "grid/accessibility_conformance_report",
"grid/events"
],
},