summaryrefslogtreecommitdiffstats
path: root/browser/components/newtab/content-src/styles
diff options
context:
space:
mode:
Diffstat (limited to 'browser/components/newtab/content-src/styles')
-rw-r--r--browser/components/newtab/content-src/styles/_activity-stream.scss177
-rw-r--r--browser/components/newtab/content-src/styles/_feature-callout-theme.scss56
-rw-r--r--browser/components/newtab/content-src/styles/_feature-callout.scss314
-rw-r--r--browser/components/newtab/content-src/styles/_icons.scss211
-rw-r--r--browser/components/newtab/content-src/styles/_mixins.scss50
-rw-r--r--browser/components/newtab/content-src/styles/_normalize.scss29
-rw-r--r--browser/components/newtab/content-src/styles/_theme.scss99
-rw-r--r--browser/components/newtab/content-src/styles/_variables.scss217
-rw-r--r--browser/components/newtab/content-src/styles/activity-stream-linux.scss11
-rw-r--r--browser/components/newtab/content-src/styles/activity-stream-mac.scss16
-rw-r--r--browser/components/newtab/content-src/styles/activity-stream-windows.scss11
11 files changed, 1191 insertions, 0 deletions
diff --git a/browser/components/newtab/content-src/styles/_activity-stream.scss b/browser/components/newtab/content-src/styles/_activity-stream.scss
new file mode 100644
index 0000000000..1261b6e916
--- /dev/null
+++ b/browser/components/newtab/content-src/styles/_activity-stream.scss
@@ -0,0 +1,177 @@
+@import './normalize';
+@import './variables';
+@import './theme';
+@import './icons';
+@import './mixins';
+
+html {
+ height: 100%;
+}
+
+body,
+#root {
+ min-height: 100vh;
+}
+
+#root {
+ position: relative;
+}
+
+body {
+ background-color: var(--newtab-background-color);
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Ubuntu, 'Helvetica Neue', sans-serif;
+ font-size: 16px;
+}
+
+.no-scroll {
+ overflow: hidden;
+}
+
+h1,
+h2 {
+ font-weight: normal;
+}
+
+.inner-border {
+ border: $border-secondary;
+ border-radius: $border-radius;
+ height: 100%;
+ left: 0;
+ pointer-events: none;
+ position: absolute;
+ top: 0;
+ width: 100%;
+ z-index: 100;
+}
+
+@keyframes fadeIn {
+ from {
+ opacity: 0;
+ }
+
+ to {
+ opacity: 1;
+ }
+}
+
+.show-on-init {
+ opacity: 0;
+ transition: opacity 0.2s ease-in;
+
+ &.on {
+ animation: fadeIn 0.2s;
+ opacity: 1;
+ }
+}
+
+.actions {
+ border-top: $border-secondary;
+ display: flex;
+ flex-direction: row;
+ flex-wrap: wrap;
+ justify-content: flex-start;
+ margin: 0;
+ padding: 15px 25px 0;
+}
+
+// Default button (grey)
+.button,
+.actions button {
+ background-color: var(--newtab-button-secondary-color);
+ border: $border-primary;
+ border-radius: 4px;
+ color: inherit;
+ cursor: pointer;
+ margin-bottom: 15px;
+ padding: 10px 30px;
+ white-space: nowrap;
+
+ &:hover:not(.dismiss),
+ &:focus:not(.dismiss) {
+ box-shadow: $shadow-primary;
+ transition: box-shadow 150ms;
+ }
+
+ &.dismiss {
+ background-color: transparent;
+ border: 0;
+ padding: 0;
+ text-decoration: underline;
+ }
+
+ // Blue button
+ &.primary,
+ &.done {
+ background-color: var(--newtab-primary-action-background);
+ border: solid 1px var(--newtab-primary-action-background);
+ color: var(--newtab-primary-element-text-color);
+ margin-inline-start: auto;
+ }
+}
+
+input {
+ &[type='text'],
+ &[type='search'] {
+ border-radius: $border-radius;
+ }
+}
+
+// These styles are needed for -webkit-line-clamp to work correctly, so reuse
+// this class name while separately setting a clamp value via CSS or JS.
+.clamp {
+ -webkit-box-orient: vertical;
+ display: -webkit-box;
+ overflow: hidden;
+ word-break: break-word;
+}
+
+// Components
+// stylelint-disable no-invalid-position-at-import-rule
+@import '../components/A11yLinkButton/A11yLinkButton';
+@import '../components/Base/Base';
+@import '../components/ErrorBoundary/ErrorBoundary';
+@import '../components/TopSites/TopSites';
+@import '../components/Sections/Sections';
+@import '../components/Topics/Topics';
+@import '../components/Search/Search';
+@import '../components/ContextMenu/ContextMenu';
+@import '../components/ConfirmDialog/ConfirmDialog';
+@import '../components/CustomizeMenu/CustomizeMenu';
+@import '../components/Card/Card';
+@import '../components/CollapsibleSection/CollapsibleSection';
+@import '../components/ASRouterAdmin/ASRouterAdmin';
+@import '../components/PocketLoggedInCta/PocketLoggedInCta';
+@import '../components/MoreRecommendations/MoreRecommendations';
+@import '../components/DiscoveryStreamBase/DiscoveryStreamBase';
+
+// Discovery Stream Components
+@import '../components/DiscoveryStreamComponents/CardGrid/CardGrid';
+@import '../components/DiscoveryStreamComponents/CollectionCardGrid/CollectionCardGrid';
+@import '../components/DiscoveryStreamComponents/Highlights/Highlights';
+@import '../components/DiscoveryStreamComponents/HorizontalRule/HorizontalRule';
+@import '../components/DiscoveryStreamComponents/Navigation/Navigation';
+@import '../components/DiscoveryStreamComponents/SectionTitle/SectionTitle';
+@import '../components/DiscoveryStreamComponents/TopSites/TopSites';
+@import '../components/DiscoveryStreamComponents/DSLinkMenu/DSLinkMenu';
+@import '../components/DiscoveryStreamComponents/DSCard/DSCard';
+@import '../components/DiscoveryStreamComponents/DSContextFooter/DSContextFooter';
+@import '../components/DiscoveryStreamComponents/DSImage/DSImage';
+@import '../components/DiscoveryStreamComponents/DSDismiss/DSDismiss';
+@import '../components/DiscoveryStreamComponents/DSMessage/DSMessage';
+@import '../components/DiscoveryStreamImpressionStats/ImpressionStats';
+@import '../components/DiscoveryStreamComponents/DSEmptyState/DSEmptyState';
+@import '../components/DiscoveryStreamComponents/DSTextPromo/DSTextPromo';
+@import '../components/DiscoveryStreamComponents/DSSignup/DSSignup';
+@import '../components/DiscoveryStreamComponents/DSPrivacyModal/DSPrivacyModal';
+@import '../components/DiscoveryStreamComponents/PrivacyLink/PrivacyLink';
+@import '../components/DiscoveryStreamComponents/TopicsWidget/TopicsWidget';
+
+// AS Router
+@import '../asrouter/components/Button/Button';
+@import '../asrouter/components/SnippetBase/SnippetBase';
+@import '../asrouter/components/ModalOverlay/ModalOverlay';
+@import '../asrouter/templates/SimpleBelowSearchSnippet/SimpleBelowSearchSnippet';
+@import '../asrouter/templates/SimpleSnippet/SimpleSnippet';
+@import '../asrouter/templates/SubmitFormSnippet/SubmitFormSnippet';
+@import '../asrouter/templates/EOYSnippet/EOYSnippet';
+// stylelint-enable no-invalid-position-at-import-rule
diff --git a/browser/components/newtab/content-src/styles/_feature-callout-theme.scss b/browser/components/newtab/content-src/styles/_feature-callout-theme.scss
new file mode 100644
index 0000000000..b62591f3ac
--- /dev/null
+++ b/browser/components/newtab/content-src/styles/_feature-callout-theme.scss
@@ -0,0 +1,56 @@
+// 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/.
+
+// stylelint-disable color-hex-length -- we want to preserve these values
+// exactly, since they're drawn from other parts of the browser.
+
+@mixin light-theme {
+ --fc-background: var(--fc-background-light, #FFF);
+ --fc-color: var(--fc-color-light, #15141A);
+ --fc-border: var(--fc-border-light, #CFCFD8);
+ --fc-accent-color: var(--fc-accent-color-light, #0061E0);
+ --fc-button-background: var(--fc-button-background-light, #F0F0F4);
+ --fc-button-color: var(--fc-button-color-light, #15141A);
+ --fc-button-border: var(--fc-button-border-light, transparent);
+ --fc-button-background-hover: var(--fc-button-background-hover-light, #E0E0E6);
+ --fc-button-color-hover: var(--fc-button-color-hover-light, #15141A);
+ --fc-button-border-hover: var(--fc-button-border-hover-light, transparent);
+ --fc-button-background-active: var(--fc-button-background-active-light, #CFCFD8);
+ --fc-button-color-active: var(--fc-button-color-active-light, #15141A);
+ --fc-button-border-active: var(--fc-button-border-active-light, transparent);
+ --fc-step-color: color-mix(in srgb, currentColor 50%, transparent);
+}
+
+@mixin dark-theme {
+ --fc-background: var(--fc-background-dark, #42414D);
+ --fc-color: var(--fc-color-dark, #FBFBFE);
+ --fc-border: var(--fc-border-dark, #3A3944);
+ --fc-accent-color: var(--fc-accent-color-dark, #00DDFF);
+ --fc-button-background: var(--fc-button-background-dark, #2B2A33);
+ --fc-button-color: var(--fc-button-color-dark, #FBFBFE);
+ --fc-button-border: var(--fc-button-border-dark, transparent);
+ --fc-button-background-hover: var(--fc-button-background-hover-dark, #52525E);
+ --fc-button-color-hover: var(--fc-button-color-hover-dark, #FBFBFE);
+ --fc-button-border-hover: var(--fc-button-border-hover-dark, transparent);
+ --fc-button-background-active: var(--fc-button-background-active-dark, #5B5B66);
+ --fc-button-color-active: var(--fc-button-color-active-dark, #FBFBFE);
+ --fc-button-border-active: var(--fc-button-border-active-dark, transparent);
+}
+
+@mixin hcm-theme {
+ --fc-background: var(--fc-background-hcm, -moz-dialog);
+ --fc-color: var(--fc-color-hcm, -moz-dialogtext);
+ --fc-border: var(--fc-border-hcm, -moz-dialogtext);
+ --fc-accent-color: var(--fc-accent-color-hcm, LinkText);
+ --fc-button-background: var(--fc-button-background-hcm, ButtonFace);
+ --fc-button-color: var(--fc-button-color-hcm, ButtonText);
+ --fc-button-border: var(--fc-button-border-hcm, ButtonText);
+ --fc-button-background-hover: var(--fc-button-background-hover-hcm, ButtonText);
+ --fc-button-color-hover: var(--fc-button-color-hover-hcm, ButtonFace);
+ --fc-button-border-hover: var(--fc-button-border-hover-hcm, ButtonText);
+ --fc-button-background-active: var(--fc-button-background-active-hcm, ButtonText);
+ --fc-button-color-active: var(--fc-button-color-active-hcm, ButtonFace);
+ --fc-button-border-active: var(--fc-button-border-active-hcm, ButtonText);
+ --fc-step-color: var(--fc-accent-color-hcm, LinkText);
+}
diff --git a/browser/components/newtab/content-src/styles/_feature-callout.scss b/browser/components/newtab/content-src/styles/_feature-callout.scss
new file mode 100644
index 0000000000..aa0ba0ed1e
--- /dev/null
+++ b/browser/components/newtab/content-src/styles/_feature-callout.scss
@@ -0,0 +1,314 @@
+// 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';
+
+$max-z-index: 2147483647;
+
+.onboardingContainer.featureCallout {
+ // See _feature-callout-theme.scss for the theme mixins and
+ // FeatureCallout.sys.mjs for the color values
+ @include light-theme;
+
+ position: absolute;
+ transition: opacity 0.5s ease;
+ z-index: $max-z-index - 2;
+ outline: none;
+ color: var(--fc-color);
+
+ @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 {
+ @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;
+ }
+ }
+
+ &.hidden {
+ opacity: 0;
+ pointer-events: none;
+ }
+
+ &,
+ & .outer-wrapper {
+ // auto height to allow for arrow positioning based on height
+ height: auto;
+ }
+
+ .screen {
+ // override transform in about:welcome
+ &:dir(rtl) {
+ transform: none;
+ }
+
+ &[pos='callout'] {
+ height: fit-content;
+ min-height: unset;
+ overflow: visible;
+
+ .logo-container {
+ display: flex;
+ justify-content: center;
+
+ .brand-logo {
+ margin: 30px 45px 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-inline: 30px;
+ padding: 20px 0 0;
+
+ h1,
+ h2 {
+ font-size: 0.8em;
+ margin: 0;
+ color: inherit;
+ }
+
+ h1 {
+ font-weight: bold;
+ }
+
+ h2 {
+ margin-block: 10px;
+ }
+ }
+
+ // 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-top: 0;
+ // Subtract 4px, the block margin of buttons
+ padding-bottom: 30px - 4px;
+ width: 25em;
+ background-color: var(--fc-background);
+
+ .steps {
+ height: auto;
+ position: absolute;
+ // 30px is the margin of the CTAs from the bottom. 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. = 36px
+ bottom: 30px + math.div(32px, 2) - math.div(8px, 2);
+ margin: 0 30px;
+ 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);
+ }
+ }
+
+ & .indicator.current,
+ &.progress-bar .indicator.complete {
+ border-color: var(--fc-accent-color);
+ }
+ }
+ }
+
+ .dismiss-button {
+ font-size: 1em;
+ top: 0;
+ margin-block: 15px 0;
+ margin-inline: 0 15px;
+ z-index: $max-z-index;
+ background-color: var(--fc-background);
+ }
+ }
+
+ .action-buttons {
+ .primary,
+ .secondary-cta .secondary {
+ padding: 4px 16px;
+ font-size: 0.8em;
+ height: 2em;
+ background-color: var(--fc-button-background);
+ }
+
+ .primary {
+ font-weight: bold;
+ float: inline-end;
+ margin-inline: 10px 30px;
+ padding: 4px 16px;
+ font-size: 0.8em;
+ line-height: 16px;
+ min-height: 32px;
+ }
+
+ .secondary-cta {
+ float: inline-end;
+ }
+ }
+
+ .action-buttons .primary,
+ .action-buttons .secondary-cta .secondary,
+ .dismiss-button {
+ border-radius: 4px;
+ border: 1px solid var(--fc-button-border);
+ cursor: pointer;
+ color: var(--fc-button-color);
+
+ &:hover {
+ 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);
+ }
+ }
+
+ &:focus-visible {
+ box-shadow: none;
+ outline: 2px solid var(--fc-accent-color);
+ outline-offset: 2px;
+ }
+ }
+ }
+ }
+
+ $arrow-size: 24px;
+ $arrow-inset-size: math.div($arrow-size, 2);
+ // the arrow already overlaps the callout by 12px (see above), but to account
+ // for different pixel scaling factors, we can overlap by 1px more, since the
+ // border is drawn underneath the callout (on ::after). this is either added
+ // to or subtracted from absolute coordinates, depending on the direction.
+ $arrow-overlap-inset: -$arrow-inset-size + 1px;
+
+ // applied to all callout arrow foreground and background
+ &.callout-arrow::before,
+ &.callout-arrow::after {
+ content: '';
+ position: absolute;
+ width: $arrow-size;
+ height: $arrow-size;
+ transform: rotate(45deg);
+ // keep the border crisp under transformation
+ transform-style: preserve-3d;
+ }
+
+ // color for all arrow foreground
+ &.callout-arrow::before {
+ z-index: $max-z-index;
+ background-color: var(--fc-background);
+ }
+
+ // styles for all arrow backgrounds
+ &.callout-arrow::after {
+ background: transparent;
+ outline: 1px solid var(--fc-border);
+ box-shadow: 0 2px 6px rgba(0, 0, 0, 15%);
+ z-index: -1;
+ }
+
+ // up arrow positioning
+ &.arrow-top::before,
+ &.arrow-top::after {
+ top: $arrow-overlap-inset;
+ inset-inline-start: calc(50% - $arrow-inset-size);
+ }
+
+ // down arrow positioning
+ &.arrow-bottom::before,
+ &.arrow-bottom::after {
+ bottom: $arrow-overlap-inset;
+ inset-inline-start: calc(50% - $arrow-inset-size);
+ }
+
+ // end arrow positioning
+ &.arrow-inline-end::before,
+ &.arrow-inline-end::after {
+ top: calc(50% - $arrow-inset-size);
+ inset-inline-end: $arrow-overlap-inset;
+ }
+
+ // start arrow positioning
+ &.arrow-inline-start::before,
+ &.arrow-inline-start::after {
+ top: calc(50% - $arrow-inset-size);
+ inset-inline-start: $arrow-overlap-inset;
+ }
+
+ // top-end arrow positioning
+ &.arrow-top-end::before,
+ &.arrow-top-end::after {
+ top: $arrow-overlap-inset;
+ inset-inline-end: $arrow-inset-size;
+ }
+
+ // top-start arrow positioning
+ &.arrow-top-start::before,
+ &.arrow-top-start::after {
+ top: $arrow-overlap-inset;
+ inset-inline-start: $arrow-inset-size;
+ }
+
+ // hidden arrow display
+ &.hidden-arrow::before,
+ &.hidden-arrow::after {
+ display: none;
+ }
+
+ &: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);
+ }
+ }
+ }
+ }
+
+ &.callout-arrow::after {
+ outline: 2px solid var(--fc-accent-color);
+ }
+ }
+}
diff --git a/browser/components/newtab/content-src/styles/_icons.scss b/browser/components/newtab/content-src/styles/_icons.scss
new file mode 100644
index 0000000000..4074f0a6a6
--- /dev/null
+++ b/browser/components/newtab/content-src/styles/_icons.scss
@@ -0,0 +1,211 @@
+.icon {
+ background-position: center center;
+ background-repeat: no-repeat;
+ background-size: $icon-size;
+ -moz-context-properties: fill;
+ display: inline-block;
+ color: var(--newtab-text-primary-color);
+ fill: currentColor;
+ height: $icon-size;
+ vertical-align: middle;
+ width: $icon-size;
+
+ // helper classes
+ &.icon-spacer {
+ margin-inline-end: 8px;
+ }
+
+ &.icon-small-spacer {
+ margin-inline-end: 6px;
+ }
+
+ &.icon-button-style {
+ fill: var(--newtab-text-secondary-color);
+ border: 0;
+
+ &:focus,
+ &:hover {
+ fill: var(--newtab-text-primary-color);
+ }
+ }
+
+ // icon images
+ &.icon-bookmark-added {
+ background-image: url('chrome://browser/skin/bookmark.svg');
+ }
+
+ &.icon-bookmark-hollow {
+ background-image: url('chrome://browser/skin/bookmark-hollow.svg');
+ }
+
+ &.icon-clear-input {
+ background-image: url('chrome://global/skin/icons/close-fill.svg');
+ }
+
+ &.icon-delete {
+ background-image: url('chrome://global/skin/icons/delete.svg');
+ }
+
+ &.icon-search {
+ background-image: url('chrome://global/skin/icons/search-glass.svg');
+ }
+
+ &.icon-modal-delete {
+ flex-shrink: 0;
+ background-image: url('chrome://activity-stream/content/data/content/assets/glyph-modal-delete-20.svg');
+ background-size: $larger-icon-size;
+ height: $larger-icon-size;
+ width: $larger-icon-size;
+ }
+
+ &.icon-mail {
+ background-image: url('chrome://activity-stream/content/data/content/assets/glyph-mail-16.svg');
+ }
+
+ &.icon-dismiss {
+ background-image: url('chrome://global/skin/icons/close.svg');
+ }
+
+ &.icon-info {
+ background-image: url('chrome://global/skin/icons/info.svg');
+ }
+
+ &.icon-new-window {
+ @include flip-icon;
+
+ background-image: url('chrome://activity-stream/content/data/content/assets/glyph-newWindow-16.svg');
+ }
+
+ &.icon-new-window-private {
+ background-image: url('chrome://browser/skin/privateBrowsing.svg');
+ }
+
+ &.icon-settings {
+ background-image: url('chrome://global/skin/icons/settings.svg');
+ }
+
+ &.icon-pin {
+ @include flip-icon;
+
+ background-image: url('chrome://activity-stream/content/data/content/assets/glyph-pin-16.svg');
+ }
+
+ &.icon-unpin {
+ @include flip-icon;
+
+ background-image: url('chrome://activity-stream/content/data/content/assets/glyph-unpin-16.svg');
+ }
+
+ &.icon-edit {
+ background-image: url('chrome://global/skin/icons/edit.svg');
+ }
+
+ &.icon-pocket {
+ background-image: url('chrome://global/skin/icons/pocket.svg');
+ }
+
+ &.icon-pocket-save {
+ background-image: url('chrome://global/skin/icons/pocket.svg');
+ fill: $white;
+ }
+
+ &.icon-pocket-delete {
+ background-image: url('chrome://activity-stream/content/data/content/assets/glyph-pocket-delete-16.svg');
+ }
+
+ &.icon-pocket-archive {
+ background-image: url('chrome://activity-stream/content/data/content/assets/glyph-pocket-archive-16.svg');
+ }
+
+ &.icon-history-item {
+ background-image: url('chrome://browser/skin/history.svg');
+ }
+
+ &.icon-trending {
+ background-image: url('chrome://browser/skin/trending.svg');
+ transform: translateY(2px); // trending bolt is visually top heavy
+ }
+
+ &.icon-now {
+ background-image: url('chrome://browser/skin/history.svg');
+ }
+
+ &.icon-topsites {
+ background-image: url('chrome://browser/skin/topsites.svg');
+ }
+
+ &.icon-pin-small {
+ @include flip-icon;
+
+ background-image: url('chrome://browser/skin/pin-12.svg');
+ background-size: $smaller-icon-size;
+ height: $smaller-icon-size;
+ width: $smaller-icon-size;
+ }
+
+ &.icon-check {
+ background-image: url('chrome://global/skin/icons/check.svg');
+ }
+
+ &.icon-download {
+ background-image: url('chrome://browser/skin/downloads/downloads.svg');
+ }
+
+ &.icon-copy {
+ background-image: url('chrome://global/skin/icons/edit-copy.svg');
+ }
+
+ &.icon-open-file {
+ background-image: url('chrome://activity-stream/content/data/content/assets/glyph-open-file-16.svg');
+ }
+
+ &.icon-webextension {
+ background-image: url('chrome://activity-stream/content/data/content/assets/glyph-webextension-16.svg');
+ }
+
+ &.icon-highlights {
+ background-image: url('chrome://global/skin/icons/highlights.svg');
+ }
+
+ &.icon-arrowhead-down {
+ background-image: url('chrome://global/skin/icons/arrow-down.svg');
+ }
+
+ &.icon-arrowhead-down-small {
+ background-image: url('chrome://global/skin/icons/arrow-down-12.svg');
+ background-size: $smaller-icon-size;
+ height: $smaller-icon-size;
+ width: $smaller-icon-size;
+ }
+
+ &.icon-arrowhead-forward-small {
+ background-image: url('chrome://global/skin/icons/arrow-right-12.svg');
+ background-size: $smaller-icon-size;
+ height: $smaller-icon-size;
+ width: $smaller-icon-size;
+
+ &:dir(rtl) {
+ background-image: url('chrome://global/skin/icons/arrow-left-12.svg');
+ }
+ }
+
+ &.icon-arrowhead-up {
+ background-image: url('chrome://global/skin/icons/arrow-up.svg');
+ }
+
+ &.icon-add {
+ background-image: url('chrome://global/skin/icons/plus.svg');
+ }
+
+ &.icon-minimize {
+ background-image: url('chrome://activity-stream/content/data/content/assets/glyph-minimize-16.svg');
+ }
+
+ &.icon-maximize {
+ background-image: url('chrome://activity-stream/content/data/content/assets/glyph-maximize-16.svg');
+ }
+
+ &.icon-arrow {
+ background-image: url('chrome://global/skin/icons/arrow-right-12.svg');
+ }
+}
diff --git a/browser/components/newtab/content-src/styles/_mixins.scss b/browser/components/newtab/content-src/styles/_mixins.scss
new file mode 100644
index 0000000000..d2b2748a60
--- /dev/null
+++ b/browser/components/newtab/content-src/styles/_mixins.scss
@@ -0,0 +1,50 @@
+// Shared styling of article images shown as background
+@mixin image-as-background {
+ background-color: var(--newtab-element-secondary-color);
+ background-position: center;
+ background-repeat: no-repeat;
+ background-size: cover;
+ border-radius: 4px;
+ box-shadow: $shadow-image-inset;
+}
+
+// Note: lineHeight and fontSize should be unitless but can be derived from pixel values
+// Bug 1550624 to clean up / remove this mixin to avoid duplicate styles
+@mixin limit-visible-lines($line-count, $line-height, $font-size) {
+ font-size: $font-size * 1px;
+ -webkit-line-clamp: $line-count;
+ line-height: $line-height * 1px;
+}
+
+@mixin dark-theme-only {
+ [lwt-newtab-brighttext] & {
+ @content;
+ }
+}
+
+@mixin ds-border-top {
+ @content;
+
+ @include dark-theme-only {
+ border-top: 1px solid $grey-60;
+ }
+
+ border-top: 1px solid $grey-30;
+}
+
+@mixin ds-border-bottom {
+ @content;
+
+ @include dark-theme-only {
+ border-bottom: 1px solid $grey-60;
+ }
+
+ border-bottom: 1px solid $grey-30;
+}
+
+@mixin ds-fade-in($halo-color: $blue-50-30) {
+ box-shadow: 0 0 0 5px $halo-color;
+ transition: box-shadow 150ms;
+ border-radius: 4px;
+ outline: none;
+}
diff --git a/browser/components/newtab/content-src/styles/_normalize.scss b/browser/components/newtab/content-src/styles/_normalize.scss
new file mode 100644
index 0000000000..a47166ef7b
--- /dev/null
+++ b/browser/components/newtab/content-src/styles/_normalize.scss
@@ -0,0 +1,29 @@
+html {
+ box-sizing: border-box;
+}
+
+*,
+*::before,
+*::after {
+ box-sizing: inherit;
+}
+
+*::-moz-focus-inner {
+ border: 0;
+}
+
+body {
+ margin: 0;
+}
+
+button,
+input {
+ background-color: inherit;
+ color: inherit;
+ font-family: inherit;
+ font-size: inherit;
+}
+
+[hidden] {
+ display: none !important; // stylelint-disable-line declaration-no-important
+}
diff --git a/browser/components/newtab/content-src/styles/_theme.scss b/browser/components/newtab/content-src/styles/_theme.scss
new file mode 100644
index 0000000000..e5761b3d3b
--- /dev/null
+++ b/browser/components/newtab/content-src/styles/_theme.scss
@@ -0,0 +1,99 @@
+@function textbox-shadow($color) {
+ @return 0 0 0 1px $color, 0 0 0 $textbox-shadow-size rgba($color, 0.3);
+}
+
+@mixin textbox-focus($color) {
+ --newtab-textbox-focus-color: #{$color};
+ --newtab-textbox-focus-boxshadow: #{textbox-shadow($color)};
+}
+
+// scss variables related to the theme.
+$border-primary: 1px solid var(--newtab-border-color);
+$border-secondary: 1px solid var(--newtab-border-color);
+$inner-box-shadow: 0 0 0 1px var(--newtab-inner-box-shadow-color);
+$input-border: 1px solid var(--newtab-border-color);
+$input-border-active: 1px solid var(--newtab-textbox-focus-color);
+$input-error-border: 1px solid var(--newtab-status-error);
+$input-error-boxshadow: textbox-shadow(var(--newtab-status-error));
+$shadow-primary: 0 0 0 5px var(--newtab-element-secondary-color);
+$shadow-secondary: 0 1px 4px 0 $grey-90-20;
+$shadow-large: 0 2px 14px 0 $black-20;
+$shadow-focus: 0 0 0 2px var(--newtab-primary-action-background-dimmed);
+$shadow-card: 0 2px 6px rgba(0, 0, 0, 15%);
+$shadow-image-inset: inset 0 0 0 0.5px $black-15;
+
+// Default theme
+:root {
+ // General styles
+ --newtab-background-color: #{$in-content-page-background};
+ --newtab-background-color-secondary: #{$newtab-background-secondary};
+ --newtab-text-primary-color: #{$in-content-page-color};
+ --newtab-primary-action-background: #{$primary-blue};
+ // A button colour closer to the Pocket brand for usage in the Pocket section.
+ --newtab-primary-action-background-pocket: #{$primary-green};
+ --newtab-text-secondary-color: color-mix(in srgb, var(--newtab-text-primary-color) 70%, transparent);
+
+ // --newtab-element-*-color is used when an element needs to be set off from
+ // the primary background color.
+ --newtab-element-hover-color: color-mix(in srgb, var(--newtab-background-color) 90%, #{$black});
+ --newtab-element-active-color: color-mix(in srgb, var(--newtab-background-color) 80%, #{$black});
+
+ // --newtab-element-secondary*-color is used when an element needs to be set
+ // off from the secondary background color.
+ --newtab-element-secondary-color: color-mix(in srgb, currentColor 5%, transparent);
+ --newtab-element-secondary-hover-color: color-mix(in srgb, currentColor 12%, transparent);
+ --newtab-element-secondary-active-color: color-mix(in srgb, currentColor 25%, transparent);
+
+ --newtab-primary-element-hover-color: color-mix(in srgb, var(--newtab-primary-action-background) 90%, #{$black});
+ --newtab-primary-element-hover-pocket-color: color-mix(in srgb, var(--newtab-primary-action-background-pocket) 90%, #{$black});
+ --newtab-primary-element-active-color: color-mix(in srgb, var(--newtab-primary-action-background) 80%, #{$black});
+ --newtab-primary-element-text-color: #{$white};
+ // --newtab-primary-action-background-dimmed is used for soft focus borders.
+ --newtab-primary-action-background-dimmed: color-mix(in srgb, var(--newtab-primary-action-background) 25%, transparent);
+ --newtab-primary-action-background-pocket-dimmed: color-mix(in srgb, var(--newtab-primary-action-background-pocket) 25%, transparent);
+ --newtab-border-color: color-mix(in srgb, var(--newtab-background-color) 75%, #{$black});
+ --newtab-wordmark-color: #{$newtab-wordmark-default-color};
+ --newtab-status-success: #{$status-green};
+ --newtab-status-error: #{$red-60};
+ --newtab-inner-box-shadow-color: #{$black-10};
+ --newtab-overlay-color: color-mix(in srgb, var(--newtab-background-color) 85%, transparent);
+ --newtab-text-emphasis-background: #{$yellow-50};
+ --newtab-text-emphasis-text-color: #{$grey-90};
+
+ @include textbox-focus(var(--newtab-primary-action-background));
+
+ // Buttons
+ --newtab-button-secondary-color: inherit;
+
+ &[lwt-newtab-brighttext] {
+ // General styles
+ --newtab-background-color: #{$in-content-page-background-dark};
+ --newtab-background-color-secondary: #{$newtab-background-secondary-dark};
+ --newtab-text-primary-color: #{$in-content-page-color-dark};
+
+ --newtab-primary-action-background: #{$primary-blue-dark};
+ --newtab-primary-action-background-pocket: #{$primary-blue-dark};
+ --newtab-primary-action-background-pocket-dimmed: color-mix(in srgb, var(--newtab-primary-action-background) 25%, transparent);
+
+ --newtab-primary-element-hover-color: color-mix(in srgb, var(--newtab-primary-action-background) 55%, #{$white});
+ --newtab-primary-element-hover-pocket-color: color-mix(in srgb, var(--newtab-primary-action-background-pocket) 55%, #{$white});
+
+ --newtab-element-hover-color: color-mix(in srgb, var(--newtab-background-color) 80%, #{$white});
+ --newtab-element-active-color: color-mix(in srgb, var(--newtab-background-color) 60%, #{$white});
+
+ --newtab-element-secondary-color: color-mix(in srgb, currentColor 10%, transparent);
+ --newtab-element-secondary-hover-color: color-mix(in srgb, currentColor 17%, transparent);
+ --newtab-element-secondary-active-color: color-mix(in srgb, currentColor 30%, transparent);
+
+ --newtab-border-color: color-mix(in srgb, var(--newtab-background-color) 75%, #{$white});
+ --newtab-primary-element-text-color: #{$primary-text-color-dark};
+ --newtab-wordmark-color: #{$newtab-wordmark-darktheme-color};
+ --newtab-status-success: #{$status-dark-green};
+ }
+}
+
+@media (prefers-contrast) {
+ :root {
+ --newtab-text-secondary-color: var(--newtab-text-primary-color);
+ }
+}
diff --git a/browser/components/newtab/content-src/styles/_variables.scss b/browser/components/newtab/content-src/styles/_variables.scss
new file mode 100644
index 0000000000..321b1ff7b8
--- /dev/null
+++ b/browser/components/newtab/content-src/styles/_variables.scss
@@ -0,0 +1,217 @@
+@use 'sass:math';
+
+$primary-blue: rgb(0, 97, 224);
+$primary-green: rgb(0, 128, 120);
+$primary-blue-dark: rgb(0, 221, 255);
+$primary-text-color-dark: rgb(43, 42, 51);
+
+// -------------------------------------------------------------------------- //
+// Photon colors from http://design.firefox.com/photon/visuals/color.html
+
+$blue-40: #45A1FF;
+$blue-50: #0A84FF;
+$grey-30: #D7D7DB;
+$grey-60: #4A4A4F;
+$grey-90: #0C0C0D;
+$red-60: #D70022;
+$yellow-50: #FFE900;
+
+$grey-90-10: rgba($grey-90, 0.1);
+$grey-90-20: rgba($grey-90, 0.2);
+
+$blue-40-40: rgba($blue-40, 0.4);
+$blue-50-30: rgba($blue-50, 0.3);
+
+$black: #000;
+$black-10: rgba($black, 0.1);
+$black-15: rgba($black, 0.15);
+$black-20: rgba($black, 0.2);
+$black-30: rgba($black, 0.3);
+$black-40: rgba($black, 0.4);
+
+// -------------------------------------------------------------------------- //
+// Other colors
+
+$white: #FFF;
+$status-green: #058B00;
+$status-dark-green: #7C6;
+$bookmark-icon-fill: #0A84FF;
+$download-icon-fill: #12BC00;
+$pocket-icon-fill: #EF4056;
+$email-input-invalid: rgba($red-60, 0.3);
+
+$newtab-wordmark-default-color: #20123A;
+$newtab-wordmark-darktheme-color: rgb(251, 251, 254);
+
+$in-content-page-color: rgb(21, 20, 26);
+$in-content-page-color-dark: rgb(251, 251, 254);
+
+// -------------------------------------------------------------------------- //
+// These colors should match the colors in the default themes
+// (toolkit/mozapps/extensions/...). Note that they could get replaced by other
+// themes. The color set in --tabpanel-background-color (tabs.inc.css) should
+// match these colors here to avoid flashing.
+
+$in-content-page-background: #F9F9FB;
+$in-content-page-background-dark: #2B2A33;
+
+$newtab-background-secondary: #FFF;
+$newtab-background-secondary-dark: rgb(66, 65, 77);
+
+// Photon transitions from http://design.firefox.com/photon/motion/duration-and-easing.html
+$photon-easing: cubic-bezier(0.07, 0.95, 0, 1);
+
+$border-radius: 3px;
+$border-radius-new: 8px;
+
+// Grid related styles
+$base-gutter: 32px;
+$section-horizontal-padding: 25px;
+$section-vertical-padding: 10px;
+$section-spacing: 40px - $section-vertical-padding * 2;
+$grid-unit: 96px; // 1 top site
+// New Tab Experience grid unit needs to be smaller, but for now we are changing
+// this UI with a pref, so requires duplication.
+$grid-unit-small: 80px; // 1 top site
+
+$icon-size: 16px;
+$smaller-icon-size: 12px;
+$larger-icon-size: 32px;
+
+$searchbar-width-small: ($grid-unit * 2 + $base-gutter * 1) - 24px;
+$searchbar-width-medium: ($grid-unit * 4 + $base-gutter * 3) - 120px;
+$searchbar-width-large: ($grid-unit * 6 + $base-gutter * 5) - 136px;
+$searchbar-width-largest: ($grid-unit * 6 + $base-gutter * 5) - 16px;
+
+$wrapper-default-width: $grid-unit * 2 + $base-gutter * 1 + $section-horizontal-padding * 2; // 2 top sites
+$wrapper-max-width-medium: $grid-unit * 4 + $base-gutter * 3 + $section-horizontal-padding * 2; // 4 top sites
+$wrapper-max-width-large: $grid-unit * 6 + $base-gutter * 5 + $section-horizontal-padding * 2; // 6 top sites
+$wrapper-max-width-widest: $grid-unit * 8 + $base-gutter * 7 + $section-horizontal-padding * 2; // 8 top sites
+// For the breakpoints, we need to add space for the scrollbar to avoid weird
+// layout issues when the scrollbar is visible. 16px is wide enough to cover all
+// OSes and keeps it simpler than a per-OS value.
+$scrollbar-width: 16px;
+
+// Breakpoints
+// If updating these breakpoints, don't forget to update uses of DSImage, which
+// might choose the right image src to use depending on the viewport size.
+$break-point-medium: $wrapper-max-width-medium + $base-gutter * 2 + $scrollbar-width; // 610px
+$break-point-large: $wrapper-max-width-large + $base-gutter * 2 + $scrollbar-width; // 866px
+$break-point-widest: $wrapper-max-width-widest + $base-gutter * 2 + $scrollbar-width; // 1122px
+
+$section-title-font-size: 17px;
+
+$card-width: $grid-unit-small * 2 + $base-gutter;
+
+$card-height: 266px;
+$card-preview-image-height: 122px;
+$card-title-margin: 2px;
+$card-text-line-height: 19px;
+
+// Larger cards for wider screens:
+$card-width-large: 309px;
+$card-height-large: 370px;
+$card-preview-image-height-large: 155px;
+
+// Compact cards for Highlights
+$card-height-compact: 160px;
+$card-preview-image-height-compact: 108px;
+
+$topic-margin-top: 12px;
+
+$context-menu-button-size: 27px;
+$context-menu-button-boxshadow: 0 2px $grey-90-10;
+$context-menu-shadow: 0 5px 10px $black-30, 0 0 0 1px $black-20;
+$context-menu-font-size: 14px;
+$context-menu-border-radius: 5px;
+$context-menu-outer-padding: 5px;
+$context-menu-item-padding: 3px 12px;
+
+$error-fallback-font-size: 12px;
+$error-fallback-line-height: 1.5;
+
+$image-path: 'chrome://activity-stream/content/data/content/assets/';
+
+$snippets-container-height: 120px;
+
+$textbox-shadow-size: 4px;
+
+$customize-menu-slide-bezier: cubic-bezier(0.46, 0.03, 0.52, 0.96);
+$customize-menu-expand-bezier: cubic-bezier(0.82, 0.085, 0.395, 0.895);
+$customize-menu-border-tint: 1px solid rgba(0, 0, 0, 15%);
+
+@mixin fade-in {
+ box-shadow: inset $inner-box-shadow, $shadow-primary;
+ transition: box-shadow 150ms;
+}
+
+@mixin fade-in-card {
+ box-shadow: $shadow-primary;
+ transition: box-shadow 150ms;
+}
+
+@mixin ds-focus {
+ border: 0;
+ outline: 0;
+ box-shadow: 0 0 0 3px var(--newtab-primary-action-background-dimmed), 0 0 0 1px var(--newtab-primary-action-background);
+}
+
+@mixin context-menu-button {
+ .context-menu-button {
+ background-clip: padding-box;
+ background-color: var(--newtab-background-color-secondary);
+ background-image: url('chrome://global/skin/icons/more.svg');
+ background-position: 55%;
+ border: $border-primary;
+ border-radius: 100%;
+ box-shadow: $context-menu-button-boxshadow;
+ cursor: pointer;
+ fill: var(--newtab-text-primary-color);
+ height: $context-menu-button-size;
+ inset-inline-end: math.div(-$context-menu-button-size, 2);
+ opacity: 0;
+ position: absolute;
+ top: math.div(-$context-menu-button-size, 2);
+ transform: scale(0.25);
+ transition-duration: 150ms;
+ transition-property: transform, opacity;
+ width: $context-menu-button-size;
+
+ &:is(:active, :focus) {
+ opacity: 1;
+ transform: scale(1);
+ }
+ }
+}
+
+@mixin context-menu-button-hover {
+ .context-menu-button {
+ opacity: 1;
+ transform: scale(1);
+ transition-delay: 333ms;
+ }
+}
+
+@mixin context-menu-open-middle {
+ .context-menu {
+ margin-inline-end: auto;
+ margin-inline-start: auto;
+ inset-inline-end: auto;
+ inset-inline-start: -$base-gutter;
+ }
+}
+
+@mixin context-menu-open-left {
+ .context-menu {
+ margin-inline-end: 5px;
+ margin-inline-start: auto;
+ inset-inline-end: 0;
+ inset-inline-start: auto;
+ }
+}
+
+@mixin flip-icon {
+ &:dir(rtl) {
+ transform: scaleX(-1);
+ }
+}
diff --git a/browser/components/newtab/content-src/styles/activity-stream-linux.scss b/browser/components/newtab/content-src/styles/activity-stream-linux.scss
new file mode 100644
index 0000000000..89128d9d04
--- /dev/null
+++ b/browser/components/newtab/content-src/styles/activity-stream-linux.scss
@@ -0,0 +1,11 @@
+/* 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/. */
+
+/* This is the linux variant */
+
+$os-infopanel-arrow-height: 10px;
+$os-infopanel-arrow-offset-end: 6px;
+$os-infopanel-arrow-width: 20px;
+
+@import './activity-stream';
diff --git a/browser/components/newtab/content-src/styles/activity-stream-mac.scss b/browser/components/newtab/content-src/styles/activity-stream-mac.scss
new file mode 100644
index 0000000000..d95665f36f
--- /dev/null
+++ b/browser/components/newtab/content-src/styles/activity-stream-mac.scss
@@ -0,0 +1,16 @@
+/* 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/. */
+
+/* This is the mac variant */
+
+$os-infopanel-arrow-height: 10px;
+$os-infopanel-arrow-offset-end: 7px;
+$os-infopanel-arrow-width: 18px;
+
+[lwt-newtab-brighttext] {
+ -moz-osx-font-smoothing: grayscale;
+}
+
+// stylelint-disable-next-line no-invalid-position-at-import-rule
+@import './activity-stream';
diff --git a/browser/components/newtab/content-src/styles/activity-stream-windows.scss b/browser/components/newtab/content-src/styles/activity-stream-windows.scss
new file mode 100644
index 0000000000..9252bdd0f6
--- /dev/null
+++ b/browser/components/newtab/content-src/styles/activity-stream-windows.scss
@@ -0,0 +1,11 @@
+/* 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/. */
+
+/* This is the windows variant */
+
+$os-infopanel-arrow-height: 10px;
+$os-infopanel-arrow-offset-end: 6px;
+$os-infopanel-arrow-width: 20px;
+
+@import './activity-stream';