From 98e23e4f2bc757cb17d38546b18727f725e60537 Mon Sep 17 00:00:00 2001 From: Masha_Rudenko Date: Mon, 2 Nov 2026 14:47:24 +0300 Subject: [PATCH 1/2] [add] github accessibility page - .github/ACCESSIBILITY.md: standalone copy of the Accessibility guide for the repository Accessibility tab - github takes .github/ first, so the tab no longer depends on docs/accessibility.md - frontmatter removed, doc links point to docs.dhtmlx.com, images to static/img, admonitions as github alerts --- .github/ACCESSIBILITY.md | 443 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 443 insertions(+) create mode 100644 .github/ACCESSIBILITY.md diff --git a/.github/ACCESSIBILITY.md b/.github/ACCESSIBILITY.md new file mode 100644 index 00000000..7d43ba74 --- /dev/null +++ b/.github/ACCESSIBILITY.md @@ -0,0 +1,443 @@ +# Accessibility in DHTMLX Spreadsheet + +This guide is for developers who embed DHTMLX Spreadsheet in an application that has to meet accessibility requirements. Use it to check the component against your checklist and to configure it for keyboard, screen reader and high-contrast users. + +The Spreadsheet renders WAI-ARIA roles and states as part of its markup. The keyboard focus stays on the active cell, and the toolbar, the menu bar and the sheet tabs are one tab stop each. Changes that have no element of their own, such as a refused edit or a search result, go to a live region that screen readers read aloud. + +> [!NOTE] +> **Target conformance** +> +> DHTMLX Spreadsheet 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). +> +> Conformance is reported criterion by criterion for DHTMLX Spreadsheet 6.0.4. The detailed **Accessibility Conformance Report (VPAT® 2.5)** is available: [Accessibility Conformance Report](https://docs.dhtmlx.com/spreadsheet/accessibility_conformance_report/). + +## Capabilities + +| Area | Support | +| ---- | ------- | +| Keyboard operation | Every command on the cells has a key. The toolbar, the menu bar and the sheet tabs are single tab stops navigated with the arrow keys. The column width, the row height and the column filter have context menu commands, so they don't require dragging or a click on an icon | +| WAI-ARIA semantics | The cells are a `grid` with `columnheader`, `rowheader` and `gridcell` elements. The roles are always rendered | +| Focus model | The keyboard focus is on the active cell. Tab enters the sheet on the active cell and leaves it from the last and the first cell. Ctrl + F6 moves the focus between the menu, the toolbar, the sheet and the sheet tabs | +| Selection model | The active cell, a range and several ranges are exposed through `aria-selected`, and the extent of a range is announced. The selection can be turned off with the [`selection`](https://docs.dhtmlx.com/spreadsheet/api/spreadsheet_selection_config/) option | +| Read-only mode | The sheet can be navigated, selected, copied and searched; edits are refused and announced, and the context menu is not available | +| Screen readers | Tested with NVDA, JAWS and VoiceOver | +| Visual accessibility | The `contrast-light` and `contrast-dark` themes, a visible focus indicator in every theme, and cues that don't depend on color | +| Text resize and zoom | The layout stays operable at 200% and 400% zoom and with text spacing overrides | +| Customization | The public [`announce()`](https://docs.dhtmlx.com/spreadsheet/api/spreadsheet_announce_method/) method for your own messages, and translatable `aria_*` locale strings for every built-in name and announcement | +| Standards | WCAG 2.2 AA, Section 508, EN 301 549 | + +## Covered areas + +This guide covers the Spreadsheet widget: + +- the cells, the column and row headers, merged cells and frozen rows and columns +- the selection: the active cell, ranges and several ranges +- the formula bar and the cell editors, including the editor of a cell with a list of values +- the toolbar with its color and border popups, the menu bar and the context menus +- the sheet tabs +- sorting, filtering, search, data validation, links in cells, import and export +- the themes and the focus indicator + +The accessibility of the final page also depends on the host application. See [Host-page responsibilities](#host-page-responsibilities). + +## WAI-ARIA support + +The Spreadsheet adds WAI-ARIA roles and attributes to its markup automatically, and you can't turn them off. Each part of the widget has its own role and name, and the names come from the [locale](#localization). + +### Spreadsheet container + +The parts of the Spreadsheet are separate named controls: + +| Part | Role / attribute | Accessible name | +| ---- | ---------------- | --------------- | +| Menu bar | `role="menubar"` + `aria-label` | "Main" | +| Toolbar | `role="toolbar"` + `aria-label` | "Formatting" | +| Formula bar | `aria-label` on the input | "Formula bar, B7", with the address of the active cell | +| Cells | `role="grid"` + `aria-label` | "Spreadsheet" | +| Sheet tabs | `role="toolbar"` + `aria-label` | "Sheets" | +| Live region | `role="status"`, `aria-live="polite"`, `aria-atomic="true"` | visually hidden, placed next to the grid outside `role="grid"` | + +The root element of the Spreadsheet has no landmark role, so you can place it inside the landmark that fits your page. + +### Cell surface + +The following attributes describe the cells as a whole. The `.dhx_grid-content` element carries them: + +| Selector | Role / attribute | Purpose | +| -------- | ---------------- | ------- | +| `.dhx_grid-content` | `role="grid"` | The interactive grid of cells | +| `.dhx_grid-content` | `aria-label` | "Spreadsheet", from the `aria_grid` locale key | +| `.dhx_grid-content` | `aria-rowcount` | The number of rows of the sheet plus the header row | +| `.dhx_grid-content` | `aria-colcount` | The number of visible columns plus the column of row numbers | +| `.dhx_grid-content` | `aria-readonly` | `"true"` in the [read-only mode](https://docs.dhtmlx.com/spreadsheet/api/spreadsheet_readonly_config/) and while the [selection](https://docs.dhtmlx.com/spreadsheet/api/spreadsheet_selection_config/) is turned off | +| `.dhx_grid-content` | `aria-multiselectable` | `"true"`; `"false"` while the selection is turned off | + +### Rows and cells + +The following table lists the roles and the position and state attributes of the rows and the cells: + +| Selector | Role / attribute | Purpose | +| -------- | ---------------- | ------- | +| Row | `role="row"` + `aria-rowindex` | A row of the sheet. Row 1 of the sheet has `aria-rowindex="2"`, since the column header is the first row | +| Cell | `role="gridcell"` + `aria-colindex` | A cell. Column A has `aria-colindex="2"`, since the row numbers are the first column | +| Row number | `role="rowheader"` | The header of the row | +| Cell | `aria-selected` | `"true"` on the active cell and on every cell of the selected ranges | +| Cell | `aria-readonly` | `"true"` in the read-only mode, while the [selection](https://docs.dhtmlx.com/spreadsheet/api/spreadsheet_selection_config/) is turned off, and on [locked cells](https://docs.dhtmlx.com/spreadsheet/work_with_cells/#locking-cells) | +| Cell | `tabindex` | `"0"` on the active cell and `"-1"` on the other cells, so the cells are one tab stop | +| Active cell | DOM focus | The keyboard focus is on the active cell itself, not on a separate input. While the cell is edited, the focus is on the cell editor | +| Merged cell | `aria-colspan` / `aria-rowspan` | The number of columns or rows that the merged cell spans. The cells it covers are hidden with `aria-hidden="true"` | +| Link in a cell | `` with `target="_blank"` and `rel="noopener noreferrer"` | A link with the `http`, `https`, `mailto`, `ftp` or `tel` scheme | + +A cell also contains visually hidden text, which screen readers read together with the value: + +| Hidden text | When | +| ----------- | ---- | +| The cell address, for example, "B7" | On the active cell and on every cell of a selected range. Screen readers read the address before the value | +| "link" | On a selected cell with a link. Alt + Enter opens the link | +| "locked" | On a selected locked cell | +| A description of the formula error, for example, "Reference error. Check the cell references" | On a cell with a formula error | +| "Invalid value. Choose a value from the list" | On a cell whose value is not in its [list of values](https://docs.dhtmlx.com/spreadsheet/work_with_cells/#using-drop-down-lists-in-cells) | +| "Filter" / "Filter applied" | On a cell with the filter icon | + +### Column and row headers + +| Selector | Role / attribute | Purpose | +| -------- | ---------------- | ------- | +| Column letter | `role="columnheader"` + `aria-colindex` | The header of the column | +| Select-all corner | `role="columnheader"` | Named "Select all" | +| Row number | `role="rowheader"` | The header of the row | +| Column menu icon, icons of hidden rows and columns | `aria-hidden="true"` | Decorative. The commands are in the context menu | + +The headers are not tab stops. A click on a column letter, a row number or the corner selects the rows or columns and returns the focus to the active cell. + +### Formula bar and editors + +| Selector | Role / attribute | Purpose | +| -------- | ---------------- | ------- | +| Formula bar input | `aria-label` | "Formula bar, B7", with the address of the active cell. The input is `readonly` on a locked cell, so its value can still be read. While the selection is turned off, the formula bar is empty and locked | +| Cell editor input | `aria-label` | "Cell editor, B7" | +| Editor of a cell with a list of values | `role="combobox"`, `aria-controls`, `aria-expanded`, `aria-activedescendant` | The list of values is a `listbox` of `option` elements, and the highlighted option is `aria-selected` | +| Editor with an invalid value | `aria-invalid="true"` | The saved value of the cell is not in its list of values. The attribute is updated after the value is saved, not while the user types | +| Close icon of the formula help | `role="button"` + `aria-label` | "Close formula help" | + +### Toolbar and menus + +| Selector | Role / attribute | Purpose | +| -------- | ---------------- | ------- | +| Toolbar | `role="toolbar"` + `aria-label` | "Formatting"; the toolbars of the Border popup, the search bar and the link popup are named "Borders", "Search" and "Link" | +| Toolbar button | `aria-label` | The value of the button. An icon button is named by its tooltip, for example, "Bold (ctrl+b)". The icons are hidden with `aria-hidden="true"` | +| Bold, Italic, Underline, Strikethrough, Lock, Filter | `aria-pressed` | Whether the formatting or the filter is on | +| Button that opens a dropdown | `aria-haspopup="menu"`, `aria-expanded` | The dropdown is a `menu` named after its button | +| Alignment, text wrapping, number formats | `role="menuitemradio"` + `aria-checked` | One option of an exclusive set | +| Text color, Background color, Border color | `aria-label` | The name of the control and of the current color, for example, "Text color: dark gray" | +| Color palette | `role="grid"` of `gridcell` elements | The grid is named "Color palette". Each color cell is named after its color, and the chosen one has `aria-selected="true"` | +| Border style list | `role="listbox"` of `option` elements | The options are named "Thin line", "Medium line", "Thick line", "Dashed line", "Dotted line", "Double line" | +| Menu bar | `role="menubar"` + `aria-label` | "Main". Its items open popups with `role="menu"`. In the popups, the formatting items have `role="menuitemcheckbox"`, and the alignment, text wrapping and number format items have `role="menuitemradio"`. Both report their state with `aria-checked` | +| Context menus | `role="menu"` + `aria-label` | "Cell" for the cells and "Sheet" for the sheet tabs | + +### Sheet tabs + +| Selector | Role / attribute | Purpose | +| -------- | ---------------- | ------- | +| Sheet tab bar | `role="toolbar"` + `aria-label` | "Sheets" | +| Sheet tab | `button` + `aria-pressed` | The tab is named after its sheet. The tab of the active sheet has `aria-pressed="true"` | +| Add sheet button | `aria-label` | "Add sheet" | + +### Dialogs + +| Selector | Role / attribute | Purpose | +| -------- | ---------------- | ------- | +| Column width and Row height dialogs | `role="dialog"`, `aria-modal="true"`, `aria-label` | Named by the dialog title. The input is labeled "Width in pixels" / "Height in pixels" | +| Search bar | `role="dialog"` + `aria-label` | Named "Search". The search input is labeled "Search", and the buttons are named "Previous match", "Next match" and "Close search" | +| Insert link, Data validation | `role="dialog"` + `aria-label` | Named by the dialog title | +| Alerts | `role="alertdialog"`, `aria-modal="true"`, `aria-labelledby`, `aria-describedby` | Named by the alert header and described by its text | + +### Hidden and decorative elements + +The Spreadsheet hides decorative parts from assistive technology with `aria-hidden="true"`. These are the lock, filter and column menu icons, the icons of hidden rows and columns, and the select-all icon. The layer that draws the selection, the copy and search highlights and the fill handle is hidden as well. So are the colored copy of the formula in the formula bar and the cells covered by a merged cell. Layout wrappers have `role="presentation"`. The focus sentinels before and after the grid only pass the focus to the active cell. + +## Selection and editing model + +The DOM focus is on the active cell itself, so a screen reader reads the cell, not a separate input. When the active cell moves, the screen reader reads the address of the new cell first, then its value and its hidden descriptions. When the user selects a range with the keyboard or the mouse, the screen reader announces the extent of the range once the selection stops changing. A cell shared by several ranges is counted once, and the cells of hidden rows and columns are counted. Nothing is announced while a cell is edited. When a range is reduced to the active cell, the address of the cell is announced. + +| Situation | What the screen reader gets | +| --------- | --------------------------- | +| The active cell moves | The cell with its address, value and descriptions, for example, "B7, 120, locked" | +| A range is selected | "B2 to D7, 18 cells" | +| Several ranges are selected with Ctrl | "B2 to B4, D2 to D4, 6 cells" | +| The editor opens with Enter, F2 or typing | The editor input named "Cell editor, B7" | +| The editor of a cell with a list of values opens | An expanded combobox. After ↑ or ↓, the highlighted option of the list is read | +| The edit is saved | New formula errors in the edited cells and in the cells that depend on them, and invalid values in the edited cells, are announced | +| An edit of a locked cell is refused | "The cell is locked" | +| An editing key is pressed in the read-only mode | "The sheet is read-only" | + +Enter, F2 or typing opens the editor. Enter saves the value and moves down, Tab saves it and moves right, and Esc cancels the edit. + +## Keyboard navigation + +The keyboard works as soon as the Spreadsheet is on the page; no configuration is needed. The tables below summarize the keyboard model. See [Hot keys list](https://docs.dhtmlx.com/spreadsheet/hotkeys/) for the complete set of shortcuts. + +![The Horizontal align dropdown of the toolbar opened with the Down arrow key, with the focus on its first item](../static/img/accessibility/toolbar_dropdown_focus.png) + +### Cells + +| Keys | Action | +| ---- | ------ | +| Arrow keys | Move the active cell. The active cell stops at the first and last visible row and column | +| Shift + arrow keys | Extend the selected range | +| Home / End | Move to the first or the last visible cell of the row | +| Ctrl + arrow keys, Ctrl + Home / End | Move to the edge of the sheet | +| Tab / Shift + Tab | Move right or left within the row. From the last or the first cell of the sheet, move the focus out of the cells to the next or the previous part of the page, for example, the sheet tabs or the formula bar | +| Enter, F2 | Open the editor | +| Esc | Close the editor without saving | +| Ctrl + Space / Shift + Space | Select the column or the row | +| Ctrl + Shift + 9 / 0 | Show the hidden rows or columns inside the selected range | +| Alt + Enter | Open the link of the active cell | +| Shift + F10 or the Menu key | Open the context menu with the commands for the cell, or for the column after Ctrl + Space | +| Alt + ↑ / ↓, Ctrl + Alt + Page Down / Page Up | Switch to the next or the previous sheet | + +### Moving between the parts + +| Keys | Action | +| ---- | ------ | +| Ctrl + F6 / Ctrl + Shift + F6 | Move the focus to the next or the previous part: the menu, the toolbar, the sheet, the sheet tabs. The formula bar and hidden parts are skipped. An open edit is saved first | +| Tab / Shift + Tab | Move the focus to the next or the previous part in the page tab order. Each bar is one tab stop, and the focus lands on the control used last | + +### Toolbar, menu bar and sheet tabs + +| Keys | Action | +| ---- | ------ | +| ← / →, Home / End | Move between the controls of the bar | +| Enter / Space | Press the control: run the command, open the dropdown or switch to the sheet | +| ↓ | Open the dropdown and move the focus to its first item | +| ↑ / ↓ | Move between the items of an open dropdown or menu | +| → / ← | Open or close a submenu | +| Esc | Close the dropdown or the menu and return the focus to its control | + +### Popups and dialogs + +| Keys | Action | +| ---- | ------ | +| Arrow keys, Home / End | Move between the colors of the color palette | +| Enter | Apply the color, the border, or the size in the Column width and Row height dialogs | +| Esc | Close the popup, the dialog or the search bar and return the focus to the control or the cell that opened it. In the custom color mode, return to the palette. In a color or style popup opened from the Border popup, close it and return the focus to its button in the Border popup | +| Tab / Shift + Tab | Move between the controls of a dialog or of the custom color mode. In a color popup or the Border popup, close it and return the focus to its toolbar button | +| ↑ / ↓, Enter | Move through the list of values of a cell and choose a value | + +> [!NOTE] +> Pointer-only actions have keyboard alternatives. The *Column width* and *Row height* commands of the context menu set an exact size without dragging, and the *Open filter* command opens a filter without a click on its icon. + +## Assistive technology + +The DHTMLX team tests the Spreadsheet with the following screen readers: + +| Screen reader | Browser | Platform | +| ------------- | ------- | -------- | +| NVDA | Firefox | Windows | +| JAWS | Chrome | Windows | +| VoiceOver | Safari | macOS | + +Screen readers get each state from the element it belongs to: + +| State | Exposed through | Read on | +| ----- | --------------- | ------- | +| Position | `aria-rowindex`, `aria-colindex`, and the cell address in the cell text | Each cell. The address is in the text of the active cell and of the cells of the selected ranges | +| Selection | `aria-selected` | The active cell and the cells of the selected ranges | +| Editability | `aria-readonly` | The grid and the cells in the read-only mode and while the selection is turned off, and locked cells | +| Merged cells | `aria-colspan`, `aria-rowspan` | The merged cell | +| Row headers | `role="rowheader"` | The row numbers | +| Toggle state | `aria-pressed` | The Bold, Italic, Underline, Strikethrough, Lock and Filter buttons and the sheet tabs | +| Checked state | `aria-checked` | The formatting items of the menu bar, and the alignment, text wrapping and number format items | +| Errors and invalid values | Hidden text in the cell, `aria-invalid` | The cell and its editor | +| Links | `` and the hidden text "link" | The cell with a link | + +## High contrast and focus + +### Themes + +The Spreadsheet has four built-in themes: `light` (default), `dark`, `contrast-light` and `contrast-dark`. The `contrast-light` and `contrast-dark` themes meet the WCAG AA contrast requirements for text. Switch a theme with the `dhx.setTheme()` method or with the `data-dhx-theme` attribute: + +~~~jsx +dhx.setTheme("contrast-light"); // or "contrast-dark" +~~~ + +See the [Built-in themes](https://docs.dhtmlx.com/spreadsheet/themes/) article for the details. + +In the light themes, the colors that mark the cell references of a formula have a contrast of at least 4.5:1. + +The `contrast-light` theme draws dark text and borders on a white background. In the Spreadsheet below, the context menu of a cell with the filter icon is opened with the keyboard. Its focused command, [*Open filter*](https://docs.dhtmlx.com/spreadsheet/filtering_data/#opening-a-filter-with-the-keyboard), is marked by a dashed outline, and the active cell is marked by a solid border in the primary color of the theme: + +![Spreadsheet in the contrast-light theme](../static/img/accessibility/spreadsheet_contrast_light.png) + +The `contrast-dark` theme draws light text and borders on a dark background. When the focus is on a toolbar control, the control is marked by a focus ring in the `--dhx-spreadsheet-focus-color` color, which is lighter than the primary color of the active cell border in the dark themes: + +![Spreadsheet in the contrast-dark theme](../static/img/accessibility/spreadsheet_contrast_dark.png) + +### Focus indicator + +The keyboard focus is shown in every theme: + +- the active cell has a 2px solid border in the primary color of the theme +- a cell and the cell editor that have the keyboard focus get a 2px outline in the primary color of the theme +- the formula bar and the controls of the toolbar, the menu bar, the sheet tabs, the Border popup, the link popup and the search bar get a 2px outline in the color of the `--dhx-spreadsheet-focus-color` variable +- in the color palette, the border style list, the dropdowns of the toolbar and the menu bar, and the context menus, the focused item gets a 1px dashed outline in the `--dhx-color-focused` color +- in the list editor of a cell, the focus stays in the editor, and the current item of the list is highlighted with a background color + +The `--dhx-spreadsheet-focus-color` variable is lighter than the primary color in the dark themes and can be redefined in a [custom theme](https://docs.dhtmlx.com/spreadsheet/themes/custom_theme/). The contrast of each indicator in each theme is given in the [Accessibility Conformance Report](https://docs.dhtmlx.com/spreadsheet/accessibility_conformance_report/). + +### Color and zoom + +- **Color is not the only signal.** The active cell and the selection have a border and a fill, an invalid value has a marker and a hidden description, and the formatting buttons report their state through `aria-pressed`. The color buttons have the name of the color in their accessible name. +- **Zoom and reflow.** The Spreadsheet stays operable at 200% and 400% zoom. The cells scroll in two directions, and the toolbar, the menu bar and the sheet tabs fit a width of 320 CSS px. +- **Text spacing.** With the WCAG text spacing overrides, no control label is cut, and the sheet tab bar scrolls when the tabs grow. +- **Scrolling into view.** The active cell is scrolled into view next to the frozen rows and columns. + +## Status announcements + +The Spreadsheet announces the changes that have no element of their own through a polite live region, so the screen reader finishes the current sentence first: + +| Event | Announced text | Locale key | +| ----- | -------------- | ---------- | +| A range is selected | "B2 to D7, 18 cells" | `aria_selectedRange`, `aria_rangeExtent`, `aria_rangeSeparator` | +| An edit causes a formula error or an invalid value | "B7: Reference error. Check the cell references" | `aria_cellMessage` | +| An edit causes several errors / invalid values | "3 new errors. B7: ..." / "3 invalid values. B7: ..." | `aria_newErrors`, `aria_invalidValues` | +| An edit of a locked cell / range is refused | "The cell is locked" / "Locked cells were not changed" | `aria_lockedCell`, `aria_lockedCells` | +| An editing key is pressed in the read-only mode | "The sheet is read-only" | `aria_readonlySheet` | +| The search text is typed | "Results: 5. 1 of 5, B2" or "No results" | `aria_searchResults`, `aria_searchMatch`, `aria_searchNoResults` | +| The next or previous match is shown | "2 of 5, B7" | `aria_searchMatch` | +| An Excel file is exported | "Exporting the file", "The file is exported" | `aria_exportStarted`, `aria_exportDone` | +| A file chosen in the file dialog is imported | "Importing the file", "The file is imported" | `aria_importStarted`, `aria_importDone` | +| The Column width / Row height command is applied | "Column width set to 120 pixels" | `aria_columnWidthSet`, `aria_rowHeightSet` | +| Ctrl + Shift + 9 / 0 finds nothing to show | "No hidden rows in the selection" | `aria_noHiddenRows`, `aria_noHiddenCols` | + +To announce the result of your own command, call the [`announce()`](https://docs.dhtmlx.com/spreadsheet/api/spreadsheet_announce_method/) method: + +~~~jsx +spreadsheet.announce("The report is saved"); +~~~ + +## Localization + +The accessible names, the cell descriptions and the announcements are stored in the `spreadsheet` locale as keys with the `aria_` prefix, next to the interface labels. Translate them with the `dhx.i18n.setLocale()` method before the Spreadsheet is initialized: + +~~~jsx +dhx.i18n.setLocale("spreadsheet", { + // other keys of the locale + aria_grid: "Tabelle", + aria_cellEditor: "Zelleneditor, {cell}", + aria_readonlySheet: "Das Blatt ist schreibgeschützt", + aria_selectedRange: "{range}, {count} Zellen", + aria_rangeExtent: "{start} bis {end}" +}); + +const spreadsheet = new dhx.Spreadsheet("spreadsheet_container"); +~~~ + +The parts in curly braces, such as `{cell}` or `{count}`, are replaced with the values and must be kept in the translated strings. The names of the colors and of the alert buttons come from the `colorpicker` and `message` locales. See [Localization](https://docs.dhtmlx.com/spreadsheet/localization/#default-locale) for the full list of keys and [Localizing built-in widgets](https://docs.dhtmlx.com/spreadsheet/localization/#localizing-built-in-widgets) for the other locales. + +## Configuration recipes + +### Accessible default setup + +The Spreadsheet needs no configuration for the keyboard and the WAI-ARIA output. To meet the WCAG AA contrast requirements for text, select a contrast theme. See [Built-in themes](https://docs.dhtmlx.com/spreadsheet/themes/) for the other ways to set a theme: + +~~~jsx +const spreadsheet = new dhx.Spreadsheet("spreadsheet_container", { + // the keyboard navigation and the WAI-ARIA output need no configuration +}); +spreadsheet.parse(data); + +dhx.setTheme("contrast-light"); // or "contrast-dark" +~~~ + +### Read-only setup + +Use the [`readonly`](https://docs.dhtmlx.com/spreadsheet/api/spreadsheet_readonly_config/) option to show data that users can read and copy but not change. Keyboard and screen reader users can still move through the cells: + +~~~jsx +const spreadsheet = new dhx.Spreadsheet("spreadsheet_container", { + readonly: true +}); +spreadsheet.parse(data); +~~~ + +To show the data without an active cell and without selection, add [`selection: false`](https://docs.dhtmlx.com/spreadsheet/api/spreadsheet_selection_config/). The grid then becomes one tab stop that the keyboard passes through. + +### Translated accessibility strings + +Screen readers read the accessibility strings from four locales: `spreadsheet` holds the names, cell descriptions and announcements, `colorpicker` holds the color names, `message` holds the names of the alert buttons, and `grid` holds the announcement of the number of loaded rows. Set all four before you create the Spreadsheet. See [Localizing built-in widgets](https://docs.dhtmlx.com/spreadsheet/localization/#localizing-built-in-widgets) for the keys: + +~~~jsx +const deSpreadsheet = { + // other keys of the locale + aria_grid: "Tabelle", + aria_readonlySheet: "Das Blatt ist schreibgeschützt" +}; +const deColorpicker = { + aria_palette: "Farbpalette", + aria_colorRed: "rot" +}; +const deMessage = { + aria_confirm: "Bestätigen" +}; +const deGrid = { + aria_rowsLoaded: "{count} Zeilen geladen" +}; + +dhx.i18n.setLocale("spreadsheet", deSpreadsheet); +dhx.i18n.setLocale("colorpicker", deColorpicker); +dhx.i18n.setLocale("message", deMessage); +dhx.i18n.setLocale("grid", deGrid); + +const spreadsheet = new dhx.Spreadsheet("spreadsheet_container"); +~~~ + +### Announcing a custom command + +When your own command changes the data, tell screen reader users about the result with the [`announce()`](https://docs.dhtmlx.com/spreadsheet/api/spreadsheet_announce_method/) method. The example adds a [menu](https://docs.dhtmlx.com/spreadsheet/customization/#menu) command that clears the active sheet: + +~~~jsx +const spreadsheet = new dhx.Spreadsheet("spreadsheet_container"); + +spreadsheet.menu.data.add({ id: "clear-sheet", value: "Clear sheet" }); + +spreadsheet.menu.events.on("click", function (id) { + if (id === "clear-sheet") { + spreadsheet.sheets.clear(); + spreadsheet.announce("The sheet is cleared"); + } +}); +~~~ + +## Host-page responsibilities + +A few requirements live at the page level, not inside the component. Make sure that the host page: + +- sets the document language, for example, ``, and a page title +- puts a heading above the Spreadsheet and places it inside a landmark, for example, `
` +- provides a skip link, if the Spreadsheet is preceded by a long navigation +- gives a second signal, such as text or an icon, to any state that you mark with a cell color, since the colors of the cell styles are part of your data +- checks the contrast of the colors that you set in the cell styles and in a custom theme + +## Testing and methodology + +The DHTMLX team validates the accessibility of Spreadsheet 6.0.4 against the component source and in the browser: + +1. **Automated testing** with [axe-core](https://github.com/dequelabs/axe-core) in the `light`, `dark`, `contrast-light` and `contrast-dark` themes, with the search bar, the list editor, the dialogs and an alert open. +2. **Manual review** of the source: the roles, states and names of each part, the keyboard handlers and the focus regions, and the theme tokens with their contrast ratios. +3. **Manual testing**: keyboard-only walkthroughs of the cells, the bars, the menus and the dialogs, screen reader passes with NVDA, JAWS and VoiceOver, 200% and 400% zoom, reflow at 320 CSS px and WCAG text spacing overrides. +4. **Conformance reporting**: the results are published criterion by criterion in the [Accessibility Conformance Report](https://docs.dhtmlx.com/spreadsheet/accessibility_conformance_report/), including the criteria that the Spreadsheet partially supports. + +## Resources + +- [Accessibility Conformance Report (VPAT 2.5)](https://docs.dhtmlx.com/spreadsheet/accessibility_conformance_report/) +- [Hot keys list](https://docs.dhtmlx.com/spreadsheet/hotkeys/) +- [`readonly`](https://docs.dhtmlx.com/spreadsheet/api/spreadsheet_readonly_config/) +- [`selection`](https://docs.dhtmlx.com/spreadsheet/api/spreadsheet_selection_config/) +- [`announce()`](https://docs.dhtmlx.com/spreadsheet/api/spreadsheet_announce_method/) +- [Localization](https://docs.dhtmlx.com/spreadsheet/localization/) +- [Built-in themes](https://docs.dhtmlx.com/spreadsheet/themes/) +- [WCAG 2.2](https://www.w3.org/TR/WCAG22/) +- [WAI-ARIA 1.2](https://www.w3.org/TR/wai-aria-1.2/) +- [WAI-ARIA Authoring Practices: Grid pattern](https://www.w3.org/WAI/ARIA/apg/patterns/grid/) +- [WAI-ARIA Authoring Practices: Toolbar pattern](https://www.w3.org/WAI/ARIA/apg/patterns/toolbar/) From e91dc1579a9e3031b26d2f06ef072d6e9de29f68 Mon Sep 17 00:00:00 2001 From: Masha_Rudenko Date: Mon, 2 Nov 2026 14:51:21 +0300 Subject: [PATCH 2/2] [fix] github accessibility page images - images point to docs.dhtmlx.com instead of relative ../static paths - relative paths didn't render in the repository Accessibility tab --- .github/ACCESSIBILITY.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/ACCESSIBILITY.md b/.github/ACCESSIBILITY.md index 7d43ba74..e64547fe 100644 --- a/.github/ACCESSIBILITY.md +++ b/.github/ACCESSIBILITY.md @@ -177,7 +177,7 @@ The DOM focus is on the active cell itself, so a screen reader reads the cell, n The keyboard works as soon as the Spreadsheet is on the page; no configuration is needed. The tables below summarize the keyboard model. See [Hot keys list](https://docs.dhtmlx.com/spreadsheet/hotkeys/) for the complete set of shortcuts. -![The Horizontal align dropdown of the toolbar opened with the Down arrow key, with the focus on its first item](../static/img/accessibility/toolbar_dropdown_focus.png) +![The Horizontal align dropdown of the toolbar opened with the Down arrow key, with the focus on its first item](https://docs.dhtmlx.com/spreadsheet/img/accessibility/toolbar_dropdown_focus.png) ### Cells @@ -267,11 +267,11 @@ In the light themes, the colors that mark the cell references of a formula have The `contrast-light` theme draws dark text and borders on a white background. In the Spreadsheet below, the context menu of a cell with the filter icon is opened with the keyboard. Its focused command, [*Open filter*](https://docs.dhtmlx.com/spreadsheet/filtering_data/#opening-a-filter-with-the-keyboard), is marked by a dashed outline, and the active cell is marked by a solid border in the primary color of the theme: -![Spreadsheet in the contrast-light theme](../static/img/accessibility/spreadsheet_contrast_light.png) +![Spreadsheet in the contrast-light theme](https://docs.dhtmlx.com/spreadsheet/img/accessibility/spreadsheet_contrast_light.png) The `contrast-dark` theme draws light text and borders on a dark background. When the focus is on a toolbar control, the control is marked by a focus ring in the `--dhx-spreadsheet-focus-color` color, which is lighter than the primary color of the active cell border in the dark themes: -![Spreadsheet in the contrast-dark theme](../static/img/accessibility/spreadsheet_contrast_dark.png) +![Spreadsheet in the contrast-dark theme](https://docs.dhtmlx.com/spreadsheet/img/accessibility/spreadsheet_contrast_dark.png) ### Focus indicator