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:
Irene Ni 2024-04-02 00:08:46 +00:00
Родитель 19da69d55e
Коммит f701879f1c
58 изменённых файлов: 884 добавлений и 187 удалений

Просмотреть файл

@ -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/",

Просмотреть файл

@ -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