Skip to content

fix(a11y): mark pressed toggles with the system highlight in forced colors (#1086) - #1087

Merged
JOY (JOY) merged 1 commit into
devfrom
fix/forced-colors-pressed
Oct 25, 2026
Merged

JOY (JOY) merged 1 commit into
devfrom
fix/forced-colors-pressed

Conversation

@JOY

@JOY JOY (JOY) commented Oct 25, 2026 •

Copy link
Copy Markdown
Contributor

Closes #1086

What

In forced-colors mode (Windows High Contrast), the browser replaces the background and text colours that set a pressed toggle apart (btn-danger text-white vs btn-outline-dark bg-light). On the leaderboard and compare category switchers, the selected category therefore looked exactly like the others.

_custom.scss adds one @media (forced-colors: active) rule. Every [aria-pressed="true"] control gets the system Highlight background and HighlightText text (forced-color-adjust: none), and its children are transparent with HighlightText. That keeps count badges readable, for example the selected "Điện thoại 9". The html prefix outranks Bootstrap's !important utilities such as bg-white on those badges. Normal colour mode is unaffected.

Test

  • e2e/selector-state.spec.ts: under forcedColors: 'active', the pressed and unpressed buttons of the leaderboard and compare category switchers have different backgrounds.
  • Mutation check: with _custom.scss reverted to origin/dev, both new tests fail (rgb(255, 255, 255) for both). With the fix, selector-state and pill-group-state pass 11/11.
  • Visual check in a local production build under forced colours, light and dark: the pressed pill is highlighted and its count badge is legible. An intermediate version that let bg-white win and hid the count was caught this way and fixed.

🤖 Generated with Claude Code


📌 TL;DR

This PR adds a CSS media query to ensure pressed toggle buttons remain visually distinct in Windows High Contrast Mode (forced colors) by overriding system defaults with Highlight colors. It includes a new E2E test to verify that the selected state is visually distinguishable from unselected states under these conditions.

🎯 Type of Change

  • 🚀 New feature
  • 🐛 Bugfix
  • 🧹 Refactor
  • ⚡ Performance
  • 📚 Documentation
  • ⚙️ CI / Configuration

🔍 Changes Walkthrough

File Summary of Changes
apps/web/src/app/style/scss/_custom.scss Added a @media (forced-colors: active) block that targets elements with [aria-pressed='true']. It disables forced-color-adjust and applies Highlight/HighlightText system colors to the background, border, and text (including child elements) to ensure the active state is visible in high-contrast modes.
apps/web/e2e/selector-state.spec.ts Added a parameterized E2E test that emulates forcedColors: 'active' on the /leaderboard and /compare pages. It asserts that the computed backgroundColor of a pressed button differs from that of an unpressed button, verifying the visual distinction required by the accessibility fix.

📊 Architectural Flow

flowchart TD
    A[User enables Windows High Contrast / Forced Colors] --> B{Browser applies forced-colors media query}
    B --> C[CSS Rule: html [aria-pressed='true']]
    C --> D[forced-color-adjust: none]
    C --> E[background-color: Highlight !important]
    C --> F[color: HighlightText !important]
    E --> G[Pressed button appears distinct from unpressed buttons]
    F --> G
    G --> H[E2E Test verifies computed styles differ]
Loading

…olors (#1086)

Forced colours replace the background and text colours that set a pressed
toggle apart, so the selected category on the leaderboard and compare
switchers looked like the others in Windows High Contrast. Draw every
[aria-pressed="true"] control with Highlight/HighlightText.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@JOY JOY (JOY) added the agent:brand Claimed by Agent: Brand label Oct 25, 2026

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Code review skipped — your organization has no extra usage available to pay for this review.

If your organization's extra usage balance is empty, an organization admin can add extra usage credits at claude.ai/admin-settings/usage. If its monthly spend limit was reached, an admin can raise it on the same page. If neither applies, contact Anthropic support.

Once extra usage is available, someone with write access to this repository can comment @claude review on this pull request to trigger a review.

@vercel

vercel Bot commented Oct 25, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
rate Ready Ready Preview Oct 25, 2026 6:40pm UTC

Request Review

@coderabbitai

coderabbitai Bot commented Oct 25, 2026

Copy link
Copy Markdown

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 14 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

Learn how review limits work.

Review configuration:

Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: d686d98c-9c0a-4f12-823a-842a661a29f9
Commits

Reviewing files that changed from the base of the PR and between ba90e86 and 698dfbb.

Files selected for processing: 2
  • apps/web/e2e/selector-state.spec.ts
  • apps/web/src/app/style/scss/_custom.scss
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added the area:frontend Frontend / Next.js / UI label Oct 25, 2026
dos[bot]
dos Bot approved these changes Oct 25, 2026

@dos dos Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⏱️ Code Review completed (2 eligible files · 2,455 chars · 1 model call(s) · 1 PR unit(s))

Whole diff with bounded context at base ba90e86 / head 698dfbb.

✅ CLEAN_PASS: Complete diff reviewed

@JOY

Copy link
Copy Markdown
Contributor Author

Local review (CodeRabbit was rate-limited): the rule lives entirely inside @media (forced-colors: active), so normal colour mode is untouched. It relies only on system colours (Highlight/HighlightText), which follow the user's chosen high-contrast theme. The descendant reset is broad (* gets a transparent background), but pressed controls hold only text, icons and count badges, all checked visually in light and dark forced-colour builds. The html prefix is needed: Bootstrap utilities are !important with equal specificity and load later. No findings.

@JOY
JOY (JOY) merged commit 45ee56c into dev Oct 25, 2026
19 checks passed
@JOY
JOY (JOY) deleted the fix/forced-colors-pressed branch October 25, 2026 19:04
@JOY JOY (JOY) mentioned this pull request Oct 25, 2026
3 of 6 tasks

This branch was successfully deployed

1 active deployment
Preview — 698dfbbd Deployed Oct 25, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agent:brand Claimed by Agent: Brand area:frontend Frontend / Next.js / UI

Projects

None yet

Development

Successfully merging this pull request may close these issues.

a11y: pressed toggles are indistinguishable in forced-colors mode

1 participant