diff --git a/examples.json b/examples.json
index caf2df7..702fa86 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:
weta_fade: a basic theme employing a single image specified in theme_frame:.
weta_fade_chrome: the weta_fade theme implemented with Chrome compatible manifest keys.
weta_tiled: a theme using a tiled image.
weta_mirror: a theme using multiple images and aligning those images in the header.
animated: use of an animated PNG.
",
"javascript_apis": [],
diff --git a/themed-icons/README.md b/themed-icons/README.md
new file mode 100644
index 0000000..952fd11
--- /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/2016509)
\ No newline at end of file
diff --git a/themed-icons/background.js b/themed-icons/background.js
new file mode 100644
index 0000000..17e9ab4
--- /dev/null
+++ b/themed-icons/background.js
@@ -0,0 +1,34 @@
+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 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/extpage.html b/themed-icons/extpage.html
new file mode 100644
index 0000000..c509aef
--- /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 0000000..250ae41
--- /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 0000000..9cf8668
--- /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 0000000..948731c
--- /dev/null
+++ b/themed-icons/prefers-color-scheme-icon.svg
@@ -0,0 +1,13 @@
+