mirror of
https://github.com/mdn/webextensions-examples.git
synced 2026-04-16 06:18:35 +02:00
Bug-2001318 example showing SVG icon reacting to theme (#620)
* Bug-2001318 example showing SVG icon reacting to theme * Updates for feedback
This commit is contained in:
@@ -548,6 +548,11 @@
|
||||
"javascript_apis": ["management.getAll", "management.setEnabled"],
|
||||
"name": "theme-switcher"
|
||||
},
|
||||
{
|
||||
"description": "Demonstration of how to use the <code>prefers-color-scheme</code> 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:<ul><li>weta_fade: a basic theme employing a single image specified in <code>theme_frame:</code>.</li><li>weta_fade_chrome: the weta_fade theme implemented with Chrome compatible manifest keys.</li><li>weta_tiled: a theme using a tiled image.</li><li>weta_mirror: a theme using multiple images and aligning those images in the header.</li><li>animated: use of an animated PNG.</li></ul>",
|
||||
"javascript_apis": [],
|
||||
|
||||
27
themed-icons/README.md
Normal file
27
themed-icons/README.md
Normal file
@@ -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)
|
||||
34
themed-icons/background.js
Normal file
34
themed-icons/background.js
Normal file
@@ -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);
|
||||
});
|
||||
32
themed-icons/extpage.html
Normal file
32
themed-icons/extpage.html
Normal file
@@ -0,0 +1,32 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>SVG themed icon using prefer-color-scheme media query</title>
|
||||
<script defer="true" src="extpage.js"></script>
|
||||
<style>
|
||||
dt { font-weight: bold; }
|
||||
|
||||
body {
|
||||
background-color: white;
|
||||
color: black;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
body {
|
||||
background-color: black;
|
||||
color: white;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>SVG themed icon using prefer-color-scheme media query</h1>
|
||||
<dl>
|
||||
<dt>Active theme:</dt>
|
||||
<dd id="active-theme">ACTIVE THEME INFO</dd>
|
||||
</dl>
|
||||
<h2>README.md</h2>
|
||||
<pre id="read-me">README.md content</pre>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
29
themed-icons/extpage.js
Normal file
29
themed-icons/extpage.js
Normal file
@@ -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);
|
||||
});
|
||||
37
themed-icons/manifest.json
Normal file
37
themed-icons/manifest.json
Normal file
@@ -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": ["<all_urls>"]
|
||||
},
|
||||
|
||||
"action": {
|
||||
"default_icon": "prefers-color-scheme-icon.svg",
|
||||
"default_area": "navbar"
|
||||
},
|
||||
|
||||
"permissions": [
|
||||
"management"
|
||||
]
|
||||
}
|
||||
13
themed-icons/prefers-color-scheme-icon.svg
Normal file
13
themed-icons/prefers-color-scheme-icon.svg
Normal file
@@ -0,0 +1,13 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
|
||||
<style>
|
||||
#outside { fill: black; }
|
||||
#inside { fill: red; }
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
#outside { fill: white; }
|
||||
#inside { fill: black; }
|
||||
}
|
||||
</style>
|
||||
<rect id="outside" width="16" height="16" />
|
||||
<rect id="inside" x="4" y="4" width="8" height="8" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 384 B |
Reference in New Issue
Block a user