зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1876432 - Added support for custom themes as its own menu in Reader View. r=reader-mode-reviewers,fluent-reviewers,desktop-theme-reviewers,hjones,accessibility-frontend-reviewers,bolsson,devtools-reviewers,sfoster,cmkm,jules,ayeddi
Differential Revision: https://phabricator.services.mozilla.com/D204519
This commit is contained in:
Родитель
19da69d55e
Коммит
f701879f1c
|
@ -217,7 +217,7 @@ const extraBrowserTestPaths = [
|
|||
"toolkit/components/pdfjs/test/",
|
||||
"toolkit/components/pictureinpicture/tests/",
|
||||
"toolkit/components/printing/tests/",
|
||||
"toolkit/components/reader/test/",
|
||||
"toolkit/components/reader/tests/",
|
||||
"toolkit/components/thumbnails/test/",
|
||||
"toolkit/components/tooltiptext/tests/",
|
||||
"toolkit/components/windowcreator/test/",
|
||||
|
|
24
.eslintrc.js
24
.eslintrc.js
|
@ -2078,18 +2078,18 @@ module.exports = {
|
|||
"toolkit/components/processtools/tests/browser/browser_test_procinfo.js",
|
||||
"toolkit/components/prompts/test/test_modal_prompts.html",
|
||||
"toolkit/components/prompts/test/test_subresources_prompts.html",
|
||||
"toolkit/components/reader/test/browser_bug1453818_samesite_cookie.js",
|
||||
"toolkit/components/reader/test/browser_drag_url_readerMode.js",
|
||||
"toolkit/components/reader/test/browser_readerMode_bc_reuse.js",
|
||||
"toolkit/components/reader/test/browser_readerMode_colorSchemePref.js",
|
||||
"toolkit/components/reader/test/browser_readerMode_hidden_nodes.js",
|
||||
"toolkit/components/reader/test/browser_readerMode_menu.js",
|
||||
"toolkit/components/reader/test/browser_readerMode_pocket.js",
|
||||
"toolkit/components/reader/test/browser_readerMode_readingTime.js",
|
||||
"toolkit/components/reader/test/browser_readerMode_refresh.js",
|
||||
"toolkit/components/reader/test/browser_readerMode_remoteType.js",
|
||||
"toolkit/components/reader/test/browser_readerMode_samesite_cookie_redirect.js",
|
||||
"toolkit/components/reader/test/browser_readerMode_with_anchor.js",
|
||||
"toolkit/components/reader/tests/browser/browser_bug1453818_samesite_cookie.js",
|
||||
"toolkit/components/reader/tests/browser/browser_drag_url_readerMode.js",
|
||||
"toolkit/components/reader/tests/browser/browser_readerMode_bc_reuse.js",
|
||||
"toolkit/components/reader/tests/browser/browser_readerMode_colorSchemePref.js",
|
||||
"toolkit/components/reader/tests/browser/browser_readerMode_hidden_nodes.js",
|
||||
"toolkit/components/reader/tests/browser/browser_readerMode_menu.js",
|
||||
"toolkit/components/reader/tests/browser/browser_readerMode_pocket.js",
|
||||
"toolkit/components/reader/tests/browser/browser_readerMode_readingTime.js",
|
||||
"toolkit/components/reader/tests/browser/browser_readerMode_refresh.js",
|
||||
"toolkit/components/reader/tests/browser/browser_readerMode_remoteType.js",
|
||||
"toolkit/components/reader/tests/browser/browser_readerMode_samesite_cookie_redirect.js",
|
||||
"toolkit/components/reader/tests/browser/browser_readerMode_with_anchor.js",
|
||||
"toolkit/components/resistfingerprinting/tests/test_spoof_english.html",
|
||||
"toolkit/components/satchel/test/browser/browser_privbrowsing_perwindowpb.js",
|
||||
"toolkit/components/startup/tests/browser/browser_bug511456.js",
|
||||
|
|
|
@ -953,8 +953,8 @@ toolkit/components/places/tests/unit/bookmarks_html_localized.html
|
|||
toolkit/components/places/tests/unit/bookmarks_html_singleframe.html
|
||||
toolkit/components/printing/tests/simplifyArticleSample.html
|
||||
toolkit/components/processtools/tests/browser/dummy.html
|
||||
toolkit/components/reader/test/readerModeArticleMedium.html
|
||||
toolkit/components/reader/test/readerModeArticleShort.html
|
||||
toolkit/components/reader/tests/browser/readerModeArticleMedium.html
|
||||
toolkit/components/reader/tests/browser/readerModeArticleShort.html
|
||||
toolkit/components/translations/content/translations.html
|
||||
toolkit/components/translations/tests/browser/translations-tester-no-tag.html
|
||||
toolkit/components/url-classifier/tests/mochitest/classifiedAnnotatedFrame.html
|
||||
|
|
|
@ -46,8 +46,8 @@ support-files = [
|
|||
"empty.xpi",
|
||||
"../../../../../toolkit/components/extensions/test/mochitest/head_webrequest.js",
|
||||
"../../../../../toolkit/components/extensions/test/mochitest/redirection.sjs",
|
||||
"../../../../../toolkit/components/reader/test/readerModeNonArticle.html",
|
||||
"../../../../../toolkit/components/reader/test/readerModeArticle.html",
|
||||
"../../../../../toolkit/components/reader/tests/browser/readerModeNonArticle.html",
|
||||
"../../../../../toolkit/components/reader/tests/browser/readerModeArticle.html",
|
||||
]
|
||||
skip-if = ["os == 'linux' && os_version == '18.04' && asan"] # Bug 1721945 - Software WebRender
|
||||
|
||||
|
|
|
@ -19,6 +19,8 @@ module.exports = {
|
|||
`${projectRoot}/toolkit/content/widgets/**/*.stories.@(js|jsx|mjs|ts|tsx|md)`,
|
||||
// about:logins components stories
|
||||
`${projectRoot}/browser/components/aboutlogins/content/components/**/*.stories.mjs`,
|
||||
// Reader View components stories
|
||||
`${projectRoot}/toolkit/components/reader/**/*.stories.mjs`,
|
||||
// Everything else
|
||||
"../stories/**/*.stories.@(js|jsx|mjs|ts|tsx|md)",
|
||||
// Design system files
|
||||
|
|
|
@ -28,7 +28,7 @@ support-files = [
|
|||
"!/devtools/client/framework/browser-toolbox/test/helpers-browser-toolbox.js",
|
||||
"!/devtools/client/shared/test/telemetry-test-helpers.js",
|
||||
"!/devtools/client/shared/test/highlighter-test-actor.js",
|
||||
"../../../../../toolkit/components/reader/test/readerModeArticle.html",
|
||||
"../../../../../toolkit/components/reader/tests/browser/readerModeArticle.html",
|
||||
]
|
||||
|
||||
["browser_jsterm_add_edited_input_to_history.js"]
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
// Ensure keyboard navigation works in editor mode and does
|
||||
// not trigger reader mode (See 1682340).
|
||||
|
||||
const TEST_URI = `http://example.com/browser/toolkit/components/reader/test/readerModeArticle.html`;
|
||||
const TEST_URI = `http://example.com/browser/toolkit/components/reader/tests/browser/readerModeArticle.html`;
|
||||
const isMacOS = AppConstants.platform === "macosx";
|
||||
|
||||
add_task(async function () {
|
||||
|
|
|
@ -3569,7 +3569,19 @@ pref("reader.line_height", 4);
|
|||
pref("reader.color_scheme", "auto");
|
||||
|
||||
// Color scheme values available in reader mode UI.
|
||||
pref("reader.color_scheme.values", "[\"light\",\"dark\",\"sepia\",\"auto\"]");
|
||||
pref("reader.color_scheme.values", "[\"auto\",\"light\",\"dark\",\"sepia\",\"contrast\",\"gray\"]");
|
||||
|
||||
// Determines if updated color theme menu is enabled in reader mode.
|
||||
pref("reader.colors_menu.enabled", false);
|
||||
|
||||
// The custom color scheme options in reader colors menu.
|
||||
pref("reader.custom_colors.foreground", "");
|
||||
pref("reader.custom_colors.background", "");
|
||||
|
||||
pref("reader.custom_colors.unvisited-links", "");
|
||||
pref("reader.custom_colors.visited-links", "");
|
||||
|
||||
pref("reader.custom_colors.selection-highlight", "");
|
||||
|
||||
// The font type in reader (sans-serif, serif)
|
||||
pref("reader.font_type", "sans-serif");
|
||||
|
|
|
@ -271,7 +271,7 @@
|
|||
"toolkit/components/pictureinpicture/tests/browser.ini": 85.82,
|
||||
"toolkit/components/places/tests/browser/browser.ini": 30.19,
|
||||
"toolkit/components/printing/tests/browser.ini": 7.15,
|
||||
"toolkit/components/reader/test/browser.ini": 17.92,
|
||||
"toolkit/components/reader/tests/browser/browser.ini": 17.92,
|
||||
"toolkit/components/remotebrowserutils/tests/browser/browser.ini": 33.48,
|
||||
"toolkit/components/remotepagemanager/tests/browser/browser.ini": 6.94,
|
||||
"toolkit/components/satchel/test/browser/browser.ini": 6.09,
|
||||
|
|
|
@ -271,7 +271,7 @@
|
|||
"toolkit/components/pictureinpicture/tests/browser.ini": 51.8,
|
||||
"toolkit/components/places/tests/browser/browser.ini": 25.44,
|
||||
"toolkit/components/printing/tests/browser.ini": 4.86,
|
||||
"toolkit/components/reader/test/browser.ini": 11.29,
|
||||
"toolkit/components/reader/tests/browser/browser.ini": 11.29,
|
||||
"toolkit/components/remotebrowserutils/tests/browser/browser.ini": 16.4,
|
||||
"toolkit/components/remotepagemanager/tests/browser/browser.ini": 2.77,
|
||||
"toolkit/components/satchel/test/browser/browser.ini": 3.38,
|
||||
|
|
|
@ -38,7 +38,7 @@ export function NarrateControls(win, languagePromise) {
|
|||
toggleButton.dataset.telemetryId = "reader-listen";
|
||||
let tip = win.document.createElement("span");
|
||||
let shortcutNarrateKey = gStrings.GetStringFromName("narrate-key-shortcut");
|
||||
let labelText = gStrings.formatStringFromName("listen-label", [
|
||||
let labelText = gStrings.formatStringFromName("read-aloud-label", [
|
||||
shortcutNarrateKey,
|
||||
]);
|
||||
tip.textContent = labelText;
|
||||
|
@ -65,10 +65,6 @@ export function NarrateControls(win, languagePromise) {
|
|||
narrateVoices.className = "narrate-row narrate-voices";
|
||||
dropdownList.appendChild(narrateVoices);
|
||||
|
||||
let dropdownArrow = win.document.createElement("div");
|
||||
dropdownArrow.className = "dropdown-arrow";
|
||||
dropdownList.appendChild(dropdownArrow);
|
||||
|
||||
let narrateSkipPrevious = win.document.createElement("button");
|
||||
narrateSkipPrevious.className = "narrate-skip-previous";
|
||||
narrateSkipPrevious.disabled = true;
|
||||
|
|
|
@ -8,6 +8,7 @@ import { AppConstants } from "resource://gre/modules/AppConstants.sys.mjs";
|
|||
|
||||
const lazy = {};
|
||||
let gScrollPositions = new Map();
|
||||
let lastSelectedTheme = "auto";
|
||||
|
||||
ChromeUtils.defineESModuleGetters(lazy, {
|
||||
AsyncPrefs: "resource://gre/modules/AsyncPrefs.sys.mjs",
|
||||
|
@ -26,10 +27,31 @@ ChromeUtils.defineLazyGetter(
|
|||
);
|
||||
|
||||
const COLORSCHEME_L10N_IDS = {
|
||||
light: "about-reader-color-scheme-light",
|
||||
dark: "about-reader-color-scheme-dark",
|
||||
sepia: "about-reader-color-scheme-sepia",
|
||||
auto: "about-reader-color-scheme-auto",
|
||||
auto: "about-reader-color-theme-auto",
|
||||
light: "about-reader-color-theme-light",
|
||||
dark: "about-reader-color-theme-dark",
|
||||
sepia: "about-reader-color-theme-sepia",
|
||||
contrast: "about-reader-color-theme-contrast",
|
||||
gray: "about-reader-color-theme-gray",
|
||||
custom: "about-reader-color-theme-custom",
|
||||
};
|
||||
|
||||
const CUSTOM_THEME_COLOR_INPUTS = [
|
||||
"foreground",
|
||||
"background",
|
||||
"unvisited-links",
|
||||
"visited-links",
|
||||
"selection-highlight",
|
||||
];
|
||||
|
||||
const COLORS_MENU_TABS = ["fxtheme", "customtheme"];
|
||||
|
||||
const DEFAULT_COLORS = {
|
||||
background: "#FFFFFF",
|
||||
foreground: "#14151A",
|
||||
"unvisited-links": "#0060DF",
|
||||
"visited-links": "#321C64",
|
||||
"selection-highlight": "#FFFFCC",
|
||||
};
|
||||
|
||||
Services.telemetry.setEventRecordingEnabled("readermode", true);
|
||||
|
@ -147,9 +169,27 @@ export var AboutReader = function (
|
|||
// we're ready for any external setup, send a signal for that.
|
||||
this._actor.sendAsyncMessage("Reader:OnSetup");
|
||||
|
||||
let colorSchemeValues = JSON.parse(
|
||||
// set up segmented tab controls for colors menu.
|
||||
this._setupColorsTabs(
|
||||
COLORS_MENU_TABS,
|
||||
this._handleColorsTabClick.bind(this)
|
||||
);
|
||||
|
||||
// fetch color scheme values from prefs.
|
||||
let colorsMenuColorSchemeValues = JSON.parse(
|
||||
Services.prefs.getCharPref("reader.color_scheme.values")
|
||||
);
|
||||
// remove contrast and gray options from regular menu.
|
||||
let colorSchemeValues = [...colorsMenuColorSchemeValues];
|
||||
colorSchemeValues.splice(colorSchemeValues.length - 2, 2);
|
||||
|
||||
let colorsMenuColorSchemeOptions = colorsMenuColorSchemeValues.map(value => ({
|
||||
l10nId: COLORSCHEME_L10N_IDS[value],
|
||||
groupName: "color-scheme",
|
||||
value,
|
||||
itemClass: value + "-button",
|
||||
}));
|
||||
|
||||
let colorSchemeOptions = colorSchemeValues.map(value => ({
|
||||
l10nId: COLORSCHEME_L10N_IDS[value],
|
||||
groupName: "color-scheme",
|
||||
|
@ -158,12 +198,33 @@ export var AboutReader = function (
|
|||
}));
|
||||
let colorScheme = Services.prefs.getCharPref("reader.color_scheme");
|
||||
|
||||
this._setupSegmentedButton(
|
||||
"color-scheme-buttons",
|
||||
colorSchemeOptions,
|
||||
colorScheme,
|
||||
this._setColorSchemePref.bind(this)
|
||||
);
|
||||
if (Services.prefs.getBoolPref("reader.colors_menu.enabled", false)) {
|
||||
doc.getElementById("regular-color-scheme").hidden = true;
|
||||
doc.getElementById("custom-colors-color-scheme").hidden = false;
|
||||
this._setupSegmentedButton(
|
||||
"colors-menu-color-scheme-buttons",
|
||||
colorsMenuColorSchemeOptions,
|
||||
colorScheme,
|
||||
this._setColorSchemePref.bind(this)
|
||||
);
|
||||
this._setupCustomColors(
|
||||
CUSTOM_THEME_COLOR_INPUTS,
|
||||
"custom-colors-selection",
|
||||
"about-reader-custom-colors"
|
||||
);
|
||||
this._setupButton(
|
||||
"custom-colors-reset-button",
|
||||
this._resetCustomColors.bind(this)
|
||||
);
|
||||
} else {
|
||||
this._setupSegmentedButton(
|
||||
"color-scheme-buttons",
|
||||
colorSchemeOptions,
|
||||
colorScheme,
|
||||
this._setColorSchemePref.bind(this)
|
||||
);
|
||||
}
|
||||
|
||||
this._setColorSchemePref(colorScheme);
|
||||
|
||||
let fontTypeOptions = [
|
||||
|
@ -738,19 +799,43 @@ AboutReader.prototype = {
|
|||
this._colorScheme = "hcm";
|
||||
}
|
||||
|
||||
if (this._colorScheme == "custom") {
|
||||
const colorInputs = this._doc.querySelectorAll("color-input");
|
||||
colorInputs.forEach(input => {
|
||||
// Set document body styles to pref values.
|
||||
let property = input.getAttribute("prop-name");
|
||||
let pref = `reader.custom_colors.${property}`;
|
||||
let customColor = Services.prefs.getStringPref(pref, "");
|
||||
// If customColor is truthy, set the value from pref.
|
||||
if (customColor) {
|
||||
let cssProp = `--custom-theme-${property}`;
|
||||
this._doc.body.style.setProperty(cssProp, customColor);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
bodyClasses.add(this._colorScheme);
|
||||
},
|
||||
|
||||
// Pref values include "dark", "light", "sepia", and "auto"
|
||||
_setColorSchemePref(colorSchemePref) {
|
||||
// Pref values include "auto", "dark", "light", "sepia",
|
||||
// "gray", "contrast", and "custom"
|
||||
_setColorSchemePref(colorSchemePref, fromInputEvent = false) {
|
||||
// The input event for the last selected segmented button is fired
|
||||
// upon loading a reader article in the same session. To prevent it
|
||||
// from overwriting custom colors, we return false.
|
||||
if (this._colorScheme == "custom" && fromInputEvent) {
|
||||
lastSelectedTheme = colorSchemePref;
|
||||
return false;
|
||||
}
|
||||
this._setColorScheme(colorSchemePref);
|
||||
|
||||
lazy.AsyncPrefs.set("reader.color_scheme", colorSchemePref);
|
||||
return true;
|
||||
},
|
||||
|
||||
_setFontType(newFontType) {
|
||||
if (this._fontType === newFontType) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
|
||||
let bodyClasses = this._doc.body.classList;
|
||||
|
@ -763,6 +848,8 @@ AboutReader.prototype = {
|
|||
bodyClasses.add(this._fontType);
|
||||
|
||||
lazy.AsyncPrefs.set("reader.font_type", this._fontType);
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
async _loadArticle(docContentType = "document") {
|
||||
|
@ -1094,14 +1181,17 @@ AboutReader.prototype = {
|
|||
label.removeAttribute("checked");
|
||||
}
|
||||
|
||||
aEvent.target.nextElementSibling.setAttribute("checked", "true");
|
||||
callback(option.value);
|
||||
let setOption = callback(option.value, true);
|
||||
if (setOption) {
|
||||
aEvent.target.setAttribute("checked", "true");
|
||||
aEvent.target.nextElementSibling.setAttribute("checked", "true");
|
||||
}
|
||||
},
|
||||
true
|
||||
);
|
||||
|
||||
if (option.value === initialValue) {
|
||||
radioButton.checked = true;
|
||||
radioButton.setAttribute("checked", "true");
|
||||
item.setAttribute("checked", "true");
|
||||
}
|
||||
}
|
||||
|
@ -1124,6 +1214,121 @@ AboutReader.prototype = {
|
|||
);
|
||||
},
|
||||
|
||||
_handleColorsTabClick(option) {
|
||||
let doc = this._doc;
|
||||
if (option == "customtheme") {
|
||||
this._setColorSchemePref("custom");
|
||||
lazy.AsyncPrefs.set("reader.color_scheme", "custom");
|
||||
|
||||
// Store the last selected preset theme button.
|
||||
const colorSchemePresets = doc.querySelector(
|
||||
".colors-menu-color-scheme-buttons"
|
||||
);
|
||||
const labels = colorSchemePresets.querySelectorAll("label");
|
||||
labels.forEach(label => {
|
||||
if (label.hasAttribute("checked")) {
|
||||
lastSelectedTheme = label.className.split("-")[0];
|
||||
}
|
||||
});
|
||||
}
|
||||
if (option == "fxtheme") {
|
||||
this._setColorSchemePref(lastSelectedTheme);
|
||||
lazy.AsyncPrefs.set("reader.color_scheme", lastSelectedTheme);
|
||||
// set the last selected button to checked.
|
||||
const colorSchemePresets = doc.querySelector(
|
||||
".colors-menu-color-scheme-buttons"
|
||||
);
|
||||
const labels = colorSchemePresets.querySelectorAll("label");
|
||||
labels.forEach(label => {
|
||||
if (label.className == `${lastSelectedTheme}-button`) {
|
||||
label.setAttribute("checked", "true");
|
||||
label.previousElementSibling.setAttribute("checked", "true");
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
_setupColorsTabs(options, callback) {
|
||||
let doc = this._doc;
|
||||
let colorScheme = Services.prefs.getCharPref("reader.color_scheme");
|
||||
for (let option of options) {
|
||||
let tabButton = doc.getElementById(`tabs-deck-button-${option}`);
|
||||
// Open custom theme tab if color scheme is set to custom.
|
||||
if (option == "customtheme" && colorScheme == "custom") {
|
||||
tabButton.click();
|
||||
}
|
||||
tabButton.addEventListener(
|
||||
"click",
|
||||
function (aEvent) {
|
||||
if (!aEvent.isTrusted) {
|
||||
return;
|
||||
}
|
||||
|
||||
callback(option);
|
||||
},
|
||||
true
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
_setupColorInput(prop) {
|
||||
let doc = this._doc;
|
||||
let input = doc.createElement("color-input");
|
||||
input.setAttribute("prop-name", prop);
|
||||
let labelL10nId = `about-reader-custom-colors-${prop}`;
|
||||
input.setAttribute("data-l10n-id", labelL10nId);
|
||||
|
||||
let pref = `reader.custom_colors.${prop}`;
|
||||
let customColor = Services.prefs.getStringPref(pref, "");
|
||||
// Set the swatch color from prefs if one has been set.
|
||||
if (customColor) {
|
||||
input.setAttribute("color", customColor);
|
||||
} else {
|
||||
let defaultColor = DEFAULT_COLORS[prop];
|
||||
input.setAttribute("color", defaultColor);
|
||||
}
|
||||
|
||||
// Attach event listener to update the pref and page colors on input.
|
||||
input.addEventListener("color-picked", e => {
|
||||
const cssPropToUpdate = `--custom-theme-${prop}`;
|
||||
this._doc.body.style.setProperty(cssPropToUpdate, e.detail);
|
||||
|
||||
const prefToUpdate = `reader.custom_colors.${prop}`;
|
||||
lazy.AsyncPrefs.set(prefToUpdate, e.detail);
|
||||
});
|
||||
|
||||
return input;
|
||||
},
|
||||
|
||||
_setupCustomColors(options, id) {
|
||||
let doc = this._doc;
|
||||
const list = doc.getElementsByClassName(id)[0];
|
||||
|
||||
for (let option of options) {
|
||||
let listItem = doc.createElement("li");
|
||||
let colorInput = this._setupColorInput(option);
|
||||
listItem.appendChild(colorInput);
|
||||
list.appendChild(listItem);
|
||||
}
|
||||
},
|
||||
|
||||
_resetCustomColors() {
|
||||
// Need to reset prefs, page colors, and color inputs.
|
||||
const colorInputs = this._doc.querySelectorAll("color-input");
|
||||
colorInputs.forEach(input => {
|
||||
let property = input.getAttribute("prop-name");
|
||||
let pref = `reader.custom_colors.${property}`;
|
||||
lazy.AsyncPrefs.set(pref, "");
|
||||
|
||||
// Set css props to empty strings so they use fallback value.
|
||||
let cssProp = `--custom-theme-${property}`;
|
||||
this._doc.body.style.setProperty(cssProp, "");
|
||||
|
||||
let defaultColor = DEFAULT_COLORS[property];
|
||||
input.setAttribute("color", defaultColor);
|
||||
});
|
||||
},
|
||||
|
||||
_toggleDropdownClicked(event) {
|
||||
let dropdown = event.target.closest(".dropdown");
|
||||
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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/. */
|
||||
|
||||
.color-input-container {
|
||||
display: flex;
|
||||
position: relative;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
gap: var(--space-small);
|
||||
min-height: 46px;
|
||||
border: 1px solid rgba(0, 0, 0, 0.2);
|
||||
padding: 0 var(--space-small);
|
||||
border-radius: var(--border-radius-small);
|
||||
}
|
||||
|
||||
.color-input-container:hover {
|
||||
background-color: var(--toolbar-button-background-hover);
|
||||
}
|
||||
|
||||
#color-swatch:focus-visible {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
.color-input-container:focus-within {
|
||||
outline: 2px solid var(--primary-color);
|
||||
outline-offset: var(--focus-outline-offset);
|
||||
}
|
||||
|
||||
.icon-container {
|
||||
display: flex;
|
||||
margin-inline: auto var(--space-xsmall);
|
||||
}
|
||||
|
||||
#color-swatch {
|
||||
appearance: none;
|
||||
width: 34px;
|
||||
height: 34px;
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#color-swatch::-moz-color-swatch {
|
||||
border-radius: var(--border-radius-circle);
|
||||
border: 1px solid rgba(0, 0, 0, 0.25);
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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/. */
|
||||
|
||||
import { html } from "chrome://global/content/vendor/lit.all.mjs";
|
||||
import { MozLitElement } from "chrome://global/content/lit-utils.mjs";
|
||||
|
||||
/**
|
||||
* @tagname color-input
|
||||
* @property {string} color - The initial color value as a hex code.
|
||||
* @property {string} propName - The property that the color input sets.
|
||||
* @property {string} l10nId - l10nId for label text.
|
||||
*/
|
||||
export default class ColorInput extends MozLitElement {
|
||||
static properties = {
|
||||
color: { type: String },
|
||||
propName: { type: String, attribute: "prop-name" },
|
||||
l10nId: { type: String, attribute: "data-l10n-id" },
|
||||
};
|
||||
|
||||
static queries = {
|
||||
inputEl: "#color-swatch",
|
||||
};
|
||||
|
||||
handleColorInput(event) {
|
||||
this.color = event.target.value;
|
||||
this.dispatchEvent(
|
||||
new CustomEvent("color-picked", {
|
||||
detail: this.color,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
/* Function to launch color picker when the user clicks anywhere in the container. */
|
||||
handleClick(event) {
|
||||
// If the user directly clicks the color swatch, no need to propagate click.
|
||||
if (event.target.matches("input")) {
|
||||
return;
|
||||
}
|
||||
this.inputEl.click();
|
||||
}
|
||||
|
||||
render() {
|
||||
return html`
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="chrome://global/content/reader/color-input.css"
|
||||
/>
|
||||
<div class="color-input-container" @click="${this.handleClick}">
|
||||
<input
|
||||
type="color"
|
||||
name="${this.propName}"
|
||||
.value="${this.color}"
|
||||
id="color-swatch"
|
||||
@input="${this.handleColorInput}"
|
||||
/>
|
||||
<label for="color-swatch" data-l10n-id=${this.l10nId}></label>
|
||||
<div class="icon-container">
|
||||
<img
|
||||
class="icon"
|
||||
role="presentation"
|
||||
src="chrome://global/skin/icons/edit-outline.svg"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
}
|
||||
customElements.define("color-input", ColorInput);
|
|
@ -0,0 +1,32 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* 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/. */
|
||||
|
||||
import { html } from "../../content/widgets/vendor/lit.all.mjs";
|
||||
// eslint-disable-next-line import/no-unassigned-import
|
||||
import "chrome://global/content/reader/color-input.mjs";
|
||||
|
||||
export default {
|
||||
title: "Domain-specific UI Widgets/Reader View/Color Input",
|
||||
component: "color-input",
|
||||
argTypes: {},
|
||||
parameters: {
|
||||
status: "stable",
|
||||
fluent: `moz-color-input-label = Background`,
|
||||
},
|
||||
};
|
||||
|
||||
const Template = ({ color, propName, labelL10nId }) => html`
|
||||
<color-input
|
||||
color=${color}
|
||||
data-l10n-id=${labelL10nId}
|
||||
prop-name=${propName}
|
||||
></color-input>
|
||||
`;
|
||||
|
||||
export const Default = Template.bind({});
|
||||
Default.args = {
|
||||
propName: "background",
|
||||
color: "#7293C9",
|
||||
labelL10nId: "moz-color-input-label",
|
||||
};
|
|
@ -12,6 +12,10 @@
|
|||
/>
|
||||
<meta content="text/html; charset=UTF-8" http-equiv="content-type" />
|
||||
<meta name="viewport" content="width=device-width; user-scalable=0" />
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="chrome://global/skin/design-system/tokens-brand.css"
|
||||
/>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="chrome://global/skin/aboutReader.css"
|
||||
|
@ -19,6 +23,14 @@
|
|||
/>
|
||||
<link rel="localization" href="toolkit/about/aboutReader.ftl" />
|
||||
<link rel="localization" href="toolkit/branding/brandings.ftl" />
|
||||
<script
|
||||
type="module"
|
||||
src="chrome://global/content/reader/color-input.mjs"
|
||||
></script>
|
||||
<script
|
||||
type="module"
|
||||
src="chrome://global/content/elements/named-deck.js"
|
||||
></script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
@ -53,7 +65,6 @@
|
|||
</button>
|
||||
</li>
|
||||
<li class="dropdown-popup">
|
||||
<div class="dropdown-arrow"></div>
|
||||
<div class="font-type-buttons radiorow"></div>
|
||||
<div class="font-size-buttons buttonrow">
|
||||
<button
|
||||
|
@ -88,7 +99,63 @@
|
|||
data-l10n-id="about-reader-toolbar-lineheightplus"
|
||||
></button>
|
||||
</div>
|
||||
<div class="color-scheme-buttons radiorow"></div>
|
||||
<div
|
||||
class="color-scheme-buttons radiorow"
|
||||
id="regular-color-scheme"
|
||||
hidden="false"
|
||||
></div>
|
||||
</li>
|
||||
</ul>
|
||||
<ul
|
||||
class="dropdown colors-dropdown"
|
||||
id="custom-colors-color-scheme"
|
||||
hidden="true"
|
||||
>
|
||||
<li>
|
||||
<button
|
||||
class="dropdown-toggle toolbar-button colors-button"
|
||||
aria-labelledby="toolbar-color-controls"
|
||||
data-telemetry-id="reader-color-controls"
|
||||
>
|
||||
<span
|
||||
class="hover-label"
|
||||
id="toolbar-color-controls"
|
||||
data-l10n-id="about-reader-toolbar-color-controls"
|
||||
></span>
|
||||
</button>
|
||||
</li>
|
||||
<li class="dropdown-popup" id="color-controls">
|
||||
<h2
|
||||
data-l10n-id="about-reader-colors-menu-header"
|
||||
id="about-reader-colors-menu-header"
|
||||
></h2>
|
||||
<button-group aria-labelledby="about-reader-colors-menu-header">
|
||||
<button
|
||||
is="named-deck-button"
|
||||
deck="tabs-deck"
|
||||
name="fxtheme"
|
||||
data-l10n-id="about-reader-fxtheme-tab"
|
||||
></button>
|
||||
<button
|
||||
is="named-deck-button"
|
||||
deck="tabs-deck"
|
||||
name="customtheme"
|
||||
data-l10n-id="about-reader-customtheme-tab"
|
||||
></button>
|
||||
</button-group>
|
||||
<named-deck id="tabs-deck" is-tabbed>
|
||||
<div
|
||||
name="fxtheme"
|
||||
class="colors-menu-color-scheme-buttons radiorow"
|
||||
></div>
|
||||
<div name="customtheme">
|
||||
<ul class="custom-colors-selection"></ul>
|
||||
<button
|
||||
class="custom-colors-reset-button"
|
||||
data-l10n-id="about-reader-custom-colors-reset-button"
|
||||
></button>
|
||||
</div>
|
||||
</named-deck>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
|
|
@ -4,3 +4,5 @@
|
|||
|
||||
toolkit.jar:
|
||||
content/global/reader/aboutReader.html (content/aboutReader.html)
|
||||
content/global/reader/color-input.css (color-input.css)
|
||||
content/global/reader/color-input.mjs (color-input.mjs)
|
||||
|
|
|
@ -22,7 +22,9 @@ EXTRA_JS_MODULES.reader = [
|
|||
"ReaderWorker.sys.mjs",
|
||||
]
|
||||
|
||||
BROWSER_CHROME_MANIFESTS += ["test/browser.toml"]
|
||||
BROWSER_CHROME_MANIFESTS += ["tests/browser/browser.toml"]
|
||||
|
||||
MOCHITEST_CHROME_MANIFESTS += ["tests/chrome/chrome.toml"]
|
||||
|
||||
with Files("**"):
|
||||
BUG_COMPONENT = ("Toolkit", "Reader Mode")
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
// contained within it, so if the article gets reloaded instead of using
|
||||
// the cached version, it would have a different value in it.
|
||||
const URL =
|
||||
"http://mochi.test:8888/browser/toolkit/components/reader/test/readerModeRandom.sjs";
|
||||
"http://mochi.test:8888/browser/toolkit/components/reader/tests/browser/readerModeRandom.sjs";
|
||||
|
||||
add_task(async function () {
|
||||
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, URL);
|
|
@ -65,3 +65,57 @@ add_task(async function () {
|
|||
await testColorScheme(0, "sepia");
|
||||
await testColorScheme(1, "sepia");
|
||||
});
|
||||
|
||||
async function testCustomColors(aPref, color) {
|
||||
// Set the theme selection to custom.
|
||||
Services.prefs.setBoolPref("reader.colors_menu.enabled", true);
|
||||
Services.prefs.setCharPref("reader.color_scheme", "custom");
|
||||
|
||||
// Set the custom pref to the color value.
|
||||
Services.prefs.setCharPref(`reader.custom_colors.${aPref}`, color);
|
||||
|
||||
// Open a browser tab, enter reader mode, and test if the page colors
|
||||
// reflect the pref selection.
|
||||
await BrowserTestUtils.withNewTab(
|
||||
TEST_PATH + "readerModeArticle.html",
|
||||
async function (browser) {
|
||||
let pageShownPromise = BrowserTestUtils.waitForContentEvent(
|
||||
browser,
|
||||
"AboutReaderContentReady"
|
||||
);
|
||||
|
||||
let readerButton = document.getElementById("reader-mode-button");
|
||||
readerButton.click();
|
||||
await pageShownPromise;
|
||||
|
||||
let colorScheme = Services.prefs.getCharPref("reader.color_scheme");
|
||||
Assert.equal(colorScheme, "custom");
|
||||
let prefValue = Services.prefs.getStringPref(
|
||||
`reader.custom_colors.${aPref}`
|
||||
);
|
||||
let cssProp = `--custom-theme-${aPref}`;
|
||||
|
||||
await SpecialPowers.spawn(
|
||||
browser,
|
||||
[prefValue, cssProp],
|
||||
(customColor, prop) => {
|
||||
let style = content.window.getComputedStyle(content.document.body);
|
||||
let actualColor = style.getPropertyValue(prop);
|
||||
Assert.equal(customColor, actualColor);
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that the custom color scheme selection updates the document colors correctly.
|
||||
*/
|
||||
add_task(async function () {
|
||||
await testCustomColors("foreground", "#ffffff");
|
||||
await testCustomColors("background", "#000000");
|
||||
await testCustomColors("unvisited-links", "#ffffff");
|
||||
await testCustomColors("visited-links", "#ffffff");
|
||||
await testCustomColors("visited-links", "#ffffff");
|
||||
await testCustomColors("selection-highlight", "#ffffff");
|
||||
});
|
|
@ -41,28 +41,34 @@ add_task(async function () {
|
|||
dispatchMouseEvent(win, target, "click");
|
||||
}
|
||||
|
||||
async function testOpenCloseDropdown(target) {
|
||||
let button = doc.querySelector(`.${target}-button`);
|
||||
|
||||
let dropdown = doc.querySelector(`.${target}-dropdown`);
|
||||
ok(!dropdown.classList.contains("open"), "dropdown is closed");
|
||||
|
||||
simulateClick(button);
|
||||
ok(dropdown.classList.contains("open"), "dropdown is open");
|
||||
|
||||
// simulate clicking on the article title to close the dropdown
|
||||
let title = doc.querySelector(".reader-title");
|
||||
simulateClick(title);
|
||||
ok(!dropdown.classList.contains("open"), "dropdown is closed");
|
||||
|
||||
// reopen the dropdown
|
||||
simulateClick(button);
|
||||
ok(dropdown.classList.contains("open"), "dropdown is open");
|
||||
|
||||
// now click on the button again to close it
|
||||
simulateClick(button);
|
||||
ok(!dropdown.classList.contains("open"), "dropdown is closed");
|
||||
}
|
||||
|
||||
let doc = content.document;
|
||||
let win = content.window;
|
||||
let styleButton = doc.querySelector(".style-button");
|
||||
|
||||
let styleDropdown = doc.querySelector(".style-dropdown");
|
||||
ok(!styleDropdown.classList.contains("open"), "dropdown is closed");
|
||||
|
||||
simulateClick(styleButton);
|
||||
ok(styleDropdown.classList.contains("open"), "dropdown is open");
|
||||
|
||||
// simulate clicking on the article title to close the dropdown
|
||||
let title = doc.querySelector("h1");
|
||||
simulateClick(title);
|
||||
ok(!styleDropdown.classList.contains("open"), "dropdown is closed");
|
||||
|
||||
// reopen the dropdown
|
||||
simulateClick(styleButton);
|
||||
ok(styleDropdown.classList.contains("open"), "dropdown is open");
|
||||
|
||||
// now click on the button again to close it
|
||||
simulateClick(styleButton);
|
||||
ok(!styleDropdown.classList.contains("open"), "dropdown is closed");
|
||||
testOpenCloseDropdown("style");
|
||||
testOpenCloseDropdown("colors");
|
||||
});
|
||||
}
|
||||
);
|
|
@ -7,7 +7,7 @@
|
|||
<article>
|
||||
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Donec et mollis dolor. Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean ut gravida lorem. Ut turpis felis, pulvinar a semper sed, adipiscing id dolor. Pellentesque auctor nisi id magna consequat sagittis. Curabitur dapibus enim sit amet elit pharetra tincidunt feugiat nisl imperdiet. Ut convallis libero in urna ultrices accumsan. Donec sed odio eros. Donec viverra mi quis quam pulvinar at malesuada arcu rhoncus. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. In rutrum accumsan ultricies. Mauris vitae nisi at sem facilisis semper ac in est.</p>
|
||||
|
||||
<p><a href="http://example.com/browser/toolkit/components/reader/test/getCookies.sjs" id="link">Cross-origin link to getCookies.html</a></p>
|
||||
<p><a href="http://example.com/browser/toolkit/components/reader/tests/browser/getCookies.sjs" id="link">Cross-origin link to getCookies.html</a></p>
|
||||
</article>
|
||||
</body>
|
||||
</html>
|
|
@ -12,7 +12,7 @@
|
|||
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec a diam lectus. Sed sit amet ipsum mauris. Maecenas congue ligula ac quam viverra nec consectetur ante hendrerit. Donec et mollis dolor. Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam tincidunt congue enim, ut porta lorem lacinia consectetur. Donec ut libero sed arcu vehicula ultricies a non tortor. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean ut gravida lorem. Ut turpis felis, pulvinar a semper sed, adipiscing id dolor. Pellentesque auctor nisi id magna consequat sagittis. Curabitur dapibus enim sit amet elit pharetra tincidunt feugiat nisl imperdiet. Ut convallis libero in urna ultrices accumsan. Donec sed odio eros. Donec viverra mi quis quam pulvinar at malesuada arcu rhoncus. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. In rutrum accumsan ultricies. Mauris vitae nisi at sem facilisis semper ac in est.</p>
|
||||
<p>Vivamus fermentum semper porta. Nunc diam velit, adipiscing ut tristique vitae, sagittis vel odio. Maecenas convallis ullamcorper ultricies. Curabitur ornare, ligula semper consectetur sagittis, nisi diam iaculis velit, id fringilla sem nunc vel mi. Nam dictum, odio nec pretium volutpat, arcu ante placerat erat, non tristique elit urna et turpis. Quisque mi metus, ornare sit amet fermentum et, tincidunt et orci. Fusce eget orci a orci congue vestibulum. Ut dolor diam, elementum et vestibulum eu, porttitor vel elit. Curabitur venenatis pulvinar tellus gravida ornare. Sed et erat faucibus nunc euismod ultricies ut id justo. Nullam cursus suscipit nisi, et ultrices justo sodales nec. Fusce venenatis facilisis lectus ac semper. Aliquam at massa ipsum. Quisque bibendum purus convallis nulla ultrices ultricies. Nullam aliquam, mi eu aliquam tincidunt, purus velit laoreet tortor, viverra pretium nisi quam vitae mi. Fusce vel volutpat elit. Nam sagittis nisi dui.</p>
|
||||
<p>Vivamus fermentum semper porta. Nunc diam velit, adipiscing ut tristique vitae, sagittis vel odio. Maecenas convallis ullamcorper ultricies. Curabitur ornare, ligula semper consectetur sagittis, nisi diam iaculis velit, id fringilla sem nunc vel mi. Nam dictum, odio nec pretium volutpat, arcu ante placerat erat, non tristique elit urna et turpis. Quisque mi metus, ornare sit amet fermentum et, tincidunt et orci. Fusce eget orci a orci congue vestibulum. Ut dolor diam, elementum et vestibulum eu, porttitor vel elit. Curabitur venenatis pulvinar tellus gravida ornare. Sed et erat faucibus nunc euismod ultricies ut id justo. Nullam cursus suscipit nisi, et ultrices justo sodales nec. Fusce venenatis facilisis lectus ac semper. Aliquam at massa ipsum. Quisque bibendum purus convallis nulla ultrices ultricies. Nullam aliquam, mi eu aliquam tincidunt, purus velit laoreet tortor, viverra pretium nisi quam vitae mi. Fusce vel volutpat elit. Nam sagittis nisi dui.</p>
|
||||
<p><a href="http://example.com/browser/toolkit/components/reader/test/readerModeArticle.html" id="link">Link to another page.</a></p>
|
||||
<p><a href="http://example.com/browser/toolkit/components/reader/tests/browser/readerModeArticle.html" id="link">Link to another page.</a></p>
|
||||
<p>Vivamus fermentum semper porta. Nunc diam velit, adipiscing ut tristique vitae, sagittis vel odio. Maecenas convallis ullamcorper ultricies. Curabitur ornare, ligula semper consectetur sagittis, nisi diam iaculis velit, id fringilla sem nunc vel mi. Nam dictum, odio nec pretium volutpat, arcu ante placerat erat, non tristique elit urna et turpis. Quisque mi metus, ornare sit amet fermentum et, tincidunt et orci. Fusce eget orci a orci congue vestibulum. Ut dolor diam, elementum et vestibulum eu, porttitor vel elit. Curabitur venenatis pulvinar tellus gravida ornare. Sed et erat faucibus nunc euismod ultricies ut id justo. Nullam cursus suscipit nisi, et ultrices justo sodales nec. Fusce venenatis facilisis lectus ac semper. Aliquam at massa ipsum. Quisque bibendum purus convallis nulla ultrices ultricies. Nullam aliquam, mi eu aliquam tincidunt, purus velit laoreet tortor, viverra pretium nisi quam vitae mi. Fusce vel volutpat elit. Nam sagittis nisi dui.</p>
|
||||
<p>Vivamus fermentum semper porta. Nunc diam velit, adipiscing ut tristique vitae, sagittis vel odio. Maecenas convallis ullamcorper ultricies. Curabitur ornare, ligula semper consectetur sagittis, nisi diam iaculis velit, id fringilla sem nunc vel mi. Nam dictum, odio nec pretium volutpat, arcu ante placerat erat, non tristique elit urna et turpis. Quisque mi metus, ornare sit amet fermentum et, tincidunt et orci. Fusce eget orci a orci congue vestibulum. Ut dolor diam, elementum et vestibulum eu, porttitor vel elit. Curabitur venenatis pulvinar tellus gravida ornare. Sed et erat faucibus nunc euismod ultricies ut id justo. Nullam cursus suscipit nisi, et ultrices justo sodales nec. Fusce venenatis facilisis lectus ac semper. Aliquam at massa ipsum. Quisque bibendum purus convallis nulla ultrices ultricies. Nullam aliquam, mi eu aliquam tincidunt, purus velit laoreet tortor, viverra pretium nisi quam vitae mi. Fusce vel volutpat elit. Nam sagittis nisi dui.</p>
|
||||
</div>
|
|
@ -0,0 +1,3 @@
|
|||
[DEFAULT]
|
||||
|
||||
["test_color_input.html"]
|
|
@ -0,0 +1,39 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>ColorInput Tests</title>
|
||||
<script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<link rel="stylesheet" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
|
||||
<script type="module" src="chrome://global/content/reader/color-input.mjs"></script>
|
||||
</head>
|
||||
<body>
|
||||
<p id="display"></p>
|
||||
<div id="content" style="display: block">
|
||||
<color-input color="#ffffff" prop-name="test-prop" data-l10n-id="color-input-test-label"></color-input>
|
||||
</div>
|
||||
<pre id="test">
|
||||
<script class="testbody" type="application/javascript">
|
||||
add_task(async function testColorInput() {
|
||||
const colorInput = document.querySelector("color-input");
|
||||
ok(colorInput, "color input element is rendered");
|
||||
|
||||
let input = colorInput.shadowRoot.querySelector("input");
|
||||
is(input.value, "#ffffff", "color input has the correct initial value");
|
||||
});
|
||||
add_task(async function testColorInputEvents() {
|
||||
const colorInput = document.querySelector("color-input");
|
||||
let input = colorInput.shadowRoot.querySelector("input");
|
||||
|
||||
const pickedColor = new Promise((resolve) => {
|
||||
colorInput.addEventListener("color-picked", (event) => resolve(event.detail), { once: true });
|
||||
});
|
||||
input.value = "#0000ff";
|
||||
input.dispatchEvent(new Event("input"));
|
||||
let color = await pickedColor;
|
||||
is(color, "#0000ff", "color-picked event dispatches on input");
|
||||
});
|
||||
</script>
|
||||
</pre>
|
||||
</body>
|
||||
</html>
|
|
@ -6,7 +6,7 @@
|
|||
# instead of having to read it themselves." This is the name
|
||||
# of the feature and it is the label for the popup button.
|
||||
# %S is the keyboard shortcut for the listen command
|
||||
listen-label = Listen (%S)
|
||||
read-aloud-label = Read aloud (%S)
|
||||
# %S is the keyboard shortcut for the skip back command
|
||||
previous-label = Back (%S)
|
||||
# %S is the keyboard shortcut for the start command
|
||||
|
|
|
@ -5,14 +5,20 @@
|
|||
about-reader-loading = Loading…
|
||||
about-reader-load-error = Failed to load article from page
|
||||
|
||||
about-reader-color-scheme-light = Light
|
||||
.title = Color Scheme Light
|
||||
about-reader-color-scheme-dark = Dark
|
||||
.title = Color Scheme Dark
|
||||
about-reader-color-scheme-sepia = Sepia
|
||||
.title = Color Scheme Sepia
|
||||
about-reader-color-scheme-auto = Auto
|
||||
.title = Color Scheme Auto
|
||||
about-reader-color-theme-light = Light
|
||||
.title = Color Theme Light
|
||||
about-reader-color-theme-dark = Dark
|
||||
.title = Color Theme Dark
|
||||
about-reader-color-theme-sepia = Sepia
|
||||
.title = Color Theme Sepia
|
||||
about-reader-color-theme-auto = Auto
|
||||
.title = Color Theme Auto
|
||||
about-reader-color-theme-gray = Gray
|
||||
.title = Color Theme Gray
|
||||
about-reader-color-theme-contrast = Contrast
|
||||
.title = Color Theme Contrast
|
||||
about-reader-color-theme-custom = Custom colors
|
||||
.title = Color Theme Custom
|
||||
|
||||
# An estimate for how long it takes to read an article,
|
||||
# expressed as a range covering both slow and fast readers.
|
||||
|
@ -49,4 +55,31 @@ about-reader-font-type-sans-serif = Sans-serif
|
|||
|
||||
about-reader-toolbar-close = Close Reader View
|
||||
about-reader-toolbar-type-controls = Type controls
|
||||
about-reader-toolbar-color-controls = Colors
|
||||
about-reader-toolbar-savetopocket = Save To { -pocket-brand-name }
|
||||
|
||||
## Reader View colors menu
|
||||
|
||||
about-reader-colors-menu-header = Theme
|
||||
|
||||
about-reader-fxtheme-tab = Default
|
||||
about-reader-customtheme-tab = Custom
|
||||
|
||||
## These are used as labels for the custom theme color pickers.
|
||||
## The .title element is used to make the editing functionality
|
||||
## clear and give context for screen reader users.
|
||||
|
||||
about-reader-custom-colors-foreground = Text
|
||||
.title = Edit color
|
||||
about-reader-custom-colors-background = Background
|
||||
.title = Edit color
|
||||
|
||||
about-reader-custom-colors-unvisited-links = Unvisited links
|
||||
.title = Edit color
|
||||
about-reader-custom-colors-visited-links = Visited links
|
||||
.title = Edit color
|
||||
|
||||
about-reader-custom-colors-selection-highlight = Highlighter for read aloud
|
||||
.title = Edit color
|
||||
|
||||
about-reader-custom-colors-reset-button = Reset defaults
|
||||
|
|
|
@ -31,6 +31,11 @@ const kAllowedPrefs = new Set([
|
|||
"reader.color_scheme",
|
||||
"reader.content_width",
|
||||
"reader.line_height",
|
||||
"reader.custom_colors.foreground",
|
||||
"reader.custom_colors.background",
|
||||
"reader.custom_colors.unvisited-links",
|
||||
"reader.custom_colors.visited-links",
|
||||
"reader.custom_colors.selection-highlight",
|
||||
|
||||
"security.tls.version.enable-deprecated",
|
||||
"security.xfocsp.errorReporting.automatic",
|
||||
|
|
|
@ -39,7 +39,6 @@ body {
|
|||
--tooltip-border: transparent;
|
||||
--popup-background: #fff;
|
||||
--popup-border: rgba(0, 0, 0, 0.12);
|
||||
--opaque-popup-border: rgb(224, 224, 224);
|
||||
--popup-line: var(--grey-30);
|
||||
--popup-shadow: rgba(49, 49, 49, 0.3);
|
||||
--popup-button-background: rgba(207, 207, 216, 0.33);
|
||||
|
@ -47,9 +46,8 @@ body {
|
|||
--popup-button-background-hover: var(--toolbar-button-background-hover);
|
||||
--popup-button-foreground-hover: var(--main-foreground);
|
||||
--popup-button-background-active: var(--toolbar-button-background-active);
|
||||
--popup-button-border: var(--popup-border);
|
||||
--popup-button-border: rgba(0, 0, 0, 0.2);
|
||||
--selected-background: rgba(0, 97, 224, 0.3);
|
||||
--selected-border: var(--primary-color);
|
||||
--outline-focus-color: var(--primary-color);
|
||||
--font-value-background: rgb(240, 240, 244);
|
||||
--font-value-border: var(--grey-30);
|
||||
|
@ -61,6 +59,11 @@ body {
|
|||
--link-selected-background: var(--selected-background);
|
||||
--link-selected-foreground: #333;
|
||||
--visited-link-foreground: #b5007f;
|
||||
--custom-theme-background: var(--color-white);
|
||||
--custom-theme-foreground: #14151A;
|
||||
--custom-theme-unvisited-links: var(--color-blue-50);
|
||||
--custom-theme-visited-links: #321C64;
|
||||
--custom-theme-selection-highlight: #FFFFCC;
|
||||
/* light colours */
|
||||
}
|
||||
|
||||
|
@ -72,26 +75,62 @@ body.sepia {
|
|||
--icon-disabled-fill: rgba(91, 70, 54, 0.4);
|
||||
}
|
||||
|
||||
body.gray {
|
||||
--main-background: var(--grey-30);
|
||||
--main-foreground: var(--light-theme-foreground);
|
||||
--toolbar-border: var(--main-foreground);
|
||||
--icon-fill: var(--main-foreground);
|
||||
}
|
||||
|
||||
body.dark,
|
||||
body.contrast {
|
||||
--toolbar-box-shadow: black;
|
||||
--toolbar-button-background-hover: rgb(82, 82, 94);
|
||||
--toolbar-button-background-active: rgb(91, 91, 102);
|
||||
--popup-background: rgb(66, 65, 77);
|
||||
--popup-button-border: rgba(255, 255, 255, 0.12);
|
||||
--popup-line: rgba(249, 249, 250, 0.1);
|
||||
--popup-button-background: rgb(43, 42, 51);
|
||||
--font-value-background: rgba(249, 249, 250, 0.15);
|
||||
--font-value-border: #656468;
|
||||
--icon-disabled-fill: rgba(251, 251, 254, 0.4);
|
||||
--link-selected-foreground: #fff;
|
||||
--visited-link-foreground: #e675fd;
|
||||
--selected-background: rgba(0, 221, 255, 0.3);
|
||||
/* dark colours */
|
||||
|
||||
.moz-reader-block-img {
|
||||
filter: brightness(0.8) contrast(1.2);
|
||||
}
|
||||
}
|
||||
|
||||
body.dark {
|
||||
--main-background: var(--dark-theme-background);
|
||||
--main-foreground: var(--dark-theme-foreground);
|
||||
--primary-color: rgb(0, 221, 255);
|
||||
--toolbar-border: rgba(249, 249, 250, 0.2);
|
||||
--toolbar-box-shadow: black;
|
||||
--toolbar-button-background-hover: rgb(82, 82, 94);
|
||||
--toolbar-button-background-active: rgb(91, 91, 102);
|
||||
--popup-background: rgb(66, 65, 77);
|
||||
--opaque-popup-border: #434146;
|
||||
--popup-line: rgba(249, 249, 250, 0.1);
|
||||
--popup-button-background: rgb(43, 42, 51);
|
||||
--selected-background: rgba(0, 221, 255, 0.3);
|
||||
--font-value-background: rgba(249, 249, 250, 0.15);
|
||||
--font-value-border: #656468;
|
||||
--icon-fill: rgb(251, 251, 254);
|
||||
--icon-disabled-fill: rgba(251, 251, 254, 0.4);
|
||||
--link-selected-foreground: #fff;
|
||||
--visited-link-foreground: #e675fd;
|
||||
/* dark colours */
|
||||
}
|
||||
|
||||
body.contrast {
|
||||
--main-background: #000000;
|
||||
--main-foreground: #fff;
|
||||
--primary-color: #D6B4FD;
|
||||
--toolbar-border: #FFEE32;
|
||||
--icon-fill: #FFEE32;
|
||||
}
|
||||
|
||||
body.custom {
|
||||
--main-background: var(--custom-theme-background);
|
||||
--main-foreground: var(--custom-theme-foreground);
|
||||
--link-foreground: var(--custom-theme-unvisited-links);
|
||||
--visited-link-foreground: var(--custom-theme-visited-links);
|
||||
--popup-button-foreground: var(--light-theme-foreground);
|
||||
--popup-button-foreground-hover: var(--light-theme-foreground);
|
||||
--tooltip-foreground: var(--light-theme-foreground);
|
||||
--toolbar-border: var(--main-foreground);
|
||||
--icon-fill: var(--main-foreground);
|
||||
--icon-disabled-fill: rgba(91, 91, 102, 0.4);
|
||||
}
|
||||
|
||||
body.hcm {
|
||||
|
@ -116,7 +155,6 @@ body.hcm {
|
|||
--tooltip-border: CanvasText;
|
||||
--popup-background: Canvas;
|
||||
--popup-border: CanvasText;
|
||||
--opaque-popup-border: CanvasText;
|
||||
--popup-line: CanvasText;
|
||||
--popup-button-background: ButtonFace;
|
||||
--popup-button-foreground: ButtonText;
|
||||
|
@ -138,6 +176,11 @@ body.hcm {
|
|||
--visited-link-foreground: VisitedText;
|
||||
}
|
||||
|
||||
body.hcm .colors-dropdown {
|
||||
/* Hide entire colors menu when HCM is on. */
|
||||
display: none;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
padding: var(--body-padding);
|
||||
|
@ -182,33 +225,31 @@ blockquote {
|
|||
border-inline-start: 2px solid var(--main-foreground) !important;
|
||||
}
|
||||
|
||||
.light-button,
|
||||
.auto-button {
|
||||
color: var(--light-theme-foreground);
|
||||
background-color: var(--light-theme-background);
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.color-scheme-buttons {
|
||||
.light-button,
|
||||
.auto-button {
|
||||
color: var(--light-theme-foreground);
|
||||
background-color: var(--light-theme-background);
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.auto-button {
|
||||
color: var(--dark-theme-foreground);
|
||||
background-color: var(--dark-theme-background);
|
||||
}
|
||||
}
|
||||
|
||||
.dark-button {
|
||||
color: var(--dark-theme-foreground);
|
||||
background-color: var(--dark-theme-background);
|
||||
}
|
||||
|
||||
.moz-reader-block-img {
|
||||
filter: brightness(0.8) contrast(1.2);
|
||||
.sepia-button {
|
||||
color: #5b4636;
|
||||
background-color: #f4ecd8;
|
||||
}
|
||||
}
|
||||
|
||||
.dark-button {
|
||||
color: var(--dark-theme-foreground);
|
||||
background-color: var(--dark-theme-background);
|
||||
}
|
||||
|
||||
.sepia-button {
|
||||
color: #5b4636;
|
||||
background-color: #f4ecd8;
|
||||
}
|
||||
|
||||
/* Loading/error message */
|
||||
|
||||
.reader-message {
|
||||
|
@ -311,7 +352,7 @@ blockquote {
|
|||
*/
|
||||
margin-inline-start: max(calc(50% - 17px - var(--inline-padding)), calc(100% - 96px - 34px - 2 * var(--inline-padding)));
|
||||
|
||||
font-family: Helvetica, Arial, sans-serif;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Ubuntu, "Helvetica Neue", sans-serif;
|
||||
list-style: none;
|
||||
user-select: none;
|
||||
|
||||
|
@ -452,42 +493,28 @@ button:disabled {
|
|||
.dropdown .dropdown-popup {
|
||||
text-align: start;
|
||||
position: absolute;
|
||||
inset-inline-start: 40px;
|
||||
inset-inline-start: 32px;
|
||||
z-index: 1000;
|
||||
background-color: var(--popup-background);
|
||||
visibility: hidden;
|
||||
border-radius: 4px;
|
||||
border: 1px solid var(--popup-border);
|
||||
box-shadow: 0 0 10px 0 var(--popup-shadow);
|
||||
top: 0;
|
||||
top: var(--space-xsmall);
|
||||
}
|
||||
|
||||
.dropdown-popup h2 {
|
||||
font-size: var(--font-size-root);
|
||||
font-weight: var(--font-weight-bold);
|
||||
color: var(--popup-button-foreground);
|
||||
margin-block: var(--space-large);
|
||||
margin-inline: var(--space-large) 0;
|
||||
}
|
||||
|
||||
.open > .dropdown-popup {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.dropdown-arrow {
|
||||
position: absolute;
|
||||
height: 24px;
|
||||
width: 16px;
|
||||
inset-inline-start: -16px;
|
||||
background-image: url("chrome://global/skin/reader/RM-Type-Controls-Arrow.svg");
|
||||
display: block;
|
||||
-moz-context-properties: fill, stroke;
|
||||
fill: var(--popup-background);
|
||||
stroke: var(--opaque-popup-border);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.dropdown-arrow:dir(rtl) {
|
||||
transform: scaleX(-1);
|
||||
}
|
||||
|
||||
/* Align the style dropdown arrow (narrate does its own) */
|
||||
.style-dropdown .dropdown-arrow {
|
||||
top: 7px;
|
||||
}
|
||||
|
||||
/* Font style popup */
|
||||
|
||||
.radio-button {
|
||||
|
@ -513,13 +540,14 @@ button:disabled {
|
|||
box-sizing: border-box;
|
||||
width: 36px;
|
||||
height: 20px;
|
||||
line-height: 20px;
|
||||
line-height: 18px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-content: center;
|
||||
margin: auto;
|
||||
border-radius: 10px;
|
||||
border: 1px solid var(--font-value-border);
|
||||
color: var(--popup-button-foreground);
|
||||
background-color: var(--font-value-background);
|
||||
}
|
||||
|
||||
|
@ -547,16 +575,11 @@ button:disabled {
|
|||
outline-offset: -2px;
|
||||
}
|
||||
|
||||
.radiorow:not(:last-child),
|
||||
.buttonrow:not(:last-child) {
|
||||
.style-dropdown .radiorow:not(:last-child),
|
||||
.style-dropdown .buttonrow:not(:last-child) {
|
||||
border-bottom: 1px solid var(--popup-line);
|
||||
}
|
||||
|
||||
body.hcm .buttonrow.line-height-buttons {
|
||||
/* On HCM the .color-scheme-buttons row is hidden, so remove the border from the row above it */
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.radiorow > label {
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
|
@ -565,27 +588,16 @@ body.hcm .buttonrow.line-height-buttons {
|
|||
}
|
||||
|
||||
.radiorow > label[checked] {
|
||||
border-color: var(--selected-border);
|
||||
border: 2px solid var(--link-selected-foreground);
|
||||
}
|
||||
|
||||
/* For the hover style, we draw a line under the item by means of a
|
||||
* pseudo-element. Because these items are variable height, and
|
||||
* because their contents are variable height, position it absolutely,
|
||||
* and give it a width of 100% (the content width) + 4px for the 2 * 2px
|
||||
* border width.
|
||||
*/
|
||||
.radiorow > input[type=radio]:focus-visible + label::after,
|
||||
.radiorow > label:hover::after {
|
||||
content: "";
|
||||
display: block;
|
||||
border-bottom: 2px solid var(--selected-border);
|
||||
border-radius: 4px;
|
||||
width: calc(100% + 4px);
|
||||
position: absolute;
|
||||
/* to skip the 2 * 2px border + 2px spacing. */
|
||||
bottom: -6px;
|
||||
/* Match the start of the 2px border of the element: */
|
||||
inset-inline-start: -2px;
|
||||
.radiorow > label:hover {
|
||||
background-color: var(--toolbar-button-background-hover);
|
||||
}
|
||||
|
||||
.radiorow > input[type=radio]:focus-visible + label {
|
||||
outline: 2px solid var(--primary-color);
|
||||
outline-offset: var(--focus-outline-offset);
|
||||
}
|
||||
|
||||
.font-type-buttons > label {
|
||||
|
@ -608,6 +620,16 @@ body.hcm .buttonrow.line-height-buttons {
|
|||
padding-top: 2px;
|
||||
}
|
||||
|
||||
.font-type-buttons {
|
||||
> label:first-of-type {
|
||||
margin-inline-start: var(--space-large);
|
||||
}
|
||||
|
||||
> label:last-of-type {
|
||||
margin-inline-end: var(--space-large);
|
||||
}
|
||||
}
|
||||
|
||||
.font-type-buttons > label[checked] {
|
||||
background-color: var(--selected-background);
|
||||
}
|
||||
|
@ -642,6 +664,7 @@ body.hcm .color-scheme-buttons {
|
|||
justify-content: center;
|
||||
/* We want 10px between items, but there's no margin collapsing in flexbox. */
|
||||
margin: 10px 5px;
|
||||
border-color: var(--popup-border);
|
||||
}
|
||||
|
||||
.color-scheme-buttons > input:first-child + label {
|
||||
|
@ -652,6 +675,108 @@ body.hcm .color-scheme-buttons {
|
|||
margin-inline-end: 10px;
|
||||
}
|
||||
|
||||
/* Separate colors menu popup */
|
||||
|
||||
#color-controls {
|
||||
padding-block-end: var(--space-large);
|
||||
width: 400px;
|
||||
}
|
||||
|
||||
button-group {
|
||||
display: flex;
|
||||
font-size: var(--font-size-small);
|
||||
}
|
||||
|
||||
button[is="named-deck-button"] {
|
||||
background: none;
|
||||
color: var(--popup-button-foreground);
|
||||
border: 1px var(--popup-button-border);
|
||||
border-style: solid none;
|
||||
padding: var(--space-small);
|
||||
flex-basis: 50%;
|
||||
|
||||
&[selected] {
|
||||
color: var(--primary-color);
|
||||
border-top: 2px solid var(--primary-color);
|
||||
}
|
||||
}
|
||||
|
||||
.custom-colors-selection {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: var(--space-small);
|
||||
padding: var(--space-large);
|
||||
list-style-type: none;
|
||||
font-size: var(--font-size-root);
|
||||
color: var(--popup-button-foreground);
|
||||
}
|
||||
|
||||
.colors-menu-color-scheme-buttons {
|
||||
flex-wrap: wrap;
|
||||
margin-block-start: var(--space-small);
|
||||
}
|
||||
|
||||
.colors-menu-color-scheme-buttons > label {
|
||||
height: 48px;
|
||||
width: calc(50% - 21px);
|
||||
font-size: var(--font-size-root);
|
||||
color: var(--popup-button-foreground);
|
||||
border: 1px solid var(--popup-button-border);
|
||||
border-radius: var(--border-radius-small);
|
||||
/* Center content vertically and justify left horizontally */
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: start;
|
||||
margin: var(--space-xsmall);
|
||||
}
|
||||
|
||||
.colors-menu-color-scheme-buttons > label:before {
|
||||
content: "";
|
||||
display: inline-block;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
border-radius: var(--border-radius-circle);
|
||||
outline: 1px solid var(--popup-button-border);
|
||||
margin: 0 10px 0 12px;
|
||||
}
|
||||
|
||||
.colors-menu-color-scheme-buttons {
|
||||
.auto-button:before {
|
||||
background: linear-gradient(to right, var(--light-theme-background) 50%, var(--dark-theme-background) 50%);;
|
||||
}
|
||||
|
||||
.light-button:before {
|
||||
background-color: var(--light-theme-background);
|
||||
}
|
||||
|
||||
.dark-button:before {
|
||||
background-color: var(--dark-theme-background);
|
||||
}
|
||||
|
||||
.sepia-button:before {
|
||||
background-color: #f4ecd8;
|
||||
}
|
||||
|
||||
.contrast-button:before {
|
||||
background-color: #000000;
|
||||
}
|
||||
|
||||
.gray-button:before {
|
||||
background-color: var(--grey-30);
|
||||
}
|
||||
}
|
||||
|
||||
.custom-colors-reset-button {
|
||||
display: block;
|
||||
background: none;
|
||||
border: none;
|
||||
padding: 0 var(--space-large);
|
||||
color: var(--primary-color);
|
||||
text-decoration: underline;
|
||||
font-size: var(--font-size-root);
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
/* Toolbar icons */
|
||||
|
||||
.close-button {
|
||||
|
@ -662,6 +787,10 @@ body.hcm .color-scheme-buttons {
|
|||
background-image: url("chrome://global/skin/reader/RM-Type-Controls-24x24.svg");
|
||||
}
|
||||
|
||||
.colors-button {
|
||||
background-image: url("chrome://mozapps/skin/extensions/category-themes.svg");
|
||||
}
|
||||
|
||||
.minus-button {
|
||||
background-size: 18px 18px;
|
||||
background-image: url("chrome://global/skin/reader/RM-Minus-24x24.svg");
|
||||
|
|
|
@ -147,7 +147,6 @@
|
|||
skin/classic/global/reader/RM-Minus-24x24.svg (../../shared/reader/RM-Minus-24x24.svg)
|
||||
skin/classic/global/reader/RM-Plus-24x24.svg (../../shared/reader/RM-Plus-24x24.svg)
|
||||
skin/classic/global/reader/RM-Type-Controls-24x24.svg (../../shared/reader/RM-Type-Controls-24x24.svg)
|
||||
skin/classic/global/reader/RM-Type-Controls-Arrow.svg (../../shared/reader/RM-Type-Controls-Arrow.svg)
|
||||
skin/classic/global/reader/RM-Content-Width-Minus-42x16.svg (../../shared/reader/RM-Content-Width-Minus-42x16.svg)
|
||||
skin/classic/global/reader/RM-Content-Width-Plus-44x16.svg (../../shared/reader/RM-Content-Width-Plus-44x16.svg)
|
||||
skin/classic/global/reader/RM-Line-Height-Minus-38x14.svg (../../shared/reader/RM-Line-Height-Minus-38x14.svg)
|
||||
|
|
|
@ -16,12 +16,17 @@ body.sepia {
|
|||
--narrating-paragraph-background-color: #e0d7c5;
|
||||
}
|
||||
|
||||
body.dark {
|
||||
body.dark,
|
||||
body.contrast {
|
||||
--current-voice: #a09eac;
|
||||
--narrate-word-highlight-color: #6f6f6f;
|
||||
--narrating-paragraph-background-color: #242424;
|
||||
}
|
||||
|
||||
body.custom {
|
||||
--narrating-paragraph-background-color: var(--custom-theme-selection-highlight);
|
||||
}
|
||||
|
||||
body.hcm {
|
||||
--current-voice: inherit;
|
||||
--narrate-word-highlight-color: SelectedItem;
|
||||
|
@ -100,14 +105,6 @@ body.hcm .speaking:not(.open) .narrate-toggle:hover {
|
|||
outline-offset: -2px;
|
||||
}
|
||||
|
||||
.narrate-dropdown > .dropdown-popup {
|
||||
top: -34px;
|
||||
}
|
||||
|
||||
.narrate-dropdown .dropdown-arrow {
|
||||
top: 40px;
|
||||
}
|
||||
|
||||
.narrate-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
@ -168,7 +165,7 @@ body.hcm .speaking:not(.open) .narrate-toggle:hover {
|
|||
background-repeat: no-repeat;
|
||||
background-size: 24px auto;
|
||||
-moz-context-properties: fill;
|
||||
fill: var(--icon-fill);
|
||||
fill: var(--popup-button-foreground);
|
||||
}
|
||||
|
||||
.narrate-rate::before {
|
||||
|
@ -193,7 +190,7 @@ body.hcm .speaking:not(.open) .narrate-toggle:hover {
|
|||
}
|
||||
|
||||
.narrate-rate-input::-moz-range-track {
|
||||
background-color: var(--icon-fill);
|
||||
background-color: var(--popup-button-foreground);
|
||||
height: 2px;
|
||||
}
|
||||
|
||||
|
@ -203,7 +200,7 @@ body.hcm .speaking:not(.open) .narrate-toggle:hover {
|
|||
}
|
||||
|
||||
.narrate-rate-input::-moz-range-thumb {
|
||||
background-color: var(--icon-fill);
|
||||
background-color: var(--popup-button-foreground);
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
border-radius: 8px;
|
||||
|
@ -244,6 +241,10 @@ body.hcm .speaking:not(.open) .narrate-toggle:hover {
|
|||
color: var(--current-voice);
|
||||
}
|
||||
|
||||
.voiceselect .label {
|
||||
color: var(--popup-button-foreground);
|
||||
}
|
||||
|
||||
.voiceselect > .options {
|
||||
display: none;
|
||||
overflow-y: auto;
|
||||
|
@ -256,6 +257,7 @@ body.hcm .speaking:not(.open) .narrate-toggle:hover {
|
|||
|
||||
.voiceselect > .options > button.option {
|
||||
box-sizing: border-box;
|
||||
color: var(--popup-button-foreground);
|
||||
}
|
||||
|
||||
.voiceselect > .options > button.option:not(:first-child) {
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- This Source Code Form is subject to the terms of the Mozilla Public
|
||||
- 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/. -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 24">
|
||||
<polygon points="16.58 0.01 16.57 0 4.58 12 16.57 24 16.58 23.98" fill="context-fill" stroke="context-stroke"/>
|
||||
</svg>
|
До Ширина: | Высота: | Размер: 433 B |
Загрузка…
Ссылка в новой задаче