From 3a1fd68604bd184adb8e3979dcc0eceddf4025f1 Mon Sep 17 00:00:00 2001 From: Julian Gaibler Date: Thu, 17 Apr 2025 13:07:02 +0000 Subject: [PATCH] Bug 1954490 - Improve contrast between active tab and tabstrip. r=desktop-theme-reviewers,reusable-components-reviewers,emilio,mstriemer Differential Revision: https://phabricator.services.mozilla.com/D243454 --- .../performance/browser_startup_flicker.js | 18 ++++++++++++++ .../test/performance/browser_windowclose.js | 3 +++ .../test/performance/browser_windowopen.js | 17 +++++++++++++ browser/themes/BuiltInThemeConfig.sys.mjs | 2 +- browser/themes/addons/light/manifest.json | 6 ++--- browser/themes/shared/browser-colors.css | 2 +- mozglue/misc/PreXULSkeletonUI.cpp | 4 +--- .../shared/design-system/design-tokens.json | 8 +++---- .../design-system/tokens-figma-theme.json | 10 ++++---- .../shared/design-system/tokens-shared.css | 6 ++--- .../shared/design-system/tokens-storybook.mjs | 24 +++++++++---------- 11 files changed, 68 insertions(+), 32 deletions(-) diff --git a/browser/base/content/test/performance/browser_startup_flicker.js b/browser/base/content/test/performance/browser_startup_flicker.js index 16300e152570..6822ada5a353 100644 --- a/browser/base/content/test/performance/browser_startup_flicker.js +++ b/browser/base/content/test/performance/browser_startup_flicker.js @@ -20,6 +20,8 @@ add_task(async function () { let unexpectedRects = 0; let alreadyFocused = false; + let inRange = (val, min, max) => min <= val && val <= max; + let tabBoundingRect = undefined; for (let i = 1; i < frames.length; ++i) { let frame = frames[i], previousFrame = frames[i - 1]; @@ -41,6 +43,22 @@ add_task(async function () { /** * Please don't add anything new unless justified! */ + { + name: "Shadow around active tab should not flicker on macOS (bug 1960967)", + condition(r) { + const tabRect = tabBoundingRect + ? tabBoundingRect + : (tabBoundingRect = gBrowser.tabContainer + .querySelector("tab[selected=true] .tab-background") + .getBoundingClientRect()); + return ( + inRange(r.x1, tabRect.x - 2, tabRect.x + 2) && + inRange(r.y1, tabRect.y - 2, tabRect.y + 2) && + inRange(r.w, tabRect.width - 4, tabRect.width + 4) && + inRange(r.h, tabRect.height - 4, tabRect.height + 4) + ); + }, + }, ]; let rectText = `${rect.toSource()}, window width: ${width}`; diff --git a/browser/base/content/test/performance/browser_windowclose.js b/browser/base/content/test/performance/browser_windowclose.js index 11fa669be058..7394a7537878 100644 --- a/browser/base/content/test/performance/browser_windowclose.js +++ b/browser/base/content/test/performance/browser_windowclose.js @@ -33,6 +33,9 @@ add_task(async function () { waitForFocus(resolve, win); }); + // Disable active tab shadow, which causes flickering (bug 1960967) + win.gBrowser.tabContainer.setAttribute("noshadowfortests", "true"); + // At the time of writing, there are no reflows on window closing. // Mochitest will fail if we have no assertions, so we add one here // to make sure nobody adds any new ones. diff --git a/browser/base/content/test/performance/browser_windowopen.js b/browser/base/content/test/performance/browser_windowopen.js index b258cb67f5b4..ddc94479755c 100644 --- a/browser/base/content/test/performance/browser_windowopen.js +++ b/browser/base/content/test/performance/browser_windowopen.js @@ -41,6 +41,7 @@ add_task(async function () { let alreadyFocused = false; let inRange = (val, min, max) => min <= val && val <= max; + let tabBoundingRect = undefined; let expectations = { expectedReflows: EXPECTED_REFLOWS, frames: { @@ -108,6 +109,22 @@ add_task(async function () { ) && // in the toolbar inRange(r.x1, 30, 90), // close to the left of the screen }, + { + name: "Shadow around active tab should not flicker on macOS (bug 1960967)", + condition(r) { + const tabRect = tabBoundingRect + ? tabBoundingRect + : (tabBoundingRect = gBrowser.tabContainer + .querySelector("tab[selected=true] .tab-background") + .getBoundingClientRect()); + return ( + inRange(r.x1, tabRect.x - 2, tabRect.x + 2) && + inRange(r.y1, tabRect.y - 2, tabRect.y + 2) && + inRange(r.w, tabRect.width - 4, tabRect.width + 4) && + inRange(r.h, tabRect.height - 4, tabRect.height + 4) + ); + }, + }, ], }, }; diff --git a/browser/themes/BuiltInThemeConfig.sys.mjs b/browser/themes/BuiltInThemeConfig.sys.mjs index 2d93ad15fd4c..081187147736 100644 --- a/browser/themes/BuiltInThemeConfig.sys.mjs +++ b/browser/themes/BuiltInThemeConfig.sys.mjs @@ -22,7 +22,7 @@ export const BuiltInThemeConfig = new Map([ [ "firefox-compact-light@mozilla.org", { - version: "1.3.1", + version: "1.3.2", path: "resource://builtin-themes/light/", }, ], diff --git a/browser/themes/addons/light/manifest.json b/browser/themes/addons/light/manifest.json index 635072ee3b2e..72a53744f80c 100644 --- a/browser/themes/addons/light/manifest.json +++ b/browser/themes/addons/light/manifest.json @@ -10,7 +10,7 @@ "name": "Light", "description": "A theme with a light color scheme.", "author": "Mozilla", - "version": "1.3.1", + "version": "1.3.2", "icons": { "32": "icon.svg" }, @@ -20,8 +20,8 @@ "tab_selected": "#fff", "tab_text": "rgb(21,20,26)", "icons": "rgb(91,91,102)", - "frame": "rgb(240, 240, 244)", - "frame_inactive": "rgb(235, 235, 239)", + "frame": "rgb(234, 234, 237)", + "frame_inactive": "rgb(240, 240, 244)", "popup": "#fff", "popup_text": "rgb(21,20,26)", "popup_border": "rgb(240,240,244)", diff --git a/browser/themes/shared/browser-colors.css b/browser/themes/shared/browser-colors.css index f5600cafc259..7e3fb4e2076d 100644 --- a/browser/themes/shared/browser-colors.css +++ b/browser/themes/shared/browser-colors.css @@ -111,7 +111,7 @@ /* stylelint-disable-next-line media-query-no-invalid */ @media not ((-moz-windows-mica) or ((-moz-windows-accent-color-in-titlebar) and -moz-pref("browser.theme.windows.accent-color-in-tabs.enabled"))) { - --toolbox-bgcolor: light-dark(rgb(240, 240, 244), rgb(28, 27, 34)); + --toolbox-bgcolor: light-dark(rgb(234, 234, 237), rgb(28, 27, 34)); --toolbox-textcolor: light-dark(rgb(21, 20, 26), rgb(251, 251, 254)); --toolbox-bgcolor-inactive: var(--toolbox-bgcolor); --toolbox-textcolor-inactive: var(--toolbox-textcolor); diff --git a/mozglue/misc/PreXULSkeletonUI.cpp b/mozglue/misc/PreXULSkeletonUI.cpp index abde018dddf5..e4cda5df2ef9 100644 --- a/mozglue/misc/PreXULSkeletonUI.cpp +++ b/mozglue/misc/PreXULSkeletonUI.cpp @@ -1365,9 +1365,7 @@ ThemeColors GetTheme(ThemeMode themeId) { theme.tabColor = 0xf9f9fb; theme.toolbarForegroundColor = 0xdddde1; theme.tabOutlineColor = 0xdddde1; - // found in browser-aero.css ":root[customtitlebar]:not(:-moz-lwtheme)" - // (set to "hsl(235,33%,19%)") - theme.titlebarColor = 0xf0f0f4; + theme.titlebarColor = 0xeaeaed; // --chrome-content-separator-color in browser.css theme.chromeContentDividerColor = 0xe1e1e2; // controlled by css variable --toolbar-color diff --git a/toolkit/themes/shared/design-system/design-tokens.json b/toolkit/themes/shared/design-system/design-tokens.json index 5b2f42be3ccb..e2578dfa30e9 100644 --- a/toolkit/themes/shared/design-system/design-tokens.json +++ b/toolkit/themes/shared/design-system/design-tokens.json @@ -1229,7 +1229,7 @@ "box": { "shadow": { "level-1": { - "value": "0 0.125px 0.25px {box.shadow.color.darker.layer-1}, 0 1px 2px {box.shadow.color.darker.layer-2}" + "value": "0 0 1px {box.shadow.color.darker.layer-1}, 0 1px 2px {box.shadow.color.darker.layer-2}" }, "level-2": { "value": "0 0.25px 0.75px {box.shadow.color.lighter.layer-1}, 0 2px 6px {box.shadow.color.lighter.layer-2}" @@ -1256,14 +1256,14 @@ "darker": { "layer-1": { "value": { - "light": "rgba(0, 0, 0, 0.1)", - "dark": "rgba(0, 0, 0, 0.4)" + "light": "rgba(0, 0, 0, 0.15)", + "dark": "rgba(0, 0, 0, 0.2)" } }, "layer-2": { "value": { "light": "rgba(0, 0, 0, 0.2)", - "dark": "rgba(0, 0, 0, 0.8)" + "dark": "rgba(0, 0, 0, 0.4)" } } }, diff --git a/toolkit/themes/shared/design-system/tokens-figma-theme.json b/toolkit/themes/shared/design-system/tokens-figma-theme.json index d0c835099e9a..20f15d52e0a4 100644 --- a/toolkit/themes/shared/design-system/tokens-figma-theme.json +++ b/toolkit/themes/shared/design-system/tokens-figma-theme.json @@ -403,8 +403,8 @@ "forcedColors": "664px" }, "box/shadow/level-1/shadow-1/x": 0, - "box/shadow/level-1/shadow-1/y": 0.125, - "box/shadow/level-1/shadow-1/blur": 0.25, + "box/shadow/level-1/shadow-1/y": 0, + "box/shadow/level-1/shadow-1/blur": 1, "box/shadow/level-1/shadow-1/spread": 0, "box/shadow/level-1/shadow-1/color": "{Theme$box/shadow/color/darker/layer-1}", "box/shadow/level-1/shadow-1/inset": false, @@ -451,13 +451,13 @@ "box/shadow/level-4/shadow-2/color": "{Theme$box/shadow/color/lighter/layer-2}", "box/shadow/level-4/shadow-2/inset": false, "box/shadow/color/darker/layer-1": { - "light": "rgba(0, 0, 0, 0.1)", - "dark": "rgba(0, 0, 0, 0.4)", + "light": "rgba(0, 0, 0, 0.15)", + "dark": "rgba(0, 0, 0, 0.2)", "forcedColors": "transparent" }, "box/shadow/color/darker/layer-2": { "light": "rgba(0, 0, 0, 0.2)", - "dark": "rgba(0, 0, 0, 0.8)", + "dark": "rgba(0, 0, 0, 0.4)", "forcedColors": "transparent" }, "box/shadow/color/lighter/layer-1": { diff --git a/toolkit/themes/shared/design-system/tokens-shared.css b/toolkit/themes/shared/design-system/tokens-shared.css index c58af032d8b0..17a428f9981a 100644 --- a/toolkit/themes/shared/design-system/tokens-shared.css +++ b/toolkit/themes/shared/design-system/tokens-shared.css @@ -30,11 +30,11 @@ /** Box Shadow **/ --box-shadow-card: var(--box-shadow-level-2); --box-shadow-card-hover: var(--box-shadow-level-4); - --box-shadow-color-darker-layer-1: light-dark(rgba(0, 0, 0, 0.1), rgba(0, 0, 0, 0.4)); - --box-shadow-color-darker-layer-2: light-dark(rgba(0, 0, 0, 0.2), rgba(0, 0, 0, 0.8)); + --box-shadow-color-darker-layer-1: light-dark(rgba(0, 0, 0, 0.15), rgba(0, 0, 0, 0.2)); + --box-shadow-color-darker-layer-2: light-dark(rgba(0, 0, 0, 0.2), rgba(0, 0, 0, 0.4)); --box-shadow-color-lighter-layer-1: light-dark(rgba(0, 0, 0, 0.05), rgba(0, 0, 0, 0.2)); --box-shadow-color-lighter-layer-2: light-dark(rgba(0, 0, 0, 0.1), rgba(0, 0, 0, 0.4)); - --box-shadow-level-1: 0 0.125px 0.25px var(--box-shadow-color-darker-layer-1), 0 1px 2px var(--box-shadow-color-darker-layer-2); + --box-shadow-level-1: 0 0 1px var(--box-shadow-color-darker-layer-1), 0 1px 2px var(--box-shadow-color-darker-layer-2); --box-shadow-level-2: 0 0.25px 0.75px var(--box-shadow-color-lighter-layer-1), 0 2px 6px var(--box-shadow-color-lighter-layer-2); --box-shadow-level-3: 0 0.375px 1.5px var(--box-shadow-color-lighter-layer-1), 0 3px 12px var(--box-shadow-color-lighter-layer-2); --box-shadow-level-4: 0 0.5px 2px var(--box-shadow-color-lighter-layer-1), 0 4px 16px var(--box-shadow-color-lighter-layer-2); diff --git a/toolkit/themes/shared/design-system/tokens-storybook.mjs b/toolkit/themes/shared/design-system/tokens-storybook.mjs index 8c53b8aeccef..49599f7a3548 100644 --- a/toolkit/themes/shared/design-system/tokens-storybook.mjs +++ b/toolkit/themes/shared/design-system/tokens-storybook.mjs @@ -900,7 +900,7 @@ export const storybookTables = { "box-shadow": [ { value: - "0 0.125px 0.25px var(--box-shadow-color-darker-layer-1), 0 1px 2px var(--box-shadow-color-darker-layer-2)", + "0 0 1px var(--box-shadow-color-darker-layer-1), 0 1px 2px var(--box-shadow-color-darker-layer-2)", name: "--box-shadow-level-1", }, { @@ -924,17 +924,17 @@ export const storybookTables = { { value: "var(--box-shadow-level-3)", name: "--box-shadow-popup" }, { value: { - light: "rgba(0, 0, 0, 0.1)", - dark: "rgba(0, 0, 0, 0.4)", - default: "light-dark(rgba(0, 0, 0, 0.1), rgba(0, 0, 0, 0.4))", + light: "rgba(0, 0, 0, 0.15)", + dark: "rgba(0, 0, 0, 0.2)", + default: "light-dark(rgba(0, 0, 0, 0.15), rgba(0, 0, 0, 0.2))", }, name: "--box-shadow-color-darker-layer-1", }, { value: { light: "rgba(0, 0, 0, 0.2)", - dark: "rgba(0, 0, 0, 0.8)", - default: "light-dark(rgba(0, 0, 0, 0.2), rgba(0, 0, 0, 0.8))", + dark: "rgba(0, 0, 0, 0.4)", + default: "light-dark(rgba(0, 0, 0, 0.2), rgba(0, 0, 0, 0.4))", }, name: "--box-shadow-color-darker-layer-2", }, @@ -1514,7 +1514,7 @@ export const variableLookupTable = { "space-xlarge": "calc(6 * var(--space-xsmall))", "space-xxlarge": "calc(8 * var(--space-xsmall))", "box-shadow-level-1": - "0 0.125px 0.25px var(--box-shadow-color-darker-layer-1), 0 1px 2px var(--box-shadow-color-darker-layer-2)", + "0 0 1px var(--box-shadow-color-darker-layer-1), 0 1px 2px var(--box-shadow-color-darker-layer-2)", "box-shadow-level-2": "0 0.25px 0.75px var(--box-shadow-color-lighter-layer-1), 0 2px 6px var(--box-shadow-color-lighter-layer-2)", "box-shadow-level-3": @@ -1526,14 +1526,14 @@ export const variableLookupTable = { "box-shadow-card-hover": "var(--box-shadow-level-4)", "box-shadow-popup": "var(--box-shadow-level-3)", "box-shadow-color-darker-layer-1": { - light: "rgba(0, 0, 0, 0.1)", - dark: "rgba(0, 0, 0, 0.4)", - default: "light-dark(rgba(0, 0, 0, 0.1), rgba(0, 0, 0, 0.4))", + light: "rgba(0, 0, 0, 0.15)", + dark: "rgba(0, 0, 0, 0.2)", + default: "light-dark(rgba(0, 0, 0, 0.15), rgba(0, 0, 0, 0.2))", }, "box-shadow-color-darker-layer-2": { light: "rgba(0, 0, 0, 0.2)", - dark: "rgba(0, 0, 0, 0.8)", - default: "light-dark(rgba(0, 0, 0, 0.2), rgba(0, 0, 0, 0.8))", + dark: "rgba(0, 0, 0, 0.4)", + default: "light-dark(rgba(0, 0, 0, 0.2), rgba(0, 0, 0, 0.4))", }, "box-shadow-color-lighter-layer-1": { light: "rgba(0, 0, 0, 0.05)",