From df6d3103a95d64ca919184167def1d8948d20818 Mon Sep 17 00:00:00 2001 From: Richard Bloor Date: Wed, 4 Mar 2026 11:34:25 +1300 Subject: [PATCH 1/2] Bug-2001318 example showing SVG icon reacting to theme --- examples.json | 5 +++ themed-icons/README.md | 27 ++++++++++++++++ themed-icons/background.js | 32 +++++++++++++++++++ themed-icons/extpage.html | 32 +++++++++++++++++++ themed-icons/extpage.js | 29 +++++++++++++++++ themed-icons/manifest.json | 37 ++++++++++++++++++++++ themed-icons/prefers-color-scheme-icon.svg | 13 ++++++++ 7 files changed, 175 insertions(+) create mode 100644 themed-icons/README.md create mode 100644 themed-icons/background.js create mode 100644 themed-icons/extpage.html create mode 100644 themed-icons/extpage.js create mode 100644 themed-icons/manifest.json create mode 100644 themed-icons/prefers-color-scheme-icon.svg diff --git a/examples.json b/examples.json index caf2df70..702fa86b 100644 --- a/examples.json +++ b/examples.json @@ -548,6 +548,11 @@ "javascript_apis": ["management.getAll", "management.setEnabled"], "name": "theme-switcher" }, + { + "description": "Demonstration of how to use the prefers-color-scheme media query to adapt an SVG icon to dark and light themes.", + "javascript_apis": ["runtime.getURL","tabs.query", "tabs.create", "tabs.update", "management.getAll","management.setEnabled","management.onEnabled", "pageAction.onClicked","action.onClicked"], + "name": "themed-icons" + }, { "description": "A collection of themes illustrating:", "javascript_apis": [], diff --git a/themed-icons/README.md b/themed-icons/README.md new file mode 100644 index 00000000..2338c910 --- /dev/null +++ b/themed-icons/README.md @@ -0,0 +1,27 @@ +# themed-icons + +This example demonstrates how to use the prefers-color-scheme media query to adapt an SVG icon to dark and light themes. + +## What it does + +This extension includes: + +* a background script, `background.js`. +* page (address bar) and browser (toolbar) action icons. + +The extension displays the [page action](https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/pageAction) on any webpage, and the extension test page, which the extension opens when it starts, and the [browser action](https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/browserAction) is pinned to the toolbar when the extension is installed. + +Clicking either icon opens the test extension page and switches to the next available theme. + +When the active theme is enabled, the page and browser action change color based on the dark or light background color used in the UI. + +For example: +- When the built-in Firefox Alpenglow or dark themes are active, the icons are black with a white outline. +- When the built-in Firefox light theme is active, the icons are red with a black outline. + +## NOTE: Implicit CSS filter applied to pageAction SVG icons in dark themes in Firefox Desktop 151 and earlier + +In builds where the `about:config` preference `extensions.webextensions.pageActionIconDarkModeFilter.enabled` is set to `true` or not defined, a greyscale and brightness CSS filter is applied to page action icons for dark themes. This filter can reduce the contrast of icons that use multiple colors. (See [Bug 2001318](https://bugzilla.mozilla.org/2001318).) + +This implicit CSS filter is turned off in Firefox Desktop Nightly in release 149 and later, and on the release channel +as part of [Bug 2016509](https://bugzilla.mozilla.org/20 \ No newline at end of file diff --git a/themed-icons/background.js b/themed-icons/background.js new file mode 100644 index 00000000..630ec8a8 --- /dev/null +++ b/themed-icons/background.js @@ -0,0 +1,32 @@ +async function openOrSelectTab(reloadExistingTab = false) { + const tabUrl = browser.runtime.getURL("/extpage.html"); + let [tab] = await browser.tabs.query({ url: tabUrl }); + if (!tab) { + await browser.tabs.create({ url: tabUrl, active: true }); + } else { + await browser.tabs.update(tab.id, { + active: true, + ...(reloadExistingTab ? { url: tabUrl } : {}) + }); + } +} + +async function switchToNextTheme() { + openOrSelectTab(); + const themes = await browser.management.getAll().then(extensions => { + return extensions.filter(ext => ext.type === "theme"); + }); + const activeThemeIndex = themes.findIndex(theme => theme.enabled); + const nextThemeIndex = activeThemeIndex < themes.length - 1 + ? activeThemeIndex + 1 + : 0 + const nextTheme = themes[nextThemeIndex]; + await browser.management.setEnabled(nextTheme.id, true); +} + +// Switch to the next theme available on pageAction or action icons clicks. +browser.pageAction.onClicked.addListener(switchToNextTheme); +browser.action.onClicked.addListener(switchToNextTheme); + +// Open or select the extension test page on addon startup. +openOrSelectTab(true); diff --git a/themed-icons/extpage.html b/themed-icons/extpage.html new file mode 100644 index 00000000..c509aef4 --- /dev/null +++ b/themed-icons/extpage.html @@ -0,0 +1,32 @@ + + + + SVG themed icon using prefer-color-scheme media query + + + + +

SVG themed icon using prefer-color-scheme media query

+
+
Active theme:
+
ACTIVE THEME INFO
+
+

README.md

+
README.md content
+ + + diff --git a/themed-icons/extpage.js b/themed-icons/extpage.js new file mode 100644 index 00000000..250ae41b --- /dev/null +++ b/themed-icons/extpage.js @@ -0,0 +1,29 @@ +let activeThemeEl = document.querySelector("#active-theme"); +let readmeEl = document.querySelector("#read-me"); + +function updateThemeInfo(info) { + activeThemeEl.textContent = `${info.name} (${info.id})`; +} + +// Include the README.md file content into the test page. +fetch("/README.md").then(r => r.text()).then(text => { + readmeEl.textContent = text; +}); + +// Set active theme info element content on page load. +browser.management.getAll().then(addons => { + updateThemeInfo(addons.find(addon => addon.type == "theme" && addon.enabled)); +}); + +// Show pageAction icon on the extension page. +browser.tabs.getCurrent().then(tabInfo => { + browser.pageAction.show(tabInfo.id); +}); + +// Update active theme info when a theme is enabled. +browser.management.onEnabled.addListener(info => { + if (info.type !== "theme") { + return; + } + updateThemeInfo(info); +}); diff --git a/themed-icons/manifest.json b/themed-icons/manifest.json new file mode 100644 index 00000000..b7a90b86 --- /dev/null +++ b/themed-icons/manifest.json @@ -0,0 +1,37 @@ +{ + + "description": "Adds page action and action SVG icons that adapt to dark and light themes using prefers-color-scheme media query.", + "manifest_version": 3, + "name": "themed-icons", + "version": "1.0", + "homepage_url": "https://github.com/mdn/webextensions-examples/tree/master/themed-icons", + "browser_specific_settings": + { "gecko": + { + "id": "themed-icons@mozilla.org", + "data_collection_permissions": { + "required": ["none"] + }, + }, + + "icons": { "32": "prefers-color-scheme-icon.svg" }, + + "background": { + "scripts": ["background.js"], + "type": "module" + }, + + "page_action": { + "default_icon": "prefers-color-scheme-icon.svg", + "show_matches": [""] + }, + + "action": { + "default_icon": "prefers-color-scheme-icon.svg", + "default_area": "navbar" + }, + + "permissions": [ + "management" + ] +} diff --git a/themed-icons/prefers-color-scheme-icon.svg b/themed-icons/prefers-color-scheme-icon.svg new file mode 100644 index 00000000..948731ce --- /dev/null +++ b/themed-icons/prefers-color-scheme-icon.svg @@ -0,0 +1,13 @@ + + + + + From 2bdc11518af99cba6680b53c119320a226f62515 Mon Sep 17 00:00:00 2001 From: Richard Bloor Date: Thu, 5 Mar 2026 04:59:08 +1300 Subject: [PATCH 2/2] Updates for feedback --- themed-icons/README.md | 4 ++-- themed-icons/background.js | 6 ++++-- themed-icons/manifest.json | 16 ++++++++-------- 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/themed-icons/README.md b/themed-icons/README.md index 2338c910..952fd118 100644 --- a/themed-icons/README.md +++ b/themed-icons/README.md @@ -21,7 +21,7 @@ For example: ## NOTE: Implicit CSS filter applied to pageAction SVG icons in dark themes in Firefox Desktop 151 and earlier -In builds where the `about:config` preference `extensions.webextensions.pageActionIconDarkModeFilter.enabled` is set to `true` or not defined, a greyscale and brightness CSS filter is applied to page action icons for dark themes. This filter can reduce the contrast of icons that use multiple colors. (See [Bug 2001318](https://bugzilla.mozilla.org/2001318).) +In builds where the `about:config` preference `extensions.webextensions.pageActionIconDarkModeFilter.enabled` is set to `true` or not defined, a greyscale and brightness CSS filter is applied to page action icons for dark themes. This filter can reduce the contrast of icons that use multiple colors, see [Bug 2001318](https://bugzilla.mozilla.org/2001318). This implicit CSS filter is turned off in Firefox Desktop Nightly in release 149 and later, and on the release channel -as part of [Bug 2016509](https://bugzilla.mozilla.org/20 \ No newline at end of file +as part of [Bug 2016509](https://bugzilla.mozilla.org/2016509) \ No newline at end of file diff --git a/themed-icons/background.js b/themed-icons/background.js index 630ec8a8..17e9ab4b 100644 --- a/themed-icons/background.js +++ b/themed-icons/background.js @@ -28,5 +28,7 @@ async function switchToNextTheme() { browser.pageAction.onClicked.addListener(switchToNextTheme); browser.action.onClicked.addListener(switchToNextTheme); -// Open or select the extension test page on addon startup. -openOrSelectTab(true); +// Open the the extension page in a new tab after the add-on is installed. +browser.runtime.onInstalled.addListener(() => { + openOrSelectTab(true); +}); \ No newline at end of file diff --git a/themed-icons/manifest.json b/themed-icons/manifest.json index b7a90b86..9cf86683 100644 --- a/themed-icons/manifest.json +++ b/themed-icons/manifest.json @@ -5,14 +5,14 @@ "name": "themed-icons", "version": "1.0", "homepage_url": "https://github.com/mdn/webextensions-examples/tree/master/themed-icons", - "browser_specific_settings": - { "gecko": - { - "id": "themed-icons@mozilla.org", - "data_collection_permissions": { - "required": ["none"] - }, - }, + "browser_specific_settings": { + "gecko": { + "id": "themed-icons@mozilla.org", + "data_collection_permissions": { + "required": ["none"] + } + } + }, "icons": { "32": "prefers-color-scheme-icon.svg" },