From 086c044dc34dfc0f74fbe41f4ecb402b2cd34884 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 03:13:33 +0200 Subject: Merging upstream version 125.0.1. Signed-off-by: Daniel Baumann --- browser/components/newtab/.eslintrc.js | 5 +- .../components/newtab/AboutNewTabService.sys.mjs | 4 +- .../newtab/components/CustomElements/paragraph.js | 2 +- .../newtab/content-src/components/Base/Base.jsx | 15 +- .../CollapsibleSection/CollapsibleSection.jsx | 17 +- .../components/ContextMenu/ContextMenuButton.jsx | 2 +- .../ContentSection/ContentSection.jsx | 19 ++ .../components/CustomizeMenu/CustomizeMenu.jsx | 1 + .../components/CustomizeMenu/_CustomizeMenu.scss | 35 +++ .../DiscoveryStreamAdmin/DiscoveryStreamAdmin.jsx | 2 +- .../DiscoveryStreamBase/DiscoveryStreamBase.jsx | 7 +- .../CardGrid/CardGrid.jsx | 8 +- .../DiscoveryStreamComponents/DSCard/DSCard.jsx | 76 +++--- .../DiscoveryStreamComponents/DSCard/_DSCard.scss | 32 +-- .../DSContextFooter/DSContextFooter.jsx | 9 + .../DSContextFooter/_DSContextFooter.scss | 3 + .../DSPrivacyModal/DSPrivacyModal.jsx | 6 +- .../FeatureHighlight/FeatureHighlight.jsx | 74 ++++++ .../FeatureHighlight/SponsoredContentHighlight.jsx | 34 +++ .../FeatureHighlight/_FeatureHighlight.scss | 98 +++++++ .../_SponsoredContentHighlight.scss | 33 +++ .../SafeAnchor/SafeAnchor.jsx | 9 +- .../components/ErrorBoundary/ErrorBoundary.jsx | 2 +- .../content-src/components/TopSites/TopSite.jsx | 79 ++++-- .../content-src/components/TopSites/TopSites.jsx | 2 +- .../content-src/components/TopSites/_TopSites.scss | 19 +- .../newtab/content-src/lib/init-store.js | 2 +- .../newtab/content-src/lib/link-menu-options.js | 2 +- .../newtab/content-src/lib/selectLayoutRender.js | 2 +- .../content-src/styles/_activity-stream.scss | 2 + .../newtab/content-src/styles/_icons.scss | 4 + .../newtab/css/activity-stream-linux.css | 176 ++++++++++++- .../components/newtab/css/activity-stream-mac.css | 176 ++++++++++++- .../newtab/css/activity-stream-windows.css | 176 ++++++++++++- .../newtab/data/content/activity-stream.bundle.js | 290 ++++++++++++++++----- .../data/content/assets/sponsor-message-icon.svg | 6 + browser/components/newtab/docs/index.rst | 2 +- .../newtab/docs/v2-system-addon/preferences.md | 2 +- .../docs/v2-system-addon/unit_testing_guide.md | 8 +- browser/components/newtab/karma.mc.config.js | 8 - .../components/newtab/lib/ActivityStream.sys.mjs | 4 +- .../lib/ActivityStreamMessageChannel.sys.mjs | 2 +- .../newtab/lib/DiscoveryStreamFeed.sys.mjs | 19 +- .../components/newtab/lib/DownloadsManager.sys.mjs | 2 +- .../lib/PersonalityProvider/RecipeExecutor.mjs | 4 +- browser/components/newtab/lib/PrefsFeed.sys.mjs | 4 +- .../newtab/lib/RecommendationProvider.sys.mjs | 2 +- .../components/newtab/lib/SectionsManager.sys.mjs | 4 +- browser/components/newtab/lib/Store.sys.mjs | 2 +- .../components/newtab/lib/TelemetryFeed.sys.mjs | 10 +- browser/components/newtab/lib/TopSitesFeed.sys.mjs | 6 +- browser/components/newtab/loaders/inject-loader.js | 59 ----- browser/components/newtab/metrics.yaml | 21 ++ browser/components/newtab/package-lock.json | 230 +--------------- browser/components/newtab/package.json | 6 - .../newtab/test/browser/browser_newtab_ping.js | 2 +- browser/components/newtab/test/schemas/pings.js | 2 +- .../DiscoveryStreamComponents/DSCard.test.jsx | 8 +- .../FeatureHighlight.test.jsx | 60 +++++ .../content-src/components/ModalOverlay.test.jsx | 69 +++++ .../unit/content-src/components/TopSites.test.jsx | 52 ++-- .../newtab/test/unit/lib/AboutPreferences.test.js | 2 +- .../newtab/test/unit/lib/ActivityStream.test.js | 10 +- .../PersonalityProvider.test.js | 4 +- .../lib/PersonalityProvider/RecipeExecutor.test.js | 2 +- browser/components/newtab/test/unit/unit-entry.js | 14 +- browser/components/newtab/test/unit/utils.js | 10 +- .../test/xpcshell/test_AboutWelcomeAttribution.js | 69 ----- .../test/xpcshell/test_AboutWelcomeTelemetry.js | 90 ------- .../xpcshell/test_AboutWelcomeTelemetry_glean.js | 238 ----------------- .../newtab/test/xpcshell/test_HighlightsFeed.js | 4 +- .../newtab/test/xpcshell/test_PlacesFeed.js | 10 +- .../components/newtab/test/xpcshell/test_Store.js | 2 +- .../newtab/test/xpcshell/test_TelemetryFeed.js | 32 +++ .../components/newtab/test/xpcshell/xpcshell.toml | 6 - .../components/newtab/tools/resourceUriPlugin.js | 9 +- .../newtab/webpack.system-addon.config.js | 3 - 77 files changed, 1521 insertions(+), 1001 deletions(-) create mode 100644 browser/components/newtab/content-src/components/DiscoveryStreamComponents/FeatureHighlight/FeatureHighlight.jsx create mode 100644 browser/components/newtab/content-src/components/DiscoveryStreamComponents/FeatureHighlight/SponsoredContentHighlight.jsx create mode 100644 browser/components/newtab/content-src/components/DiscoveryStreamComponents/FeatureHighlight/_FeatureHighlight.scss create mode 100644 browser/components/newtab/content-src/components/DiscoveryStreamComponents/FeatureHighlight/_SponsoredContentHighlight.scss create mode 100644 browser/components/newtab/data/content/assets/sponsor-message-icon.svg delete mode 100644 browser/components/newtab/loaders/inject-loader.js create mode 100644 browser/components/newtab/test/unit/content-src/components/DiscoveryStreamComponents/FeatureHighlight.test.jsx create mode 100644 browser/components/newtab/test/unit/content-src/components/ModalOverlay.test.jsx delete mode 100644 browser/components/newtab/test/xpcshell/test_AboutWelcomeAttribution.js delete mode 100644 browser/components/newtab/test/xpcshell/test_AboutWelcomeTelemetry.js delete mode 100644 browser/components/newtab/test/xpcshell/test_AboutWelcomeTelemetry_glean.js (limited to 'browser/components/newtab') diff --git a/browser/components/newtab/.eslintrc.js b/browser/components/newtab/.eslintrc.js index 5fc7a4dcff..f541cdd988 100644 --- a/browser/components/newtab/.eslintrc.js +++ b/browser/components/newtab/.eslintrc.js @@ -58,7 +58,7 @@ module.exports = { { // Use a configuration that's appropriate for modules, workers and // non-production files. - files: ["*.jsm", "lib/cache.worker.js", "test/**"], + files: ["lib/cache.worker.js", "test/**"], rules: { "no-implicit-globals": "off", }, @@ -123,15 +123,12 @@ module.exports = { "consistent-this": ["error", "use-bind"], eqeqeq: "error", "func-name-matching": "error", - "getter-return": "error", "guard-for-in": "error", - "max-depth": ["error", 4], "max-nested-callbacks": ["error", 4], "max-params": ["error", 6], "max-statements": ["error", 50], "new-cap": ["error", { newIsCap: true, capIsNew: false }], "no-alert": "error", - "no-console": ["error", { allow: ["error"] }], "no-div-regex": "error", "no-duplicate-imports": "error", "no-eq-null": "error", diff --git a/browser/components/newtab/AboutNewTabService.sys.mjs b/browser/components/newtab/AboutNewTabService.sys.mjs index e73e1b1880..73502fcb4f 100644 --- a/browser/components/newtab/AboutNewTabService.sys.mjs +++ b/browser/components/newtab/AboutNewTabService.sys.mjs @@ -339,7 +339,7 @@ export const AboutHomeStartupCacheChild = { }); }, - observe(subject, topic, data) { + observe(subject, topic) { if (topic === "memory-pressure" && this._cacheWorker) { this._cacheWorker.terminate(); this._cacheWorker = null; @@ -447,7 +447,7 @@ class BaseAboutNewTabService { return this.defaultURL; } - aboutHomeChannel(uri, loadInfo) { + aboutHomeChannel() { throw Components.Exception( "AboutHomeChannel not implemented for this process.", Cr.NS_ERROR_NOT_IMPLEMENTED diff --git a/browser/components/newtab/components/CustomElements/paragraph.js b/browser/components/newtab/components/CustomElements/paragraph.js index dce8a229a4..f9818dbde9 100644 --- a/browser/components/newtab/components/CustomElements/paragraph.js +++ b/browser/components/newtab/components/CustomElements/paragraph.js @@ -49,7 +49,7 @@ return ["fluent-remote-id"]; } - attributeChangedCallback(name, oldValue, newValue) { + attributeChangedCallback() { this.render(); } diff --git a/browser/components/newtab/content-src/components/Base/Base.jsx b/browser/components/newtab/content-src/components/Base/Base.jsx index 0580267f26..20402b09f5 100644 --- a/browser/components/newtab/content-src/components/Base/Base.jsx +++ b/browser/components/newtab/content-src/components/Base/Base.jsx @@ -165,6 +165,7 @@ export class BaseContent extends React.PureComponent { const { App } = props; const { initialized, customizeMenuVisible } = App; const prefs = props.Prefs.values; + const { pocketConfig } = prefs; const isDiscoveryStream = props.DiscoveryStream.config && props.DiscoveryStream.config.enabled; @@ -172,6 +173,14 @@ export class BaseContent extends React.PureComponent { section => section.id !== "topstories" ); + let spocMessageVariant = ""; + if ( + props.App.locale?.startsWith("en-") && + pocketConfig?.spocMessageVariant === "variant-c" + ) { + spocMessageVariant = pocketConfig.spocMessageVariant; + } + const pocketEnabled = prefs["feeds.section.topstories"] && prefs["feeds.system.topstories"]; const noSectionsEnabled = @@ -218,6 +227,7 @@ export class BaseContent extends React.PureComponent { pocketRegion={pocketRegion} mayHaveSponsoredTopSites={mayHaveSponsoredTopSites} mayHaveSponsoredStories={mayHaveSponsoredStories} + spocMessageVariant={spocMessageVariant} showing={customizeMenuVisible} /> {/* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions*/} @@ -239,7 +249,10 @@ export class BaseContent extends React.PureComponent {
{isDiscoveryStream ? ( - + ) : ( diff --git a/browser/components/newtab/content-src/components/CollapsibleSection/CollapsibleSection.jsx b/browser/components/newtab/content-src/components/CollapsibleSection/CollapsibleSection.jsx index 679e8e137f..98bf88fbea 100644 --- a/browser/components/newtab/content-src/components/CollapsibleSection/CollapsibleSection.jsx +++ b/browser/components/newtab/content-src/components/CollapsibleSection/CollapsibleSection.jsx @@ -4,6 +4,7 @@ import { ErrorBoundary } from "content-src/components/ErrorBoundary/ErrorBoundary"; import { FluentOrText } from "content-src/components/FluentOrText/FluentOrText"; +import { SponsoredContentHighlight } from "../DiscoveryStreamComponents/FeatureHighlight/SponsoredContentHighlight"; import React from "react"; import { connect } from "react-redux"; @@ -48,7 +49,14 @@ export class _CollapsibleSection extends React.PureComponent { render() { const { isAnimating, maxHeight, menuButtonHover, showContextMenu } = this.state; - const { id, collapsed, learnMore, title, subTitle } = this.props; + const { + id, + collapsed, + learnMore, + title, + subTitle, + mayHaveSponsoredStories, + } = this.props; const active = menuButtonHover || showContextMenu; let bodyStyle; if (isAnimating && !collapsed) { @@ -91,6 +99,13 @@ export class _CollapsibleSection extends React.PureComponent { )} + {mayHaveSponsoredStories && + this.props.spocMessageVariant === "variant-a" && ( + + )}
diff --git a/browser/components/newtab/content-src/components/ContextMenu/ContextMenuButton.jsx b/browser/components/newtab/content-src/components/ContextMenu/ContextMenuButton.jsx index 0364f5386a..58df7d012b 100644 --- a/browser/components/newtab/content-src/components/ContextMenu/ContextMenuButton.jsx +++ b/browser/components/newtab/content-src/components/ContextMenu/ContextMenuButton.jsx @@ -16,7 +16,7 @@ export class ContextMenuButton extends React.PureComponent { this.onUpdate = this.onUpdate.bind(this); } - openContextMenu(isKeyBoard, event) { + openContextMenu(isKeyBoard) { if (this.props.onUpdate) { this.props.onUpdate(true); } diff --git a/browser/components/newtab/content-src/components/CustomizeMenu/ContentSection/ContentSection.jsx b/browser/components/newtab/content-src/components/CustomizeMenu/ContentSection/ContentSection.jsx index 57ed935e93..298dedcee5 100644 --- a/browser/components/newtab/content-src/components/CustomizeMenu/ContentSection/ContentSection.jsx +++ b/browser/components/newtab/content-src/components/CustomizeMenu/ContentSection/ContentSection.jsx @@ -4,6 +4,7 @@ import React from "react"; import { actionCreators as ac } from "common/Actions.sys.mjs"; +import { SafeAnchor } from "../../DiscoveryStreamComponents/SafeAnchor/SafeAnchor"; export class ContentSection extends React.PureComponent { constructor(props) { @@ -96,6 +97,7 @@ export class ContentSection extends React.PureComponent { mayHaveSponsoredStories, mayHaveRecentSaves, openPreferences, + spocMessageVariant, } = this.props; const { topSitesEnabled, @@ -254,6 +256,23 @@ export class ContentSection extends React.PureComponent { + {pocketRegion && + mayHaveSponsoredStories && + spocMessageVariant === "variant-c" && ( +
+
+
+ Sponsored content supports our mission to build a better web.{" "} + + Find out how + +
+
+ )} +
diff --git a/browser/components/newtab/content-src/components/CustomizeMenu/CustomizeMenu.jsx b/browser/components/newtab/content-src/components/CustomizeMenu/CustomizeMenu.jsx index 3d33f6fde7..54dcd550c4 100644 --- a/browser/components/newtab/content-src/components/CustomizeMenu/CustomizeMenu.jsx +++ b/browser/components/newtab/content-src/components/CustomizeMenu/CustomizeMenu.jsx @@ -71,6 +71,7 @@ export class _CustomizeMenu extends React.PureComponent { mayHaveSponsoredTopSites={this.props.mayHaveSponsoredTopSites} mayHaveSponsoredStories={this.props.mayHaveSponsoredStories} mayHaveRecentSaves={this.props.DiscoveryStream.recentSavesEnabled} + spocMessageVariant={this.props.spocMessageVariant} dispatch={this.props.dispatch} />
diff --git a/browser/components/newtab/content-src/components/CustomizeMenu/_CustomizeMenu.scss b/browser/components/newtab/content-src/components/CustomizeMenu/_CustomizeMenu.scss index f534b8701b..579e455a3f 100644 --- a/browser/components/newtab/content-src/components/CustomizeMenu/_CustomizeMenu.scss +++ b/browser/components/newtab/content-src/components/CustomizeMenu/_CustomizeMenu.scss @@ -143,6 +143,10 @@ border-radius: 4px; appearance: none; background-color: var(--newtab-element-secondary-color); + + &:hover { + background-color: var(--newtab-element-secondary-hover-color); + } } .sponsored-checkbox:checked { @@ -151,6 +155,14 @@ background: url('chrome://global/skin/icons/check.svg') center no-repeat; background-color: var(--newtab-primary-action-background); + &:hover { + background-color: var(--newtab-primary-element-hover-color); + } + + &:active { + background-color: var(--newtab-primary-element-active-color); + } + @media (forced-colors: active) { fill: $black; } @@ -178,6 +190,10 @@ background-origin: content-box; background-color: var(--newtab-background-color-secondary); + &:hover { + background-color: var(--newtab-element-secondary-hover-color); + } + &:dir(rtl) { background-position-x: left; } @@ -201,6 +217,25 @@ } } + .sponsored-content-info { + display: flex; + gap: var(--space-small); + font-size: var(--font-size-small); + border-radius: var(--border-radius-medium); + background-color: var(--newtab-element-secondary-color); + padding: var(--space-small) var(--space-large); + + .icon-help { + flex-shrink: 0; + color: var(--color-accent-primary); + height: 20px; + } + + a { + color: var(--newtab-primary-action-background); + } + } + .divider { border-top: 1px var(--newtab-border-color) solid; margin: 0 -16px; diff --git a/browser/components/newtab/content-src/components/DiscoveryStreamAdmin/DiscoveryStreamAdmin.jsx b/browser/components/newtab/content-src/components/DiscoveryStreamAdmin/DiscoveryStreamAdmin.jsx index 0112013391..3c31a5a29f 100644 --- a/browser/components/newtab/content-src/components/DiscoveryStreamAdmin/DiscoveryStreamAdmin.jsx +++ b/browser/components/newtab/content-src/components/DiscoveryStreamAdmin/DiscoveryStreamAdmin.jsx @@ -143,7 +143,7 @@ export class DiscoveryStreamAdminUI extends React.PureComponent { ); } - restorePrefDefaults(event) { + restorePrefDefaults() { this.props.dispatch( ac.OnlyToMain({ type: at.DISCOVERY_STREAM_CONFIG_RESET_DEFAULTS, diff --git a/browser/components/newtab/content-src/components/DiscoveryStreamBase/DiscoveryStreamBase.jsx b/browser/components/newtab/content-src/components/DiscoveryStreamBase/DiscoveryStreamBase.jsx index dff122b366..0f0ee51ab9 100644 --- a/browser/components/newtab/content-src/components/DiscoveryStreamBase/DiscoveryStreamBase.jsx +++ b/browser/components/newtab/content-src/components/DiscoveryStreamBase/DiscoveryStreamBase.jsx @@ -110,7 +110,7 @@ export class _DiscoveryStreamBase extends React.PureComponent { }); } - renderComponent(component, embedWidth) { + renderComponent(component) { switch (component.type) { case "Highlights": return ; @@ -196,6 +196,7 @@ export class _DiscoveryStreamBase extends React.PureComponent { onboardingExperience={component.properties.onboardingExperience} ctaButtonSponsors={component.properties.ctaButtonSponsors} ctaButtonVariant={component.properties.ctaButtonVariant} + spocMessageVariant={component.properties.spocMessageVariant} editorsPicksHeader={component.properties.editorsPicksHeader} recentSavesEnabled={this.props.DiscoveryStream.recentSavesEnabled} hideDescriptions={this.props.DiscoveryStream.hideDescriptions} @@ -218,7 +219,7 @@ export class _DiscoveryStreamBase extends React.PureComponent { } render() { - const { locale } = this.props; + const { locale, mayHaveSponsoredStories } = this.props; // Select layout render data by adding spocs and position to recommendations const { layoutRender } = selectLayoutRender({ state: this.props.DiscoveryStream, @@ -322,6 +323,8 @@ export class _DiscoveryStreamBase extends React.PureComponent { showPrefName={topStories.pref.feed} title={sectionTitle} subTitle={subTitle} + mayHaveSponsoredStories={mayHaveSponsoredStories} + spocMessageVariant={message?.properties?.spocMessageVariant} eventSource="CARDGRID" > {this.renderLayout(layoutRender)} diff --git a/browser/components/newtab/content-src/components/DiscoveryStreamComponents/CardGrid/CardGrid.jsx b/browser/components/newtab/content-src/components/DiscoveryStreamComponents/CardGrid/CardGrid.jsx index f13e0eb7ed..cf00361df2 100644 --- a/browser/components/newtab/content-src/components/DiscoveryStreamComponents/CardGrid/CardGrid.jsx +++ b/browser/components/newtab/content-src/components/DiscoveryStreamComponents/CardGrid/CardGrid.jsx @@ -31,11 +31,7 @@ export function DSSubHeader({ children }) { ); } -export function OnboardingExperience({ - children, - dispatch, - windowObj = global, -}) { +export function OnboardingExperience({ dispatch, windowObj = global }) { const [dismissed, setDismissed] = useState(false); const [maxHeight, setMaxHeight] = useState(null); const heightElement = useRef(null); @@ -330,6 +326,7 @@ export class _CardGrid extends React.PureComponent { onboardingExperience, ctaButtonSponsors, ctaButtonVariant, + spocMessageVariant, widgets, recentSavesEnabled, hideDescriptions, @@ -378,6 +375,7 @@ export class _CardGrid extends React.PureComponent { saveToPocketCard={saveToPocketCard} ctaButtonSponsors={ctaButtonSponsors} ctaButtonVariant={ctaButtonVariant} + spocMessageVariant={spocMessageVariant} recommendation_id={rec.recommendation_id} /> ) diff --git a/browser/components/newtab/content-src/components/DiscoveryStreamComponents/DSCard/DSCard.jsx b/browser/components/newtab/content-src/components/DiscoveryStreamComponents/DSCard/DSCard.jsx index 6aef56fb33..f3e1eab503 100644 --- a/browser/components/newtab/content-src/components/DiscoveryStreamComponents/DSCard/DSCard.jsx +++ b/browser/components/newtab/content-src/components/DiscoveryStreamComponents/DSCard/DSCard.jsx @@ -85,8 +85,9 @@ export const DefaultMeta = ({ sponsor, sponsored_by_override, saveToPocketCard, - isRecentSave, ctaButtonVariant, + dispatch, + spocMessageVariant, }) => (
@@ -100,9 +101,7 @@ export const DefaultMeta = ({ sponsored_by_override={sponsored_by_override} /> )} -
- {title} -
+
{title}
{excerpt &&

{excerpt}

}
{!newSponsoredLabel && ( @@ -113,6 +112,8 @@ export const DefaultMeta = ({ sponsored_by_override={sponsored_by_override} cta_button_variant={ctaButtonVariant} source={source} + dispatch={dispatch} + spocMessageVariant={spocMessageVariant} /> )} {/* Sponsored label is normally in the way of any message. @@ -183,7 +184,7 @@ export class _DSCard extends React.PureComponent { ]; } - onLinkClick(event) { + onLinkClick() { if (this.props.dispatch) { this.props.dispatch( ac.DiscoveryStreamUserEvent({ @@ -223,7 +224,7 @@ export class _DSCard extends React.PureComponent { } } - onSaveClick(event) { + onSaveClick() { if (this.props.dispatch) { this.props.dispatch( ac.AlsoToMain({ @@ -408,43 +409,28 @@ export class _DSCard extends React.PureComponent { }; return ( -
+
+ +
-
- -
- {ctaButtonVariant === "variant-b" && ( -
Shop Now
- )} -
+ {ctaButtonVariant === "variant-b" && ( +
Shop Now
+ )} + {saveToPocketCard && (
@@ -512,7 +516,7 @@ export class _DSCard extends React.PureComponent { isRecentSave={isRecentSave} /> )} -
+ ); } } @@ -526,4 +530,4 @@ export const DSCard = connect(state => ({ DiscoveryStream: state.DiscoveryStream, }))(_DSCard); -export const PlaceholderDSCard = props => ; +export const PlaceholderDSCard = () => ; diff --git a/browser/components/newtab/content-src/components/DiscoveryStreamComponents/DSCard/_DSCard.scss b/browser/components/newtab/content-src/components/DiscoveryStreamComponents/DSCard/_DSCard.scss index 92afedff26..9004e609df 100644 --- a/browser/components/newtab/content-src/components/DiscoveryStreamComponents/DSCard/_DSCard.scss +++ b/browser/components/newtab/content-src/components/DiscoveryStreamComponents/DSCard/_DSCard.scss @@ -118,6 +118,16 @@ $ds-card-image-gradient-solid: rgba(0, 0, 0, 100%); transform: scale(1); } } + + header { + color: var(--newtab-primary-action-background); + } + } + + &:active { + header { + color: var(--newtab-primary-element-active-color); + } } .img { @@ -131,31 +141,15 @@ $ds-card-image-gradient-solid: rgba(0, 0, 0, 100%); } .ds-card-link { + position: absolute; height: 100%; - display: flex; - flex-direction: column; + width: 100%; text-decoration: none; - &:hover { - header { - color: var(--newtab-primary-action-background); - } - } - &:focus { @include ds-focus; transition: none; - - header { - color: var(--newtab-primary-action-background); - } - } - - &:active { - header { - color: var(--newtab-primary-element-active-color); - } } } @@ -255,7 +249,7 @@ $ds-card-image-gradient-solid: rgba(0, 0, 0, 100%); flex-wrap: wrap; justify-content: space-between; align-items: center; - column-gap: var(--space-small); + gap: 0 var(--space-small); margin-top: 0; } diff --git a/browser/components/newtab/content-src/components/DiscoveryStreamComponents/DSContextFooter/DSContextFooter.jsx b/browser/components/newtab/content-src/components/DiscoveryStreamComponents/DSContextFooter/DSContextFooter.jsx index 5c7e79685e..6c0641cfc1 100644 --- a/browser/components/newtab/content-src/components/DiscoveryStreamComponents/DSContextFooter/DSContextFooter.jsx +++ b/browser/components/newtab/content-src/components/DiscoveryStreamComponents/DSContextFooter/DSContextFooter.jsx @@ -3,6 +3,7 @@ * You can obtain one at http://mozilla.org/MPL/2.0/. */ import { cardContextTypes } from "../../Card/types.js"; +import { SponsoredContentHighlight } from "../FeatureHighlight/SponsoredContentHighlight"; import { CSSTransition, TransitionGroup } from "react-transition-group"; import { FluentOrText } from "../../FluentOrText/FluentOrText.jsx"; import React from "react"; @@ -82,6 +83,8 @@ export class DSContextFooter extends React.PureComponent { sponsored_by_override, cta_button_variant, source, + spocMessageVariant, + dispatch, } = this.props; const sponsorLabel = SponsorLabel({ @@ -119,6 +122,12 @@ export class DSContextFooter extends React.PureComponent { return (
{sponsorLabel} + {sponsorLabel && spocMessageVariant === "variant-b" && ( + + )} {dsMessageLabel}
); diff --git a/browser/components/newtab/content-src/components/DiscoveryStreamComponents/DSContextFooter/_DSContextFooter.scss b/browser/components/newtab/content-src/components/DiscoveryStreamComponents/DSContextFooter/_DSContextFooter.scss index c23bb1c661..b28b498682 100644 --- a/browser/components/newtab/content-src/components/DiscoveryStreamComponents/DSContextFooter/_DSContextFooter.scss +++ b/browser/components/newtab/content-src/components/DiscoveryStreamComponents/DSContextFooter/_DSContextFooter.scss @@ -2,7 +2,10 @@ color: var(--newtab-text-secondary-color); inset-inline-start: 0; margin-top: 12px; + display: flex; + gap: var(--space-large); position: relative; + pointer-events: none; .story-sponsored-label span { display: inline-block; diff --git a/browser/components/newtab/content-src/components/DiscoveryStreamComponents/DSPrivacyModal/DSPrivacyModal.jsx b/browser/components/newtab/content-src/components/DiscoveryStreamComponents/DSPrivacyModal/DSPrivacyModal.jsx index f342c9829b..b251fb0401 100644 --- a/browser/components/newtab/content-src/components/DiscoveryStreamComponents/DSPrivacyModal/DSPrivacyModal.jsx +++ b/browser/components/newtab/content-src/components/DiscoveryStreamComponents/DSPrivacyModal/DSPrivacyModal.jsx @@ -17,7 +17,7 @@ export class DSPrivacyModal extends React.PureComponent { this.onManageLinkClick = this.onManageLinkClick.bind(this); } - onLearnLinkClick(event) { + onLearnLinkClick() { this.props.dispatch( ac.DiscoveryStreamUserEvent({ event: "CLICK_PRIVACY_INFO", @@ -26,7 +26,7 @@ export class DSPrivacyModal extends React.PureComponent { ); } - onManageLinkClick(event) { + onManageLinkClick() { this.props.dispatch(ac.OnlyToMain({ type: at.SETTINGS_OPEN })); } @@ -50,7 +50,7 @@ export class DSPrivacyModal extends React.PureComponent { className="modal-link modal-link-privacy" data-l10n-id="newtab-privacy-modal-link" onClick={this.onLearnLinkClick} - href="https://help.getpocket.com/article/1142-firefox-new-tab-recommendations-faq" + href="https://support.mozilla.org/kb/pocket-recommendations-firefox-new-tab" /> +
+
{icon}
+

{message}

+ +
+
+ ); +} diff --git a/browser/components/newtab/content-src/components/DiscoveryStreamComponents/FeatureHighlight/SponsoredContentHighlight.jsx b/browser/components/newtab/content-src/components/DiscoveryStreamComponents/FeatureHighlight/SponsoredContentHighlight.jsx new file mode 100644 index 0000000000..8fdd03be6d --- /dev/null +++ b/browser/components/newtab/content-src/components/DiscoveryStreamComponents/FeatureHighlight/SponsoredContentHighlight.jsx @@ -0,0 +1,34 @@ +/* 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 { FeatureHighlight } from "./FeatureHighlight"; +import { SafeAnchor } from "../SafeAnchor/SafeAnchor"; +import React from "react"; + +export function SponsoredContentHighlight({ position, dispatch }) { + return ( +
+ + Sponsored content supports our mission to build a better web.{" "} + + Find out how + + + } + icon={
} + toggle={
} + /> +
+ ); +} diff --git a/browser/components/newtab/content-src/components/DiscoveryStreamComponents/FeatureHighlight/_FeatureHighlight.scss b/browser/components/newtab/content-src/components/DiscoveryStreamComponents/FeatureHighlight/_FeatureHighlight.scss new file mode 100644 index 0000000000..c0fdd52f58 --- /dev/null +++ b/browser/components/newtab/content-src/components/DiscoveryStreamComponents/FeatureHighlight/_FeatureHighlight.scss @@ -0,0 +1,98 @@ +.feature-highlight { + position: relative; + // This is needed because in 1 case this is positioned under a link + // and in an element that's not clickable. + pointer-events: auto; + z-index: 1; + + .feature-highlight-modal { + position: absolute; + display: flex; + opacity: 0; + visibility: hidden; + cursor: default; + justify-content: space-between; + border-radius: var(--border-radius-small); + background: var(--newtab-background-color-secondary); + box-shadow: 0 2px 6px rgba(0, 0, 0, 15%); + width: 298px; + transition: opacity 0.3s, visibility 0.3s; + + .icon-dismiss { + flex-shrink: 0; + cursor: pointer; + background-size: $smaller-icon-size; + height: $smaller-icon-size; + width: $smaller-icon-size; + margin: var(--space-medium); + color: var(--icon-color); + border: none; + } + + .message-icon { + margin-block: var(--space-large); + margin-inline: var(--space-large) var(--space-medium); + } + + &.opened { + opacity: 1; + visibility: visible; + } + + &::after { + content: ''; + position: absolute; + height: 24px; + width: 24px; + background: var(--newtab-background-color-secondary); + box-shadow: 4px 4px 6px -2px rgba(0, 0, 0, 15%); + } + + &.inset-block-start { + inset-block-end: 100%; + margin-bottom: var(--space-xlarge); + + &::after { + inset-block-end: -12px; + transform: rotate(45deg); + } + } + + &.inset-block-end { + inset-block-start: 100%; + margin-top: var(--space-xlarge); + + &::after { + inset-block-start: -12px; + transform: rotate(225deg); + } + } + + &.inset-inline-start { + inset-inline-end: calc(var(--space-xxlarge) * -1); + + &::after { + inset-inline-end: calc(var(--space-xxlarge) - 12px); + } + } + + &.inset-inline-end { + inset-inline-start: calc(var(--space-xxlarge) * -1); + + &::after { + inset-inline-start: calc(var(--space-xxlarge) - 12px); + } + } + + p { + font-size: var(--font-size-small); + font-weight: normal; + margin: var(--space-large) 0; + } + } + + .toggle-button { + border: none; + padding: 0; + } +} diff --git a/browser/components/newtab/content-src/components/DiscoveryStreamComponents/FeatureHighlight/_SponsoredContentHighlight.scss b/browser/components/newtab/content-src/components/DiscoveryStreamComponents/FeatureHighlight/_SponsoredContentHighlight.scss new file mode 100644 index 0000000000..1dc024b7c0 --- /dev/null +++ b/browser/components/newtab/content-src/components/DiscoveryStreamComponents/FeatureHighlight/_SponsoredContentHighlight.scss @@ -0,0 +1,33 @@ +.sponsored-content-highlight { + float: inline-end; + + .sponsored-message-icon { + background-image: url('chrome://activity-stream/content/data/content/assets/sponsor-message-icon.svg'); + background-size: 18px; + height: 18px; + width: 18px; + } + + .icon-help { + cursor: pointer; + height: 20px; + width: 20px; + background-size: 20px; + color: var(--icon-color); + vertical-align: text-bottom; + } + + .feature-highlight-modal { + &.inset-inline-start { + &::after { + margin-inline-end: 11px; + } + } + + &.inset-inline-end { + &::after { + margin-inline-start: 9px; + } + } + } +} diff --git a/browser/components/newtab/content-src/components/DiscoveryStreamComponents/SafeAnchor/SafeAnchor.jsx b/browser/components/newtab/content-src/components/DiscoveryStreamComponents/SafeAnchor/SafeAnchor.jsx index cfbc6fe6cb..72ec94e1fe 100644 --- a/browser/components/newtab/content-src/components/DiscoveryStreamComponents/SafeAnchor/SafeAnchor.jsx +++ b/browser/components/newtab/content-src/components/DiscoveryStreamComponents/SafeAnchor/SafeAnchor.jsx @@ -55,9 +55,14 @@ export class SafeAnchor extends React.PureComponent { } render() { - const { url, className } = this.props; + const { url, className, title } = this.props; return ( - + {this.props.children} ); diff --git a/browser/components/newtab/content-src/components/ErrorBoundary/ErrorBoundary.jsx b/browser/components/newtab/content-src/components/ErrorBoundary/ErrorBoundary.jsx index 1834a0a521..6bf1614ce7 100644 --- a/browser/components/newtab/content-src/components/ErrorBoundary/ErrorBoundary.jsx +++ b/browser/components/newtab/content-src/components/ErrorBoundary/ErrorBoundary.jsx @@ -52,7 +52,7 @@ export class ErrorBoundary extends React.PureComponent { this.state = { hasError: false }; } - componentDidCatch(error, info) { + componentDidCatch() { this.setState({ hasError: true }); } diff --git a/browser/components/newtab/content-src/components/TopSites/TopSite.jsx b/browser/components/newtab/content-src/components/TopSites/TopSite.jsx index b7f0038558..c0932104af 100644 --- a/browser/components/newtab/content-src/components/TopSites/TopSite.jsx +++ b/browser/components/newtab/content-src/components/TopSites/TopSite.jsx @@ -159,7 +159,10 @@ export class TopSiteLink extends React.PureComponent { // If we have tabbed to a search shortcut top site, and we click 'enter', // we should execute the onClick function. This needs to be added because // search top sites are anchor tags without an href. See bug 1483135 - if (this.props.link.searchTopSite && event.key === "Enter") { + if ( + event.key === "Enter" && + (this.props.link.searchTopSite || this.props.isAddButton) + ) { this.props.onClick(event); } } @@ -250,8 +253,15 @@ export class TopSiteLink extends React.PureComponent { } render() { - const { children, className, isDraggable, link, onClick, title } = - this.props; + const { + children, + className, + isDraggable, + link, + onClick, + title, + isAddButton, + } = this.props; const topSiteOuterClassName = `top-site-outer${ className ? ` ${className}` : "" }${link.isDragged ? " dragged" : ""}${ @@ -266,6 +276,10 @@ export class TopSiteLink extends React.PureComponent { selectedColor, } = this.calculateStyle(); + let addButtonl10n = { + "data-l10n-id": "newtab-topsites-add-shortcut-label", + }; + let draggableProps = {}; if (isDraggable) { draggableProps = { @@ -380,14 +394,14 @@ export class TopSiteLink extends React.PureComponent { : "" }`} > - + {link.isPinned &&
} {title ||
} - +
{children} @@ -635,19 +649,23 @@ export class TopSitePlaceholder extends React.PureComponent { } render() { + let addButtonProps = {}; + if (this.props.isAddButton) { + addButtonProps = { + title: "newtab-topsites-add-shortcut-label", + onClick: this.onEditButtonClick, + }; + } + return ( -