Skip to content

Comments

fix: icons disappear in Windows High Contrast Mode#1150

Merged
danielroe merged 7 commits intonpmx-dev:mainfrom
RYGRIT:fix/windows-high-contrast-mode
Feb 8, 2026
Merged

fix: icons disappear in Windows High Contrast Mode#1150
danielroe merged 7 commits intonpmx-dev:mainfrom
RYGRIT:fix/windows-high-contrast-mode

Conversation

@RYGRIT
Copy link
Contributor

@RYGRIT RYGRIT commented Feb 7, 2026

fixes: #1130

freecompress-2026-02-07.22-06-31.mp4

@vercel
Copy link

vercel bot commented Feb 7, 2026

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

Project Deployment Actions Updated (UTC)
docs.npmx.dev Ready Ready Preview, Comment Feb 8, 2026 7:16am
npmx.dev Ready Ready Preview, Comment Feb 8, 2026 7:16am
1 Skipped Deployment
Project Deployment Actions Updated (UTC)
npmx-lunaria Ignored Ignored Feb 8, 2026 7:16am

Request Review

@codecov
Copy link

codecov bot commented Feb 7, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ All tests successful. No failed tests found.

📢 Thoughts on this report? Let us know!

@userquin
Copy link
Member

userquin commented Feb 7, 2026

nice ❤️

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Feb 7, 2026

📝 Walkthrough

Walkthrough

Adds forced-colours accessibility handling: a new annotated @media (forced-colors: active) block (commented in app/assets/main.css) plus active forced-colours CSS in several components (AccentColorPicker.vue, BgThemePicker.vue, Toggle.client.vue, app/pages/index.vue) to preserve visibility of icons, radio swatches, toggle switches and the homepage accent dot under Windows forced-colours. Also updates uno.config.ts to add forced-color-adjust: 'preserve-parent-color' for the icons preset. Changes are CSS-only and additive; no runtime logic changes.

Possibly related PRs

  • fix: remove border opacity on toggle #1011: Modifies app/components/Settings/Toggle.client.vue styling for toggle visibility/contrast (accessibility-focused CSS changes), closely related at the component styling level.

Suggested reviewers

  • danielroe
  • RamaHerbin
  • shuuji3
🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description check ✅ Passed The PR description references issue #1130 and includes a video attachment, which relates to the changeset addressing icon visibility in Windows High Contrast Mode.
Linked Issues check ✅ Passed The PR successfully implements the core requirement from issue #1130: applying forced-color-adjust properties to preserve icon visibility in Windows High Contrast Mode across components and configuration.
Out of Scope Changes check ✅ Passed All changes are scoped to addressing Windows High Contrast Mode visibility, with CSS/styling adjustments collocated to affected components and configuration, with no unrelated modifications.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

No actionable comments were generated in the recent review. 🎉

🧹 Recent nitpick comments
app/components/Settings/AccentColorPicker.vue (1)

63-74: Confirm CSS nesting support or flatten the forced‑colours selectors.

This block relies on CSS nesting (&:has(...)). If the build or target browsers don’t support nesting, the forced‑colours fix won’t apply. Consider flattening selectors to be safe.

Suggested non‑nested equivalent
 `@media` (forced-colors: active) {
   /* keep accent radio swatches visible in forced colors. */
   label {
     forced-color-adjust: none;
     border: 1px solid CanvasText;
-
-    &:has(> input:checked) {
-      outline: 2px solid Highlight;
-      outline-offset: 2px;
-    }
   }
+  label:has(> input:checked) {
+    outline: 2px solid Highlight;
+    outline-offset: 2px;
+  }
 }
app/components/Settings/Toggle.client.vue (1)

55-79: Confirm CSS nesting support or flatten the forced‑colours selectors.

These nested selectors require CSS nesting support. If unsupported, the forced‑colours styles will be ignored. A flat selector form avoids that risk.

Suggested non‑nested equivalent
 `@media` (forced-colors: active) {
   /* make toggle tracks and thumb visible in forced colors. */
-  button[role='switch'] {
-    & > span:last-of-type {
-      forced-color-adjust: none;
-    }
-
-    &[aria-checked='false'] > span:last-of-type {
-      background: Canvas;
-      border-color: CanvasText;
-
-      & > span {
-        background: CanvasText;
-      }
-    }
-
-    &[aria-checked='true'] > span:last-of-type {
-      background: Highlight;
-      border-color: Highlight;
-
-      & > span {
-        background: HighlightText;
-      }
-    }
-  }
+  button[role='switch'] > span:last-of-type {
+    forced-color-adjust: none;
+  }
+  button[role='switch'][aria-checked='false'] > span:last-of-type {
+    background: Canvas;
+    border-color: CanvasText;
+  }
+  button[role='switch'][aria-checked='false'] > span:last-of-type > span {
+    background: CanvasText;
+  }
+  button[role='switch'][aria-checked='true'] > span:last-of-type {
+    background: Highlight;
+    border-color: Highlight;
+  }
+  button[role='switch'][aria-checked='true'] > span:last-of-type > span {
+    background: HighlightText;
+  }
 }

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

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
app/assets/main.css (1)

207-211: Fragile selector based on utility class combination.

This selector depends on a specific combination of utility classes (bg-accent, rounded-full, w-1, h-1). If any of these classes change in the component, this rule will silently break. Consider adding a dedicated class (e.g., .homepage-tag-dot) or a data-* attribute to make this selector more robust.

♻️ Suggested approach

Add a dedicated class to the element in the component:

-:where([class~='bg-accent'][class~='rounded-full'][class~='w-1'][class~='h-1']) {
+:where(.tag-dot) {
   forced-color-adjust: none;
   background: CanvasText;
 }

Then add the .tag-dot class to the element in the relevant Vue component alongside the existing utility classes.

Copy link
Member

@userquin userquin left a comment

Choose a reason for hiding this comment

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

LGTM

Copy link
Contributor

@carwack carwack left a comment

Choose a reason for hiding this comment

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

LGTM!

I added a suggestion nit pick, but I don't think changes are really required!

Comment on lines 189 to 205
button[role='switch'][aria-checked='false'] > span:last-of-type {
background: Canvas;
border-color: CanvasText;
}

button[role='switch'][aria-checked='false'] > span:last-of-type > span {
background: CanvasText;
}

button[role='switch'][aria-checked='true'] > span:last-of-type {
background: Highlight;
border-color: Highlight;
}

button[role='switch'][aria-checked='true'] > span:last-of-type > span {
background: HighlightText;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Nit pick: css does support nesting now, I do think this could be nested down.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Updated to use CSS nesting in the components. Thanks for the suggestion!'❤️

Copy link
Member

@knowler knowler left a comment

Choose a reason for hiding this comment

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

Can we colocate any page specific changes with the corresponding page?

Comment on lines 160 to 163
:where([class^='i-'], [class*=' i-']) {
forced-color-adjust: none;
color: CanvasText;
}
Copy link
Member

@knowler knowler Feb 7, 2026

Choose a reason for hiding this comment

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

@userquin This overrides the effect of forced-color-adjust: preserve-parent-color that is being applied with the UnoConfig. Which do you think is better?

Copy link
Member

Choose a reason for hiding this comment

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

oh, sorry, I didn't see this comment: that's why I use icon class in the selector (check my comment in linked issue), if not present I add the corresponding colors

@RYGRIT
Copy link
Contributor Author

RYGRIT commented Feb 8, 2026

Can we colocate any page specific changes with the corresponding page?

@knowler You are absolutely right! I re-tested the pages used in most scenarios and found that the default preserve-parent-color property handles the icons correctly in most cases.

To keep the code clean, I've temporarily commented out the global override styles in main.css, but kept them as a reference in case we encounter any special situations where masking/inheritance fails (e.g., in certain button states or with transparent backgrounds).

Additionally, as you suggested, I have moved all other specific styles (homepage dots, settings switches) to their respective components.

@danielroe danielroe added this pull request to the merge queue Feb 8, 2026
Merged via the queue into npmx-dev:main with commit 77a7aa8 Feb 8, 2026
17 checks passed
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.

Icons disappear in Windows High Contrast Mode

5 participants