summaryrefslogtreecommitdiffstats
path: root/toolkit/components/reader
diff options
context:
space:
mode:
Diffstat (limited to 'toolkit/components/reader')
-rw-r--r--toolkit/components/reader/AboutReader.sys.mjs242
-rw-r--r--toolkit/components/reader/content/aboutReader.html58
-rw-r--r--toolkit/components/reader/jar.mn2
-rw-r--r--toolkit/components/reader/moz-slider.css43
-rw-r--r--toolkit/components/reader/moz-slider.mjs126
-rw-r--r--toolkit/components/reader/moz-slider.stories.mjs42
-rw-r--r--toolkit/components/reader/tests/browser/browser_drag_url_readerMode.js2
-rw-r--r--toolkit/components/reader/tests/browser/browser_readerMode_bc_reuse.js2
-rw-r--r--toolkit/components/reader/tests/chrome/chrome.toml2
-rw-r--r--toolkit/components/reader/tests/chrome/test_moz_slider.html48
10 files changed, 548 insertions, 19 deletions
diff --git a/toolkit/components/reader/AboutReader.sys.mjs b/toolkit/components/reader/AboutReader.sys.mjs
index 75776b619f..57fa9d5b48 100644
--- a/toolkit/components/reader/AboutReader.sys.mjs
+++ b/toolkit/components/reader/AboutReader.sys.mjs
@@ -25,15 +25,19 @@ ChromeUtils.defineLazyGetter(
"pluralRules",
() => new Services.intl.PluralRules(undefined)
);
+ChromeUtils.defineLazyGetter(
+ lazy,
+ "l10n",
+ () => new Localization(["toolkit/about/aboutReader.ftl"], true)
+);
const COLORSCHEME_L10N_IDS = {
- 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",
+ auto: "about-reader-color-auto-theme",
+ light: "about-reader-color-light-theme",
+ dark: "about-reader-color-dark-theme",
+ sepia: "about-reader-color-sepia-theme",
+ contrast: "about-reader-color-contrast-theme",
+ gray: "about-reader-color-gray-theme",
};
const CUSTOM_THEME_COLOR_INPUTS = [
@@ -201,6 +205,7 @@ export var AboutReader = function (
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,
@@ -243,13 +248,140 @@ export var AboutReader = function (
];
let fontType = Services.prefs.getCharPref("reader.font_type");
- this._setupSegmentedButton(
- "font-type-buttons",
- fontTypeOptions,
- fontType,
- this._setFontType.bind(this)
- );
- this._setFontType(fontType);
+
+ // Differentiates between the tick mark labels for width vs spacing controls
+ // for localization purposes.
+ const [narrowWidthLabel, wideWidthLabel] = lazy.l10n.formatMessagesSync([
+ "about-reader-slider-label-width-narrow",
+ "about-reader-slider-label-width-wide",
+ ]);
+ const [narrowSpacingLabel, standardSpacingLabel, wideSpacingLabel] =
+ lazy.l10n.formatMessagesSync([
+ "about-reader-slider-label-spacing-narrow",
+ "about-reader-slider-label-spacing-standard",
+ "about-reader-slider-label-spacing-wide",
+ ]);
+
+ let contentWidthSliderOptions = {
+ min: 1,
+ max: 9,
+ ticks: 9,
+ tickLabels: `["${narrowWidthLabel.value}", "${wideWidthLabel.value}"]`,
+ l10nId: "about-reader-content-width-label",
+ icon: "chrome://global/skin/reader/content-width-20.svg",
+ };
+
+ let lineSpacingSliderOptions = {
+ min: 1,
+ max: 9,
+ ticks: 9,
+ tickLabels: `["${narrowSpacingLabel.value}", "${wideSpacingLabel.value}"]`,
+ l10nId: "about-reader-line-spacing-label",
+ icon: "chrome://global/skin/reader/line-spacing-20.svg",
+ };
+
+ let characterSpacingSliderOptions = {
+ min: 1,
+ max: 9,
+ ticks: 9,
+ tickLabels: `["${standardSpacingLabel.value}", "${wideSpacingLabel.value}"]`,
+ l10nId: "about-reader-character-spacing-label",
+ icon: "chrome://global/skin/reader/character-spacing-20.svg",
+ };
+
+ let wordSpacingSliderOptions = {
+ min: 1,
+ max: 9,
+ ticks: 9,
+ tickLabels: `["${standardSpacingLabel.value}", "${wideSpacingLabel.value}"]`,
+ l10nId: "about-reader-word-spacing-label",
+ icon: "chrome://global/skin/reader/word-spacing-20.svg",
+ };
+
+ let textAlignmentOptions = [
+ {
+ l10nId: "about-reader-text-alignment-left",
+ groupName: "text-alignment",
+ value: "left",
+ itemClass: "left-align-button",
+ },
+ {
+ l10nId: "about-reader-text-alignment-center",
+ groupName: "text-alignment",
+ value: "center",
+ itemClass: "center-align-button",
+ },
+ {
+ l10nId: "about-reader-text-alignment-right",
+ groupName: "text-alignment",
+ value: "right",
+ itemClass: "right-align-button",
+ },
+ ];
+
+ // If the page is rtl, reverse order of text alignment options.
+ if (isAppLocaleRTL) {
+ textAlignmentOptions = textAlignmentOptions.reverse();
+ }
+
+ if (Services.prefs.getBoolPref("reader.improved_text_menu.enabled", false)) {
+ doc.getElementById("regular-text-menu").hidden = true;
+ doc.getElementById("improved-text-menu").hidden = false;
+
+ let contentWidth = Services.prefs.getIntPref("reader.content_width");
+ this._setupSlider(
+ "content-width",
+ contentWidthSliderOptions,
+ contentWidth,
+ this._setContentWidthSlider.bind(this)
+ );
+ this._setContentWidthSlider(contentWidth);
+
+ let lineSpacing = Services.prefs.getIntPref("reader.line_height");
+ this._setupSlider(
+ "line-spacing",
+ lineSpacingSliderOptions,
+ lineSpacing,
+ this._setLineSpacing.bind(this)
+ );
+ this._setLineSpacing(lineSpacing);
+
+ let characterSpacing = Services.prefs.getStringPref(
+ "reader.character_spacing"
+ );
+ this._setupSlider(
+ "character-spacing",
+ characterSpacingSliderOptions,
+ characterSpacing,
+ this._setCharacterSpacing.bind(this)
+ );
+ this._setCharacterSpacing(characterSpacing);
+
+ let wordSpacing = Services.prefs.getStringPref("reader.word_spacing");
+ this._setupSlider(
+ "word-spacing",
+ wordSpacingSliderOptions,
+ wordSpacing,
+ this._setWordSpacing.bind(this)
+ );
+ this._setWordSpacing(wordSpacing);
+
+ let textAlignment = Services.prefs.getCharPref("reader.text_alignment");
+ this._setupSegmentedButton(
+ "text-alignment-buttons",
+ textAlignmentOptions,
+ textAlignment,
+ this._setTextAlignment.bind(this)
+ );
+ this._setTextAlignment(textAlignment);
+ } else {
+ this._setupSegmentedButton(
+ "font-type-buttons",
+ fontTypeOptions,
+ fontType,
+ this._setFontType.bind(this)
+ );
+ }
this._setupFontSizeButtons();
@@ -257,6 +389,8 @@ export var AboutReader = function (
this._setupLineHeightButtons();
+ this._setFontType(fontType);
+
if (win.speechSynthesis && Services.prefs.getBoolPref("narrate.enabled")) {
new lazy.NarrateControls(win, this._languagePromise);
}
@@ -775,6 +909,80 @@ AboutReader.prototype = {
);
},
+ _setupSlider(id, options, initialValue, callback) {
+ let doc = this._doc;
+ let slider = doc.createElement("moz-slider");
+
+ slider.setAttribute("min", options.min);
+ slider.setAttribute("max", options.max);
+ slider.setAttribute("value", initialValue);
+ slider.setAttribute("ticks", options.ticks);
+ slider.setAttribute("tick-labels", options.tickLabels);
+ slider.setAttribute("data-l10n-id", options.l10nId);
+ slider.setAttribute("data-l10n-attrs", "label");
+ slider.setAttribute("slider-icon", options.icon);
+
+ slider.addEventListener("slider-changed", e => {
+ callback(e.detail);
+ });
+
+ let sliderContainer = doc.getElementById(`${id}-slider`);
+ sliderContainer.appendChild(slider);
+ },
+
+ // Rename this function to setContentWidth when the old menu is retired.
+ _setContentWidthSlider(newContentWidth) {
+ // We map the slider range [1-9] to 20-60em.
+ let width = 20 + 5 * (newContentWidth - 1) + "em";
+ this._doc.body.style.setProperty("--content-width", width);
+ this._scheduleToolbarOverlapHandler();
+ return lazy.AsyncPrefs.set(
+ "reader.content_width",
+ parseInt(newContentWidth)
+ );
+ },
+
+ _setLineSpacing(newLineSpacing) {
+ // We map the slider range [1-9] to 1-2.6em.
+ let spacing = 1 + 0.2 * (newLineSpacing - 1) + "em";
+ this._containerElement.style.setProperty("--line-height", spacing);
+ return lazy.AsyncPrefs.set("reader.line_height", parseInt(newLineSpacing));
+ },
+
+ _setCharacterSpacing(newCharSpacing) {
+ // We map the slider range [1-9] to 0-0.24em.
+ let spacing = (newCharSpacing - 1) * 0.03;
+ this._containerElement.style.setProperty(
+ "--letter-spacing",
+ `${parseFloat(spacing).toFixed(2)}em`
+ );
+ lazy.AsyncPrefs.set("reader.character_spacing", newCharSpacing);
+ },
+
+ _setWordSpacing(newWordSpacing) {
+ // We map the slider range [1-9] to 0-0.4em.
+ let spacing = (newWordSpacing - 1) * 0.05;
+ this._containerElement.style.setProperty(
+ "--word-spacing",
+ `${parseFloat(spacing).toFixed(2)}em`
+ );
+ lazy.AsyncPrefs.set("reader.word_spacing", newWordSpacing);
+ },
+
+ _setTextAlignment(newTextAlignment) {
+ if (this._textAlignment === newTextAlignment) {
+ return false;
+ }
+
+ this._containerElement.style.setProperty(
+ "--text-alignment",
+ newTextAlignment
+ );
+
+ lazy.AsyncPrefs.set("reader.text_alignment", newTextAlignment);
+ return true;
+ },
+
_setColorScheme(newColorScheme) {
// There's nothing to change if the new color scheme is the same as our current scheme.
if (this._colorScheme === newColorScheme) {
@@ -823,7 +1031,11 @@ AboutReader.prototype = {
// 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) {
+ const colorsMenuEnabled = Services.prefs.getBoolPref(
+ "reader.colors_menu.enabled",
+ false
+ );
+ if (colorsMenuEnabled && this._colorScheme == "custom" && fromInputEvent) {
lastSelectedTheme = colorSchemePref;
return false;
}
diff --git a/toolkit/components/reader/content/aboutReader.html b/toolkit/components/reader/content/aboutReader.html
index d1c9164d42..452d4590b8 100644
--- a/toolkit/components/reader/content/aboutReader.html
+++ b/toolkit/components/reader/content/aboutReader.html
@@ -25,6 +25,10 @@
<link rel="localization" href="toolkit/branding/brandings.ftl" />
<script
type="module"
+ src="chrome://global/content/reader/moz-slider.mjs"
+ ></script>
+ <script
+ type="module"
src="chrome://global/content/reader/color-input.mjs"
></script>
<script
@@ -50,7 +54,57 @@
data-l10n-id="about-reader-toolbar-close"
></span>
</button>
- <ul class="dropdown style-dropdown">
+ <ul
+ class="dropdown improved-style-dropdown"
+ id="improved-text-menu"
+ hidden="true"
+ >
+ <li>
+ <button
+ class="dropdown-toggle toolbar-button improved-style-button"
+ aria-labelledby="toolbar-text-layout-controls"
+ data-telemetry-id="reader-text-layout-controls"
+ >
+ <span
+ class="hover-label"
+ id="toolbar-text-layout-controls"
+ data-l10n-id="about-reader-toolbar-text-layout-controls"
+ ></span>
+ </button>
+ </li>
+ <li class="dropdown-popup" id="text-layout-controls">
+ <h2
+ data-l10n-id="about-reader-layout-header"
+ id="about-reader-layout-header"
+ ></h2>
+ <div id="content-width-slider" class="slider-container"></div>
+ <div id="line-spacing-slider" class="slider-container"></div>
+ <hr />
+ <details id="about-reader-advanced-layout">
+ <summary class="accordion-header">
+ <h2
+ data-l10n-id="about-reader-advanced-layout-header"
+ id="about-reader-advanced-layout-header"
+ ></h2>
+ <span class="chevron-icon"></span>
+ </summary>
+ <div
+ id="character-spacing-slider"
+ class="slider-container"
+ ></div>
+ <div id="word-spacing-slider" class="slider-container"></div>
+ <label
+ for="text-alignment-buttons"
+ data-l10n-id="about-reader-text-alignment-label"
+ ></label>
+ <div
+ class="text-alignment-buttons radiorow"
+ id="text-alignment-buttons"
+ ></div>
+ </details>
+ </li>
+ </ul>
+ <ul class="dropdown style-dropdown" id="regular-text-menu">
<li>
<button
class="dropdown-toggle toolbar-button style-button"
@@ -120,7 +174,7 @@
<span
class="hover-label"
id="toolbar-color-controls"
- data-l10n-id="about-reader-toolbar-color-controls"
+ data-l10n-id="about-reader-toolbar-theme-controls"
></span>
</button>
</li>
diff --git a/toolkit/components/reader/jar.mn b/toolkit/components/reader/jar.mn
index 587dd45cf8..a17d00c076 100644
--- a/toolkit/components/reader/jar.mn
+++ b/toolkit/components/reader/jar.mn
@@ -6,3 +6,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)
+ content/global/reader/moz-slider.css (moz-slider.css)
+ content/global/reader/moz-slider.mjs (moz-slider.mjs)
diff --git a/toolkit/components/reader/moz-slider.css b/toolkit/components/reader/moz-slider.css
new file mode 100644
index 0000000000..5238bd02a3
--- /dev/null
+++ b/toolkit/components/reader/moz-slider.css
@@ -0,0 +1,43 @@
+/* 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/. */
+
+.container {
+ display: flex;
+ align-items: center;
+ gap: var(--space-large);
+ margin-inline-start: var(--space-medium);
+}
+
+.slider-label {
+ display: inline-block;
+ margin-block-end: var(--space-medium);
+}
+
+.icon-container + .slider-container .slider-label {
+ margin-inline-start: calc(-2 * var(--space-xlarge));
+}
+
+.icon-container {
+ position: relative;
+ top: 6px;
+}
+
+.icon {
+ -moz-context-properties: fill;
+ fill: var(--popup-button-foreground);
+ height: 20px;
+ width: 20px;
+}
+
+.slider-container,
+input {
+ width: 100%;
+}
+
+datalist {
+ display: flex;
+ justify-content: space-between;
+ white-space: nowrap;
+ font-size: var(--font-size-small);
+}
diff --git a/toolkit/components/reader/moz-slider.mjs b/toolkit/components/reader/moz-slider.mjs
new file mode 100644
index 0000000000..057738f2cc
--- /dev/null
+++ b/toolkit/components/reader/moz-slider.mjs
@@ -0,0 +1,126 @@
+/* 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";
+
+/**
+ * A range slider component that can be used to select a value.
+ *
+ * @tagname moz-slider
+ * @property {number} min - The minimum value of the slider.
+ * @property {number} max - The maximum value of the slider.
+ * @property {number} value - The initial value of the slider.
+ * @property {number} ticks - The number of tick marks to display under the slider.
+ * @property {Array<string>} tickLabels - A list containing the tick label strings.
+ * @property {string} label - The label text for the slider.
+ * @property {string} sliderIcon - The url of the slider icon.
+ */
+
+export default class MozSlider extends MozLitElement {
+ static properties = {
+ min: { type: Number },
+ max: { type: Number },
+ value: { type: Number },
+ ticks: { type: Number },
+ tickLabels: { type: Array, attribute: "tick-labels" },
+ label: { type: String },
+ sliderIcon: { type: String, attribute: "slider-icon" },
+ };
+
+ static get queries() {
+ return {
+ tickMarks: "datalist",
+ sliderTrack: "#inputSlider",
+ };
+ }
+
+ constructor() {
+ super();
+ this.ticks = 0;
+ this.tickLabels = [];
+ this.sliderIcon = "";
+ }
+
+ getStepSize() {
+ const stepSize = (this.max - this.min) / (this.ticks - 1);
+ return stepSize;
+ }
+
+ setupIcon() {
+ if (this.sliderIcon) {
+ return html`<div class="icon-container">
+ <img class="icon" role="presentation" src=${this.sliderIcon} />
+ </div> `;
+ }
+ return "";
+ }
+
+ ticksTemplate() {
+ if (this.ticks > 0) {
+ let tickList = [];
+ let value = this.min;
+ let stepSize = this.getStepSize();
+ for (let i = 0; i < this.ticks; i++) {
+ let optionId = "";
+ let label = "";
+ if (this.tickLabels.length) {
+ if (i == 0) {
+ optionId = "inline-start-label";
+ label = this.tickLabels[0];
+ } else if (i == this.ticks - 1) {
+ optionId = "inline-end-label";
+ label = this.tickLabels[1];
+ }
+ }
+ tickList.push(
+ html`<option
+ id=${optionId}
+ value=${parseFloat(value).toFixed(2)}
+ label=${label}
+ ></option>`
+ );
+ value += stepSize;
+ }
+ return html` <datalist id="slider-ticks">${tickList}</datalist> `;
+ }
+ return "";
+ }
+
+ handleChange(event) {
+ this.value = event.target.value;
+ this.dispatchEvent(
+ new CustomEvent("slider-changed", {
+ detail: this.value,
+ })
+ );
+ }
+
+ render() {
+ return html`
+ <link
+ rel="stylesheet"
+ href="chrome://global/content/reader/moz-slider.css"
+ />
+ <div class="container">
+ ${this.setupIcon()}
+ <div class="slider-container">
+ <label class="slider-label" for="inputSlider">${this.label}</label>
+ <input
+ id="inputSlider"
+ max=${this.max}
+ min=${this.min}
+ step=${this.getStepSize()}
+ type="range"
+ .value=${this.value}
+ list="slider-ticks"
+ @change=${this.handleChange}
+ />
+ ${this.ticksTemplate()}
+ </div>
+ </div>
+ `;
+ }
+}
+customElements.define("moz-slider", MozSlider);
diff --git a/toolkit/components/reader/moz-slider.stories.mjs b/toolkit/components/reader/moz-slider.stories.mjs
new file mode 100644
index 0000000000..3f4083439c
--- /dev/null
+++ b/toolkit/components/reader/moz-slider.stories.mjs
@@ -0,0 +1,42 @@
+/* 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/moz-slider.mjs";
+
+export default {
+ title: "Domain-specific UI Widgets/Reader View/Slider",
+ component: "moz-slider",
+ argTypes: {},
+ parameters: {
+ status: "stable",
+ fluent: `moz-slider-label =
+ .label = Slider test
+ `,
+ },
+};
+
+const Template = ({ min, max, value, ticks, labelL10nId, sliderIcon }) => html`
+ <moz-slider
+ min=${min}
+ max=${max}
+ value=${value}
+ ticks=${ticks}
+ tick-labels='["Narrow", "Wide"]'
+ data-l10n-id=${labelL10nId}
+ data-l10n-attrs="label"
+ slider-icon=${sliderIcon}
+ ></moz-slider>
+`;
+
+export const Default = Template.bind({});
+Default.args = {
+ min: 0,
+ max: 4,
+ value: 2,
+ ticks: 9,
+ labelL10nId: "moz-slider-label",
+ sliderIcon: "chrome://global/skin/icons/defaultFavicon.svg",
+};
diff --git a/toolkit/components/reader/tests/browser/browser_drag_url_readerMode.js b/toolkit/components/reader/tests/browser/browser_drag_url_readerMode.js
index 2dae1872c3..615e67bd56 100644
--- a/toolkit/components/reader/tests/browser/browser_drag_url_readerMode.js
+++ b/toolkit/components/reader/tests/browser/browser_drag_url_readerMode.js
@@ -5,7 +5,7 @@
const TEST_PATH = getRootDirectory(gTestPath).replace(
"chrome://mochitests/content",
- "http://example.com"
+ "https://example.com"
);
add_task(async function test_readerModeURLDrag() {
diff --git a/toolkit/components/reader/tests/browser/browser_readerMode_bc_reuse.js b/toolkit/components/reader/tests/browser/browser_readerMode_bc_reuse.js
index 9ac0e367ca..d1d0e8b0d5 100644
--- a/toolkit/components/reader/tests/browser/browser_readerMode_bc_reuse.js
+++ b/toolkit/components/reader/tests/browser/browser_readerMode_bc_reuse.js
@@ -5,7 +5,7 @@
const TEST_PATH = getRootDirectory(gTestPath).replace(
"chrome://mochitests/content",
- "http://example.com"
+ "https://example.com"
);
const TEST_URL = TEST_PATH + "readerModeArticle.html";
diff --git a/toolkit/components/reader/tests/chrome/chrome.toml b/toolkit/components/reader/tests/chrome/chrome.toml
index e416c49181..2697e13db8 100644
--- a/toolkit/components/reader/tests/chrome/chrome.toml
+++ b/toolkit/components/reader/tests/chrome/chrome.toml
@@ -1,3 +1,5 @@
[DEFAULT]
["test_color_input.html"]
+
+["test_moz_slider.html"]
diff --git a/toolkit/components/reader/tests/chrome/test_moz_slider.html b/toolkit/components/reader/tests/chrome/test_moz_slider.html
new file mode 100644
index 0000000000..01af33ed14
--- /dev/null
+++ b/toolkit/components/reader/tests/chrome/test_moz_slider.html
@@ -0,0 +1,48 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>MozSlider Tests</title>
+ <script src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" href="chrome://mochikit/content/tests/SimpleTest/test.css"/>
+ <script src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>
+ <script type="module" src="chrome://global/content/reader/moz-slider.mjs"></script>
+</head>
+<body>
+<p id="display"></p>
+<div id="content" style="max-width: fit-content">
+ <moz-slider min="0" max="3" value="2" ticks="7" ticklabels='["Narrow", "Wide"]'></moz-slider>
+</div>
+<pre id="test">
+<script class="testbody" type="application/javascript">
+ add_task(async function testMozSliderDisplay() {
+ const mozSlider = document.querySelector("moz-slider");
+ ok(mozSlider, "moz-slider is rendered");
+ is(mozSlider.value, 2, "moz-slider should set initial value based on prop");
+
+ const ticks = mozSlider.tickMarks;
+ ok(ticks, "moz-slider contains tick marks");
+ is(ticks.childElementCount, 7, "should have the correct number of ticks");
+ });
+
+ add_task(async function testMozSliderValues() {
+ const mozSlider = document.querySelector("moz-slider");
+ const firstVal = mozSlider.value;
+
+ const sliderChanged = new Promise((resolve) => {
+ mozSlider.addEventListener("slider-changed", (event) => resolve(event.detail), { once: true });
+ });
+ mozSlider.sliderTrack.focus();
+ synthesizeKey("KEY_ArrowRight");
+ await sliderChanged;
+ ok(mozSlider.value > firstVal, "moving slider to the right should increase value");
+ is(mozSlider.value - firstVal, 0.5, "should increment by correct step size");
+
+ synthesizeKey("KEY_ArrowRight", { repeat: 2 });
+ await sliderChanged;
+ ok(mozSlider.value == 3, "should not increment beyond max value");
+ });
+</script>
+</pre>
+</body>
+</html>