diff options
Diffstat (limited to 'browser/components/newtab/content-src/components/DiscoveryStreamComponents/TopicsWidget')
2 files changed, 213 insertions, 0 deletions
diff --git a/browser/components/newtab/content-src/components/DiscoveryStreamComponents/TopicsWidget/TopicsWidget.jsx b/browser/components/newtab/content-src/components/DiscoveryStreamComponents/TopicsWidget/TopicsWidget.jsx new file mode 100644 index 0000000000..1fe2343b94 --- /dev/null +++ b/browser/components/newtab/content-src/components/DiscoveryStreamComponents/TopicsWidget/TopicsWidget.jsx @@ -0,0 +1,125 @@ +/* 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"; +import { actionCreators as ac } from "common/Actions.sys.mjs"; +import { SafeAnchor } from "../SafeAnchor/SafeAnchor"; +import { ImpressionStats } from "../../DiscoveryStreamImpressionStats/ImpressionStats"; +import { connect } from "react-redux"; + +export function _TopicsWidget(props) { + const { id, source, position, DiscoveryStream, dispatch } = props; + + const { utmCampaign, utmContent, utmSource } = DiscoveryStream.experimentData; + + let queryParams = `?utm_source=${utmSource}`; + if (utmCampaign && utmContent) { + queryParams += `&utm_content=${utmContent}&utm_campaign=${utmCampaign}`; + } + + const topics = [ + { label: "Technology", name: "technology" }, + { label: "Science", name: "science" }, + { label: "Self-Improvement", name: "self-improvement" }, + { label: "Travel", name: "travel" }, + { label: "Career", name: "career" }, + { label: "Entertainment", name: "entertainment" }, + { label: "Food", name: "food" }, + { label: "Health", name: "health" }, + { + label: "Must-Reads", + name: "must-reads", + url: `https://getpocket.com/collections${queryParams}`, + }, + ]; + + function onLinkClick(topic, positionInCard) { + if (dispatch) { + dispatch( + ac.DiscoveryStreamUserEvent({ + event: "CLICK", + source, + action_position: position, + value: { + card_type: "topics_widget", + topic, + ...(positionInCard || positionInCard === 0 + ? { position_in_card: positionInCard } + : {}), + }, + }) + ); + dispatch( + ac.ImpressionStats({ + source, + click: 0, + window_inner_width: props.windowObj.innerWidth, + window_inner_height: props.windowObj.innerHeight, + tiles: [ + { + id, + pos: position, + }, + ], + }) + ); + } + } + + function mapTopicItem(topic, index) { + return ( + <li + key={topic.name} + className={topic.overflow ? "ds-topics-widget-list-overflow-item" : ""} + > + <SafeAnchor + url={ + topic.url || + `https://getpocket.com/explore/${topic.name}${queryParams}` + } + dispatch={dispatch} + onLinkClick={() => onLinkClick(topic.name, index)} + > + {topic.label} + </SafeAnchor> + </li> + ); + } + + return ( + <div className="ds-topics-widget"> + <header className="ds-topics-widget-header">Popular Topics</header> + <hr /> + <div className="ds-topics-widget-list-container"> + <ul>{topics.map(mapTopicItem)}</ul> + </div> + <SafeAnchor + className="ds-topics-widget-button button primary" + url={`https://getpocket.com/${queryParams}`} + dispatch={dispatch} + onLinkClick={() => onLinkClick("more-topics")} + > + More Topics + </SafeAnchor> + <ImpressionStats + dispatch={dispatch} + rows={[ + { + id, + pos: position, + }, + ]} + source={source} + /> + </div> + ); +} + +_TopicsWidget.defaultProps = { + windowObj: window, // Added to support unit tests +}; + +export const TopicsWidget = connect(state => ({ + DiscoveryStream: state.DiscoveryStream, +}))(_TopicsWidget); diff --git a/browser/components/newtab/content-src/components/DiscoveryStreamComponents/TopicsWidget/_TopicsWidget.scss b/browser/components/newtab/content-src/components/DiscoveryStreamComponents/TopicsWidget/_TopicsWidget.scss new file mode 100644 index 0000000000..d05d46cd07 --- /dev/null +++ b/browser/components/newtab/content-src/components/DiscoveryStreamComponents/TopicsWidget/_TopicsWidget.scss @@ -0,0 +1,88 @@ +.ds-topics-widget { + display: flex; + position: relative; + flex-direction: column; + + .ds-topics-widget-header { + font-size: 18px; + line-height: 20px; + } + + hr { + background-color: color-mix(in srgb, var(--newtab-border-color) 52%, transparent); + height: 1px; + border: 0; + margin: 10px 0 0; + } + + .ds-topics-widget-list-container { + flex-grow: 1; + + ul { + margin: 14px 0 0; + padding: 0; + display: flex; + align-items: center; + grid-gap: 10px; + flex-wrap: wrap; + + li { + display: flex; + + a { + font-size: 14px; + line-height: 16px; + text-decoration: none; + padding: 8px 15px; + background: var(--newtab-background-color-secondary); + border: 1px solid color-mix(in srgb, var(--newtab-border-color) 52%, transparent); + color: var(--newtab-text-primary-color); + border-radius: 8px; + + &:hover { + background: var(--newtab-element-hover-color); + } + + &:focus { + outline: 0; + box-shadow: 0 0 0 3px var(--newtab-primary-action-background-dimmed), 0 0 0 1px var(--newtab-primary-action-background); + transition: box-shadow 150ms; + } + } + } + + .ds-topics-widget-list-overflow-item { + display: flex; + + @media (min-width: $break-point-medium) { + display: none; + } + + @media (min-width: $break-point-widest) { + display: flex; + } + } + } + } + + .ds-topics-widget-button { + margin: 14px 0 0; + font-size: 16px; + line-height: 24px; + text-align: center; + padding: 8px; + border-radius: 4px; + background-color: var(--newtab-primary-action-background-pocket); + border: 0; + + &:hover { + background: var(--newtab-primary-element-hover-pocket-color); + } + + &:focus { + outline: 0; + box-shadow: 0 0 0 3px var(--newtab-primary-action-background-pocket-dimmed), 0 0 0 1px var(--newtab-primary-action-background-pocket); + transition: box-shadow 150ms; + } + } +} |