Replace hardcoded SCSS color values with CSS custom properties#14085
Replace hardcoded SCSS color values with CSS custom properties#14085abyrne-moz wants to merge 5 commits intomozilla:masterfrom
Conversation
Introduces CSS custom properties in _theme.scss for key color values (backgrounds, text, links, borders, inputs) and updates 29 component SCSS files to reference them via var(). All values resolve to the existing light mode colors — no visual change. This lays the groundwork for runtime theme switching (e.g. dark mode) in a follow-up PR. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #14085 +/- ##
=======================================
Coverage 98.15% 98.15%
=======================================
Files 265 265
Lines 10680 10680
Branches 3280 3280
=======================================
Hits 10483 10483
Misses 184 184
Partials 13 13 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
diox
left a comment
There was a problem hiding this comment.
I don't think this goes far enough - this is the problem I encountered when looking at dark mode in the past.
The following very crude grep finds 183 more potentially problematic lines where we're using SCSS variables or plain hardcoded values:
egrep 'color:|background:|background-color:' src -r --include="*.scss" --exclude=vars.scss | fgrep -v 'var(' | egrep -v 'transparent|none|inherit|initial'
There are a few false positives (and maybe some missing as well!), but we should use the CSS variables in almost all of these cases.
Adds 14 new CSS custom properties and converts ~95 more hardcoded color references across 43 files. The remaining ~84 hardcoded values are false positives: SCSS mixin parameters (Button, Notice), @for loop variables (CategoryIcon, Categories), literal color swatches (SearchFilters), brand-specific colors (VPNPromoBanner), SVG references (Icon, Rating), and gradients (RatingManager, AddonReviewCard). New variables: --amo-text-on-dark, --amo-text-dark, --amo-text-muted, --amo-text-muted-light, --amo-text-date, --amo-bg-neutral, --amo-focus-border, --amo-action-hover, --amo-accent-color, --amo-rating-bar-bg, --amo-rating-bar-fill, --amo-loading-bg. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The photon-colors package doesn't export $yellow-40 — it only has $yellow-50. Replace with the hardcoded hex value #ffbd4f. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Missed in the initial pass: border shorthand, border-top/bottom/left/right, and outline properties with hardcoded SCSS color variables. Converts 11 instances across 9 files. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
diox
left a comment
There was a problem hiding this comment.
All values resolve to the existing light mode colors — no visual change.
That is a lie. I found a lot of subtle differences, which I have commented on. We need to double-check them all, they might all be changes we want to make for consistency, but they are changes nonetheless.
| &:hover, | ||
| &:active { | ||
| color: $blue-50; | ||
| color: var(--amo-link-color); |
There was a problem hiding this comment.
Note: here and in other places where $blue-50 is replaced by var(--amo-link-color), this is a slight departure from the previous style, since --amo-link-color is $link-color, which is $blue-60.
It's not necessarily a bad thing (fewer colors to worry about is probably a good thing), but worth double-checking in case that has undesirable effects with regards to contrast etc.
| background-color: transparentize($blue-50, 0.95); | ||
| border-radius: $border-radius-default; | ||
| color: $type-black; | ||
| color: var(--amo-text-heading); |
There was a problem hiding this comment.
Another potential change since --amo-text-heading is not equivalent to $type-black
| &:link, | ||
| &:visited { | ||
| color: $black; | ||
| color: var(--amo-input-text); |
There was a problem hiding this comment.
Not the right choice - It's not a text input/form widget
| @include font-bold; | ||
|
|
||
| color: $black; | ||
| color: var(--amo-input-text); |
There was a problem hiding this comment.
Not the right choice - It's not a text input/form widget
| a, | ||
| a:link { | ||
| color: $black; | ||
| color: var(--amo-input-text); |
There was a problem hiding this comment.
Not the right choice - It's not a text input/form widget
| --amo-block-hover: #{$block-hover-white-color}; | ||
| --amo-bg-grey: #{$background-grey}; | ||
| --amo-hover-bg: #{$grey-10}; | ||
| --amo-select-bg: #{$grey-30}; |
There was a problem hiding this comment.
Weird name considering it's not just used for <select> elements (used in pagination, language tools page rows...)
|
|
||
| .DropdownMenuItem-section { | ||
| color: $grey-50; | ||
| color: var(--amo-text-secondary); |
|
|
||
| .SearchFilters-label { | ||
| color: $grey-50; | ||
| color: var(--amo-text-secondary); |
| justify-content: center; | ||
| text-align: center; | ||
| text-shadow: 0 0 2px $white; | ||
| text-shadow: none; |
There was a problem hiding this comment.
I don't think this text-shadow was accidental. Need to double-check.
| align-items: center; | ||
| background: #ccc; | ||
| color: $black; | ||
| background: var(--amo-placeholder-bg); |
There was a problem hiding this comment.
We might want to merge --amo-placeholder-bg with --amo-loading-bg, not sure it's worth having 2 different ones.
diox
left a comment
There was a problem hiding this comment.
The subtle changes are fine, but we need to fix the following if we want to use this as the foundation for implementing Dark Mode correctly:
--amo-input-textbeing used for non-inputs--amo-select-bgbeing used for more than just<select>/form elements


Moves towards fixing mozilla/addons#2193
Introduces CSS custom properties in _theme.scss for key color values (backgrounds, text, links, borders, inputs) and updates 29 component SCSS files to reference them via var(). All values resolve to the existing light mode colors — no visual change. This lays the groundwork for runtime theme switching (e.g. dark mode) in a follow-up PR.