diff --git a/res/css/categories.css b/res/css/categories.css
index 8d1d533854..6ec2b8e2e4 100644
--- a/res/css/categories.css
+++ b/res/css/categories.css
@@ -20,6 +20,22 @@
--category-color-darkgrey: var(--grey-50);
}
+@supports (color-scheme: dark) {
+ @media (prefers-color-scheme: dark) {
+ :root {
+ --category-color-purple: var(--purple-60);
+ --category-color-green: var(--green-80);
+ --category-color-orange: var(--orange-60);
+ --category-color-yellow: var(--yellow-70);
+ --category-color-magenta: var(--magenta-70);
+ --category-color-gray: var(--grey-50);
+ --category-color-grey: var(--grey-50);
+ --category-color-darkgray: var(--grey-60);
+ --category-color-darkgrey: var(--grey-60);
+ }
+ }
+}
+
/**
* These classes should be used to create a small color swatch to describe a
* category. They should be used with the class `colored-square` that's defined
diff --git a/res/css/focus.css b/res/css/focus.css
index a6291dcff1..3925aa3858 100644
--- a/res/css/focus.css
+++ b/res/css/focus.css
@@ -18,15 +18,15 @@ input[type='range']:focus-visible,
select:focus-visible,
button:focus-visible {
box-shadow:
- 0 0 0 1px var(--blue-50) inset,
- 0 0 0 1px var(--blue-50),
- 0 0 0 4px var(--blue-50-a30);
+ 0 0 0 1px var(--focus-border-color) inset,
+ 0 0 0 1px var(--focus-border-color),
+ 0 0 0 4px var(--focus-shadow-color);
outline: 0;
}
a:focus-visible {
box-shadow:
- 0 0 0 2px var(--blue-50),
- 0 0 0 6px var(--blue-50-a30);
+ 0 0 0 2px var(--focus-border-color),
+ 0 0 0 6px var(--focus-shadow-color);
outline: 0;
}
diff --git a/res/css/global.css b/res/css/global.css
index 72c99c9064..8d4b99bc3a 100644
--- a/res/css/global.css
+++ b/res/css/global.css
@@ -2,6 +2,102 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+:root {
+ --base-foreground-color: #000;
+ --base-background-color: #fff;
+ --base-border-color: var(--grey-30);
+ --base-shadow-color: rgb(0 0 0 / 0.2);
+ --link-foreground-color: var(--blue-60);
+ --link-visited-foreground-color: var(--purple-70);
+ --link-active-foreground-color: var(--red-50);
+ --clickable-foreground-color: var(--grey-90);
+ --clickable-background-color: var(--grey-90-a10);
+ --clickable-border-color: var(--grey-90-a30);
+ --clickable-hover-background-color: var(--grey-90-a20);
+ --clickable-active-background-color: var(--grey-90-a30);
+ --clickable-ghost-hover-background-color: var(--grey-90-a10);
+ --clickable-ghost-active-background-color: var(--grey-90-a20);
+ --clickable-checked-background-color: var(--blue-60);
+ --clickable-checked-hover-background-color: var(--blue-70);
+ --clickable-checked-active-background-color: var(--blue-80);
+ --focus-border-color: var(--blue-50);
+ --focus-shadow-color: var(--blue-50-a30);
+ --kbd-foreground-color: var(--base-foreground-color);
+ --kbd-background-color: #f6f6f6;
+ --kbd-border-color: #ccc;
+ --kbd-shadow-color: #bbb;
+ --home-border-color: #ccc;
+ --home-shadow-color: #0b1f50;
+ --row-odd-background-color: #f5f5f5;
+ --panel-foreground-color: var(--ink-70);
+ --panel-background-color: var(--grey-10);
+ --panel-border-color: var(--grey-30);
+ --track-selected-background-color: #edf6ff;
+ --tooltip-number-foreground-color: var(--grey-60);
+ --colored-border-color: rgb(0 0 0 / 0.1);
+
+ background-color: var(--base-background-color);
+ color: var(--base-foreground-color);
+}
+
+@supports (color-scheme: dark) {
+ @media (prefers-color-scheme: dark) {
+ :root {
+ --base-foreground-color: var(--grey-20);
+ --base-background-color: var(--ink-90);
+ --base-border-color: var(--grey-50);
+ --base-shadow-color: rgb(0 0 0 / 0.4);
+ --link-foreground-color: var(--blue-40);
+ --link-visited-foreground-color: var(--purple-40);
+ --link-active-foreground-color: var(--red-50);
+ --clickable-foreground-color: var(--grey-20);
+ --clickable-background-color: var(--grey-10-a10);
+ --clickable-border-color: var(--grey-10-a40);
+ --clickable-hover-background-color: var(--grey-10-a20);
+ --clickable-active-background-color: var(--grey-10-a40);
+ --clickable-ghost-hover-background-color: var(--grey-10-a10);
+ --clickable-ghost-active-background-color: var(--grey-10-a20);
+ --clickable-checked-background-color: var(--blue-50);
+ --clickable-checked-hover-background-color: var(--blue-60);
+ --clickable-checked-active-background-color: var(--blue-70);
+ --focus-border-color: var(--blue-40);
+ --focus-shadow-color: var(--blue-50-a30);
+ --kbd-background-color: var(--ink-70);
+ --kbd-border-color: var(--ink-60);
+ --kbd-shadow-color: var(--ink-50);
+ --home-border-color: var(--ink-70);
+ --home-shadow-color: var(--ink-90);
+ --row-odd-background-color: color-mix(
+ in hsl,
+ var(--ink-80) 50%,
+ var(--ink-90) 50%
+ );
+ --panel-foreground-color: var(--grey-20);
+ --panel-background-color: var(--ink-80);
+ --panel-border-color: var(--ink-60);
+ --selected-track-background-color: color-mix(
+ in hsl,
+ var(--ink-90) 80%,
+ var(--teal-50) 20%
+ );
+ --tooltip-number-foreground-color: var(--grey-40);
+ --colored-border-color: rgb(237 237 240 / 0.1);
+ }
+ }
+}
+
+a {
+ color: var(--link-foreground-color);
+}
+
+a:visited {
+ color: var(--link-visited-foreground-color);
+}
+
+a:active {
+ color: var(--link-active-foreground-color);
+}
+
/**
* This class should be used to create a small colored square. It's used
* especially for categories and network mime types.
@@ -11,7 +107,7 @@
width: 9px;
height: 9px;
box-sizing: border-box;
- border: 0.5px solid rgb(0 0 0 / 0.1);
+ border: 0.5px solid var(--colored-border-color);
margin-right: 3px;
/* Opt-out of forced colors so the color is applied */
@@ -19,7 +115,7 @@
}
.colored-border {
- border: 2px solid rgb(0 0 0 / 0.1);
+ border: 2px solid var(--colored-border-color);
margin-right: 3px;
/* Opt-out of forced colors so the color is applied */
diff --git a/res/css/photon/button.css b/res/css/photon/button.css
index aeff4be412..14eccf58ea 100644
--- a/res/css/photon/button.css
+++ b/res/css/photon/button.css
@@ -4,6 +4,15 @@
/* See https://design.firefox.com/photon/components/buttons.html for the spec */
.photon-button {
+ --internal-primary-foreground-color: #fff;
+ --internal-primary-background-color: var(--blue-60);
+ --internal-primary-hover-background-color: var(--blue-70);
+ --internal-primary-active-background-color: var(--blue-80);
+ --internal-destructive-foreground-color: #fff;
+ --internal-destructive-background-color: var(--red-60);
+ --internal-destructive-hover-background-color: var(--red-70);
+ --internal-destructive-active-background-color: var(--red-80);
+
/* These flex and sizing properties aren't necessary when a real
string;
+ readonly getUnselectedFillStyle: () => string;
+ readonly getSelectedTextColor: () => string;
readonly gravity: number;
};
-const GRAY_STYLE = {
- selectedFillStyle: GREY_40,
- unselectedFillStyle: GREY_40 + '60',
- selectedTextColor: '#000',
+const DEFAULT_STYLE: ColorStyles = {
+ _selectedFillStyle: ['#ffffff', '#0f1126'],
+ _unselectedFillStyle: ['#ffffff60', '#0f112660'],
+ _selectedTextColor: ['#000000', GREY_20],
+ getSelectedFillStyle: function () {
+ return maybeLightDark(this._selectedFillStyle);
+ },
+ getUnselectedFillStyle: function () {
+ return maybeLightDark(this._unselectedFillStyle);
+ },
+ getSelectedTextColor: function () {
+ return maybeLightDark(this._selectedTextColor);
+ },
+ gravity: 0,
+};
+
+const PSEUDO_TRANSPARENT_STYLE: ColorStyles = {
+ ...DEFAULT_STYLE,
+ _selectedFillStyle: [GREY_30, GREY_70],
+ _unselectedFillStyle: [GREY_30 + '60', GREY_70 + '60'],
+ _selectedTextColor: ['#000', GREY_20],
+ gravity: 8,
+};
+
+const GRAY_STYLE: ColorStyles = {
+ ...DEFAULT_STYLE,
+ _selectedFillStyle: [GREY_40, GREY_50],
+ _unselectedFillStyle: [GREY_40 + '60', GREY_50 + '60'],
+ _selectedTextColor: ['#000', GREY_20],
gravity: 10,
};
-const DARK_GRAY_STYLE = {
- selectedFillStyle: GREY_50,
- unselectedFillStyle: GREY_50 + '60',
- selectedTextColor: '#fff',
+const DARK_GRAY_STYLE: ColorStyles = {
+ ...DEFAULT_STYLE,
+ _selectedFillStyle: [GREY_50, GREY_60],
+ _unselectedFillStyle: [GREY_50 + '60', GREY_60 + '60'],
+ _selectedTextColor: '#fff',
gravity: 11,
};
const STYLE_MAP: { [key: string]: ColorStyles } = {
transparent: {
- selectedFillStyle: 'transparent',
- unselectedFillStyle: 'transparent',
- selectedTextColor: '#000',
+ ...DEFAULT_STYLE,
+ _selectedFillStyle: 'transparent',
+ _unselectedFillStyle: 'transparent',
+ _selectedTextColor: ['#000', GREY_20],
gravity: 0,
},
lightblue: {
- selectedFillStyle: BLUE_40,
+ ...DEFAULT_STYLE,
+ _selectedFillStyle: BLUE_40,
// Colors are assumed to have the form #RRGGBB, so concatenating 2 more digits to
// the end defines the transparency #RRGGBBAA.
- unselectedFillStyle: BLUE_40 + '60',
- selectedTextColor: '#000',
+ _unselectedFillStyle: BLUE_40 + '60',
+ _selectedTextColor: ['#000', GREY_20],
gravity: 1,
},
red: {
- selectedFillStyle: RED_60,
- unselectedFillStyle: RED_60 + '60',
- selectedTextColor: '#fff',
+ ...DEFAULT_STYLE,
+ _selectedFillStyle: RED_60,
+ _unselectedFillStyle: RED_60 + '60',
+ _selectedTextColor: '#fff',
gravity: 1,
},
lightred: {
- selectedFillStyle: RED_70 + '60',
- unselectedFillStyle: RED_70 + '30',
- selectedTextColor: '#000',
+ ...DEFAULT_STYLE,
+ _selectedFillStyle: RED_70 + '60',
+ _unselectedFillStyle: RED_70 + '30',
+ _selectedTextColor: ['#000', GREY_20],
gravity: 1,
},
orange: {
- selectedFillStyle: ORANGE_50,
- unselectedFillStyle: ORANGE_50 + '60',
- selectedTextColor: '#fff',
+ ...DEFAULT_STYLE,
+ _selectedFillStyle: [ORANGE_50, ORANGE_60],
+ _unselectedFillStyle: [ORANGE_50 + '60', ORANGE_60 + '60'],
+ _selectedTextColor: '#fff',
gravity: 2,
},
blue: {
- selectedFillStyle: BLUE_60,
- unselectedFillStyle: BLUE_60 + '60',
- selectedTextColor: '#fff',
+ ...DEFAULT_STYLE,
+ _selectedFillStyle: BLUE_60,
+ _unselectedFillStyle: BLUE_60 + '60',
+ _selectedTextColor: '#fff',
gravity: 3,
},
green: {
- selectedFillStyle: GREEN_60,
- unselectedFillStyle: GREEN_60 + '60',
- selectedTextColor: '#fff',
+ ...DEFAULT_STYLE,
+ _selectedFillStyle: [GREEN_60, GREEN_80],
+ _unselectedFillStyle: [GREEN_60 + '60', GREEN_80 + '60'],
+ _selectedTextColor: '#fff',
gravity: 4,
},
purple: {
- selectedFillStyle: PURPLE_70,
- unselectedFillStyle: PURPLE_70 + '60',
- selectedTextColor: '#fff',
+ ...DEFAULT_STYLE,
+ _selectedFillStyle: [PURPLE_70, PURPLE_60],
+ _unselectedFillStyle: [PURPLE_70 + '60', PURPLE_60 + '60'],
+ _selectedTextColor: '#fff',
gravity: 5,
},
yellow: {
- selectedFillStyle: '#ffe129', // This yellow has more contrast than YELLOW_50.
- unselectedFillStyle: YELLOW_50 + '70',
- selectedTextColor: '#000',
+ ...DEFAULT_STYLE,
+ _selectedFillStyle: [
+ // This yellow has more contrast than YELLOW_50.
+ '#ffe129',
+ YELLOW_70,
+ ],
+ _unselectedFillStyle: [YELLOW_50 + '70', YELLOW_60 + '70'],
+ _selectedTextColor: ['#000', GREY_20],
gravity: 6,
},
brown: {
- selectedFillStyle: ORANGE_70,
- unselectedFillStyle: ORANGE_70 + '60',
- selectedTextColor: '#fff',
+ ...DEFAULT_STYLE,
+ _selectedFillStyle: ORANGE_70,
+ _unselectedFillStyle: ORANGE_70 + '60',
+ _selectedTextColor: '#fff',
gravity: 7,
},
magenta: {
- selectedFillStyle: MAGENTA_60,
- unselectedFillStyle: MAGENTA_60 + '60',
- selectedTextColor: '#fff',
+ ...DEFAULT_STYLE,
+ _selectedFillStyle: [MAGENTA_60, MAGENTA_70],
+ _unselectedFillStyle: [MAGENTA_60 + '60', MAGENTA_70 + '60'],
+ _selectedTextColor: '#fff',
gravity: 8,
},
lightgreen: {
- selectedFillStyle: GREEN_50,
- unselectedFillStyle: GREEN_50 + '60',
- selectedTextColor: '#fff',
+ ...DEFAULT_STYLE,
+ _selectedFillStyle: [GREEN_50, GREEN_70],
+ _unselectedFillStyle: [GREEN_50 + '60', GREEN_70 + '60'],
+ _selectedTextColor: '#fff',
gravity: 9,
},
gray: GRAY_STYLE,
@@ -200,12 +247,15 @@ export function mapCategoryColorNameToStackChartStyles(
colorName: string
): ColorStyles {
if (colorName === 'transparent') {
- return {
- selectedFillStyle: GREY_30,
- unselectedFillStyle: GREY_30 + '60',
- selectedTextColor: '#000',
- gravity: 8,
- };
+ return PSEUDO_TRANSPARENT_STYLE;
}
return mapCategoryColorNameToStyles(colorName);
}
+
+export function getForegroundColor(): string {
+ return lightDark('#000000', GREY_20);
+}
+
+export function getBackgroundColor(): string {
+ return lightDark('#ffffff', INK_90);
+}
diff --git a/src/utils/dark-mode.ts b/src/utils/dark-mode.ts
new file mode 100644
index 0000000000..e63131c46a
--- /dev/null
+++ b/src/utils/dark-mode.ts
@@ -0,0 +1,28 @@
+let _isDarkModeSetup = false;
+let _isDarkMode = false;
+
+export function isDarkMode() {
+ if (!_isDarkModeSetup) {
+ if (window.matchMedia) {
+ const result = window.matchMedia('(prefers-color-scheme: dark)');
+ _isDarkMode = result.matches;
+ result.addEventListener('change', (event) => {
+ _isDarkMode = event.matches;
+ });
+ }
+ _isDarkModeSetup = true;
+ }
+
+ return _isDarkMode;
+}
+
+export function lightDark(light: string, dark: string): string {
+ return isDarkMode() ? dark : light;
+}
+
+export function maybeLightDark(value: string | [string, string]): string {
+ if (typeof value === 'string') {
+ return value;
+ }
+ return lightDark(value[0], value[1]);
+}