tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit f71aa40659e07cafa692ab77ac81a1e6edbfbeb0
parent f65b5bd1491fe89e625bf8a01fde0413cc9ef440
Author: Maxx Crawford <mcrawford@mozilla.com>
Date:   Wed, 19 Nov 2025 16:22:32 +0000

Bug 1996308 - Add container element around Widgets section r=home-newtab-reviewers,reemhamz

Differential Revision: https://phabricator.services.mozilla.com/D270924

Diffstat:
Mbrowser/extensions/newtab/content-src/components/Base/_Base.scss | 3++-
Mbrowser/extensions/newtab/content-src/components/DiscoveryStreamComponents/TrendingSearches/_TrendingSearches.scss | 2+-
Mbrowser/extensions/newtab/content-src/components/Widgets/FocusTimer/_FocusTimer.scss | 8+++++++-
Mbrowser/extensions/newtab/content-src/components/Widgets/Lists/_Lists.scss | 8+++++++-
Mbrowser/extensions/newtab/content-src/components/Widgets/Widgets.jsx | 29++++++++++++++++-------------
Mbrowser/extensions/newtab/content-src/components/Widgets/_Widgets.scss | 83+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------
Mbrowser/extensions/newtab/content-src/styles/_variables.scss | 1+
Mbrowser/extensions/newtab/css/activity-stream.css | 80++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------
Mbrowser/extensions/newtab/data/content/activity-stream.bundle.js | 6+++++-
9 files changed, 169 insertions(+), 51 deletions(-)

diff --git a/browser/extensions/newtab/content-src/components/Base/_Base.scss b/browser/extensions/newtab/content-src/components/Base/_Base.scss @@ -76,7 +76,8 @@ main { padding-block-end: 0; .ds-card { - width: 296px; + // Note: This differs when the Sections layout is enabled + width: var(--newtab-card-grid-layout-width); } .ds-card-grid:not(.ds-section-grid) { diff --git a/browser/extensions/newtab/content-src/components/DiscoveryStreamComponents/TrendingSearches/_TrendingSearches.scss b/browser/extensions/newtab/content-src/components/DiscoveryStreamComponents/TrendingSearches/_TrendingSearches.scss @@ -106,7 +106,7 @@ .trending-searches-list-view { .ds-column-grid & { // Match width of other items in grid layout - width: 296px; + width: var(--newtab-card-grid-layout-width); } .ds-section-grid & { diff --git a/browser/extensions/newtab/content-src/components/Widgets/FocusTimer/_FocusTimer.scss b/browser/extensions/newtab/content-src/components/Widgets/FocusTimer/_FocusTimer.scss @@ -6,7 +6,13 @@ @include newtab-card-style; grid-column: span 1; - width: var(--newtab-card-width-medium); + width: var(--newtab-card-grid-layout-width); + + // Match the new card width if sections are enabled + .has-sections-grid & { + width: var(--newtab-card-width-medium); + } + border-radius: var(--border-radius-large); padding-block: var(--space-medium); height: var(--newtab-card-height); diff --git a/browser/extensions/newtab/content-src/components/Widgets/Lists/_Lists.scss b/browser/extensions/newtab/content-src/components/Widgets/Lists/_Lists.scss @@ -6,7 +6,13 @@ @include newtab-card-style; grid-column: span 1; - width: var(--newtab-card-width-medium); + width: var(--newtab-card-grid-layout-width); + + // Match the new card width if sections are enabled + .has-sections-grid & { + width: var(--newtab-card-width-medium); + } + border-radius: var(--border-radius-large); padding-block-start: var(--space-medium); height: var(--newtab-card-height); diff --git a/browser/extensions/newtab/content-src/components/Widgets/Widgets.jsx b/browser/extensions/newtab/content-src/components/Widgets/Widgets.jsx @@ -105,19 +105,22 @@ function Widgets() { return ( <div className="widgets-wrapper"> - <div className="widgets-container"> - {listsEnabled && ( - <Lists - dispatch={dispatch} - handleUserInteraction={handleUserInteraction} - /> - )} - {timerEnabled && ( - <FocusTimer - dispatch={dispatch} - handleUserInteraction={handleUserInteraction} - /> - )} + <div className="widgets-section-container"> + <h1 data-l10n-id="newtab-widget-section-title"></h1> + <div className="widgets-container"> + {listsEnabled && ( + <Lists + dispatch={dispatch} + handleUserInteraction={handleUserInteraction} + /> + )} + {timerEnabled && ( + <FocusTimer + dispatch={dispatch} + handleUserInteraction={handleUserInteraction} + /> + )} + </div> </div> {messageData?.content?.messageType === "WidgetMessage" && ( <MessageWrapper dispatch={dispatch}> diff --git a/browser/extensions/newtab/content-src/components/Widgets/_Widgets.scss b/browser/extensions/newtab/content-src/components/Widgets/_Widgets.scss @@ -7,35 +7,86 @@ } .widgets-wrapper { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - position: relative; + margin-inline: auto; padding-block-end: var(--space-large); + max-width: max-content; } +.widgets-section-container { + padding-block: var(--space-xsmall) var(--space-large); + padding-inline: var(--space-large); + background-color: var(--button-background-color); + border-radius: var(--border-radius-large); + + // Bug 1908010 - This overwrites the design system color because of a + // known transparency issue with color-mix syntax when a wallpaper is set + .lightWallpaper &, + .darkWallpaper & { + background-color: var(--newtab-weather-background-color); // stylelint-disable-line stylelint-plugin-mozilla/use-background-color-tokens + + @media (prefers-contrast) { + background-color: var(--background-color-box); + } + } + + // Mirrors the grid-gap spacing used on + // .ds-outer-wrapper-breakpoint-override .ds-card-grid + @media(min-width: $break-point-widest) { + padding-block-end: var(--space-xlarge); + padding-inline: var(--space-xlarge); + } + + // Sections Layout Override + .has-sections-grid & { + @media(min-width: $break-point-widest) { + padding-block-end: var(--space-large); + padding-inline: var(--space-large); + } + } + + h1 { + font-size: var(--font-size-large); + font-weight: var(--font-weight-bold); + } +} + +// Bug 1996308: This layout is somewhat brittle as the design dictates the parent container (.widgets-wrapper) +// be only as wide as the width of this container (.widgets-container) while still being responsive. +// Once we have four widgets, we can revert most of this logic as the container will be 100%. .widgets-container { + --widgets-card-width: var(--newtab-card-grid-layout-width); + // This is the maximum number of widgets the Widgets row can support + --widgets-max-cols: 2; + --widgets-grid-gap: var(--space-large); + + // Update the card width when Sections is enabled + .has-sections-grid & { + --widgets-card-width: var(--newtab-card-width-medium); + } + &:has(.lists), &:has(.focus-timer) { display: grid; - align-items: flex-start; - grid-template-columns: repeat(auto-fit, minmax(300px, 300px)); - gap: var(--space-large); - justify-content: center; - width: 100%; + grid-template-columns: repeat(auto-fit, var(--widgets-card-width)); + gap: var(--widgets-grid-gap); + + // The max-width logic is only necessary when displaying more than one column + @media(min-width: $break-point-medium) { + max-width: calc(var(--widgets-max-cols) * var(--widgets-card-width) + (var(--widgets-max-cols) - 1) * var(--widgets-grid-gap)); + justify-content: center; + } // Mirrors the grid-gap spacing used on // .ds-outer-wrapper-breakpoint-override .ds-card-grid @media(min-width: $break-point-widest) { - gap: var(--space-xlarge); + --widgets-grid-gap: var(--space-xlarge); } - } - // Sections Layout Override - .has-sections-grid & { - @media(min-width: $break-point-widest) { - gap: var(--space-large); + // Sections Layout Override + .has-sections-grid & { + @media(min-width: $break-point-widest) { + --widgets-grid-gap: var(--space-large); + } } } } diff --git a/browser/extensions/newtab/content-src/styles/_variables.scss b/browser/extensions/newtab/content-src/styles/_variables.scss @@ -4,6 +4,7 @@ :root { --newtab-card-height: 282px; --newtab-card-width-medium: 300px; + --newtab-card-grid-layout-width: 296px; // Matches widget used in Base.jsx } $primary-blue: var(--color-accent-primary); diff --git a/browser/extensions/newtab/css/activity-stream.css b/browser/extensions/newtab/css/activity-stream.css @@ -31,6 +31,7 @@ input { :root { --newtab-card-height: 282px; --newtab-card-width-medium: 300px; + --newtab-card-grid-layout-width: 296px; } :root { @@ -516,7 +517,7 @@ main section { padding-block-end: 0; } .ds-outer-wrapper-breakpoint-override main .ds-card { - width: 296px; + width: var(--newtab-card-grid-layout-width); } .ds-outer-wrapper-breakpoint-override main .ds-card-grid:not(.ds-section-grid) { grid-gap: var(--space-large); @@ -4366,30 +4367,69 @@ dialog:dir(rtl)::after { } .widgets-wrapper { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - position: relative; + margin-inline: auto; padding-block-end: var(--space-large); + max-width: max-content; } +.widgets-section-container { + padding-block: var(--space-xsmall) var(--space-large); + padding-inline: var(--space-large); + background-color: var(--button-background-color); + border-radius: var(--border-radius-large); +} +.lightWallpaper .widgets-section-container, .darkWallpaper .widgets-section-container { + background-color: var(--newtab-weather-background-color); +} +@media (prefers-contrast) { + .lightWallpaper .widgets-section-container, .darkWallpaper .widgets-section-container { + background-color: var(--background-color-box); + } +} +@media (min-width: 1122px) { + .widgets-section-container { + padding-block-end: var(--space-xlarge); + padding-inline: var(--space-xlarge); + } +} +@media (min-width: 1122px) { + .has-sections-grid .widgets-section-container { + padding-block-end: var(--space-large); + padding-inline: var(--space-large); + } +} +.widgets-section-container h1 { + font-size: var(--font-size-large); + font-weight: var(--font-weight-bold); +} + +.widgets-container { + --widgets-card-width: var(--newtab-card-grid-layout-width); + --widgets-max-cols: 2; + --widgets-grid-gap: var(--space-large); +} +.has-sections-grid .widgets-container { + --widgets-card-width: var(--newtab-card-width-medium); +} .widgets-container:has(.lists), .widgets-container:has(.focus-timer) { display: grid; - align-items: flex-start; - grid-template-columns: repeat(auto-fit, minmax(300px, 300px)); - gap: var(--space-large); - justify-content: center; - width: 100%; + grid-template-columns: repeat(auto-fit, var(--widgets-card-width)); + gap: var(--widgets-grid-gap); +} +@media (min-width: 610px) { + .widgets-container:has(.lists), .widgets-container:has(.focus-timer) { + max-width: calc(var(--widgets-max-cols) * var(--widgets-card-width) + (var(--widgets-max-cols) - 1) * var(--widgets-grid-gap)); + justify-content: center; + } } @media (min-width: 1122px) { .widgets-container:has(.lists), .widgets-container:has(.focus-timer) { - gap: var(--space-xlarge); + --widgets-grid-gap: var(--space-xlarge); } } @media (min-width: 1122px) { - .has-sections-grid .widgets-container { - gap: var(--space-large); + .has-sections-grid .widgets-container:has(.lists), .has-sections-grid .widgets-container:has(.focus-timer) { + --widgets-grid-gap: var(--space-large); } } @@ -4429,7 +4469,7 @@ dialog:dir(rtl)::after { background: var(--newtab-background-card); transition: opacity 0.2s ease; grid-column: span 1; - width: var(--newtab-card-width-medium); + width: var(--newtab-card-grid-layout-width); border-radius: var(--border-radius-large); padding-block-start: var(--space-medium); height: var(--newtab-card-height); @@ -4441,6 +4481,9 @@ dialog:dir(rtl)::after { .lists:hover { background: var(--newtab-background-color-secondary); } +.has-sections-grid .lists { + width: var(--newtab-card-width-medium); +} .lists .confetti-canvas { position: absolute; top: 0; @@ -4649,7 +4692,7 @@ dialog:dir(rtl)::after { background: var(--newtab-background-card); transition: opacity 0.2s ease; grid-column: span 1; - width: var(--newtab-card-width-medium); + width: var(--newtab-card-grid-layout-width); border-radius: var(--border-radius-large); padding-block: var(--space-medium); height: var(--newtab-card-height); @@ -4661,6 +4704,9 @@ dialog:dir(rtl)::after { .focus-timer:hover { background: var(--newtab-background-color-secondary); } +.has-sections-grid .focus-timer { + width: var(--newtab-card-width-medium); +} .focus-timer-tabs { display: flex; @@ -9238,7 +9284,7 @@ dialog:dir(rtl)::after { } .ds-column-grid .trending-searches-list-view { - width: 296px; + width: var(--newtab-card-grid-layout-width); } .ds-section-grid .trending-searches-list-view { order: 1; diff --git a/browser/extensions/newtab/data/content/activity-stream.bundle.js b/browser/extensions/newtab/data/content/activity-stream.bundle.js @@ -13609,6 +13609,10 @@ function Widgets() { return /*#__PURE__*/external_React_default().createElement("div", { className: "widgets-wrapper" }, /*#__PURE__*/external_React_default().createElement("div", { + className: "widgets-section-container" + }, /*#__PURE__*/external_React_default().createElement("h1", { + "data-l10n-id": "newtab-widget-section-title" + }), /*#__PURE__*/external_React_default().createElement("div", { className: "widgets-container" }, listsEnabled && /*#__PURE__*/external_React_default().createElement(Lists, { dispatch: dispatch, @@ -13616,7 +13620,7 @@ function Widgets() { }), timerEnabled && /*#__PURE__*/external_React_default().createElement(FocusTimer, { dispatch: dispatch, handleUserInteraction: handleUserInteraction - })), messageData?.content?.messageType === "WidgetMessage" && /*#__PURE__*/external_React_default().createElement(MessageWrapper, { + }))), messageData?.content?.messageType === "WidgetMessage" && /*#__PURE__*/external_React_default().createElement(MessageWrapper, { dispatch: dispatch }, /*#__PURE__*/external_React_default().createElement(WidgetsFeatureHighlight, { dispatch: dispatch