Bug 1921325 - Replace new tab toast notification with moz-message-bar r=reusable-components-reviewers,desktop-theme-reviewers,fluent-reviewers,home-newtab-reviewers,hjones,maxx,flod

* Make moz-message-bar reusable component available to New Tab page

* Replace custom implementation with reusable moz-message-bar component

* Remove all unnecessary CSS styling of custom implementation

* Use new Fluent IDs that adhere to the structure of moz-message-bar usage

* Consolidate Thumbs up and Thumbs down logic into same component to avoid duplicating code unnecessarily

Differential Revision: https://phabricator.services.mozilla.com/D232106
This commit is contained in:
mark
2025-01-21 15:29:45 +00:00
parent 92c7d19736
commit 7303f8d639
14 changed files with 136 additions and 207 deletions

View File

@@ -78,6 +78,7 @@ function templateHTML(options) {
<link rel="localization" href="branding/brand.ftl" />
<link rel="localization" href="toolkit/branding/brandings.ftl" />
<link rel="localization" href="browser/newtab/newtab.ftl" />
<link rel="localization" href="toolkit/global/mozMessageBar.ftl" />
<link
rel="stylesheet"
href="chrome://global/skin/design-system/tokens-brand.css"
@@ -113,6 +114,11 @@ function templateHTML(options) {
type="module"
src="chrome://global/content/elements/moz-box-button.mjs"
></script>
<script
async
type="module"
src="chrome://global/content/elements/moz-message-bar.mjs"
></script>
</body>
</html>
`.trimLeft();

View File

@@ -5,8 +5,7 @@
import React, { useCallback, useEffect } from "react";
import { useSelector } from "react-redux";
import { actionCreators as ac, actionTypes as at } from "common/Actions.mjs";
import { ThumbsUpToast } from "./Toasts/ThumbsUpToast";
import { ThumbsDownToast } from "./Toasts/ThumbsDownToast";
import { ThumbUpThumbDownToast } from "./Toasts/ThumbUpThumbDownToast";
function Notifications({ dispatch }) {
const toastQueue = useSelector(state => state.Notifications.toastQueue);
@@ -40,26 +39,17 @@ function Notifications({ dispatch }) {
// Note: This architecture could expand to support multiple toast notifications at once
const latestToastItem = toastQueue[toastQueue.length - 1];
switch (latestToastItem) {
case "thumbsDownToast":
return (
<ThumbsDownToast
onDismissClick={syncHiddenToastData}
onAnimationEnd={syncHiddenToastData}
key={toastCounter}
/>
);
case "thumbsUpToast":
return (
<ThumbsUpToast
onDismissClick={syncHiddenToastData}
onAnimationEnd={syncHiddenToastData}
key={toastCounter}
/>
);
default:
throw new Error("No toast found");
if (!latestToastItem) {
throw new Error("No toast found");
}
return (
<ThumbUpThumbDownToast
onDismissClick={syncHiddenToastData}
onAnimationEnd={syncHiddenToastData}
key={toastCounter}
/>
);
}, [syncHiddenToastData, toastCounter, toastQueue]);
useEffect(() => {
@@ -67,9 +57,7 @@ function Notifications({ dispatch }) {
}, [toastQueue, getToast]);
return toastQueue.length ? (
<div className="notification-wrapper">
<ul className="notification-feed">{getToast()}</ul>
</div>
<div className="notification-wrapper">{getToast()}</div>
) : (
""
);

View File

@@ -0,0 +1,41 @@
/* 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 React, { useEffect, useRef } from "react";
function ThumbUpThumbDownToast({ onDismissClick, onAnimationEnd }) {
const mozMessageBarRef = useRef(null);
useEffect(() => {
const { current: mozMessageBarElement } = mozMessageBarRef;
mozMessageBarElement.addEventListener(
"message-bar:user-dismissed",
onDismissClick,
{
once: true,
}
);
return () => {
mozMessageBarElement.removeEventListener(
"message-bar:user-dismissed",
onDismissClick
);
};
}, [onDismissClick]);
return (
<moz-message-bar
type="success"
class="notification-feed-item"
dismissable={true}
data-l10n-id="newtab-toast-thumbs-up-or-down2"
ref={mozMessageBarRef}
onAnimationEnd={onAnimationEnd}
></moz-message-bar>
);
}
export { ThumbUpThumbDownToast };

View File

@@ -1,27 +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/. */
import React from "react";
function ThumbsDownToast({ onDismissClick, onAnimationEnd }) {
return (
<div
className="notification-feed-item is-success"
onAnimationEnd={onAnimationEnd}
>
<div className="icon icon-check-filled icon-themed"></div>
<div
className="notification-feed-item-text"
data-l10n-id="newtab-toast-thumbs-up-or-down"
></div>
<button
onClick={onDismissClick}
className="icon icon-dismiss"
data-l10n-id="newtab-toast-dismiss-button"
></button>
</div>
);
}
export { ThumbsDownToast };

View File

@@ -1,27 +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/. */
import React from "react";
function ThumbsUpToast({ onDismissClick, onAnimationEnd }) {
return (
<div
className="notification-feed-item is-success"
onAnimationEnd={onAnimationEnd}
>
<div className="icon icon-check-filled icon-themed"></div>
<div
className="notification-feed-item-text"
data-l10n-id="newtab-toast-thumbs-up-or-down"
></div>
<button
onClick={onDismissClick}
className="icon icon-dismiss"
data-l10n-id="newtab-toast-dismiss-button"
></button>
</div>
);
}
export { ThumbsUpToast };

View File

@@ -2,50 +2,12 @@
position: fixed;
inset-inline-end: var(--space-medium);
inset-block-end: var(--space-medium);
}
.notification-feed {
display: flex;
flex-direction: column;
gap: var(--space-medium);
z-index: 1;
}
.notification-feed-item {
position: relative;
padding: var(--space-small) var(--space-large);
border: 1px solid var(--border-color-interactive);
display: flex;
max-width: 280px;
border-radius: var(--border-radius-small);
align-items: center;
justify-content: flex-start;
gap: var(--space-small);
animation: toastSlideInSlideOut 4s ease-in-out forwards;
.icon {
flex-shrink: 0;
}
.notification-feed-item-text {
font-size: var(--font-size-small);
font-weight: var(--font-weight);
}
&.is-success {
background-color: var(--background-color-success);
.icon.icon-themed {
fill: var(--icon-color-success);
}
}
button {
appearance: none;
border: 0;
}
}
@keyframes toastSlideInSlideOut {

View File

@@ -4215,43 +4215,13 @@ main section {
position: fixed;
inset-inline-end: var(--space-medium);
inset-block-end: var(--space-medium);
}
.notification-feed {
display: flex;
flex-direction: column;
gap: var(--space-medium);
z-index: 1;
}
.notification-feed-item {
position: relative;
padding: var(--space-small) var(--space-large);
border: 1px solid var(--border-color-interactive);
display: flex;
max-width: 280px;
border-radius: var(--border-radius-small);
align-items: center;
justify-content: flex-start;
gap: var(--space-small);
animation: toastSlideInSlideOut 4s ease-in-out forwards;
}
.notification-feed-item .icon {
flex-shrink: 0;
}
.notification-feed-item .notification-feed-item-text {
font-size: var(--font-size-small);
font-weight: var(--font-weight);
}
.notification-feed-item.is-success {
background-color: var(--background-color-success);
}
.notification-feed-item.is-success .icon.icon-themed {
fill: var(--icon-color-success);
}
.notification-feed-item button {
appearance: none;
border: 0;
}
@keyframes toastSlideInSlideOut {
0%, 100% {

View File

@@ -30,6 +30,7 @@
<link rel="localization" href="branding/brand.ftl" />
<link rel="localization" href="toolkit/branding/brandings.ftl" />
<link rel="localization" href="browser/newtab/newtab.ftl" />
<link rel="localization" href="toolkit/global/mozMessageBar.ftl" />
<link rel="stylesheet" href="chrome://global/skin/design-system/tokens-brand.css">
<link rel="stylesheet" href="chrome://browser/content/contentSearchUI.css" />
<link rel="stylesheet" href="chrome://activity-stream/content/css/activity-stream.css" />
@@ -46,5 +47,6 @@
<script async type="module" src="chrome://global/content/elements/moz-button.mjs"></script>
<script async type="module" src="chrome://global/content/elements/moz-button-group.mjs"></script>
<script async type="module" src="chrome://global/content/elements/moz-box-button.mjs"></script>
<script async type="module" src="chrome://global/content/elements/moz-message-bar.mjs"></script>
</body>
</html>

View File

@@ -12146,54 +12146,36 @@ const Weather_Weather = (0,external_ReactRedux_namespaceObject.connect)(state =>
IntersectionObserver: globalThis.IntersectionObserver,
document: globalThis.document
}))(_Weather);
;// CONCATENATED MODULE: ./content-src/components/Notifications/Toasts/ThumbsUpToast.jsx
;// CONCATENATED MODULE: ./content-src/components/Notifications/Toasts/ThumbUpThumbDownToast.jsx
/* 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/. */
function ThumbsUpToast({
function ThumbUpThumbDownToast({
onDismissClick,
onAnimationEnd
}) {
return /*#__PURE__*/external_React_default().createElement("div", {
className: "notification-feed-item is-success",
const mozMessageBarRef = (0,external_React_namespaceObject.useRef)(null);
(0,external_React_namespaceObject.useEffect)(() => {
const {
current: mozMessageBarElement
} = mozMessageBarRef;
mozMessageBarElement.addEventListener("message-bar:user-dismissed", onDismissClick, {
once: true
});
return () => {
mozMessageBarElement.removeEventListener("message-bar:user-dismissed", onDismissClick);
};
}, [onDismissClick]);
return /*#__PURE__*/external_React_default().createElement("moz-message-bar", {
type: "success",
class: "notification-feed-item",
dismissable: true,
"data-l10n-id": "newtab-toast-thumbs-up-or-down2",
ref: mozMessageBarRef,
onAnimationEnd: onAnimationEnd
}, /*#__PURE__*/external_React_default().createElement("div", {
className: "icon icon-check-filled icon-themed"
}), /*#__PURE__*/external_React_default().createElement("div", {
className: "notification-feed-item-text",
"data-l10n-id": "newtab-toast-thumbs-up-or-down"
}), /*#__PURE__*/external_React_default().createElement("button", {
onClick: onDismissClick,
className: "icon icon-dismiss",
"data-l10n-id": "newtab-toast-dismiss-button"
}));
}
;// CONCATENATED MODULE: ./content-src/components/Notifications/Toasts/ThumbsDownToast.jsx
/* 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/. */
function ThumbsDownToast({
onDismissClick,
onAnimationEnd
}) {
return /*#__PURE__*/external_React_default().createElement("div", {
className: "notification-feed-item is-success",
onAnimationEnd: onAnimationEnd
}, /*#__PURE__*/external_React_default().createElement("div", {
className: "icon icon-check-filled icon-themed"
}), /*#__PURE__*/external_React_default().createElement("div", {
className: "notification-feed-item-text",
"data-l10n-id": "newtab-toast-thumbs-up-or-down"
}), /*#__PURE__*/external_React_default().createElement("button", {
onClick: onDismissClick,
className: "icon icon-dismiss",
"data-l10n-id": "newtab-toast-dismiss-button"
}));
});
}
;// CONCATENATED MODULE: ./content-src/components/Notifications/Notifications.jsx
@@ -12205,7 +12187,6 @@ function ThumbsDownToast({
function Notifications_Notifications({
dispatch
}) {
@@ -12233,31 +12214,21 @@ function Notifications_Notifications({
const getToast = (0,external_React_namespaceObject.useCallback)(() => {
// Note: This architecture could expand to support multiple toast notifications at once
const latestToastItem = toastQueue[toastQueue.length - 1];
switch (latestToastItem) {
case "thumbsDownToast":
return /*#__PURE__*/external_React_default().createElement(ThumbsDownToast, {
onDismissClick: syncHiddenToastData,
onAnimationEnd: syncHiddenToastData,
key: toastCounter
});
case "thumbsUpToast":
return /*#__PURE__*/external_React_default().createElement(ThumbsUpToast, {
onDismissClick: syncHiddenToastData,
onAnimationEnd: syncHiddenToastData,
key: toastCounter
});
default:
throw new Error("No toast found");
if (!latestToastItem) {
throw new Error("No toast found");
}
return /*#__PURE__*/external_React_default().createElement(ThumbUpThumbDownToast, {
onDismissClick: syncHiddenToastData,
onAnimationEnd: syncHiddenToastData,
key: toastCounter
});
}, [syncHiddenToastData, toastCounter, toastQueue]);
(0,external_React_namespaceObject.useEffect)(() => {
getToast();
}, [toastQueue, getToast]);
return toastQueue.length ? /*#__PURE__*/external_React_default().createElement("div", {
className: "notification-wrapper"
}, /*#__PURE__*/external_React_default().createElement("ul", {
className: "notification-feed"
}, getToast())) : "";
}, getToast()) : "";
}
;// CONCATENATED MODULE: ./content-src/components/DiscoveryStreamComponents/TopicSelection/TopicSelection.jsx

View File

@@ -21,6 +21,7 @@
<link rel="localization" href="branding/brand.ftl" />
<link rel="localization" href="toolkit/branding/brandings.ftl" />
<link rel="localization" href="browser/newtab/newtab.ftl" />
<link rel="localization" href="toolkit/global/mozMessageBar.ftl" />
<link
rel="stylesheet"
href="chrome://global/skin/design-system/tokens-brand.css"
@@ -67,5 +68,10 @@
type="module"
src="chrome://global/content/elements/moz-box-button.mjs"
></script>
<script
async
type="module"
src="chrome://global/content/elements/moz-message-bar.mjs"
></script>
</body>
</html>

View File

@@ -21,6 +21,7 @@
<link rel="localization" href="branding/brand.ftl" />
<link rel="localization" href="toolkit/branding/brandings.ftl" />
<link rel="localization" href="browser/newtab/newtab.ftl" />
<link rel="localization" href="toolkit/global/mozMessageBar.ftl" />
<link
rel="stylesheet"
href="chrome://global/skin/design-system/tokens-brand.css"
@@ -56,5 +57,10 @@
type="module"
src="chrome://global/content/elements/moz-box-button.mjs"
></script>
<script
async
type="module"
src="chrome://global/content/elements/moz-message-bar.mjs"
></script>
</body>
</html>

View File

@@ -21,6 +21,7 @@
<link rel="localization" href="branding/brand.ftl" />
<link rel="localization" href="toolkit/branding/brandings.ftl" />
<link rel="localization" href="browser/newtab/newtab.ftl" />
<link rel="localization" href="toolkit/global/mozMessageBar.ftl" />
<link
rel="stylesheet"
href="chrome://global/skin/design-system/tokens-brand.css"
@@ -67,5 +68,10 @@
type="module"
src="chrome://global/content/elements/moz-box-button.mjs"
></script>
<script
async
type="module"
src="chrome://global/content/elements/moz-message-bar.mjs"
></script>
</body>
</html>

View File

@@ -249,7 +249,9 @@ newtab-pocket-thumbs-up-tooltip =
# Clicking the thumbs down button for this story informs us that the user does not feel like the story is interesting for them
newtab-pocket-thumbs-down-tooltip =
.title = Not for me
newtab-toast-thumbs-up-or-down = Thanks. Your feedback will help us improve your feed.
# Used to show the user a message upon clicking the thumbs up or down buttons
newtab-toast-thumbs-up-or-down2 =
.message = Thanks. Your feedback will help us improve your feed.
newtab-toast-dismiss-button =
.title = Dismiss
.aria-label = Dismiss

View File

@@ -0,0 +1,23 @@
# Any copyright is dedicated to the Public Domain.
# http://creativecommons.org/publicdomain/zero/1.0/
from fluent.migrate.helpers import transforms_from
def migrate(ctx):
"""Bug 1921325 - Update structure of new tab toast notification message for moz-message-bar, part {index}."""
source = "browser/browser/newtab/newtab.ftl"
target = source
ctx.add_transforms(
target,
target,
transforms_from(
"""
newtab-toast-thumbs-up-or-down2 =
.message = {COPY_PATTERN(from_path, "newtab-toast-thumbs-up-or-down")}
""",
from_path=source,
),
)