From 8dd16259287f58f9273002717ec4d27e97127719 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 12 Jun 2024 07:43:14 +0200 Subject: Merging upstream version 127.0. Signed-off-by: Daniel Baumann --- toolkit/content/widgets/arrowscrollbox.js | 4 +- .../content/widgets/autocomplete-richlistitem.js | 4 +- toolkit/content/widgets/datetimebox.js | 28 +-- toolkit/content/widgets/message-bar.css | 219 --------------------- toolkit/content/widgets/message-bar.js | 91 --------- .../widgets/moz-button-group/moz-button-group.css | 3 +- .../widgets/moz-button-group/moz-button-group.mjs | 25 ++- toolkit/content/widgets/moz-button/moz-button.css | 26 ++- toolkit/content/widgets/moz-button/moz-button.mjs | 21 +- .../widgets/moz-button/moz-button.stories.mjs | 29 +-- .../widgets/moz-message-bar/moz-message-bar.mjs | 12 +- .../content/widgets/moz-page-nav/README.stories.md | 46 ++++- .../widgets/moz-page-nav/moz-page-nav-button.css | 23 ++- .../content/widgets/moz-page-nav/moz-page-nav.mjs | 86 +++++++- .../widgets/moz-page-nav/moz-page-nav.stories.mjs | 32 ++- .../widgets/moz-support-link/moz-support-link.mjs | 6 +- toolkit/content/widgets/notificationbox.js | 3 +- toolkit/content/widgets/panel-list/panel-list.js | 4 - toolkit/content/widgets/popupnotification.js | 2 - toolkit/content/widgets/videocontrols.js | 17 +- 20 files changed, 276 insertions(+), 405 deletions(-) delete mode 100644 toolkit/content/widgets/message-bar.css delete mode 100644 toolkit/content/widgets/message-bar.js (limited to 'toolkit/content/widgets') diff --git a/toolkit/content/widgets/arrowscrollbox.js b/toolkit/content/widgets/arrowscrollbox.js index 7109891faf..5983435d06 100644 --- a/toolkit/content/widgets/arrowscrollbox.js +++ b/toolkit/content/widgets/arrowscrollbox.js @@ -21,7 +21,7 @@ return ` - + @@ -29,7 +29,7 @@ - + `; } diff --git a/toolkit/content/widgets/autocomplete-richlistitem.js b/toolkit/content/widgets/autocomplete-richlistitem.js index b339ab1e27..0ec8a19243 100644 --- a/toolkit/content/widgets/autocomplete-richlistitem.js +++ b/toolkit/content/widgets/autocomplete-richlistitem.js @@ -832,9 +832,7 @@ setTimeout(() => { let selectedIndex = popup ? popup.selectedIndex : -1; - actor.manager - .getActor("FormAutofill") - .sendAsyncMessage("FormAutofill:PreviewProfile", { selectedIndex }); + actor.previewAutofillProfile(selectedIndex); }, 0); } diff --git a/toolkit/content/widgets/datetimebox.js b/toolkit/content/widgets/datetimebox.js index 04ed398bd7..1c63b09269 100644 --- a/toolkit/content/widgets/datetimebox.js +++ b/toolkit/content/widgets/datetimebox.js @@ -650,6 +650,10 @@ this.DateTimeBoxWidget = class { onKeyDown(aEvent) { this.log("onKeyDown key: " + aEvent.key); + if (aEvent.defaultPrevented) { + return; + } + switch (aEvent.key) { // Toggle the picker on Space/Enter on Calendar button or Space on input, // close on Escape anywhere. @@ -691,21 +695,17 @@ this.DateTimeBoxWidget = class { aEvent.preventDefault(); break; } - if (this.isEditable()) { - // TODO(emilio, bug 1571533): These functions should look at - // defaultPrevented. - // Ctrl+Backspace/Delete on non-macOS and - // Cmd+Backspace/Delete on macOS to clear the field - if (aEvent.getModifierState("Accel")) { - // Clear the input's value - this.clearInputFields(false); - } else { - let targetField = aEvent.originalTarget; - this.clearFieldValue(targetField); - this.setInputValueFromFields(); - } - aEvent.preventDefault(); + // Ctrl+Backspace/Delete on non-macOS and + // Cmd+Backspace/Delete on macOS to clear the field + if (aEvent.getModifierState("Accel")) { + // Clear the input's value + this.clearInputFields(false); + } else { + let targetField = aEvent.originalTarget; + this.clearFieldValue(targetField); + this.setInputValueFromFields(); } + aEvent.preventDefault(); break; } case "ArrowRight": diff --git a/toolkit/content/widgets/message-bar.css b/toolkit/content/widgets/message-bar.css deleted file mode 100644 index eddc5a3ae6..0000000000 --- a/toolkit/content/widgets/message-bar.css +++ /dev/null @@ -1,219 +0,0 @@ -/* 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/. */ - -:host { - --info-icon-url: url("chrome://global/skin/icons/info-filled.svg"); - --warn-icon-url: url("chrome://global/skin/icons/warning.svg"); - --success-icon-url: url("chrome://global/skin/icons/check.svg"); - --error-icon-url: url("chrome://global/skin/icons/error.svg"); - --close-icon-url: url("chrome://global/skin/icons/close-12.svg"); - --close-fill-color: var(--in-content-icon-color); - --icon-size: 16px; - --close-icon-size: 28px; -} - -:host { - --message-bar-background-color: var(--in-content-box-info-background); - --message-bar-text-color: var(--in-content-text-color); - --message-bar-icon-url: var(--info-icon-url); - /* The default values of --in-content-button* are sufficient, even for dark themes */ -} - -:host([type=warning]) { - --message-bar-icon-url: var(--warn-icon-url); -} - -:host([type=success]) { - --message-bar-icon-url: var(--success-icon-url); -} - -:host([type=error]), -:host([type=critical]) { - --message-bar-icon-url: var(--error-icon-url); -} - -:host { - border: 1px solid transparent; - border-radius: 4px; -} - -/* Make the host to behave as a block by default, but allow hidden to hide it. */ -:host(:not([hidden])) { - display: block; -} - -::slotted(button) { - /* Enforce micro-button width. */ - min-width: -moz-fit-content !important; -} - -/* MessageBar Grid Layout */ - -.container { - background: var(--message-bar-background-color); - color: var(--message-bar-text-color); - - padding: 3px 7px; - position: relative; - - border-radius: 4px; - - display: flex; - /* Ensure that the message bar shadow dom elements are vertically aligned. */ - align-items: center; -} - -:host([align="center"]) .container { - justify-content: center; -} - -.content { - margin: 0 4px; - display: inline-block; - /* Ensure that the message bar content is vertically aligned. */ - align-items: center; - /* Ensure that the message bar content is wrapped. */ - word-break: break-word; -} - -/* MessageBar icon style */ - -.icon { - padding: 4px; - width: var(--icon-size); - height: var(--icon-size); - flex-shrink: 0; -} - -.icon::after { - display: inline-block; - appearance: none; - -moz-context-properties: fill, stroke; - fill: currentColor; - stroke: currentColor; - content: ""; - background-image: var(--message-bar-icon-url); - background-size: var(--icon-size); - width: var(--icon-size); - height: var(--icon-size); -} - -/* Use a spacer to position the close button at the end, but also support - * centering if required. */ -.spacer { - flex-grow: 1; -} - -/* Close icon styles */ - -:host(:not([dismissable])) .close { - display: none; -} - -.close { - background-image: var(--close-icon-url); - background-repeat: no-repeat; - background-position: center center; - -moz-context-properties: fill; - fill: currentColor; - min-width: auto; - min-height: auto; - width: var(--close-icon-size); - height: var(--close-icon-size); - padding: 0; - flex-shrink: 0; - margin: 4px 8px; - background-size: 12px; -} - -@media (prefers-contrast) { - :host { - border-color: CanvasText; - } -} - -@media not (prefers-contrast) { - /* MessageBar colors by message type */ - /* Colors from: https://design.firefox.com/photon/components/message-bars.html#type-specific-style */ - - :host([type=warning]) { - /* Ensure colors within the bar are adjusted and controls are readable */ - color-scheme: light; - - --message-bar-background-color: var(--yellow-50); - --message-bar-text-color: var(--yellow-90); - - --in-content-button-background: var(--yellow-60); - --in-content-button-background-hover: var(--yellow-70); - --in-content-button-background-active: var(--yellow-80); - - --close-fill-color: var(--message-bar-text-color); - } - - :host([type=success]) { - /* Ensure colors within the bar are adjusted and controls are readable */ - color-scheme: light; - - --message-bar-background-color: var(--green-50); - --message-bar-text-color: var(--green-90); - - --in-content-button-background: var(--green-60); - --in-content-button-background-hover: var(--green-70); - --in-content-button-background-active: var(--green-80); - } - - :host([type=error]) { - --message-bar-background-color: var(--red-60); - --message-bar-text-color: #ffffff; - - --in-content-button-background: var(--red-70); - --in-content-button-background-hover: var(--red-80); - --in-content-button-background-active: var(--red-90); - } - - :host([type=info]) .icon { - color: rgb(0,144,237); - } - - :host([type=warning]) .icon { - color: rgb(255,164,54); - } - - :host([type=critical]) .icon { - color: rgb(226,40,80); - } - - .close { - fill: var(--close-fill-color); - } - - @media (prefers-color-scheme: dark) { - /* Don't set the background in prefers-contrast mode or macOS can end up - * with black on black text. */ - :host([type=info]) .icon { - color: rgb(128,235,255); - } - - :host([type=warning]) .icon { - color: rgb(255,189,79); - } - - :host([type=critical]) .icon { - color: rgb(255,154,162); - } - } -} - -strong { - font-weight: 600; -} - -.text-link:hover { - cursor: pointer; -} - -@keyframes spin { - from { transform: rotate(0); } - to { transform: rotate(360deg); } -} diff --git a/toolkit/content/widgets/message-bar.js b/toolkit/content/widgets/message-bar.js deleted file mode 100644 index d38347b40a..0000000000 --- a/toolkit/content/widgets/message-bar.js +++ /dev/null @@ -1,91 +0,0 @@ -/* 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/. */ - -"use strict"; - -// This is loaded into chrome windows with the subscript loader. Wrap in -// a block to prevent accidentally leaking globals onto `window`. -{ - class MessageBarElement extends HTMLElement { - constructor() { - super(); - const shadowRoot = this.attachShadow({ mode: "open" }); - window.MozXULElement?.insertFTLIfNeeded( - "toolkit/global/notification.ftl" - ); - document.l10n.connectRoot(this.shadowRoot); - const content = this.constructor.template.content.cloneNode(true); - shadowRoot.append(content); - this.closeButton.addEventListener("click", () => this.dismiss(), { - once: true, - }); - } - - disconnectedCallback() { - this.dispatchEvent(new CustomEvent("message-bar:close")); - } - - get closeButton() { - return this.shadowRoot.querySelector("button.close"); - } - - static get template() { - const template = document.createElement("template"); - - const commonStyles = document.createElement("link"); - commonStyles.rel = "stylesheet"; - commonStyles.href = "chrome://global/skin/in-content/common.css"; - const messageBarStyles = document.createElement("link"); - messageBarStyles.rel = "stylesheet"; - messageBarStyles.href = - "chrome://global/content/elements/message-bar.css"; - template.content.append(commonStyles, messageBarStyles); - - // A container for the entire message bar content, - // most of the css rules needed to provide the - // expected message bar layout is applied on this - // element. - const container = document.createElement("div"); - container.part = "container"; - container.classList.add("container"); - template.content.append(container); - - const icon = document.createElement("span"); - icon.classList.add("icon"); - icon.part = "icon"; - container.append(icon); - - const barcontent = document.createElement("span"); - barcontent.classList.add("content"); - barcontent.append(document.createElement("slot")); - container.append(barcontent); - - const spacer = document.createElement("span"); - spacer.classList.add("spacer"); - container.append(spacer); - - const closeIcon = document.createElement("button"); - closeIcon.classList.add("close", "ghost-button"); - document.l10n.setAttributes(closeIcon, "notification-close-button"); - container.append(closeIcon); - - Object.defineProperty(this, "template", { - value: template, - }); - - return template; - } - - dismiss() { - this.dispatchEvent(new CustomEvent("message-bar:user-dismissed")); - this.close(); - } - - close() { - this.remove(); - } - } - - customElements.define("message-bar", MessageBarElement); -} diff --git a/toolkit/content/widgets/moz-button-group/moz-button-group.css b/toolkit/content/widgets/moz-button-group/moz-button-group.css index ba79d69e12..5b6f7deace 100644 --- a/toolkit/content/widgets/moz-button-group/moz-button-group.css +++ b/toolkit/content/widgets/moz-button-group/moz-button-group.css @@ -11,6 +11,7 @@ margin: 0 !important; } -::slotted(button:not(:first-child, .popup-notification-dropmarker)) { +::slotted(button:not(:first-child, .popup-notification-dropmarker)), +::slotted(moz-button:not(:first-child)) { margin-inline-start: var(--space-small) !important; } diff --git a/toolkit/content/widgets/moz-button-group/moz-button-group.mjs b/toolkit/content/widgets/moz-button-group/moz-button-group.mjs index 8bf553c23d..6858367ab7 100644 --- a/toolkit/content/widgets/moz-button-group/moz-button-group.mjs +++ b/toolkit/content/widgets/moz-button-group/moz-button-group.mjs @@ -50,15 +50,22 @@ export default class MozButtonGroup extends MozLitElement { // Text nodes won't support classList or getAttribute. continue; } - // Bug 1791816: These should check moz-button instead of button. - if ( - child.localName == "button" && - (child.classList.contains("primary") || - child.getAttribute("type") == "submit" || - child.hasAttribute("autofocus") || - child.hasAttribute("default")) - ) { - child.slot = "primary"; + switch (child.localName) { + case "button": + if ( + child.classList.contains("primary") || + child.getAttribute("type") == "submit" || + child.hasAttribute("autofocus") || + child.hasAttribute("default") + ) { + child.slot = "primary"; + } + break; + case "moz-button": + if (child.type == "primary" || child.type == "destructive") { + child.slot = "primary"; + } + break; } } this.#reorderLightDom(); diff --git a/toolkit/content/widgets/moz-button/moz-button.css b/toolkit/content/widgets/moz-button/moz-button.css index 71d57ea93a..4eb6839e06 100644 --- a/toolkit/content/widgets/moz-button/moz-button.css +++ b/toolkit/content/widgets/moz-button/moz-button.css @@ -23,6 +23,10 @@ button { /* Ensure font-size isn't overridden by widget styling (e.g. in forms.css) */ font-size: var(--button-font-size); width: 100%; + display: flex; + justify-content: center; + align-items: center; + gap: var(--space-small); &[size=small] { min-height: var(--button-min-height-small); @@ -125,21 +129,33 @@ button { } } - &[type~=icon] { + &[type~=icon]:not(.labelled) { background-size: var(--icon-size-default); background-position: center; background-repeat: no-repeat; - -moz-context-properties: fill, stroke; - fill: currentColor; - stroke: currentColor; + } + + &[type~=icon]:not(.labelled), + &:not(.labelled):has(img) { width: var(--button-size-icon); height: var(--button-size-icon); padding: var(--button-padding-icon); - color: var(--icon-color); &[size=small] { width: var(--button-size-icon-small); height: var(--button-size-icon-small); } } + + img, + &[type~=icon]:not(.labelled) { + -moz-context-properties: fill, fill-opacity, stroke; + fill: currentColor; + stroke: currentColor; + } + + img { + width: var(--icon-size-default); + height: var(--icon-size-default); + } } diff --git a/toolkit/content/widgets/moz-button/moz-button.mjs b/toolkit/content/widgets/moz-button/moz-button.mjs index a951dbf5d8..9a239d4e56 100644 --- a/toolkit/content/widgets/moz-button/moz-button.mjs +++ b/toolkit/content/widgets/moz-button/moz-button.mjs @@ -2,7 +2,7 @@ * 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, ifDefined } from "../vendor/lit.all.mjs"; +import { html, ifDefined, classMap } from "../vendor/lit.all.mjs"; import { MozLitElement } from "../lit-utils.mjs"; /** @@ -19,8 +19,11 @@ import { MozLitElement } from "../lit-utils.mjs"; * @property {string} titleAttribute - Internal, map title attribute to the title JS property. * @property {string} tooltipText - Set the title property, the title attribute will be used first. * @property {string} ariaLabel - The button's arial-label attribute, used in shadow DOM and therefore not as an attribute on moz-button. + * @property {string} iconSrc - Path to the icon that should be displayed in the button. * @property {string} ariaLabelAttribute - Internal, map aria-label attribute to the ariaLabel JS property. + * @property {string} hasVisibleLabel - Internal, tracks whether or not the button has a visible label. * @property {HTMLButtonElement} buttonEl - The internal button element in the shadow DOM. + * @property {HTMLButtonElement} slotEl - The internal slot element in the shadow DOM. * @slot default - The button's content, overrides label property. * @fires click - The click event. */ @@ -44,10 +47,13 @@ export default class MozButton extends MozLitElement { reflect: true, }, ariaLabel: { type: String, state: true }, + iconSrc: { type: String }, + hasVisibleLabel: { type: Boolean, state: true }, }; static queries = { buttonEl: "button", + slotEl: "slot", }; constructor() { @@ -55,6 +61,7 @@ export default class MozButton extends MozLitElement { this.type = "default"; this.size = "default"; this.disabled = false; + this.hasVisibleLabel = !!this.label; } willUpdate(changes) { @@ -73,6 +80,12 @@ export default class MozButton extends MozLitElement { this.buttonEl.click(); } + checkForLabelText() { + this.hasVisibleLabel = this.slotEl + .assignedNodes() + .some(node => node.textContent.trim()); + } + render() { return html` - ${this.label} + ${this.iconSrc + ? html`` + : ""} + ${this.label} `; } diff --git a/toolkit/content/widgets/moz-button/moz-button.stories.mjs b/toolkit/content/widgets/moz-button/moz-button.stories.mjs index 52a459e807..dd8d6369db 100644 --- a/toolkit/content/widgets/moz-button/moz-button.stories.mjs +++ b/toolkit/content/widgets/moz-button/moz-button.stories.mjs @@ -2,7 +2,7 @@ * 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 "../vendor/lit.all.mjs"; +import { html, ifDefined } from "../vendor/lit.all.mjs"; // eslint-disable-next-line import/no-unassigned-import import "./moz-button.mjs"; @@ -22,6 +22,10 @@ export default { options: ["default", "small"], control: { type: "radio" }, }, + type: { + options: ["default", "primary", "destructive", "icon", "icon ghost"], + control: { type: "select" }, + }, }, parameters: { actions: { @@ -40,17 +44,13 @@ moz-button-aria-labelled = }, }; -const Template = ({ type, size, l10nId, iconUrl, disabled }) => html` - +const Template = ({ type, size, l10nId, iconSrc, disabled }) => html` `; @@ -59,7 +59,7 @@ Default.args = { type: "default", size: "default", l10nId: "moz-button-labelled", - iconUrl: "chrome://global/skin/icons/more.svg", + iconSrc: "", disabled: false, }; export const DefaultSmall = Template.bind({}); @@ -67,7 +67,7 @@ DefaultSmall.args = { type: "default", size: "small", l10nId: "moz-button-labelled", - iconUrl: "chrome://global/skin/icons/more.svg", + iconSrc: "", disabled: false, }; export const Primary = Template.bind({}); @@ -85,7 +85,7 @@ Destructive.args = { export const Icon = Template.bind({}); Icon.args = { ...Default.args, - type: "icon", + iconSrc: "chrome://global/skin/icons/more.svg", l10nId: "moz-button-titled", }; export const IconSmall = Template.bind({}); @@ -96,5 +96,12 @@ IconSmall.args = { export const IconGhost = Template.bind({}); IconGhost.args = { ...Icon.args, - type: "icon ghost", + type: "ghost", +}; +export const IconText = Template.bind({}); +IconText.args = { + type: "default", + size: "default", + iconSrc: "chrome://global/skin/icons/edit-copy.svg", + l10nId: "moz-button-labelled", }; diff --git a/toolkit/content/widgets/moz-message-bar/moz-message-bar.mjs b/toolkit/content/widgets/moz-message-bar/moz-message-bar.mjs index 8f0c997149..9a186b41c9 100644 --- a/toolkit/content/widgets/moz-message-bar/moz-message-bar.mjs +++ b/toolkit/content/widgets/moz-message-bar/moz-message-bar.mjs @@ -49,10 +49,10 @@ const messageTypeToIconData = { export default class MozMessageBar extends MozLitElement { static queries = { - actionsSlotEl: "slot[name=actions]", + actionsSlot: "slot[name=actions]", actionsEl: ".actions", - closeButtonEl: "moz-button.close", - supportLinkSlotEl: "slot[name=support-link]", + closeButton: "moz-button.close", + supportLinkSlot: "slot[name=support-link]", }; static properties = { @@ -72,13 +72,13 @@ export default class MozMessageBar extends MozLitElement { } onSlotchange() { - let actions = this.actionsSlotEl.assignedNodes(); + let actions = this.actionsSlot.assignedNodes(); this.actionsEl.classList.toggle("active", actions.length); } connectedCallback() { super.connectedCallback(); - this.setAttribute("role", "status"); + this.setAttribute("role", "alert"); } disconnectedCallback() { @@ -87,7 +87,7 @@ export default class MozMessageBar extends MozLitElement { } get supportLinkEls() { - return this.supportLinkSlotEl.assignedElements(); + return this.supportLinkSlot.assignedElements(); } iconTemplate() { diff --git a/toolkit/content/widgets/moz-page-nav/README.stories.md b/toolkit/content/widgets/moz-page-nav/README.stories.md index 800d446478..c2f1b37bb5 100644 --- a/toolkit/content/widgets/moz-page-nav/README.stories.md +++ b/toolkit/content/widgets/moz-page-nav/README.stories.md @@ -4,7 +4,7 @@ intended to change the selected view, provide a heading, and have links to external resources. ```html story - +

Test 3

+ +

Support Link

+
+ +

External Link

+
``` ## When to use * Use moz-page-nav for single-page navigation to switch between different views. -* moz-page-nav will also support footer buttons for external support links in the future (See [bug 1877826](https://bugzilla.mozilla.org/show_bug.cgi?id=1877826)) +* moz-page-nav also supports footer buttons for external and support links * This component will be used in about: pages such as about:firefoxview, about:preferences, about:addons, about:debugging, etc. ## When not to use @@ -53,18 +67,34 @@ And used as follows: ```html - - - + - - + - + + + + + + + + + + + ``` diff --git a/toolkit/content/widgets/moz-page-nav/moz-page-nav-button.css b/toolkit/content/widgets/moz-page-nav/moz-page-nav-button.css index 5d00198d65..781398056a 100644 --- a/toolkit/content/widgets/moz-page-nav/moz-page-nav-button.css +++ b/toolkit/content/widgets/moz-page-nav/moz-page-nav-button.css @@ -4,11 +4,13 @@ :host { border-radius: var(--border-radius-small); + font-size: var(--font-size-large); &:focus-visible { outline-offset: var(--page-nav-focus-outline-inset); } } +a[href], button { background-color: var(--page-nav-button-background-color); border: 1px solid var(--page-nav-border-color); @@ -28,11 +30,17 @@ button { padding: var(--page-nav-button-padding); } +a[href] { + text-decoration: none; + box-sizing: border-box; +} + button:hover { cursor: pointer; } @media not (prefers-contrast) { + a[href], button { position: relative; } @@ -55,6 +63,7 @@ button:hover { background-color: var(--icon-color); } + a[href]:hover, button:hover, button[selected]:hover { background-color: var(--page-nav-button-background-color-hover); @@ -72,6 +81,7 @@ button:hover { } } +a[href]:focus-visible, button:focus-visible, button[selected]:focus-visible { outline: var(--focus-outline); @@ -86,13 +96,24 @@ button[selected]:focus-visible { fill: currentColor; } +:host(.secondary-nav-item) { + font-size: var(--font-size-small); + + & .page-nav-icon { + height: var(--icon-size-default); + width: var(--icon-size-default); + } +} + @media (prefers-contrast) { + a[href], button { transition: none; border-color: ButtonText; background-color: var(--button-background-color); } + a[href]:hover, button:hover { color: SelectedItem; } @@ -105,13 +126,13 @@ button[selected]:focus-visible { } slot { - font-size: var(--font-size-large); margin: 0; padding-inline-start: 0; user-select: none; } @media (max-width: 52rem) { + a[href], button { grid-template-columns: min-content; justify-content: center; diff --git a/toolkit/content/widgets/moz-page-nav/moz-page-nav.mjs b/toolkit/content/widgets/moz-page-nav/moz-page-nav.mjs index f998ee735f..c720e76e26 100644 --- a/toolkit/content/widgets/moz-page-nav/moz-page-nav.mjs +++ b/toolkit/content/widgets/moz-page-nav/moz-page-nav.mjs @@ -4,6 +4,8 @@ import { html } from "chrome://global/content/vendor/lit.all.mjs"; import { MozLitElement } from "chrome://global/content/lit-utils.mjs"; +// eslint-disable-next-line import/no-unassigned-import +import "chrome://global/content/elements/moz-support-link.mjs"; /** * A grouping of navigation buttons that is displayed at the page level, @@ -35,6 +37,14 @@ export default class MozPageNav extends MozLitElement { ); } + get secondaryNavButtons() { + return this.secondaryNavGroupSlot + .assignedNodes() + .filter( + node => node?.localName === "moz-page-nav-button" && !node.hidden + ); + } + onChangeView(e) { this.currentView = e.target.view; } @@ -69,6 +79,12 @@ export default class MozPageNav extends MozLitElement { } } + onSecondaryNavChange() { + this.secondaryNavGroupSlot.assignedElements()?.forEach(el => { + el.classList.add("secondary-nav-item"); + }); + } + render() { return html`
- +
`; @@ -114,16 +133,18 @@ customElements.define("moz-page-nav", MozPageNav); * A navigation button intended to change the selected view within a page. * * @tagname moz-page-nav-button + * @property {string} href - (optional) The url for an external link if not a support page URL * @property {string} iconSrc - The chrome:// url for the icon used for the button. - * @property {string} l10nId - The fluent ID for the button's text * @property {boolean} selected - Whether or not the button is currently selected. + * @property {string} supportPage - (optional) The short name for the support page a secondary link should launch to * @slot [default] - Used to append the l10n string to the button. */ export class MozPageNavButton extends MozLitElement { static properties = { iconSrc: { type: String }, - l10nId: { type: String }, + href: { type: String }, selected: { type: Boolean }, + supportPage: { type: String, attribute: "support-page" }, }; connectedCallback() { @@ -133,6 +154,7 @@ export class MozPageNavButton extends MozLitElement { static queries = { buttonEl: "button", + linkEl: "a", }; get view() { @@ -148,12 +170,15 @@ export class MozPageNavButton extends MozLitElement { ); } - render() { + itemTemplate() { + if (this.href || this.supportPage) { + return this.linkTemplate(); + } + return this.buttonTemplate(); + } + + buttonTemplate() { return html` - `; } + + linkTemplate() { + if (this.supportPage) { + return html` + + ${this.innerContentTemplate()} + + `; + } + return html` + + ${this.innerContentTemplate()} + + `; + } + + innerContentTemplate() { + return html` + ${this.iconSrc + ? html`` + : ""} + + `; + } + + render() { + return html` + + ${this.itemTemplate()} + `; + } } customElements.define("moz-page-nav-button", MozPageNavButton); diff --git a/toolkit/content/widgets/moz-page-nav/moz-page-nav.stories.mjs b/toolkit/content/widgets/moz-page-nav/moz-page-nav.stories.mjs index 4ac7b455cf..d1c565efe9 100644 --- a/toolkit/content/widgets/moz-page-nav/moz-page-nav.stories.mjs +++ b/toolkit/content/widgets/moz-page-nav/moz-page-nav.stories.mjs @@ -2,7 +2,7 @@ * 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 "../vendor/lit.all.mjs"; +import { html, when } from "../vendor/lit.all.mjs"; // eslint-disable-next-line import/no-unassigned-import import "./moz-page-nav.mjs"; @@ -21,15 +21,17 @@ moz-page-nav-button-two = View 2 .title = View 2 moz-page-nav-button-three = View 3 .title = View 3 -moz-page-link-one = Support Page - .title = Support Page +moz-page-nav-button-four = Support Link + .title = Support Link +moz-page-nav-button-five = External Link + .title = External Link moz-page-nav-heading = .heading = Heading `, }, }; -const Template = () => html` +const Template = ({ hasFooterLinks }) => html`