commit ecfd420667a415fc31d65dbf41a12f33801acd0d
parent 33294a54240daf8cd6d85d0216b0bc77b82ae64f
Author: Maxx Crawford <mcrawford@mozilla.com>
Date: Wed, 1 Oct 2025 14:03:13 +0000
Bug 1991678 - Add remote data support (images, custom text strings) to ShortcutFeatureHighlight component r=home-newtab-reviewers,nbarrett
Differential Revision: https://phabricator.services.mozilla.com/D266908
Diffstat:
6 files changed, 101 insertions(+), 37 deletions(-)
diff --git a/browser/extensions/newtab/content-src/components/DiscoveryStreamComponents/FeatureHighlight/ShortcutFeatureHighlight.jsx b/browser/extensions/newtab/content-src/components/DiscoveryStreamComponents/FeatureHighlight/ShortcutFeatureHighlight.jsx
@@ -6,11 +6,12 @@ import React, { useCallback } from "react";
import { FeatureHighlight } from "./FeatureHighlight";
export function ShortcutFeatureHighlight({
- position,
dispatch,
- handleDismiss,
- handleBlock,
feature,
+ handleBlock,
+ handleDismiss,
+ messageData,
+ position,
}) {
const onDismiss = useCallback(() => {
handleDismiss();
@@ -18,28 +19,49 @@ export function ShortcutFeatureHighlight({
}, [handleDismiss, handleBlock]);
return (
- <div className="shortcut-feature-highlight">
+ <div
+ className={`shortcut-feature-highlight ${messageData.content?.darkModeDismiss ? "is-inverted-dark-dismiss-button" : ""}`}
+ >
<FeatureHighlight
position={position}
feature={feature}
dispatch={dispatch}
message={
<div className="shortcut-feature-highlight-content">
- <img
- src="chrome://global/skin/icons/open-in-new.svg"
- width="24"
- height="24"
- alt=""
- />
- <div className="shortcut-feature-highlight-copy">
- <p
- className="title"
- data-l10n-id="newtab-shortcuts-highlight-title"
+ <picture className="follow-section-button-highlight-image">
+ <source
+ srcSet={
+ messageData.content?.darkModeImageURL ||
+ "chrome://newtab/content/data/content/assets/highlights/omc-newtab-shortcuts.svg"
+ }
+ media="(prefers-color-scheme: dark)"
/>
- <p
- className="subtitle"
- data-l10n-id="newtab-shortcuts-highlight-subtitle"
+ <source
+ srcSet={
+ messageData.content?.imageURL ||
+ "chrome://newtab/content/data/content/assets/highlights/omc-newtab-shortcuts.svg"
+ }
+ media="(prefers-color-scheme: light)"
/>
+ <img width="320" height="195" alt="" />
+ </picture>
+ <div className="shortcut-feature-highlight-copy">
+ {messageData.content?.cardTitle ? (
+ <p className="title">{messageData.content.cardTitle}</p>
+ ) : (
+ <p
+ className="title"
+ data-l10n-id="newtab-shortcuts-highlight-title"
+ />
+ )}
+ {messageData.content?.cardMessage ? (
+ <p className="subtitle">{messageData.content.cardMessage}</p>
+ ) : (
+ <p
+ className="subtitle"
+ data-l10n-id="newtab-shortcuts-highlight-subtitle"
+ />
+ )}
</div>
</div>
}
diff --git a/browser/extensions/newtab/content-src/components/DiscoveryStreamComponents/FeatureHighlight/_ShortcutFeatureHighlight.scss b/browser/extensions/newtab/content-src/components/DiscoveryStreamComponents/FeatureHighlight/_ShortcutFeatureHighlight.scss
@@ -2,6 +2,7 @@
.shortcut-feature-highlight {
.feature-highlight-modal {
padding: var(--space-large);
+ width: auto;
p {
margin: 0;
@@ -22,14 +23,30 @@
inset-inline-end: var(--space-xlarge);
}
- img {
- -moz-context-properties: fill;
- fill: currentColor;
+ // The "Dismiss" button in the top right corner of the highlight needs to be in front of the image
+ >moz-button {
+ position: absolute;
+ inset-inline-end: var(--space-large);
+ inset-block-start: var(--space-large);
+ }
+ }
+
+ // Custom override for dismiss-contrast
+ &.is-inverted-dark-dismiss-button {
+ .feature-highlight-modal {
+ @media (prefers-color-scheme: dark) {
+
+ // override color so that it is visible on the image
+ >moz-button {
+ --button-icon-fill: var(--color-gray-70);
+ }
+ }
}
}
.shortcut-feature-highlight-content {
display: flex;
+ flex-direction: column;
gap: var(--space-medium);
}
diff --git a/browser/extensions/newtab/content-src/components/TopSites/TopSite.jsx b/browser/extensions/newtab/content-src/components/TopSites/TopSite.jsx
@@ -445,6 +445,7 @@ export class TopSiteLink extends React.PureComponent {
dispatch={this.props.dispatch}
feature="FEATURE_SHORTCUT_HIGHLIGHT"
position="inset-block-end inset-inline-start"
+ messageData={this.props.Messages?.messageData}
/>
</MessageWrapper>
)}
diff --git a/browser/extensions/newtab/css/activity-stream.css b/browser/extensions/newtab/css/activity-stream.css
@@ -8555,6 +8555,7 @@ dialog::after {
.shortcut-feature-highlight .feature-highlight-modal {
padding: var(--space-large);
+ width: auto;
}
.shortcut-feature-highlight .feature-highlight-modal p {
margin: 0;
@@ -8570,12 +8571,19 @@ dialog::after {
margin-block-start: var(--space-large);
inset-inline-end: var(--space-xlarge);
}
-.shortcut-feature-highlight .feature-highlight-modal img {
- -moz-context-properties: fill;
- fill: currentColor;
+.shortcut-feature-highlight .feature-highlight-modal > moz-button {
+ position: absolute;
+ inset-inline-end: var(--space-large);
+ inset-block-start: var(--space-large);
+}
+@media (prefers-color-scheme: dark) {
+ .shortcut-feature-highlight.is-inverted-dark-dismiss-button .feature-highlight-modal > moz-button {
+ --button-icon-fill: var(--color-gray-70);
+ }
}
.shortcut-feature-highlight .shortcut-feature-highlight-content {
display: flex;
+ flex-direction: column;
gap: var(--space-medium);
}
.shortcut-feature-highlight .shortcut-feature-highlight-copy {
diff --git a/browser/extensions/newtab/data/content/activity-stream.bundle.js b/browser/extensions/newtab/data/content/activity-stream.bundle.js
@@ -8928,35 +8928,47 @@ function FeatureHighlight({
function ShortcutFeatureHighlight({
- position,
dispatch,
- handleDismiss,
+ feature,
handleBlock,
- feature
+ handleDismiss,
+ messageData,
+ position
}) {
const onDismiss = (0,external_React_namespaceObject.useCallback)(() => {
handleDismiss();
handleBlock();
}, [handleDismiss, handleBlock]);
return /*#__PURE__*/external_React_default().createElement("div", {
- className: "shortcut-feature-highlight"
+ className: `shortcut-feature-highlight ${messageData.content?.darkModeDismiss ? "is-inverted-dark-dismiss-button" : ""}`
}, /*#__PURE__*/external_React_default().createElement(FeatureHighlight, {
position: position,
feature: feature,
dispatch: dispatch,
message: /*#__PURE__*/external_React_default().createElement("div", {
className: "shortcut-feature-highlight-content"
- }, /*#__PURE__*/external_React_default().createElement("img", {
- src: "chrome://global/skin/icons/open-in-new.svg",
- width: "24",
- height: "24",
+ }, /*#__PURE__*/external_React_default().createElement("picture", {
+ className: "follow-section-button-highlight-image"
+ }, /*#__PURE__*/external_React_default().createElement("source", {
+ srcSet: messageData.content?.darkModeImageURL || "chrome://newtab/content/data/content/assets/highlights/omc-newtab-shortcuts.svg",
+ media: "(prefers-color-scheme: dark)"
+ }), /*#__PURE__*/external_React_default().createElement("source", {
+ srcSet: messageData.content?.imageURL || "chrome://newtab/content/data/content/assets/highlights/omc-newtab-shortcuts.svg",
+ media: "(prefers-color-scheme: light)"
+ }), /*#__PURE__*/external_React_default().createElement("img", {
+ width: "320",
+ height: "195",
alt: ""
- }), /*#__PURE__*/external_React_default().createElement("div", {
+ })), /*#__PURE__*/external_React_default().createElement("div", {
className: "shortcut-feature-highlight-copy"
- }, /*#__PURE__*/external_React_default().createElement("p", {
+ }, messageData.content?.cardTitle ? /*#__PURE__*/external_React_default().createElement("p", {
+ className: "title"
+ }, messageData.content.cardTitle) : /*#__PURE__*/external_React_default().createElement("p", {
className: "title",
"data-l10n-id": "newtab-shortcuts-highlight-title"
- }), /*#__PURE__*/external_React_default().createElement("p", {
+ }), messageData.content?.cardMessage ? /*#__PURE__*/external_React_default().createElement("p", {
+ className: "subtitle"
+ }, messageData.content.cardMessage) : /*#__PURE__*/external_React_default().createElement("p", {
className: "subtitle",
"data-l10n-id": "newtab-shortcuts-highlight-subtitle"
}))),
@@ -9359,7 +9371,8 @@ class TopSiteLink extends (external_React_default()).PureComponent {
}, /*#__PURE__*/external_React_default().createElement(ShortcutFeatureHighlight, {
dispatch: this.props.dispatch,
feature: "FEATURE_SHORTCUT_HIGHLIGHT",
- position: "inset-block-end inset-inline-start"
+ position: "inset-block-end inset-inline-start",
+ messageData: this.props.Messages?.messageData
})), children, impressionStats));
}
}
diff --git a/browser/extensions/newtab/test/unit/content-src/components/DiscoveryStreamComponents/ShortcutFeatureHighlight.test.jsx b/browser/extensions/newtab/test/unit/content-src/components/DiscoveryStreamComponents/ShortcutFeatureHighlight.test.jsx
@@ -8,20 +8,23 @@ describe("Discovery Stream <ShortcutFeatureHighlight>", () => {
let dispatch;
let handleDismiss;
let handleBlock;
+ let messageData;
beforeEach(() => {
sandbox = sinon.createSandbox();
dispatch = sandbox.stub();
handleDismiss = sandbox.stub();
handleBlock = sandbox.stub();
+ messageData = sandbox.stub();
wrapper = mount(
<ShortcutFeatureHighlight
dispatch={dispatch}
- handleDismiss={handleDismiss}
+ feature="FEATURE_SHORTCUT_HIGHLIGHT"
handleBlock={handleBlock}
+ handleDismiss={handleDismiss}
+ messageData={messageData}
position="inset-block-end inset-inline-start"
- feature="FEATURE_SHORTCUT_HIGHLIGHT"
/>
);
});