Skip to content

fix(a11y): topbar logo and dark-mode toggle visible in HCM - #10847

Merged
robert-hebel-sb merged 2 commits into
swagger-api:mainfrom
bmatar:bug/7350-topbar-hcm-refinements
Aug 10, 2026
Merged

fix(a11y): topbar logo and dark-mode toggle visible in HCM#10847
robert-hebel-sb merged 2 commits into
swagger-api:mainfrom
bmatar:bug/7350-topbar-hcm-refinements

Conversation

@bmatar

@bmatar bmatar commented Apr 19, 2026

Copy link
Copy Markdown
Contributor

Description

In Windows High Contrast Mode (Edge / Chromium with forced-colors: active), the standalone topbar's Swagger logo wordmark and the dark-mode toggle's lightbulb icon both become invisible or near-invisible against the HCM-substituted Canvas. The logo wordmark paths use literal fill="#fff", and the dark-mode toggle SVG uses fill: #e4e6e6 — both preserved by Chromium's spec-correct default forced-color-adjust: preserve-parent-color for SVG. The dark-mode toggle wrapper also has opacity: 0.8, which composites multiplicatively and dims the icon further regardless of the path fill.

In HCM-light, the white logo wordmark is invisible on Canvas-white. In HCM-dark, the gray lightbulb sits at low contrast. The toggle button is operable (it has a focusable <button>) but sighted HCM users have no visible cue.

A new @media (forced-colors: active) block in _topbar.scss pins the logo wordmark paths to CanvasText and the dark-mode toggle SVG to ButtonText, both with forced-color-adjust: none, and resets the wrapper opacity to 1 so the system-color contrast guarantee isn't dimmed.

Motivation and Context

Part of the HCM accessibility backlog tracked in #7350; this PR fixes the standalone topbar surface specifically. Detected by Tactual. WCAG 1.4.11 Non-text Contrast.

How Has This Been Tested?

  • npm run test:unit — all suites pass (829 tests)
  • npm run build — clean
  • Local build served alongside an unfixed master build for direct side-by-side comparison
  • Per-element pixel diff across 8 mode combinations (page-mode × HCM-scheme × forced-colors-on/off), with state receipts asserting html.dark-mode and forced-colors: active at capture time. Topbar elements show diffs only in HCM scenarios; non-HCM scenarios are byte-identical
  • Manual verification with Microsoft Edge with OS-level High Contrast Mode enabled
  • Manual verification with NVDA — no regression in announced labels or focus order

Screenshots

Same swagger-ui commit on both ports, only this patch differing. The html.dark-mode class is irrelevant to the topbar surface in HCM (the OS substitutes Canvas/CanvasText regardless), so only the HCM scheme axis has distinct visual states.

HCM light:

BEFORE AFTER
topbar-hcm-light-before topbar-hcm-light-after

HCM dark:

BEFORE AFTER
topbar-hcm-dark-before topbar-hcm-dark-after

Out of scope

Checklist

My PR contains...

  • No code changes (src/ is unmodified: changes to documentation, CI, metadata, etc.)
  • Dependency changes (any modification to dependencies in package.json)
  • Bug fixes (non-breaking change which fixes an issue)
  • Improvements (misc. changes to existing features)
  • Features (non-breaking change which adds functionality)

My changes...

  • are breaking changes to a public API (config options, System API, major UI change, etc).
  • are breaking changes to a private API (Redux, component props, utility functions, etc.).
  • are breaking changes to a developer API (npm script behavior changes, new dev system dependencies, etc).
  • are not breaking changes.

Documentation

  • My changes do not require a change to the project documentation.
  • My changes require a change to the project documentation.
  • If yes to above: I have updated the documentation accordingly.

Automated tests

  • My changes can not or do not need to be tested.
  • My changes can and should be tested by unit and/or integration tests.
  • If yes to above: I have added tests to cover my changes.
  • If yes to above: I have taken care to cover edge cases in my tests.
  • All new and existing tests passed.

bmatar and others added 2 commits April 19, 2026 16:23
In Windows High Contrast Mode the standalone topbar Swagger logo and
the dark-mode toggle's lightbulb icon both become invisible or near-
invisible against the HCM-substituted Canvas. The logo's wordmark
paths use literal fill #fff which preserves under Chromium's default
forced-color-adjust: preserve-parent-color for SVG and disappears in
HCM light. The dark-mode toggle's SVG fill #e4e6e6 likewise preserves
and renders at low contrast in any HCM theme; the parent .dark-mode-
toggle also has opacity: 0.8, which composites multiplicatively and
dims the icon further.

A new @media (forced-colors: active) block in _topbar.scss pins the
logo wordmark paths to CanvasText and the dark-mode toggle SVG to
ButtonText with forced-color-adjust: none, and resets the parent
opacity to 1 so the system-color contrast guarantee isn't dimmed.
ButtonText/CanvasText are the system colors paired with ButtonFace/
Canvas and guarantee contrast in any user HCM theme.

Refs swagger-api#7350
@robert-hebel-sb

Copy link
Copy Markdown
Contributor

LGTM 💅

thanks for the contribution @bmatar 🥇 ; I will merge this PR as soon CI checks passess

@robert-hebel-sb
robert-hebel-sb merged commit 6beaebd into swagger-api:main Aug 10, 2026
9 checks passed
swagger-bot pushed a commit that referenced this pull request Aug 11, 2026
## [5.32.13](v5.32.12...v5.32.13) (2026-08-11)

### Bug Fixes

* **a11y:** add aria-labels to copy-to-clipboard buttons ([#10842](#10842)) ([e6ce7d8](e6ce7d8))
* **a11y:** add skip-to-operations link, banner and main landmarks ([#10849](#10849)) ([92669ea](92669ea))
* **a11y:** close Authorization popup with Escape key and backdrop click ([#10987](#10987)) ([311b0d2](311b0d2))
* **a11y:** name and state for dark-mode toggle button ([#10848](#10848)) ([13a90fa](13a90fa))
* **a11y:** restore icon visibility in Windows High Contrast Mode ([#10846](#10846)) ([edec467](edec467))
* **a11y:** topbar logo and dark-mode toggle visible in HCM ([#10847](#10847)) ([6beaebd](6beaebd))
* **a11y:** use <strong> for model titles to convey emphasis semantically ([#10876](#10876)) ([b4501b6](b4501b6))
* **ci:** bump cycjimmy/semantic-release-action to v6.0.0 ([#11001](#11001)) ([9b3eacb](9b3eacb))
* **ci:** fix Trivy security scan and add dependency vulnerability scan ([#10996](#10996)) ([ff221a8](ff221a8))
* **style:** reduce padding on inline code blocks in markdown ([#7569](#7569)) ([#10789](#10789)) ([a1a6cdc](a1a6cdc))
@swagger-bot

Copy link
Copy Markdown
Contributor

🎉 This PR is included in version 5.32.13 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants