commit 01216edab9dc9a676f232bb7a74270ee3e356e33 parent 02272ef7d215c4352f4080cb6ce1bb98ceae577e Author: Atila Butkovits <abutkovits@mozilla.com> Date: Tue, 18 Nov 2025 21:32:01 +0200 Revert "Bug 1996310, Bug 1997673, Bug 1996309, Bug 1996308, Bug 1996691 - Add maximize all widgets logic button to widget container r=home-newtab-reviewers,ini" This reverts commit 1614dd7ebbd368f0ad9563268c15cbb89bd9fe8e. Revert "Bug 1997673 - Add maximize/minimize icons for new tab r=home-newtab-reviewers,desktop-theme-reviewers,reemhamz" This reverts commit a33c0e85699e439db041ed10d49309ac7beab990. Revert "Bug 1996309 - Add button to Widget container to turn off all widgets r=home-newtab-reviewers,reemhamz" This reverts commit ea57fcfbf3664ddfafefdd44359121ce6fec5d49. Revert "Bug 1996308 - Add container element around Widgets section r=home-newtab-reviewers,reemhamz" This reverts commit 7549bb9105c06c9d9910f306f4f59e3765131b51. Revert "Bug 1996691 - Add strings for new Widgets container r=home-newtab-reviewers,fluent-reviewers,bolsson,reemhamz" This reverts commit a808fef82504c803c4b7271ba2bb7aab84ebfdbf. Diffstat:
17 files changed, 61 insertions(+), 731 deletions(-)
diff --git a/browser/extensions/newtab/content-src/components/Base/_Base.scss b/browser/extensions/newtab/content-src/components/Base/_Base.scss @@ -76,8 +76,7 @@ main { padding-block-end: 0; .ds-card { - // Note: This differs when the Sections layout is enabled - width: var(--newtab-card-grid-layout-width); + width: 296px; } .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: var(--newtab-card-grid-layout-width); + width: 296px; } .ds-section-grid & { diff --git a/browser/extensions/newtab/content-src/components/Widgets/FocusTimer/FocusTimer.jsx b/browser/extensions/newtab/content-src/components/Widgets/FocusTimer/FocusTimer.jsx @@ -104,11 +104,7 @@ export const getClipPath = progress => { return `polygon(${points.join(", ")})`; }; -export const FocusTimer = ({ - dispatch, - handleUserInteraction, - isMaximized, -}) => { +export const FocusTimer = ({ dispatch, handleUserInteraction }) => { const [timeLeft, setTimeLeft] = useState(0); // calculated value for the progress circle; 1 = 100% const [progress, setProgress] = useState(0); @@ -534,7 +530,7 @@ export const FocusTimer = ({ return timerData ? ( <article - className={`focus-timer ${isMaximized ? "is-maximized" : ""}`} + className="focus-timer" ref={el => { timerRef.current = [el]; }} 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,13 +6,7 @@ @include newtab-card-style; grid-column: span 1; - 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); - } - + 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.jsx b/browser/extensions/newtab/content-src/components/Widgets/Lists/Lists.jsx @@ -34,7 +34,7 @@ const PREF_WIDGETS_LISTS_MAX_LISTITEMS = "widgets.lists.maxListItems"; const PREF_WIDGETS_LISTS_BADGE_ENABLED = "widgets.lists.badge.enabled"; const PREF_WIDGETS_LISTS_BADGE_LABEL = "widgets.lists.badge.label"; -function Lists({ dispatch, handleUserInteraction, isMaximized }) { +function Lists({ dispatch, handleUserInteraction }) { const prefs = useSelector(state => state.Prefs.values); const { selected, lists } = useSelector(state => state.ListsWidget); const [newTask, setNewTask] = useState(""); @@ -591,7 +591,7 @@ function Lists({ dispatch, handleUserInteraction, isMaximized }) { return ( <article - className={`lists ${isMaximized ? "is-maximized" : ""}`} + className="lists" ref={el => { listsRef.current = [el]; }} 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,13 +6,7 @@ @include newtab-card-style; grid-column: span 1; - 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); - } - + 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 @@ -3,7 +3,7 @@ * You can obtain one at http://mozilla.org/MPL/2.0/. */ import React, { useEffect, useRef } from "react"; -import { useDispatch, useSelector, batch } from "react-redux"; +import { useDispatch, useSelector } from "react-redux"; import { Lists } from "./Lists/Lists"; import { FocusTimer } from "./FocusTimer/FocusTimer"; import { MessageWrapper } from "content-src/components/MessageWrapper/MessageWrapper"; @@ -14,8 +14,6 @@ const PREF_WIDGETS_LISTS_ENABLED = "widgets.lists.enabled"; const PREF_WIDGETS_SYSTEM_LISTS_ENABLED = "widgets.system.lists.enabled"; const PREF_WIDGETS_TIMER_ENABLED = "widgets.focusTimer.enabled"; const PREF_WIDGETS_SYSTEM_TIMER_ENABLED = "widgets.system.focusTimer.enabled"; -const PREF_WIDGETS_MAXIMIZED = "widgets.maximized"; -const PREF_WIDGETS_SYSTEM_MAXIMIZED = "widgets.system.maximized"; // resets timer to default values (exported for testing) // In practice, this logic runs inside a useEffect when @@ -54,7 +52,6 @@ function Widgets() { const { messageData } = useSelector(state => state.Messages); const timerType = useSelector(state => state.TimerWidget.timerType); const timerData = useSelector(state => state.TimerWidget); - const isMaximized = prefs[PREF_WIDGETS_MAXIMIZED]; const dispatch = useDispatch(); const nimbusListsEnabled = prefs.widgetsConfig?.listsEnabled; @@ -93,38 +90,6 @@ function Widgets() { prevTimerEnabledRef.current = isTimerEnabled; }, [timerEnabled, timerData, dispatch, timerType]); - // Sends a dispatch to disable all widgets - function handleHideAllWidgetsClick(e) { - e.preventDefault(); - batch(() => { - dispatch(ac.SetPref(PREF_WIDGETS_LISTS_ENABLED, false)); - dispatch(ac.SetPref(PREF_WIDGETS_TIMER_ENABLED, false)); - }); - } - - function handleHideAllWidgetsKeyDown(e) { - if (e.key === "Enter" || e.key === " ") { - e.preventDefault(); - batch(() => { - dispatch(ac.SetPref(PREF_WIDGETS_LISTS_ENABLED, false)); - dispatch(ac.SetPref(PREF_WIDGETS_TIMER_ENABLED, false)); - }); - } - } - - // Toggles the maximized state of widgets - function handleToggleMaximizeClick(e) { - e.preventDefault(); - dispatch(ac.SetPref(PREF_WIDGETS_MAXIMIZED, !isMaximized)); - } - - function handleToggleMaximizeKeyDown(e) { - if (e.key === "Enter" || e.key === " ") { - e.preventDefault(); - dispatch(ac.SetPref(PREF_WIDGETS_MAXIMIZED, !isMaximized)); - } - } - function handleUserInteraction(widgetName) { const prefName = `widgets.${widgetName}.interaction`; const hasInteracted = prefs[prefName]; @@ -140,53 +105,19 @@ function Widgets() { return ( <div className="widgets-wrapper"> - <div className="widgets-section-container"> - <div className="widgets-title-container"> - <h1 data-l10n-id="newtab-widget-section-title"></h1> - {prefs[PREF_WIDGETS_SYSTEM_MAXIMIZED] && ( - <moz-button - id="toggle-widgets-size-button" - type="icon ghost" - size="small" - // Toggle the icon and hover text - data-l10n-id={ - isMaximized - ? "newtab-widget-section-maximize" - : "newtab-widget-section-minimize" - } - iconsrc={`chrome://global/skin/icons/${isMaximized ? "fullscreen" : "fullscreen-exit"}.svg`} - onClick={handleToggleMaximizeClick} - onKeyDown={handleToggleMaximizeKeyDown} - /> - )} - <moz-button - id="hide-all-widgets-button" - type="icon ghost" - size="small" - data-l10n-id="newtab-widget-section-hide-all-button" - iconsrc="chrome://global/skin/icons/close.svg" - onClick={handleHideAllWidgetsClick} - onKeyDown={handleHideAllWidgetsKeyDown} + <div className="widgets-container"> + {listsEnabled && ( + <Lists + dispatch={dispatch} + handleUserInteraction={handleUserInteraction} + /> + )} + {timerEnabled && ( + <FocusTimer + dispatch={dispatch} + handleUserInteraction={handleUserInteraction} /> - </div> - <div - className={`widgets-container ${isMaximized ? "is-maximized" : ""}`} - > - {listsEnabled && ( - <Lists - dispatch={dispatch} - handleUserInteraction={handleUserInteraction} - isMaximized={isMaximized} - /> - )} - {timerEnabled && ( - <FocusTimer - dispatch={dispatch} - handleUserInteraction={handleUserInteraction} - isMaximized={isMaximized} - /> - )} - </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,96 +7,35 @@ } .widgets-wrapper { - margin-inline: auto; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + position: relative; 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); - } - } - - .widgets-title-container { - display: flex; - justify-content: flex-end; - align-items: center; - gap: var(--space-medium); - - h1 { - margin-inline-end: auto; - } - } - - // 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; - 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; - } + align-items: flex-start; + grid-template-columns: repeat(auto-fit, minmax(300px, 300px)); + gap: var(--space-large); + justify-content: center; + width: 100%; // Mirrors the grid-gap spacing used on // .ds-outer-wrapper-breakpoint-override .ds-card-grid @media(min-width: $break-point-widest) { - --widgets-grid-gap: var(--space-xlarge); + gap: var(--space-xlarge); } + } - // Sections Layout Override - .has-sections-grid & { - @media(min-width: $break-point-widest) { - --widgets-grid-gap: var(--space-large); - } + // Sections Layout Override + .has-sections-grid & { + @media(min-width: $break-point-widest) { + 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,7 +4,6 @@ :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,7 +31,6 @@ input { :root { --newtab-card-height: 282px; --newtab-card-width-medium: 300px; - --newtab-card-grid-layout-width: 296px; } :root { @@ -517,7 +516,7 @@ main section { padding-block-end: 0; } .ds-outer-wrapper-breakpoint-override main .ds-card { - width: var(--newtab-card-grid-layout-width); + width: 296px; } .ds-outer-wrapper-breakpoint-override main .ds-card-grid:not(.ds-section-grid) { grid-gap: var(--space-large); @@ -4367,78 +4366,30 @@ dialog:dir(rtl)::after { } .widgets-wrapper { - 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); - } -} -.widgets-section-container .widgets-title-container { display: flex; - justify-content: flex-end; + flex-direction: column; align-items: center; - gap: var(--space-medium); -} -.widgets-section-container .widgets-title-container h1 { - margin-inline-end: auto; -} -@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); + justify-content: center; + position: relative; + padding-block-end: var(--space-large); } -.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; - 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; - } + align-items: flex-start; + grid-template-columns: repeat(auto-fit, minmax(300px, 300px)); + gap: var(--space-large); + justify-content: center; + width: 100%; } @media (min-width: 1122px) { .widgets-container:has(.lists), .widgets-container:has(.focus-timer) { - --widgets-grid-gap: var(--space-xlarge); + gap: var(--space-xlarge); } } @media (min-width: 1122px) { - .has-sections-grid .widgets-container:has(.lists), .has-sections-grid .widgets-container:has(.focus-timer) { - --widgets-grid-gap: var(--space-large); + .has-sections-grid .widgets-container { + gap: var(--space-large); } } @@ -4478,7 +4429,7 @@ dialog:dir(rtl)::after { background: var(--newtab-background-card); transition: opacity 0.2s ease; grid-column: span 1; - width: var(--newtab-card-grid-layout-width); + width: var(--newtab-card-width-medium); border-radius: var(--border-radius-large); padding-block-start: var(--space-medium); height: var(--newtab-card-height); @@ -4490,9 +4441,6 @@ 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; @@ -4701,7 +4649,7 @@ dialog:dir(rtl)::after { background: var(--newtab-background-card); transition: opacity 0.2s ease; grid-column: span 1; - width: var(--newtab-card-grid-layout-width); + width: var(--newtab-card-width-medium); border-radius: var(--border-radius-large); padding-block: var(--space-medium); height: var(--newtab-card-height); @@ -4713,9 +4661,6 @@ 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; @@ -9293,7 +9238,7 @@ dialog:dir(rtl)::after { } .ds-column-grid .trending-searches-list-view { - width: var(--newtab-card-grid-layout-width); + width: 296px; } .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 @@ -12149,8 +12149,7 @@ const PREF_WIDGETS_LISTS_BADGE_ENABLED = "widgets.lists.badge.enabled"; const PREF_WIDGETS_LISTS_BADGE_LABEL = "widgets.lists.badge.label"; function Lists({ dispatch, - handleUserInteraction, - isMaximized + handleUserInteraction }) { const prefs = (0,external_ReactRedux_namespaceObject.useSelector)(state => state.Prefs.values); const { @@ -12615,7 +12614,7 @@ function Lists({ const badgeEnabled = (nimbusBadgeEnabled || nimbusBadgeTrainhopEnabled) ?? prefs[PREF_WIDGETS_LISTS_BADGE_ENABLED] ?? false; const badgeLabel = (nimbusBadgeLabel || nimbusBadgeTrainhopLabel) ?? prefs[PREF_WIDGETS_LISTS_BADGE_LABEL] ?? ""; return /*#__PURE__*/external_React_default().createElement("article", { - className: `lists ${isMaximized ? "is-maximized" : ""}`, + className: "lists", ref: el => { listsRef.current = [el]; } @@ -13016,8 +13015,7 @@ const getClipPath = progress => { }; const FocusTimer = ({ dispatch, - handleUserInteraction, - isMaximized + handleUserInteraction }) => { const [timeLeft, setTimeLeft] = (0,external_React_namespaceObject.useState)(0); // calculated value for the progress circle; 1 = 100% @@ -13367,7 +13365,7 @@ const FocusTimer = ({ handleTimerInteraction(); } return timerData ? /*#__PURE__*/external_React_default().createElement("article", { - className: `focus-timer ${isMaximized ? "is-maximized" : ""}`, + className: "focus-timer", ref: el => { timerRef.current = [el]; } @@ -13538,8 +13536,6 @@ const PREF_WIDGETS_LISTS_ENABLED = "widgets.lists.enabled"; const PREF_WIDGETS_SYSTEM_LISTS_ENABLED = "widgets.system.lists.enabled"; const PREF_WIDGETS_TIMER_ENABLED = "widgets.focusTimer.enabled"; const PREF_WIDGETS_SYSTEM_TIMER_ENABLED = "widgets.system.focusTimer.enabled"; -const PREF_WIDGETS_MAXIMIZED = "widgets.maximized"; -const PREF_WIDGETS_SYSTEM_MAXIMIZED = "widgets.system.maximized"; // resets timer to default values (exported for testing) // In practice, this logic runs inside a useEffect when @@ -13575,7 +13571,6 @@ function Widgets() { } = (0,external_ReactRedux_namespaceObject.useSelector)(state => state.Messages); const timerType = (0,external_ReactRedux_namespaceObject.useSelector)(state => state.TimerWidget.timerType); const timerData = (0,external_ReactRedux_namespaceObject.useSelector)(state => state.TimerWidget); - const isMaximized = prefs[PREF_WIDGETS_MAXIMIZED]; const dispatch = (0,external_ReactRedux_namespaceObject.useDispatch)(); const nimbusListsEnabled = prefs.widgetsConfig?.listsEnabled; const nimbusTimerEnabled = prefs.widgetsConfig?.timerEnabled; @@ -13600,36 +13595,6 @@ function Widgets() { // Update the ref to track current state prevTimerEnabledRef.current = isTimerEnabled; }, [timerEnabled, timerData, dispatch, timerType]); - - // Sends a dispatch to disable all widgets - function handleHideAllWidgetsClick(e) { - e.preventDefault(); - (0,external_ReactRedux_namespaceObject.batch)(() => { - dispatch(actionCreators.SetPref(PREF_WIDGETS_LISTS_ENABLED, false)); - dispatch(actionCreators.SetPref(PREF_WIDGETS_TIMER_ENABLED, false)); - }); - } - function handleHideAllWidgetsKeyDown(e) { - if (e.key === "Enter" || e.key === " ") { - e.preventDefault(); - (0,external_ReactRedux_namespaceObject.batch)(() => { - dispatch(actionCreators.SetPref(PREF_WIDGETS_LISTS_ENABLED, false)); - dispatch(actionCreators.SetPref(PREF_WIDGETS_TIMER_ENABLED, false)); - }); - } - } - - // Toggles the maximized state of widgets - function handleToggleMaximizeClick(e) { - e.preventDefault(); - dispatch(actionCreators.SetPref(PREF_WIDGETS_MAXIMIZED, !isMaximized)); - } - function handleToggleMaximizeKeyDown(e) { - if (e.key === "Enter" || e.key === " ") { - e.preventDefault(); - dispatch(actionCreators.SetPref(PREF_WIDGETS_MAXIMIZED, !isMaximized)); - } - } function handleUserInteraction(widgetName) { const prefName = `widgets.${widgetName}.interaction`; const hasInteracted = prefs[prefName]; @@ -13644,40 +13609,14 @@ 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("div", { - className: "widgets-title-container" - }, /*#__PURE__*/external_React_default().createElement("h1", { - "data-l10n-id": "newtab-widget-section-title" - }), prefs[PREF_WIDGETS_SYSTEM_MAXIMIZED] && /*#__PURE__*/external_React_default().createElement("moz-button", { - id: "toggle-widgets-size-button", - type: "icon ghost", - size: "small" - // Toggle the icon and hover text - , - "data-l10n-id": isMaximized ? "newtab-widget-section-maximize" : "newtab-widget-section-minimize", - iconsrc: `chrome://global/skin/icons/${isMaximized ? "fullscreen" : "fullscreen-exit"}.svg`, - onClick: handleToggleMaximizeClick, - onKeyDown: handleToggleMaximizeKeyDown - }), /*#__PURE__*/external_React_default().createElement("moz-button", { - id: "hide-all-widgets-button", - type: "icon ghost", - size: "small", - "data-l10n-id": "newtab-widget-section-hide-all-button", - iconsrc: "chrome://global/skin/icons/close.svg", - onClick: handleHideAllWidgetsClick, - onKeyDown: handleHideAllWidgetsKeyDown - })), /*#__PURE__*/external_React_default().createElement("div", { - className: `widgets-container ${isMaximized ? "is-maximized" : ""}` + className: "widgets-container" }, listsEnabled && /*#__PURE__*/external_React_default().createElement(Lists, { dispatch: dispatch, - handleUserInteraction: handleUserInteraction, - isMaximized: isMaximized + handleUserInteraction: handleUserInteraction }), timerEnabled && /*#__PURE__*/external_React_default().createElement(FocusTimer, { dispatch: dispatch, - handleUserInteraction: handleUserInteraction, - isMaximized: isMaximized - }))), messageData?.content?.messageType === "WidgetMessage" && /*#__PURE__*/external_React_default().createElement(MessageWrapper, { + handleUserInteraction: handleUserInteraction + })), messageData?.content?.messageType === "WidgetMessage" && /*#__PURE__*/external_React_default().createElement(MessageWrapper, { dispatch: dispatch }, /*#__PURE__*/external_React_default().createElement(WidgetsFeatureHighlight, { dispatch: dispatch diff --git a/browser/extensions/newtab/lib/ActivityStream.sys.mjs b/browser/extensions/newtab/lib/ActivityStream.sys.mjs @@ -1053,20 +1053,6 @@ export const PREFS_CONFIG = new Map([ }, ], [ - "widgets.maximized", - { - title: "Toggles maximized state for all widgets in the widgets section", - value: false, - }, - ], - [ - "widgets.system.maximized", - { - title: "Enables the maximize widget feature experiment in Nimbus", - value: false, - }, - ], - [ "widgets.focusTimer.enabled", { title: "Enables the focus timer widget", diff --git a/browser/extensions/newtab/test/unit/content-src/components/Widgets.test.jsx b/browser/extensions/newtab/test/unit/content-src/components/Widgets.test.jsx @@ -132,370 +132,4 @@ describe("<Widgets>", () => { assert.equal(resetCall.args[0].data.timerType, "break"); }); }); - - describe("handleHideAllWidgets", () => { - let wrapper; - let state; - let store; - - beforeEach(() => { - state = { - ...INITIAL_STATE, - Prefs: { - ...INITIAL_STATE.Prefs, - values: { - ...INITIAL_STATE.Prefs.values, - [PREF_WIDGETS_LISTS_ENABLED]: true, - [PREF_WIDGETS_SYSTEM_LISTS_ENABLED]: true, - [PREF_WIDGETS_TIMER_ENABLED]: true, - [PREF_WIDGETS_SYSTEM_TIMER_ENABLED]: true, - }, - }, - }; - store = createStore(combineReducers(reducers), state); - sinon.spy(store, "dispatch"); - wrapper = mount( - <Provider store={store}> - <Widgets /> - </Provider> - ); - }); - - afterEach(() => { - store.dispatch.restore(); - }); - - it("should dispatch SetPref actions when hide button is clicked", () => { - const hideButton = wrapper.find("#hide-all-widgets-button"); - assert.ok(hideButton.exists(), "hide all button should exist"); - - // Get the onClick handler and call it - const onClickHandler = hideButton.prop("onClick"); - assert.ok(onClickHandler, "onClick handler should exist"); - onClickHandler({ preventDefault: () => {} }); - - const allCalls = store.dispatch.getCalls(); - const setPrefCalls = allCalls.filter( - call => call.args[0]?.type === at.SET_PREF - ); - - assert.equal( - setPrefCalls.length, - 2, - `should dispatch two SetPref actions, got ${setPrefCalls.length}.` - ); - - const listsPrefCall = setPrefCalls.find( - call => call.args[0].data?.name === PREF_WIDGETS_LISTS_ENABLED - ); - const timerPrefCall = setPrefCalls.find( - call => call.args[0].data?.name === PREF_WIDGETS_TIMER_ENABLED - ); - - assert.ok(listsPrefCall, "should dispatch SetPref for lists"); - assert.equal( - listsPrefCall.args[0].data.value, - false, - "should set lists pref to false" - ); - - assert.ok(timerPrefCall, "should dispatch SetPref for timer"); - assert.equal( - timerPrefCall.args[0].data.value, - false, - "should set timer pref to false" - ); - }); - - it("should dispatch SetPref actions when Enter key is pressed on hide button", () => { - const hideButton = wrapper.find("#hide-all-widgets-button"); - - // Trigger onKeyDown handler directly with Enter key - hideButton.prop("onKeyDown")({ key: "Enter", preventDefault: () => {} }); - - const setPrefCalls = store.dispatch - .getCalls() - .filter(call => call.args[0]?.type === at.SET_PREF); - - assert.equal( - setPrefCalls.length, - 2, - "should dispatch two SetPref actions" - ); - - const listsPrefCall = setPrefCalls.find( - call => call.args[0].data?.name === PREF_WIDGETS_LISTS_ENABLED - ); - const timerPrefCall = setPrefCalls.find( - call => call.args[0].data?.name === PREF_WIDGETS_TIMER_ENABLED - ); - - assert.ok(listsPrefCall, "should dispatch SetPref for lists"); - assert.equal( - listsPrefCall.args[0].data.value, - false, - "should set lists pref to false" - ); - - assert.ok(timerPrefCall, "should dispatch SetPref for timer"); - assert.equal( - timerPrefCall.args[0].data.value, - false, - "should set timer pref to false" - ); - }); - - it("should dispatch SetPref actions when Space key is pressed on hide button", () => { - const hideButton = wrapper.find("#hide-all-widgets-button"); - - // Trigger onKeyDown handler directly with Space key - hideButton.prop("onKeyDown")({ key: " ", preventDefault: () => {} }); - - const setPrefCalls = store.dispatch - .getCalls() - .filter(call => call.args[0]?.type === at.SET_PREF); - - assert.equal( - setPrefCalls.length, - 2, - "should dispatch two SetPref actions" - ); - - const listsPrefCall = setPrefCalls.find( - call => call.args[0].data?.name === PREF_WIDGETS_LISTS_ENABLED - ); - const timerPrefCall = setPrefCalls.find( - call => call.args[0].data?.name === PREF_WIDGETS_TIMER_ENABLED - ); - - assert.ok(listsPrefCall, "should dispatch SetPref for lists"); - assert.equal( - listsPrefCall.args[0].data.value, - false, - "should set lists pref to false" - ); - - assert.ok(timerPrefCall, "should dispatch SetPref for timer"); - assert.equal( - timerPrefCall.args[0].data.value, - false, - "should set timer pref to false" - ); - }); - - it("should not dispatch SetPref actions when other keys are pressed", () => { - const hideButton = wrapper.find("#hide-all-widgets-button"); - - const testKeys = ["Escape", "Tab", "a", "ArrowDown"]; - - for (const key of testKeys) { - store.dispatch.resetHistory(); - // Trigger onKeyDown handler directly - hideButton.prop("onKeyDown")({ key }); - - const setPrefCalls = store.dispatch - .getCalls() - .filter(call => call.args[0]?.type === at.SET_PREF); - - assert.equal( - setPrefCalls.length, - 0, - `should not dispatch SetPref for key: ${key}` - ); - } - }); - }); - - describe("handleToggleMaximize", () => { - let wrapper; - let state; - let store; - - beforeEach(() => { - state = { - ...INITIAL_STATE, - Prefs: { - ...INITIAL_STATE.Prefs, - values: { - ...INITIAL_STATE.Prefs.values, - [PREF_WIDGETS_LISTS_ENABLED]: true, - [PREF_WIDGETS_SYSTEM_LISTS_ENABLED]: true, - "widgets.maximized": false, - "widgets.system.maximized": true, - }, - }, - }; - store = createStore(combineReducers(reducers), state); - sinon.spy(store, "dispatch"); - wrapper = mount( - <Provider store={store}> - <Widgets /> - </Provider> - ); - }); - - afterEach(() => { - store.dispatch.restore(); - }); - - it("should dispatch SetPref action when toggle button is clicked", () => { - const toggleButton = wrapper.find("#toggle-widgets-size-button"); - assert.ok(toggleButton.exists(), "toggle button should exist"); - - // Get the onClick handler and call it - const onClickHandler = toggleButton.prop("onClick"); - assert.ok(onClickHandler, "onClick handler should exist"); - onClickHandler({ preventDefault: () => {} }); - - const allCalls = store.dispatch.getCalls(); - const setPrefCalls = allCalls.filter( - call => call.args[0]?.type === at.SET_PREF - ); - - assert.equal( - setPrefCalls.length, - 1, - `should dispatch one SetPref action, got ${setPrefCalls.length}.` - ); - - const maximizedPrefCall = setPrefCalls.find( - call => call.args[0].data?.name === "widgets.maximized" - ); - - assert.ok(maximizedPrefCall, "should dispatch SetPref for maximized"); - assert.equal( - maximizedPrefCall.args[0].data.value, - true, - "should toggle maximized pref to true" - ); - }); - - it("should dispatch SetPref action when Enter key is pressed on toggle button", () => { - const toggleButton = wrapper.find("#toggle-widgets-size-button"); - - // Trigger onKeyDown handler directly with Enter key - toggleButton.prop("onKeyDown")({ - key: "Enter", - preventDefault: () => {}, - }); - - const setPrefCalls = store.dispatch - .getCalls() - .filter(call => call.args[0]?.type === at.SET_PREF); - - assert.equal( - setPrefCalls.length, - 1, - "should dispatch one SetPref action" - ); - - const maximizedPrefCall = setPrefCalls.find( - call => call.args[0].data?.name === "widgets.maximized" - ); - - assert.ok(maximizedPrefCall, "should dispatch SetPref for maximized"); - assert.equal( - maximizedPrefCall.args[0].data.value, - true, - "should toggle maximized pref to true" - ); - }); - - it("should dispatch SetPref action when Space key is pressed on toggle button", () => { - const toggleButton = wrapper.find("#toggle-widgets-size-button"); - - // Trigger onKeyDown handler directly with Space key - toggleButton.prop("onKeyDown")({ key: " ", preventDefault: () => {} }); - - const setPrefCalls = store.dispatch - .getCalls() - .filter(call => call.args[0]?.type === at.SET_PREF); - - assert.equal( - setPrefCalls.length, - 1, - "should dispatch one SetPref action" - ); - - const maximizedPrefCall = setPrefCalls.find( - call => call.args[0].data?.name === "widgets.maximized" - ); - - assert.ok(maximizedPrefCall, "should dispatch SetPref for maximized"); - assert.equal( - maximizedPrefCall.args[0].data.value, - true, - "should toggle maximized pref to true" - ); - }); - - it("should not dispatch SetPref actions when other keys are pressed", () => { - const toggleButton = wrapper.find("#toggle-widgets-size-button"); - - const testKeys = ["Escape", "Tab", "a", "ArrowDown"]; - - for (const key of testKeys) { - store.dispatch.resetHistory(); - // Trigger onKeyDown handler directly - toggleButton.prop("onKeyDown")({ key }); - - const setPrefCalls = store.dispatch - .getCalls() - .filter(call => call.args[0]?.type === at.SET_PREF); - - assert.equal( - setPrefCalls.length, - 0, - `should not dispatch SetPref for key: ${key}` - ); - } - }); - - it("should toggle from maximized to minimized state", () => { - // Update state to start with maximized = true - const maximizedState = { - ...INITIAL_STATE, - Prefs: { - ...INITIAL_STATE.Prefs, - values: { - ...INITIAL_STATE.Prefs.values, - [PREF_WIDGETS_LISTS_ENABLED]: true, - [PREF_WIDGETS_SYSTEM_LISTS_ENABLED]: true, - "widgets.maximized": true, - "widgets.system.maximized": true, - }, - }, - }; - const maximizedStore = createStore( - combineReducers(reducers), - maximizedState - ); - sinon.spy(maximizedStore, "dispatch"); - const maximizedWrapper = mount( - <Provider store={maximizedStore}> - <Widgets /> - </Provider> - ); - - const toggleButton = maximizedWrapper.find("#toggle-widgets-size-button"); - toggleButton.prop("onClick")({ preventDefault: () => {} }); - - const setPrefCalls = maximizedStore.dispatch - .getCalls() - .filter(call => call.args[0]?.type === at.SET_PREF); - - const maximizedPrefCall = setPrefCalls.find( - call => call.args[0].data?.name === "widgets.maximized" - ); - - assert.ok(maximizedPrefCall, "should dispatch SetPref for maximized"); - assert.equal( - maximizedPrefCall.args[0].data.value, - false, - "should toggle maximized pref to false" - ); - - maximizedStore.dispatch.restore(); - }); - }); }); diff --git a/browser/locales/en-US/browser/newtab/newtab.ftl b/browser/locales/en-US/browser/newtab/newtab.ftl @@ -561,17 +561,6 @@ newtab-trending-searches-dismiss = Hide trending searches ## Strings for task / to-do list productivity widget -newtab-widget-section-title = Widgets -# Tooltip for hide all widgets button -newtab-widget-section-hide-all-button = - .title = Hide widgets - .aria-label = Hide all widgets -newtab-widget-section-maximize = - .title = Expand widgets - .aria-label = Expand all widgets to full size -newtab-widget-section-minimize = - .title = Minimize widgets - .aria-label = Collapse all widgets to compact size newtab-widget-lists-name-label-default = .label = Task list newtab-widget-lists-name-placeholder-default = diff --git a/toolkit/themes/shared/desktop-jar.inc.mn b/toolkit/themes/shared/desktop-jar.inc.mn @@ -84,8 +84,6 @@ skin/classic/global/icons/error.svg (../../shared/icons/error.svg) skin/classic/global/icons/experiments.svg (../../shared/icons/experiments.svg) skin/classic/global/icons/folder.svg (../../shared/icons/folder.svg) - skin/classic/global/icons/fullscreen.svg (../../shared/icons/fullscreen.svg) - skin/classic/global/icons/fullscreen-exit.svg (../../shared/icons/fullscreen-exit.svg) skin/classic/global/icons/heart.svg (../../shared/icons/heart.svg) skin/classic/global/icons/help.svg (../../shared/icons/help.svg) skin/classic/global/icons/highlights.svg (../../shared/icons/highlights.svg) diff --git a/toolkit/themes/shared/icons/fullscreen-exit.svg b/toolkit/themes/shared/icons/fullscreen-exit.svg @@ -1,7 +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/. --> -<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16" fill="context-fill" fill-opacity="context-fill-opacity"> - <path d="M15.817.183a.626.626 0 0 0-.885 0l-3.625 3.625-.281-.281-1.173-1.173A.5.5 0 0 0 9 2.707L9 6.7l.3.3 3.993 0a.5.5 0 0 0 .354-.854l-1.454-1.454 3.625-3.625a.626.626 0 0 0-.001-.884z"/> - <path d="M3.707 8a.5.5 0 0 0-.354.854l1.454 1.454-3.625 3.625a.628.628 0 0 0 0 .885.63.63 0 0 0 .885-.001l3.625-3.625.281.281 1.173 1.173A.5.5 0 0 0 8 12.293L8 8.3 7.7 8 3.707 8z"/> -</svg> diff --git a/toolkit/themes/shared/icons/fullscreen.svg b/toolkit/themes/shared/icons/fullscreen.svg @@ -1,6 +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/. --> -<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" width="16" height="16" fill="context-fill" fill-opacity="context-fill-opacity"> - <path d="m14.7 1-3.993 0a.5.5 0 0 0-.354.854l1.454 1.454-7.5 7.5-1.454-1.454A.5.5 0 0 0 2 9.707L2 13.7l.3.3 3.993 0a.5.5 0 0 0 .354-.854l-1.454-1.454 7.5-7.5 1.454 1.454A.5.5 0 0 0 15 5.293L15 1.3l-.3-.3z"/> -</svg>