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 --- .../content-src/styles/_feature-callout.scss | 775 +++++++++++++++++++++ 1 file changed, 775 insertions(+) create mode 100644 browser/components/asrouter/content-src/styles/_feature-callout.scss (limited to 'browser/components/asrouter/content-src/styles/_feature-callout.scss') diff --git a/browser/components/asrouter/content-src/styles/_feature-callout.scss b/browser/components/asrouter/content-src/styles/_feature-callout.scss new file mode 100644 index 0000000000..66770c2238 --- /dev/null +++ b/browser/components/asrouter/content-src/styles/_feature-callout.scss @@ -0,0 +1,775 @@ +// 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 'feature-callout-theme'; + +/* stylelint-disable max-nesting-depth */ + +#feature-callout { + // See _feature-callout-theme.scss for the theme mixins and + // FeatureCallout.sys.mjs for the color values + @include light-theme; + + position: absolute; + z-index: 2147483647; + outline: none; + color: var(--fc-color); + accent-color: var(--fc-accent-color); + // Make sure HTML content uses non-native theming, even in chrome windows. + -moz-theme: non-native; + + @media (prefers-color-scheme: dark) { + @include dark-theme; + } + + @media (prefers-contrast) { + @include hcm-theme; + } + + // Account for feature callouts that may be rendered in the chrome but + // displayed on top of content. Each context has its own color scheme, so they + // may not match. In that case, we use the special media query below. + &.simulateContent { + color-scheme: env(-moz-content-preferred-color-scheme); + + // TODO - replace 2 mixins with a single mixin with light-dark() values. + @media (-moz-content-prefers-color-scheme: light) { + @include light-theme; + } + + @media (-moz-content-prefers-color-scheme: dark) { + @include dark-theme; + } + + @media (prefers-contrast) { + @include hcm-theme; + } + } + + // The desired width of the arrow (the triangle base). + --arrow-width: 33.9411px; + // The width/height of the square that, rotated 90deg, will become the arrow. + --arrow-square-size: calc(var(--arrow-width) / sqrt(2)); + // After rotating, the width is no longer the square width. It's now equal to + // the diagonal from corner to corner, i.e. √2 * the square width. We need to + // account for this extra width in some calculations. + --extra-width-from-rotation: calc(var(--arrow-width) - var(--arrow-square-size)); + // The height of the arrow, once rotated and cut in half. + --arrow-visible-height: calc(var(--arrow-width) / 2); + // Half the width/height of the square. Calculations on the arrow itself need + // to treat the arrow as a square, since they are operating on the element + // _before_ it is rotated. Calculations on other elements (like the panel + // margin that needs to make space for the arrow) should use the visible + // height that treats it as a triangle. + --arrow-visible-size: calc(var(--arrow-square-size) / 2); + --arrow-center-inset: calc(50% - var(--arrow-visible-size)); + // Move the arrow 1.5px closer to the callout to account for subpixel rounding + // differences, which might cause the corners of the arrow (which is actually + // a rotated square) to be visible. + --arrow-offset: calc(1.5px - var(--arrow-visible-size)); + // For positions like top-end, the arrow is 12px away from the corner. + --arrow-corner-distance: 12px; + --arrow-corner-inset: calc(var(--arrow-corner-distance) + (var(--extra-width-from-rotation) / 2)); + --arrow-overlap-magnitude: 5px; + + @at-root panel#{&} { + --panel-color: var(--fc-color); + --panel-shadow: none; + // Extra space around the panel for the shadow to be drawn in. The panel + // content can't overflow the XUL popup frame, so the frame must be extended. + --panel-shadow-margin: 6px; + // The panel needs more extra space on the side that the arrow is on, since + // the arrow is absolute positioned. This adds the visible height of the + // arrow to the margin and subtracts 1 since the arrow is inset by 1.5px + // (see --arrow-offset). + --panel-arrow-space: calc(var(--panel-shadow-margin) + var(--arrow-visible-height) - 1.5px); + // The callout starts with its edge aligned with the edge of the anchor. But + // we want the arrow to align to the anchor, not the callout edge. So we need + // to offset the callout by the arrow size and margin, as well as the margin + // of the entire callout (it has margins on all sides to make room for the + // shadow when displayed in a panel, which would normally cut off the shadow). + --panel-margin-offset: calc(-1 * (var(--panel-shadow-margin) + var(--arrow-corner-distance) + (var(--arrow-width) / 2))); + } + + @at-root panel#{&}::part(content) { + width: initial; + border: 0; + border-radius: 0; + padding: 0; + margin: var(--panel-shadow-margin); + background: none; + color: inherit; + // stylelint-disable-next-line declaration-no-important + overflow: visible !important; + } + + @at-root div#{&} { + transition: opacity 0.5s ease; + + &.hidden { + opacity: 0; + pointer-events: none; + } + } + + .onboardingContainer, + .onboardingContainer .outer-wrapper { + // Override the element transitions from aboutwelcome.scss + --transition: none; + + // auto height to allow for arrow positioning based on height + height: auto; + } + + // use a different approach to flipping to avoid the fuzzy aliasing that + // transform causes. + &:dir(rtl) { + transform: none; + direction: ltr; + } + + & .outer-wrapper:dir(rtl) { + transform: none; + direction: rtl; + } + + .screen { + // override transform in about:welcome + &:dir(rtl) { + transform: none; + } + + &[pos='callout'] { + height: fit-content; + min-height: unset; + overflow: visible; + + &[layout='inline'] { + .section-main { + .main-content, + .main-content.no-steps { + width: 18em; + padding-inline: 16px; + padding-block: 0; + + .welcome-text { + // Same height as the dismiss button + height: 24px; + margin-block: 12px; + margin-inline: 0; + padding: 0; + white-space: nowrap; + } + } + + .dismiss-button { + height: 24px; + width: 24px; + min-height: 24px; + min-width: 24px; + margin: 0; + top: calc(50% - 12px); + inset-inline-end: 12px; + } + } + } + + .logo-container { + display: flex; + justify-content: center; + + .brand-logo { + margin: 0; + + // This may not work for all future messages, so we may want to make + // flipping the logo image in RTL mode configurable + &:dir(rtl) { + transform: rotateY(180deg); + } + } + } + + .welcome-text { + align-items: baseline; + text-align: start; + margin: 0; + padding: 0; + gap: 8px; + + h1, + h2 { + font-size: 0.813em; + margin: 0; + color: inherit; + } + + h1 { + font-weight: 600; + } + + .inline-icon-container { + display: flex; + flex-flow: row wrap; + align-items: center; + + .logo-container { + height: 16px; + width: 16px; + margin-inline-end: 6px; + box-sizing: border-box; + -moz-context-properties: fill; + fill: currentColor; + + img { + height: 16px; + width: 16px; + margin: 0; + } + } + + &[alignment='top'], + &[alignment='bottom'] { + flex-wrap: nowrap; + + .logo-container { + height: 1.5em; // match the title's line-height + align-items: center; + padding-bottom: 0.15em; + box-sizing: border-box; + } + } + + &[alignment='top'] { + align-items: start; + } + + &[alignment='bottom'] { + align-items: end; + } + } + + } + + .multi-select-container { + margin: 0; + font-size: 0.813em; + row-gap: 12px; + color: inherit; + overflow: visible; + + #multi-stage-multi-select-label { + font-size: inherit; + // There's a 12px gap that pushes the .multi-select-container down + // away from the .welcome-text. And there's an 8px gap between the h1 + // and h2 in the .welcome-text container. So subtract 4px to get the + // desired 8px margin, so spacing is the same as for `subtitle`. + margin: -4px 0 0; + color: inherit; + } + } + + .cta-link { + background: none; + text-decoration: underline; + cursor: pointer; + border: none; + padding: 0; + color: var(--fc-link-color); + order: -1; + margin-inline-end: auto; + margin-block: 8px; + + &:hover { + color: var(--fc-link-color-hover); + } + + &:active { + color: var(--fc-link-color-active); + } + } + + // Secondary section is not included in callouts + .section-secondary { + display: none; + } + + .section-main { + height: fit-content; + width: fit-content; + + .main-content { + position: relative; + overflow: hidden; + border: 1px solid var(--fc-border); + box-shadow: 0 2px 6px rgba(0, 0, 0, 15%); + border-radius: 4px; + padding: var(--callout-padding, 24px); + width: 25em; + gap: 16px; + background-color: var(--fc-background); + + .main-content-inner { + gap: 12px; + } + + .steps { + height: auto; + position: absolute; + // 24px is the callout's bottom padding. The CTAs are 32px tall, and + // the steps are 8px tall. So we need to offset the steps by half + // the difference in order to center them. 32/2 - 8/2 = 12. + bottom: calc(var(--callout-padding, 24px) + 12px); + padding-block: 0; + + .indicator { + // using border will show up in Windows High Contrast Mode to improve accessibility. + border: 4px solid var(--fc-step-color); + + &.current { + border-color: var(--fc-accent-color); + } + } + + &:not(.progress-bar) { + flex-flow: row nowrap; + gap: 8px; + + .indicator { + margin: 0; + } + } + + & .indicator.current, + &.progress-bar .indicator.complete { + border-color: var(--fc-accent-color); + } + } + } + + .dismiss-button { + font-size: 1em; + inset-block: 0 auto; + inset-inline: auto 0; + margin-block: 16px 0; + margin-inline: 0 16px; + background-color: var(--fc-background); + + &[button-size='small'] { + height: 24px; + width: 24px; + min-height: 24px; + min-width: 24px; + } + } + } + + .action-buttons { + display: flex; + flex-flow: row nowrap; + align-items: stretch; + justify-content: end; + gap: 10px; + // The Figma spec wants a 16px gap between major content blocks and the + // action buttons. But the action buttons are siblings with the minor + // content blocks, which want a 12px gap. So we use a 12px gap and just + // add 4px of margin to the action buttons. + margin-top: 4px; + + &[alignment='start'] { + justify-content: start; + } + + &[alignment='space-between'] { + justify-content: space-between; + } + + .secondary-cta { + font-size: inherit; + } + + .primary, + .secondary { + padding: 4px 16px; + margin: 0; + font-size: 0.813em; + font-weight: 600; + line-height: 16px; + min-height: 32px; + text-decoration: none; + cursor: default; + } + + .secondary { + background-color: var(--fc-button-background); + } + + .primary { + background-color: var(--fc-primary-button-background); + } + + .split-button-container { + align-items: stretch; + + &:not([hidden]) { + display: flex; + } + + .primary, + .secondary, + .additional-cta { + &:not(.submenu-button) { + border-start-end-radius: 0; + border-end-end-radius: 0; + margin-inline-end: 0; + } + + &:focus-visible { + z-index: 2; + } + } + + .submenu-button { + border-start-start-radius: 0; + border-end-start-radius: 0; + margin-inline-start: 1px; + padding: 8px; + min-width: 30px; + box-sizing: border-box; + background-image: url('chrome://global/skin/icons/arrow-down.svg'); + background-repeat: no-repeat; + background-size: 16px; + background-position: center; + -moz-context-properties: fill; + fill: currentColor; + } + } + } + + .action-buttons .primary, + .action-buttons .secondary, + .dismiss-button { + border-radius: 4px; + + &:focus-visible { + box-shadow: none; + outline: 2px solid var(--fc-accent-color); + outline-offset: 2px; + } + + &:disabled { + opacity: 0.4; + cursor: auto; + } + } + + .action-buttons .secondary, + .dismiss-button { + border: 1px solid var(--fc-button-border); + color: var(--fc-button-color); + + &:hover:not(:disabled), + &[open] { + background-color: var(--fc-button-background-hover); + color: var(--fc-button-color-hover); + border: 1px solid var(--fc-button-border-hover); + + &:active { + background-color: var(--fc-button-background-active); + color: var(--fc-button-color-active); + border: 1px solid var(--fc-button-border-active); + } + } + } + + .action-buttons .primary { + border: 1px solid var(--fc-primary-button-border); + color: var(--fc-primary-button-color); + + &:hover:not(:disabled), + &[open] { + background-color: var(--fc-primary-button-background-hover); + color: var(--fc-primary-button-color-hover); + border: 1px solid var(--fc-primary-button-border-hover); + + &:active { + background-color: var(--fc-primary-button-background-active); + color: var(--fc-primary-button-color-active); + border: 1px solid var(--fc-primary-button-border-active); + } + } + } + } + } + + @at-root panel#{&}:is([side='top'], [side='bottom']):not([hide-arrow='permanent']) { + margin-inline: var(--panel-margin-offset); + } + + @at-root panel#{&}:is([side='left'], [side='right']):not([hide-arrow='permanent']) { + margin-block: var(--panel-margin-offset); + } + + @at-root panel#{&}::part(content) { + position: relative; + } + + // all visible callout arrow boxes. boxes are for rotating 45 degrees, arrows + // are for the actual arrow shape and are children of the boxes. + .arrow-box { + position: absolute; + overflow: visible; + transform: rotate(45deg); + // keep the border crisp under transformation + transform-style: preserve-3d; + } + + &:not([arrow-position]) .arrow-box, + &[hide-arrow] .arrow-box { + display: none; + } + + // both shadow arrow and background arrow + .arrow { + width: var(--arrow-square-size); + height: var(--arrow-square-size); + } + + // the arrow's shadow box + .shadow-arrow-box { + z-index: -1; + } + + // the arrow's shadow + .shadow-arrow { + background: transparent; + outline: 1px solid var(--fc-border); + box-shadow: 0 2px 6px rgba(0, 0, 0, 15%); + } + + // the 'filled' arrow box + .background-arrow-box { + z-index: 1; + // the background arrow technically can overlap the dismiss button. it + // doesn't visibly overlap it because of the clip-path rule below, but it + // can still be clicked. so we need to make sure it doesn't block inputs on + // the button. the visible part of the arrow can still catch clicks because + // we don't add this rule to .shadow-arrow-box. + pointer-events: none; + } + + // the 'filled' arrow + .background-arrow { + background-color: var(--fc-background); + clip-path: var(--fc-arrow-clip-path); + } + + // top (center) arrow positioning + &[arrow-position='top'] .arrow-box { + top: var(--arrow-offset); + inset-inline-start: var(--arrow-center-inset); + // the callout arrow is actually a diamond (a rotated square), with the + // lower half invisible. the part that appears in front of the callout has + // only a background, so that where it overlaps the callout's border, the + // border is not visible. the part that appears behind the callout has only + // a border/shadow, so that it can't be seen overlapping the callout. but + // because the background is the same color as the callout, that half of the + // diamond would visibly overlap any callout content that happens to be in + // the same place. so we clip it to a triangle, with a 2% extension on the + // bottom to account for any subpixel rounding differences. + --fc-arrow-clip-path: polygon(100% 0, 100% 2%, 2% 100%, 0 100%, 0 0); + } + + @at-root panel#{&}[arrow-position='top']::part(content) { + margin-top: var(--panel-arrow-space); + } + + @at-root panel#{&}[arrow-position='top'] { + margin-top: calc(-1 * (var(--panel-shadow-margin) + var(--arrow-overlap-magnitude))); + } + + // bottom (center) arrow positioning + &[arrow-position='bottom'] .arrow-box { + bottom: var(--arrow-offset); + inset-inline-start: var(--arrow-center-inset); + --fc-arrow-clip-path: polygon(100% 0, 98% 0, 0 98%, 0 100%, 100% 100%); + } + + @at-root panel#{&}[arrow-position='bottom']::part(content) { + margin-bottom: var(--panel-arrow-space); + } + + @at-root panel#{&}[arrow-position='bottom'] { + margin-bottom: calc(-1 * (var(--panel-shadow-margin) + var(--arrow-overlap-magnitude))); + } + + // end (center) arrow positioning + &[arrow-position='inline-end'] .arrow-box { + top: var(--arrow-center-inset); + inset-inline-end: var(--arrow-offset); + --fc-arrow-clip-path: polygon(100% 0, 100% 100%, 98% 100%, 0 2%, 0 0); + } + + @at-root panel#{&}[arrow-position='inline-end']::part(content) { + margin-inline-end: var(--panel-arrow-space); + } + + @at-root panel#{&}[arrow-position='inline-end'] { + margin-inline-end: calc(-1 * (var(--panel-shadow-margin) + var(--arrow-overlap-magnitude))); + } + + // start (center) arrow positioning + &[arrow-position='inline-start'] .arrow-box { + top: var(--arrow-center-inset); + inset-inline-start: var(--arrow-offset); + --fc-arrow-clip-path: polygon(0 100%, 100% 100%, 100% 98%, 2% 0, 0 0); + } + + @at-root panel#{&}[arrow-position='inline-start']::part(content) { + margin-inline-start: var(--panel-arrow-space); + } + + @at-root panel#{&}[arrow-position='inline-start'] { + margin-inline-start: calc(-1 * (var(--panel-shadow-margin) + var(--arrow-overlap-magnitude))); + } + + // top-end arrow positioning + &[arrow-position='top-end'] .arrow-box { + top: var(--arrow-offset); + inset-inline-end: var(--arrow-corner-inset); + --fc-arrow-clip-path: polygon(100% 0, 100% 2%, 2% 100%, 0 100%, 0 0); + } + + @at-root panel#{&}[arrow-position='top-end']::part(content) { + margin-top: var(--panel-arrow-space); + } + + @at-root panel#{&}[arrow-position='top-end'] { + margin-top: calc(-1 * (var(--panel-shadow-margin) + var(--arrow-overlap-magnitude))); + } + + // top-start arrow positioning + &[arrow-position='top-start'] .arrow-box { + top: var(--arrow-offset); + inset-inline-start: var(--arrow-corner-inset); + --fc-arrow-clip-path: polygon(100% 0, 100% 2%, 2% 100%, 0 100%, 0 0); + } + + @at-root panel#{&}[arrow-position='top-start']::part(content) { + margin-top: var(--panel-arrow-space); + } + + @at-root panel#{&}[arrow-position='top-start'] { + margin-top: calc(-1 * (var(--panel-shadow-margin) + var(--arrow-overlap-magnitude))); + } + + // bottom-end arrow positioning + &[arrow-position='bottom-end'] .arrow-box { + bottom: var(--arrow-offset); + inset-inline-end: var(--arrow-corner-inset); + --fc-arrow-clip-path: polygon(100% 0, 98% 0, 0 98%, 0 100%, 100% 100%); + } + + @at-root panel#{&}[arrow-position='bottom-end']::part(content) { + margin-bottom: var(--panel-arrow-space); + } + + @at-root panel#{&}[arrow-position='bottom-end'] { + margin-bottom: calc(-1 * (var(--panel-shadow-margin) + var(--arrow-overlap-magnitude))); + } + + // bottom-start arrow positioning + &[arrow-position='bottom-start'] .arrow-box { + bottom: var(--arrow-offset); + inset-inline-start: var(--arrow-corner-inset); + --fc-arrow-clip-path: polygon(100% 0, 98% 0, 0 98%, 0 100%, 100% 100%); + } + + @at-root panel#{&}[arrow-position='bottom-start']::part(content) { + margin-bottom: var(--panel-arrow-space); + } + + @at-root panel#{&}[arrow-position='bottom-start'] { + margin-bottom: calc(-1 * (var(--panel-shadow-margin) + var(--arrow-overlap-magnitude))); + } + + // inline-end-top arrow positioning + &[arrow-position='inline-end-top'] .arrow-box { + top: var(--arrow-corner-inset); + inset-inline-end: var(--arrow-offset); + --fc-arrow-clip-path: polygon(100% 0, 100% 100%, 98% 100%, 0 2%, 0 0); + } + + @at-root panel#{&}[arrow-position='inline-end-top']::part(content) { + margin-inline-end: var(--panel-arrow-space); + } + + @at-root panel#{&}[arrow-position='inline-end-top'] { + margin-inline-end: calc(-1 * (var(--panel-shadow-margin) + var(--arrow-overlap-magnitude))); + } + + // inline-end-bottom arrow positioning + &[arrow-position='inline-end-bottom'] .arrow-box { + bottom: var(--arrow-corner-inset); + inset-inline-end: var(--arrow-offset); + --fc-arrow-clip-path: polygon(100% 0, 100% 100%, 98% 100%, 0 2%, 0 0); + } + + @at-root panel#{&}[arrow-position='inline-end-bottom']::part(content) { + margin-inline-end: var(--panel-arrow-space); + } + + @at-root panel#{&}[arrow-position='inline-end-bottom'] { + margin-inline-end: calc(-1 * (var(--panel-shadow-margin) + var(--arrow-overlap-magnitude))); + } + + // inline-start-top arrow positioning + &[arrow-position='inline-start-top'] .arrow-box { + top: var(--arrow-corner-inset); + inset-inline-start: var(--arrow-offset); + --fc-arrow-clip-path: polygon(0 100%, 100% 100%, 100% 98%, 2% 0, 0 0); + } + + @at-root panel#{&}[arrow-position='inline-start-top']::part(content) { + margin-inline-start: var(--panel-arrow-space); + } + + @at-root panel#{&}[arrow-position='inline-start-top'] { + margin-inline-start: calc(-1 * (var(--panel-shadow-margin) + var(--arrow-overlap-magnitude))); + } + + // inline-start-bottom arrow positioning + &[arrow-position='inline-start-bottom'] .arrow-box { + bottom: var(--arrow-corner-inset); + inset-inline-start: var(--arrow-offset); + --fc-arrow-clip-path: polygon(0 100%, 100% 100%, 100% 98%, 2% 0, 0 0); + } + + @at-root panel#{&}[arrow-position='inline-start-bottom']::part(content) { + margin-inline-start: var(--panel-arrow-space); + } + + @at-root panel#{&}[arrow-position='inline-start-bottom'] { + margin-inline-start: calc(-1 * (var(--panel-shadow-margin) + var(--arrow-overlap-magnitude))); + } + + // focus outline for the callout itself + &:focus-visible { + .screen { + &[pos='callout'] { + .section-main .main-content { + outline: 2px solid var(--fc-accent-color); + border-color: transparent; + + @media (prefers-contrast) { + border-color: var(--fc-background); + } + } + } + } + + .shadow-arrow { + outline: 2px solid var(--fc-accent-color); + } + } +} -- cgit v1.2.3