commit 11d4b58923f03d45f7d64b85c6ef819cd40c2e08 parent 46fc23ce550d665431bfe76e6fa7301cc2b17a89 Author: Cristina Horotan <chorotan@mozilla.com> Date: Sat, 13 Dec 2025 01:24:48 +0200 Revert "Bug 2000343, Bug 1972360, Bug 1972367 - Ignore keypress from nested children in SelectControlBaseElement r=hjones" for causing chrome failures in test_moz_fieldset.html This reverts commit 7cce9daae246b808d55379579b74f58712524ebf. Revert "Bug 1972360 - Convert Color contrast section to config-based prefs r=fluent-reviewers,bolsson,hjones,desktop-theme-reviewers" This reverts commit 7f4f986b9d3e98b5a52d7eab0e1b5836b01af39f. Revert "Bug 1972367 - Convert Zoom settings section to config-based prefs r=fluent-reviewers,desktop-theme-reviewers,bolsson,hjones" This reverts commit d5e1aac51c7e6c56958a028b8e312695df2be159. Diffstat:
14 files changed, 226 insertions(+), 435 deletions(-)
diff --git a/accessible/tests/browser/telemetry/browser_HCM_telemetry.js b/accessible/tests/browser/telemetry/browser_HCM_telemetry.js @@ -101,7 +101,7 @@ add_task(async function testInit() { if (AppConstants.platform == "win") { is( contrastControlRadios.value, - 0, + "0", "HCM menulist should be set to only with HCM theme on startup for windows" ); @@ -115,7 +115,7 @@ add_task(async function testInit() { } else { is( contrastControlRadios.value, - 1, + "1", "HCM menulist should be set to never on startup for non-windows platforms" ); @@ -170,7 +170,7 @@ add_task(async function testSetAlways() { ); newOption.click(); - is(contrastControlRadios.value, 2, "HCM menulist should be set to always"); + is(contrastControlRadios.value, "2", "HCM menulist should be set to always"); await refresh(); @@ -207,7 +207,7 @@ add_task(async function testSetDefault() { ); newOption.click(); - is(contrastControlRadios.value, 0, "HCM menulist should be set to default"); + is(contrastControlRadios.value, "0", "HCM menulist should be set to default"); await refresh(); @@ -260,7 +260,7 @@ add_task(async function testSetNever() { ); newOption.click(); - is(contrastControlRadios.value, 1, "HCM menulist should be set to never"); + is(contrastControlRadios.value, "1", "HCM menulist should be set to never"); await refresh(); diff --git a/browser/components/preferences/main.inc.xhtml b/browser/components/preferences/main.inc.xhtml @@ -77,7 +77,37 @@ </groupbox> <!-- Colors --> -<html:setting-group id="contrastControlGroup" groupid="contrast" data-category="paneGeneral" hidden="true" /> +<groupbox id="contrastControlGroup" data-category="paneGeneral" hidden="true"> + <label><html:h2 data-l10n-id="preferences-contrast-control-header"/></label> + <description class="description-deemphasized" data-l10n-id="preferences-contrast-control-description"/> + + <radiogroup id="contrastControlSettings" preference="browser.display.document_color_use"> + <radio id="contrastSettingsAuto" + value="0" + data-l10n-id="preferences-contrast-control-use-platform-settings"/> + <radio id="contrastSettingsOff" + value="1" + data-l10n-id="preferences-contrast-control-off"/> + <vbox align="start"> + <radio id="contrastSettingsOn" + value="2" + flex="1" + data-l10n-id="preferences-contrast-control-custom"/> + <button id="colors" + is="highlightable-button" + class="accessory-button indent" + data-l10n-id="preferences-colors-manage-button" + search-l10n-ids=" + colors-text-and-background, + colors-text, + colors-text-background, + colors-links-header, + colors-links-unvisited, + colors-links-visited + "/> + </vbox> + </radiogroup> +</groupbox> <!-- Fonts --> <groupbox id="fontsGroup" data-category="paneGeneral" hidden="true"> @@ -170,7 +200,21 @@ </groupbox> <!-- Zoom --> -<html:setting-group id="zoomGroup" groupid="zoom" data-category="paneGeneral" hidden="true" /> +<groupbox id="zoomGroup" data-category="paneGeneral" hidden="true" data-srd-groupid="zoom"> + <label><html:h2 data-l10n-id="preferences-zoom-header"/></label> + <hbox id="zoomBox" align="center" hidden="true"> + <label control="defaultZoom" data-l10n-id="preferences-default-zoom"/> + <menulist id="defaultZoom"> + <menupopup/> + </menulist> + </hbox> + <html:moz-message-bar id="text-zoom-override-warning" data-l10n-id="preferences-text-zoom-override-warning"/> + <checkbox id="zoomText" + data-l10n-id="preferences-zoom-text-only"/> + +</groupbox> + +<html:setting-group hidden="true" data-category="paneGeneral" groupid="zoom" /> <!-- Languages --> <groupbox id="languagesGroup" data-category="paneGeneral" hidden="true"> diff --git a/browser/components/preferences/main.js b/browser/components/preferences/main.js @@ -142,9 +142,6 @@ Preferences.addAll([ { id: "accessibility.typeaheadfind", type: "bool" }, { id: "accessibility.blockautorefresh", type: "bool" }, - /* Zoom */ - { id: "browser.zoom.full", type: "bool" }, - /* Browsing * general.autoScroll - when set to true, clicking the scroll wheel on the mouse activates a @@ -636,6 +633,7 @@ Preferences.addSetting({ }, }); +Preferences.addSetting({ id: "zoomPlaceholder" }); Preferences.addSetting({ id: "containersPane", onUserClick(e) { @@ -1664,127 +1662,6 @@ Preferences.addSetting({ }, }); -/** - * Helper object for managing the various zoom related settings. - */ -const ZoomHelpers = { - win: window.browsingContext.topChromeWindow, - get FullZoom() { - return this.win.FullZoom; - }, - get ZoomManager() { - return this.win.ZoomManager; - }, - - /** - * Set the global default zoom value. - * - * @param {number} newZoom - The new zoom - * @returns {Promise<void>} - */ - async setDefaultZoom(newZoom) { - let cps2 = Cc["@mozilla.org/content-pref/service;1"].getService( - Ci.nsIContentPrefService2 - ); - let nonPrivateLoadContext = Cu.createLoadContext(); - let resolvers = Promise.withResolvers(); - /* Because our setGlobal function takes in a browsing context, and - * because we want to keep this property consistent across both private - * and non-private contexts, we create a non-private context and use that - * to set the property, regardless of our actual context. - */ - cps2.setGlobal(this.FullZoom.name, newZoom, nonPrivateLoadContext, { - handleCompletion: resolvers.resolve, - handleError: resolvers.reject, - }); - return resolvers.promise; - }, - - async getDefaultZoom() { - /** @import { ZoomUI as GlobalZoomUI } from "resource:///modules/ZoomUI.sys.mjs" */ - /** @type {GlobalZoomUI} */ - let ZoomUI = this.win.ZoomUI; - return await ZoomUI.getGlobalValue(); - }, - - /** - * The possible zoom values. - * - * @returns {number[]} - */ - get zoomValues() { - return this.ZoomManager.zoomValues; - }, - - toggleFullZoom() { - this.ZoomManager.toggleZoom(); - }, -}; -Preferences.addSetting( - class extends Preferences.AsyncSetting { - static id = "defaultZoom"; - /** @type {Record<"options", object[]>} */ - optionsConfig; - - /** - * @param {string} val - zoom value as a string - */ - async set(val) { - ZoomHelpers.setDefaultZoom( - parseFloat((parseInt(val, 10) / 100).toFixed(2)) - ); - } - async get() { - return Math.round((await ZoomHelpers.getDefaultZoom()) * 100); - } - async getControlConfig() { - if (!this.optionsConfig) { - this.optionsConfig = { - options: ZoomHelpers.zoomValues.map(a => { - let value = Math.round(a * 100); - return { - value, - l10nId: "preferences-default-zoom-value", - l10nArgs: { percentage: value }, - }; - }), - }; - } - return this.optionsConfig; - } - } -); -Preferences.addSetting({ - id: "zoomTextPref", - pref: "browser.zoom.full", -}); -Preferences.addSetting({ - id: "zoomText", - deps: ["zoomTextPref"], - // Use the Setting since the ZoomManager getter may not have updated yet. - get: (_, { zoomTextPref }) => !zoomTextPref.value, - set: () => ZoomHelpers.toggleFullZoom(), - disabled: ({ zoomTextPref }) => zoomTextPref.locked, -}); -Preferences.addSetting({ - id: "zoomWarning", - deps: ["zoomText"], - visible: ({ zoomText }) => Boolean(zoomText.value), -}); -Preferences.addSetting({ - id: "contrastControlSettings", - pref: "browser.display.document_color_use", -}); -Preferences.addSetting({ - id: "colors", - onUserClick() { - gSubDialog.open( - "chrome://browser/content/preferences/dialogs/colors.xhtml", - { features: "resizable=no" } - ); - }, -}); - SettingGroupManager.registerGroups({ containers: { // This section is marked as in progress for testing purposes @@ -2101,24 +1978,21 @@ SettingGroupManager.registerGroups({ ], }, zoom: { - l10nId: "preferences-zoom-header2", - headingLevel: 2, + // This section is marked as in progress for testing purposes + inProgress: true, items: [ { - id: "defaultZoom", - l10nId: "preferences-default-zoom-label", - control: "moz-select", - }, - { - id: "zoomText", - l10nId: "preferences-zoom-text-only", + id: "zoomPlaceholder", + control: "moz-message-bar", + controlAttrs: { + message: "Placeholder for updated zoom controls", + }, }, { - id: "zoomWarning", - l10nId: "preferences-text-zoom-override-warning", - control: "moz-message-bar", + id: "containersPane", + control: "moz-button", controlAttrs: { - type: "warning", + label: "Manage container settings", }, }, ], @@ -2209,45 +2083,6 @@ SettingGroupManager.registerGroups({ }, ], }, - contrast: { - l10nId: "preferences-contrast-control-group", - headingLevel: 2, - items: [ - { - id: "contrastControlSettings", - control: "moz-radio-group", - l10nId: "preferences-contrast-control-radio-group", - options: [ - { - id: "contrastSettingsAuto", - value: 0, - l10nId: "preferences-contrast-control-use-platform-settings", - }, - { - id: "contrastSettingsOff", - value: 1, - l10nId: "preferences-contrast-control-off", - }, - { - id: "contrastSettingsOn", - value: 2, - l10nId: "preferences-contrast-control-custom", - items: [ - { - id: "colors", - l10nId: "preferences-colors-manage-button", - control: "moz-box-button", - controlAttrs: { - "search-l10n-ids": - "colors-text-and-background, colors-text.label, colors-text-background.label, colors-links-header, colors-links-unvisited.label, colors-links-visited.label", - }, - }, - ], - }, - ], - }, - ], - }, browsing: { l10nId: "browsing-group-label", items: [ @@ -3492,13 +3327,17 @@ var gMainPane = { gMainPane.initPrimaryBrowserLanguageUI(); } + // We call `initDefaultZoomValues` to set and unhide the + // default zoom preferences menu, and to establish a + // listener for future menu changes. + gMainPane.initDefaultZoomValues(); + gMainPane.initTranslations(); // Initialize settings groups from the config object. initSettingGroup("appearance"); initSettingGroup("downloads"); initSettingGroup("drm"); - initSettingGroup("contrast"); initSettingGroup("browsing"); initSettingGroup("zoom"); initSettingGroup("support"); @@ -3547,6 +3386,12 @@ var gMainPane = { gMainPane._rebuildFonts.bind(gMainPane) ); setEventListener("advancedFonts", "command", gMainPane.configureFonts); + setEventListener("colors", "command", gMainPane.configureColors); + Preferences.get("browser.display.document_color_use").on( + "change", + gMainPane.updateColorsButton.bind(gMainPane) + ); + gMainPane.updateColorsButton(); document .getElementById("browserLayoutShowSidebar") @@ -3858,6 +3703,58 @@ var gMainPane = { }, /** + * Fetch the existing default zoom value, initialise and unhide + * the preferences menu. This method also establishes a listener + * to ensure handleDefaultZoomChange is called on future menu + * changes. + */ + async initDefaultZoomValues() { + let win = window.browsingContext.topChromeWindow; + let selected = await win.ZoomUI.getGlobalValue(); + let menulist = document.getElementById("defaultZoom"); + + new SelectionChangedMenulist(menulist, event => { + let parsedZoom = parseFloat((event.target.value / 100).toFixed(2)); + gMainPane.handleDefaultZoomChange(parsedZoom); + }); + + setEventListener("zoomText", "command", function () { + win.ZoomManager.toggleZoom(); + document.getElementById("text-zoom-override-warning").hidden = + !document.getElementById("zoomText").checked; + }); + + let zoomValues = win.ZoomManager.zoomValues.map(a => { + return Math.round(a * 100); + }); + + let fragment = document.createDocumentFragment(); + for (let zoomLevel of zoomValues) { + let menuitem = document.createXULElement("menuitem"); + document.l10n.setAttributes(menuitem, "preferences-default-zoom-value", { + percentage: zoomLevel, + }); + menuitem.setAttribute("value", zoomLevel); + fragment.appendChild(menuitem); + } + + let menupopup = menulist.querySelector("menupopup"); + menupopup.appendChild(fragment); + menulist.value = Math.round(selected * 100); + + let checkbox = document.getElementById("zoomText"); + checkbox.checked = !win.ZoomManager.useFullZoom; + document.getElementById("text-zoom-override-warning").hidden = + !checkbox.checked; + document.getElementById("zoomBox").hidden = false; + }, + + updateColorsButton() { + document.getElementById("colors").disabled = + Preferences.get("browser.display.document_color_use").value != 2; + }, + + /** * Initialize the translations view. */ async initTranslations() { @@ -4473,6 +4370,27 @@ var gMainPane = { }, /** + * Takes as newZoom a floating point value representing the + * new default zoom. This value should not be a string, and + * should not carry a percentage sign/other localisation + * characteristics. + */ + handleDefaultZoomChange(newZoom) { + let cps2 = Cc["@mozilla.org/content-pref/service;1"].getService( + Ci.nsIContentPrefService2 + ); + let nonPrivateLoadContext = Cu.createLoadContext(); + /* Because our setGlobal function takes in a browsing context, and + * because we want to keep this property consistent across both private + * and non-private contexts, we crate a non-private context and use that + * to set the property, regardless of our actual context. + */ + + let win = window.browsingContext.topChromeWindow; + cps2.setGlobal(win.FullZoom.name, newZoom, nonPrivateLoadContext); + }, + + /** * Shows a subdialog containing the profile selector page. */ manageProfiles() { @@ -4671,6 +4589,17 @@ var gMainPane = { ); }, + /** + * Displays the colors dialog, where default web page/link/etc. colors can be + * configured. + */ + configureColors() { + gSubDialog.open( + "chrome://browser/content/preferences/dialogs/colors.xhtml", + { features: "resizable=no" } + ); + }, + // NETWORK /** * Displays a dialog in which proxy settings may be changed. diff --git a/browser/components/preferences/tests/browser_colors_dialog.js b/browser/components/preferences/tests/browser_colors_dialog.js @@ -38,26 +38,32 @@ add_task(async function testColorPicker() { const button = gBrowser.contentDocument.getElementById("colors"); + const radiogroup = content.document.getElementById("contrastControlSettings"); const radioOff = content.document.getElementById("contrastSettingsOff"); const radioCustom = content.document.getElementById("contrastSettingsOn"); - radioOff.focus(); + // Focus "Off" Contrast radio button: + radiogroup.focus(); Assert.equal( - radioOff, + radiogroup, gBrowser.contentDocument.activeElement, "Radio group for Custom Colors is focused" ); - Assert.ok(button.buttonEl.disabled, "Manage Colors button is disabled"); + Assert.equal( + radioOff, + radiogroup.querySelector("radio[focused='true']"), + "Radio group with option 'Off' is focused" + ); + Assert.ok(button.disabled, "Manage Colors button is disabled"); // Focus "Custom" Contrast radio button: EventUtils.synthesizeKey("KEY_ArrowDown"); Assert.equal( radioCustom, - gBrowser.contentDocument.activeElement, + radiogroup.querySelector("radio[focused='true']"), "Radio group with option 'Custom' is focused" ); - await new Promise(r => requestAnimationFrame(r)); - Assert.ok(!button.buttonEl.disabled, "Manage Colors button is now enabled"); + Assert.ok(!button.disabled, "Manage Colors button is now enabled"); // Focus "Manage Colors" button: EventUtils.synthesizeKey("KEY_Tab"); diff --git a/browser/components/preferences/tests/browser_setting_group_in_progress.js b/browser/components/preferences/tests/browser_setting_group_in_progress.js @@ -3,87 +3,45 @@ "use strict"; -async function openPrefsWithSettings({ allEnabled, sectionEnabled }) { +async function openPrefsWithSettings({ allEnabled, zoomEnabled }) { await SpecialPowers.pushPrefEnv({ set: [ ["browser.settings-redesign.enabled", allEnabled], - ["browser.settings-redesign.mysection.enabled", sectionEnabled], + ["browser.settings-redesign.zoom.enabled", zoomEnabled], ], }); - await openPreferencesViaOpenPreferencesAPI("privacy", { leaveOpen: true }); - let doc = gBrowser.selectedBrowser.contentDocument; - let win = doc.ownerGlobal; - win.Preferences.addSetting({ - id: "testSetting", - get: () => true, - }); - win.SettingGroupManager.registerGroup("mysection", { - inProgress: true, - l10nId: "downloads-header-2", - headingLevel: 2, - items: [ - { - id: "testSetting", - controlAttrs: { - label: "Test setting", - }, - }, - ], - }); - let zoomGroup = doc.getElementById("zoomGroup"); - let legacyGroup = doc.createXULElement("groupbox"); - legacyGroup.id = "mysectionGroup"; - legacyGroup.setAttribute("data-srd-groupid", "mysection"); - legacyGroup.setAttribute("data-category", "paneGeneral"); - legacyGroup.hidden = true; - let mysectionGroup = doc.createElement("setting-group"); - mysectionGroup.setAttribute("groupid", "mysection"); - mysectionGroup.setAttribute("data-category", "paneGeneral"); - mysectionGroup.hidden = true; - zoomGroup.parentElement.insertBefore(mysectionGroup, zoomGroup); - zoomGroup.parentElement.insertBefore(legacyGroup, zoomGroup); - win.initSettingGroup("mysection"); - let paneLoaded = waitForPaneChange("general"); - EventUtils.synthesizeMouseAtCenter( - doc.getElementById("category-general"), - {}, - win - ); - await paneLoaded; - return doc; + await openPreferencesViaOpenPreferencesAPI("general", { leaveOpen: true }); + return gBrowser.selectedBrowser.contentDocument; } add_task(async function test_section_disabled() { - try { - let doc = await openPrefsWithSettings({ - allEnabled: false, - sectionEnabled: false, - }); - let legacyGroup = doc.getElementById("mysectionGroup"); - let redesignGroup = doc.querySelector('setting-group[groupid="mysection"]'); - ok(legacyGroup.checkVisibility(), "The legacy group is visible"); - is( - legacyGroup.dataset.category, - "paneGeneral", - "The legacy group has a category" - ); - ok( - !legacyGroup.hasAttribute("data-hidden-from-search"), - "The legacy group is visible to search" - ); - ok(!redesignGroup, "The redesign group was removed"); - } finally { - gBrowser.removeCurrentTab(); - } + let doc = await openPrefsWithSettings({ + allEnabled: false, + zoomEnabled: false, + }); + let legacyGroup = doc.getElementById("zoomGroup"); + let redesignGroup = doc.querySelector('setting-group[groupid="zoom"]'); + ok(legacyGroup.checkVisibility(), "The legacy group is visible"); + is( + legacyGroup.dataset.category, + "paneGeneral", + "The legacy group has a category" + ); + ok( + !legacyGroup.hasAttribute("data-hidden-from-search"), + "The legacy group is visible to search" + ); + ok(!redesignGroup, "The redesign group was removed"); + gBrowser.removeCurrentTab(); }); add_task(async function test_section_enabled() { let doc = await openPrefsWithSettings({ allEnabled: false, - sectionEnabled: true, + zoomEnabled: true, }); - let legacyGroup = doc.getElementById("mysectionGroup"); - let redesignGroup = doc.querySelector('setting-group[groupid="mysection"]'); + let legacyGroup = doc.getElementById("zoomGroup"); + let redesignGroup = doc.querySelector('setting-group[groupid="zoom"]'); ok(!legacyGroup.checkVisibility(), "The legacy group is hidden"); ok(!legacyGroup.dataset.category, "The legacy group category is removed"); is( @@ -103,10 +61,10 @@ add_task(async function test_section_enabled() { add_task(async function test_all_enabled() { let doc = await openPrefsWithSettings({ allEnabled: true, - sectionEnabled: false, + zoomEnabled: false, }); - let legacyGroup = doc.getElementById("mysectionGroup"); - let redesignGroup = doc.querySelector('setting-group[groupid="mysection"]'); + let legacyGroup = doc.getElementById("zoomGroup"); + let redesignGroup = doc.querySelector('setting-group[groupid="zoom"]'); ok(!legacyGroup.checkVisibility(), "The legacy group is hidden"); ok(!legacyGroup.dataset.category, "The legacy group category is removed"); is( diff --git a/browser/components/preferences/widgets/setting-control/setting-control.css b/browser/components/preferences/widgets/setting-control/setting-control.css @@ -6,8 +6,3 @@ .reenable-extensions-message-bar { margin-block: var(--space-large); } - -setting-control[hidden]:has(> moz-message-bar) { - display: block; - margin-block-start: calc(-1 * var(--space-large)); -} diff --git a/browser/components/preferences/widgets/setting-control/setting-control.mjs b/browser/components/preferences/widgets/setting-control/setting-control.mjs @@ -33,8 +33,6 @@ import MozInputFolder from "chrome://global/content/elements/moz-input-folder.mj * @property {string} [control] * The element tag to render, default assumed based on parent control. * @property {any} [value] A value to set on the option. - * @property {boolean} [disabled] If the option should be disabled. - * @property {boolean} [hidden] If the option should be hidden. */ /** @@ -224,6 +222,7 @@ export class SettingControl extends SettingElement { * * @override * @param {SettingElementConfig} config + * @returns {ReturnType<SettingElement['getCommonPropertyMapping']>} */ getCommonPropertyMapping(config) { return { @@ -239,12 +238,11 @@ export class SettingControl extends SettingElement { * @param {SettingOptionConfig} config */ getOptionPropertyMapping(config) { - return { - ...this.getCommonPropertyMapping(config), - ".value": config.value, - ".disabled": config.disabled, - ".hidden": config.hidden, - }; + const props = this.getCommonPropertyMapping(config); + props[".value"] = config.value; + props[".disabled"] = config.disabled; + props[".hidden"] = config.hidden; + return props; } /** @@ -253,17 +251,14 @@ export class SettingControl extends SettingElement { * @param {SettingControlConfig} config */ getControlPropertyMapping(config) { - return { - ...this.getCommonPropertyMapping(config), - ".parentDisabled": this.parentDisabled, - "?disabled": - this.setting.disabled || - this.setting.locked || - this.isControlledByExtension(), - // Hide moz-message-bar directly to maintain the role=alert functionality. - // This setting-control will be visually hidden in CSS. - ".hidden": config.control == "moz-message-bar" && this.hidden, - }; + const props = this.getCommonPropertyMapping(config); + props[".parentDisabled"] = this.parentDisabled; + props["?disabled"] = + this.setting.disabled || + this.setting.locked || + this.isControlledByExtension(); + + return props; } getValue() { diff --git a/browser/locales/en-US/browser/preferences/preferences.ftl b/browser/locales/en-US/browser/preferences/preferences.ftl @@ -347,11 +347,9 @@ preferences-web-appearance-override-warning3 = preferences-web-appearance-link = .label = Manage { -brand-short-name } themes in Extensions & Themes -preferences-contrast-control-group = - .label = Website contrast - .description = Websites use a variety of foreground and background colors. For consistent contrast, you can use the same colors across websites. -preferences-contrast-control-radio-group = - .label = Override colors +preferences-contrast-control-header = Contrast Control + +preferences-contrast-control-description = Websites have a variety of foreground and background colors. Configure { -brand-short-name } to use the same colors across websites for improved readability. preferences-contrast-control-use-platform-settings = .label = Automatic (use system settings) @@ -381,11 +379,9 @@ advanced-fonts = .accesskey = A # Zoom is a noun, and the message is used as header for a group of options -preferences-zoom-header2 = - .label = Zoom +preferences-zoom-header = Zoom -preferences-default-zoom-label = - .label = Default zoom +preferences-default-zoom = Default zoom .accesskey = z # Variables: diff --git a/browser/themes/shared/preferences/preferences.css b/browser/themes/shared/preferences/preferences.css @@ -14,7 +14,6 @@ --heading-font-size-xlarge: var(--font-size-xlarge); --heading-font-size-large: var(--font-size-large); --heading-font-size-medium: var(--font-size-medium); - --select-max-width: 20rem; user-select: text; } diff --git a/python/l10n/fluent_migrations/bug_1972367_preferences_zoom.py b/python/l10n/fluent_migrations/bug_1972367_preferences_zoom.py @@ -1,25 +0,0 @@ -# Any copyright is dedicated to the Public Domain. -# http://creativecommons.org/publicdomain/zero/1.0/ - -from fluent.migrate.helpers import transforms_from - - -def migrate(ctx): - """Bug 1972367 - Convert Zoom settings section to config-based prefs, part {index}.""" - - target = "browser/browser/preferences/preferences.ftl" - - ctx.add_transforms( - target, - target, - transforms_from( - """ -preferences-zoom-header2 = - .label = {COPY_PATTERN(from_path, "preferences-zoom-header")} -preferences-default-zoom-label = - .label = {COPY_PATTERN(from_path, "preferences-default-zoom")} - .accesskey = {COPY_PATTERN(from_path, "preferences-default-zoom.accesskey")} -""", - from_path=target, - ), - ) diff --git a/toolkit/content/tests/widgets/test_moz_radio_group.html b/toolkit/content/tests/widgets/test_moz_radio_group.html @@ -744,107 +744,6 @@ await firstButton.updateComplete; verifyElementStates("enabled"); }); - - // Verify that keyboard events from nested focusable elements don't trigger - // radio group navigation (Bug 2000343). - add_task(async function testNestedElementKeyboardEvents() { - let template = html` - <moz-radio-group - name="test-name" - label="Radio group with nested button" - > - <moz-radio checked value="first" label="First"></moz-radio> - <moz-radio value="second" label="Second"> - <button id="nested-button" slot="nested">Nested Button</button> - </moz-radio> - <moz-radio value="third" label="Third"></moz-radio> - </moz-radio-group> - `; - let renderTarget = await testHelpers.renderTemplate(template); - let radioGroup = renderTarget.querySelector("moz-radio-group"); - let [firstRadio, secondRadio, thirdRadio] = - renderTarget.querySelectorAll("moz-radio"); - let nestedButton = renderTarget.querySelector("#nested-button"); - - // Focus the first radio and verify it's selected. - firstRadio.focus(); - is(document.activeElement, firstRadio, "First radio has focus."); - is(radioGroup.value, "first", "First radio is selected."); - - // Press arrow down to navigate to second radio. - synthesizeKey("KEY_ArrowDown", {}); - await radioGroup.updateComplete; - is( - radioGroup.value, - "second", - "Radio group navigated to second radio." - ); - is(document.activeElement, secondRadio, "Second radio has focus."); - - // Tab to focus the nested button. - synthesizeKey("KEY_Tab", {}); - is( - document.activeElement, - nestedButton, - "Nested button has focus after tab." - ); - - // Press arrow down key - this should NOT navigate the radio group. - synthesizeKey("KEY_ArrowDown", {}); - await radioGroup.updateComplete; - is( - radioGroup.value, - "second", - "Radio group value unchanged after down arrow on nested button." - ); - is( - document.activeElement, - nestedButton, - "Focus remains on nested button." - ); - - // Press arrow up key - this should NOT navigate the radio group. - synthesizeKey("KEY_ArrowUp", {}); - await radioGroup.updateComplete; - is( - radioGroup.value, - "second", - "Radio group value unchanged after up arrow on nested button." - ); - is( - document.activeElement, - nestedButton, - "Focus remains on nested button." - ); - - // Shift+Tab to go back to the second radio. - synthesizeKey("KEY_Tab", { shiftKey: true }); - is( - document.activeElement, - secondRadio, - "Focus moved back to second radio with shift+tab." - ); - - // Arrow down should navigate to third radio. - synthesizeKey("KEY_ArrowDown", {}); - await radioGroup.updateComplete; - is(radioGroup.value, "third", "Radio group navigates to third radio."); - is(document.activeElement, thirdRadio, "Focus moved to third radio."); - - // Arrow up should navigate back to second radio. - synthesizeKey("KEY_ArrowUp", {}); - await radioGroup.updateComplete; - is( - radioGroup.value, - "second", - "Radio group navigates back to second radio." - ); - is( - document.activeElement, - secondRadio, - "Focus moved back to second radio." - ); - }); </script> </head> <body></body> diff --git a/toolkit/content/widgets/lit-select-control.mjs b/toolkit/content/widgets/lit-select-control.mjs @@ -196,14 +196,9 @@ export class SelectControlBaseElement extends MozLitElement { this.focusedIndex = undefined; } - /** - * @param {KeyboardEvent & { target: HTMLElement }} event - */ + // NB: We may need to revise this to avoid bugs when we add more focusable + // elements to select control base/items. handleKeydown(event) { - if (event.target.parentElement != this) { - // Ignore events from nested controls. - return; - } let directions = this.getNavigationDirections(); switch (event.key) { case "Down": diff --git a/toolkit/content/widgets/moz-fieldset/moz-fieldset.css b/toolkit/content/widgets/moz-fieldset/moz-fieldset.css @@ -19,7 +19,7 @@ legend { gap: var(--space-small); align-items: baseline; - &:has(+ .description) { + &:has(+ #description) { display: flex; } @@ -48,9 +48,9 @@ h6 { margin: 0; } -.description { +#description { margin: 0; - margin-block-start: var(--space-xsmall); + margin-block-start: var(--space-xxsmall); color: var(--text-color-deemphasized); } @@ -66,7 +66,7 @@ h6 { column-gap: var(--space-medium); } - :is(legend, .description) ~ & { + :is(legend, #description) ~ & { margin-top: var(--space-small); :host([hasheading]) & { diff --git a/toolkit/content/widgets/moz-fieldset/moz-fieldset.mjs b/toolkit/content/widgets/moz-fieldset/moz-fieldset.mjs @@ -106,10 +106,10 @@ export default class MozFieldset extends MozLitElement { descriptionTemplate() { if (this.description) { - return html`<div class="description"> - <span id="description">${this.description}</span> - ${this.supportPageTemplate()} - </div>`; + return html`<span id="description" class="description"> + ${this.description} + </span> + ${this.supportPageTemplate()}`; } return ""; }