Skip to content

Download table: put the full checksum in the DOM, truncate it with CSS - #2139

Merged
cwickham merged 2 commits into
mainfrom
download-checksum-a11y
Sep 23, 2026
Merged

cwickham merged 2 commits into
mainfrom
download-checksum-a11y

Conversation

@cwickham

@cwickham cwickham commented Aug 7, 2026

Copy link
Copy Markdown
Member

The site audit flagged two WCAG failures on /docs/download/, both on the checksum cells:

  • aria-allowed-attr (critical, WCAG 4.1.2): tippy's interactive mode adds aria-expanded to the checksum <div>, which is invalid on an element with no role.
  • color-contrast (serious, WCAG 1.4.3): the truncated hash used --bs-primary (3.97:1 on white; small text needs 4.5:1).

The deeper problem: the full SHA-256 lived only in a hover tooltip. Keyboard users could not reach it, screen readers never heard it, and copying it meant drag-selecting text inside a floating tooltip.

The fix: the cell's text is now the complete hash, and only the rendering truncates (text-overflow: ellipsis). The tooltip, tippy init, and JS truncation are gone. The SHA-256 column header links to the release's checksums.txt.

We tried a copy button, an aria-describedby span, and a <details> disclosure before settling here. This version won because it does both things at once with zero interactive machinery:

  • No visual clutter — the table looks exactly as it does today.
  • The full hash is available to everyone — screen readers announce all 64 characters, double-click selects the whole hash for copying, find-in-page matches it, and the header link provides the full values at any viewport, since the CSS truncation only affects what's rendered, not what's in the DOM.

Net diff: +17/−17 lines. Axe scan of the page is clean at 1440×900 and 390×844, light and dark.

The full SHA-256 lived only in a hover tooltip: keyboard users could not
reach it, screen readers never heard it, nobody could copy it easily,
and tippy put an invalid aria-expanded on the role-less div (axe
aria-allowed-attr, WCAG 4.1.2). The truncated hash also used
--bs-primary, which fails WCAG AA contrast for small text.

Now the cell's text is the complete hash and only the rendering
truncates (CSS ellipsis). The table looks the same as before, but
screen readers announce the full value, double-click selects it for
copying, and find-in-page matches it — no tooltip, no ARIA, default
text color. The SHA-256 column header links to the release's
checksums.txt so the full values are also visible at every viewport
(WCAG 1.4.10 reflow). Also removes the tippy init for a.checksum,
which matched nothing (checksums were divs).
@github-actions
github-actions Bot temporarily deployed to pull request August 7, 2026 21:37 Inactive
@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

📝 Preview Deployment

🔍 Full site preview: https://deploy-preview-2139.quarto.org

createHeadingRow was assigning cell.outerHTML from a template literal
containing an interpolated URL, the only place in this file that builds
markup that way instead of createElement + .href/.innerText. Match the
existing pattern so header cells are never built from unescaped strings.

Also drops the WCAG 1.4.10 citation for the header link in the code
comment - the mapping was shaky; the plain rationale stands on its own.
@github-actions

Copy link
Copy Markdown
Contributor

📝 Preview Deployment

🔍 Full site preview: https://deploy-preview-2139.quarto.org

@cwickham
cwickham marked this pull request as ready for review September 23, 2026 22:49
@cwickham
cwickham merged commit 664eab8 into main Sep 23, 2026
3 checks passed
@cwickham
cwickham deleted the download-checksum-a11y branch September 23, 2026 22:49
@github-actions

Copy link
Copy Markdown
Contributor

cwickham added a commit that referenced this pull request Sep 23, 2026
#2139) (#2201)

* Put the full checksum in the DOM, truncate it with CSS

The full SHA-256 lived only in a hover tooltip: keyboard users could not
reach it, screen readers never heard it, nobody could copy it easily,
and tippy put an invalid aria-expanded on the role-less div (axe
aria-allowed-attr, WCAG 4.1.2). The truncated hash also used
--bs-primary, which fails WCAG AA contrast for small text.

Now the cell's text is the complete hash and only the rendering
truncates (CSS ellipsis). The table looks the same as before, but
screen readers announce the full value, double-click selects it for
copying, and find-in-page matches it — no tooltip, no ARIA, default
text color. The SHA-256 column header links to the release's
checksums.txt so the full values are also visible at every viewport
(WCAG 1.4.10 reflow). Also removes the tippy init for a.checksum,
which matched nothing (checksums were divs).

* Build the checksum header link with DOM APIs, not an HTML string

createHeadingRow was assigning cell.outerHTML from a template literal
containing an interpolated URL, the only place in this file that builds
markup that way instead of createElement + .href/.innerText. Match the
existing pattern so header cells are never built from unescaped strings.

Also drops the WCAG 1.4.10 citation for the header link in the code
comment - the mapping was shaky; the plain rationale stands on its own.

(cherry picked from commit 664eab8)

Co-authored-by: Charlotte Wickham <charlotte.wickham@posit.co>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant