From 26a029d407be480d791972afb5975cf62c9360a6 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 02:47:55 +0200 Subject: Adding upstream version 124.0.1. Signed-off-by: Daniel Baumann --- toolkit/content/widgets/moz-card/moz-card.css | 180 +++++++++++++++++++++ toolkit/content/widgets/moz-card/moz-card.mjs | 112 +++++++++++++ .../content/widgets/moz-card/moz-card.stories.mjs | 88 ++++++++++ 3 files changed, 380 insertions(+) create mode 100644 toolkit/content/widgets/moz-card/moz-card.css create mode 100644 toolkit/content/widgets/moz-card/moz-card.mjs create mode 100644 toolkit/content/widgets/moz-card/moz-card.stories.mjs (limited to 'toolkit/content/widgets/moz-card') diff --git a/toolkit/content/widgets/moz-card/moz-card.css b/toolkit/content/widgets/moz-card/moz-card.css new file mode 100644 index 0000000000..52c0ac0980 --- /dev/null +++ b/toolkit/content/widgets/moz-card/moz-card.css @@ -0,0 +1,180 @@ +/* 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 { + --card-border-color: color-mix(in srgb, currentColor 10%, transparent); + --card-border-radius: var(--border-radius-medium); + --card-border-width: var(--border-width); + --card-border: var(--card-border-width) solid var(--card-border-color); + --card-background-color: var(--box-background-color); + --card-focus-outline: var(--focus-outline); + --card-box-shadow: var(--box-shadow-10); + /* Bug 1791816, 1839523: replace with spacing tokens */ + --card-padding: 1em; + --card-gap: var(--card-padding); + --card-article-gap: 0.45em; + + /* Bug 1791816: replace with button tokens */ + @media (prefers-contrast) { + --button-border-color: var(--border-interactive-color); + --button-border-color-hover: var(--border-interactive-color-hover); + --button-border-color-active: var(--border-interactive-color-active); + --card-border-color: color-mix(in srgb, currentColor 41%, transparent); + } + /* Bug 1791816: replace with button tokens */ + @media (forced-colors) { + --button-background-color: ButtonFace; + --button-background-color-hover: SelectedItemText; + --button-background-color-active: SelectedItemText; + --button-border-color: var(--border-interactive-color); + --button-border-color-hover: var(--border-interactive-color-hover); + --button-border-color-active: var(--border-interactive-color-active); + --button-text-color: ButtonText; + --button-text-color-hover: SelectedItem; + --button-text-color-active: SelectedItem; + } +} + +:host { + display: block; + border: var(--card-border); + border-radius: var(--card-border-radius); + background-color: var(--card-background-color); + box-shadow: var(--card-box-shadow); + box-sizing: border-box; +} + +:host([type=accordion]) { + summary { + padding-block: var(--card-padding); + } + #content { + padding-block-end: var(--card-padding); + } +} +:host(:not([type=accordion])) { + .moz-card { + padding-block: var(--card-padding); + } +} + +.moz-card { + display: flex; + flex-direction: column; + align-items: flex-start; + gap: var(--card-article-gap); +} + +#moz-card-details { + width: 100%; +} + +summary { + cursor: pointer; +} + +#heading-wrapper { + display: flex; + align-items: center; + justify-content: flex-start; + gap: var(--card-gap); + padding-inline: var(--card-padding); + border-radius: var(--card-border-radius); +} + +#heading { + font-size: var(--font-size-root); + font-weight: var(--font-weight-bold); +} + +#content { + align-self: stretch; + padding-inline: var(--card-padding); + border-end-start-radius: var(--card-border-radius); + border-end-end-radius: var(--card-border-radius); + + @media (prefers-contrast) { + :host([type=accordion]) & { + border-block-start: 0; + padding-block-start: var(--card-padding); + } + } +} + +details { + > summary { + list-style: none; + border-radius: var(--card-border-radius); + cursor: pointer; + + &:hover { + background-color: var(--button-background-color-hover); + } + @media (prefers-contrast) { + outline: var(--button-border-color) solid var(--border-width); + + &:hover { + outline-color: var(--button-border-color-hover); + } + + &:active { + outline-color: var(--button-border-color-active); + } + } + + @media (forced-colors) { + color: var(--button-text-color); + background-color: var(--button-background-color); + + &:hover { + background-color: var(--button-background-color-hover); + color: var(--button-text-color-hover); + } + + &:active { + background-color: var(--button-background-color-active); + color: var(--button-text-color-active); + } + } + } + + &[open] { + summary { + border-end-start-radius: 0; + border-end-end-radius: 0; + } + @media not (prefers-contrast) { + #content { + /* + There is a border shown above this element in prefers-contrast. + When there isn't a border, there's no need for the extra space. + */ + padding-block-start: 0; + } + } + } + + &:focus-visible { + outline: var(--card-focus-outline); + } +} + +.chevron-icon { + background-image: url("chrome://global/skin/icons/arrow-down.svg"); + background-position: center; + background-repeat: no-repeat; + -moz-context-properties: fill; + fill: currentColor; + width: 24px; + height: 24px; + min-width: 24px; + min-height: 24px; + padding: 0; + flex-shrink: 0; + align-self: flex-start; + + details[open] & { + background-image: url("chrome://global/skin/icons/arrow-up.svg"); + } +} diff --git a/toolkit/content/widgets/moz-card/moz-card.mjs b/toolkit/content/widgets/moz-card/moz-card.mjs new file mode 100644 index 0000000000..2bd6e0f987 --- /dev/null +++ b/toolkit/content/widgets/moz-card/moz-card.mjs @@ -0,0 +1,112 @@ +/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- + * 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, ifDefined } from "chrome://global/content/vendor/lit.all.mjs"; +import { MozLitElement } from "chrome://global/content/lit-utils.mjs"; + +/** + * Cards contain content and actions about a single subject. + * There are two card types: + * The default type where no type attribute is required and the card + * will have no extra functionality. + * + * The "accordion" type will initially not show any content. The card + * will contain an arrow to expand the card so that all of the content + * is visible. + * + * + * @property {string} heading - The heading text that will be used for the card. + * @property {string} type - (optional) The type of card. No type specified + * will be the default card. The other available type is "accordion" + * @slot content - The content to show inside of the card. + */ +export default class MozCard extends MozLitElement { + static queries = { + detailsEl: "#moz-card-details", + headingEl: "#heading", + contentSlotEl: "#content", + }; + + static properties = { + heading: { type: String }, + type: { type: String, reflect: true }, + expanded: { type: Boolean }, + }; + + constructor() { + super(); + this.expanded = false; + this.type = "default"; + } + + headingTemplate() { + if (!this.heading) { + return ""; + } + return html` +
+ ${this.type == "accordion" + ? html`
` + : ""} + ${this.heading} +
+ `; + } + + cardTemplate() { + if (this.type === "accordion") { + return html` +
+ ${this.headingTemplate()} +
+
+ `; + } + + return html` + ${this.headingTemplate()} +
+ +
+ `; + } + /** + * Handles the click event on the chevron icon. + * + * Without this, the click event would be passed to + * toggleDetails which would force the details element + * to stay open. + * + * @memberof MozCard + */ + onDetailsClick() { + this.toggleDetails(); + } + + /** + * @param {boolean} force - Used to force open or force close the + * details element. + * @memberof MozCard + */ + toggleDetails(force) { + this.detailsEl.open = force ?? !this.detailsEl.open; + } + + render() { + return html` + +
+ ${this.cardTemplate()} +
+ `; + } +} +customElements.define("moz-card", MozCard); diff --git a/toolkit/content/widgets/moz-card/moz-card.stories.mjs b/toolkit/content/widgets/moz-card/moz-card.stories.mjs new file mode 100644 index 0000000000..da3279b2a4 --- /dev/null +++ b/toolkit/content/widgets/moz-card/moz-card.stories.mjs @@ -0,0 +1,88 @@ +/* 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/. */ + +// eslint-disable-next-line import/no-unresolved +import { html, ifDefined } from "lit.all.mjs"; +// eslint-disable-next-line import/no-unassigned-import +import "./moz-card.mjs"; + +export default { + title: "UI Widgets/Card", + component: "moz-card", + parameters: { + status: "in-development", + fluent: ` +moz-card-heading = + .heading = This is the label + `, + }, + argTypes: { + type: { + options: ["default", "accordion"], + control: { type: "select" }, + }, + }, +}; + +const Template = ({ l10nId, content, type }) => html` +
+ +
${content}
+
+
+`; + +export const DefaultCard = Template.bind({}); +DefaultCard.args = { + l10nId: "moz-card-heading", + content: "This is the content", +}; + +export const CardOnlyContent = Template.bind({}); +CardOnlyContent.args = { + content: "This card only contains content", +}; + +export const CardTypeAccordion = Template.bind({}); +CardTypeAccordion.args = { + ...DefaultCard.args, + content: `Lorem ipsum dolor sit amet, consectetur adipiscing elit. + Nunc velit turpis, mollis a ultricies vitae, accumsan ut augue. + In a eros ac dolor hendrerit varius et at mauris.`, + type: "accordion", +}; +CardTypeAccordion.parameters = { + a11y: { + config: { + rules: [ + /* + The accordion card can be expanded either by the chevron icon + button or by activating the details element. Mouse users can + click on the chevron button or the details element, while + keyboard users can tab to the details element and have a + focus ring around the details element in the card. + Additionally, the details element is announced as a button + so I don't believe we are providing a degraded experience + to non-mouse users. + + Bug 1854008: We should probably make the accordion button a + clickable div or something that isn't announced to screen + readers. + */ + { + id: "button-name", + reviewOnFail: true, + }, + { + id: "nested-interactive", + reviewOnFail: true, + }, + ], + }, + }, +}; -- cgit v1.2.3