From e8408455bf13d56f1c606cbee8ff476416660a2a Mon Sep 17 00:00:00 2001 From: Jay Harris Date: Fri, 12 Jan 2024 12:21:29 +1300 Subject: [PATCH] [Brave News]: Tweaks round 5 (#21516) * Migrate article channel names Hide sidebar on small screens PoC sidebar Lazy load sidebar Fix background Fix ad link Add articles with no images Create top bar Styling improvements Sidebar color tweaks Sidebar color tweaks Make buttons nicer * Same top level headings * Remove sidebar title * Monochrome news icon on peeking card * Fix peek button not showing on empty feeds * Heading cleanup --- browser/ui/webui/brave_webui_source.cc | 2 - .../components/default/braveNews/FeedV2.tsx | 59 +++++++++++++----- .../default/braveNews/SidebarMenu.tsx | 60 +++++++++++++++++++ .../browser/combined_feed_parsing.cc | 16 +++-- .../browser/resources/FeedNavigation.tsx | 50 +++++++--------- .../brave_news/browser/resources/Peek.tsx | 13 ++-- .../browser/resources/SettingsButton.tsx | 24 ++++++++ .../brave_news/browser/resources/feed/Ad.tsx | 2 +- .../browser/resources/shared/Icons.tsx | 56 ++++++++--------- components/common/useMediaQuery.ts | 23 +++++++ components/resources/brave_news_strings.grdp | 6 -- ui/webui/resources/BUILD.gn | 1 + 12 files changed, 219 insertions(+), 93 deletions(-) create mode 100644 components/brave_new_tab_ui/components/default/braveNews/SidebarMenu.tsx create mode 100644 components/brave_news/browser/resources/SettingsButton.tsx create mode 100644 components/common/useMediaQuery.ts diff --git a/browser/ui/webui/brave_webui_source.cc b/browser/ui/webui/brave_webui_source.cc index 0b22235c3bc3..aee21c474b8c 100644 --- a/browser/ui/webui/brave_webui_source.cc +++ b/browser/ui/webui/brave_webui_source.cc @@ -232,10 +232,8 @@ void CustomizeWebUIHTMLSource(content::WebUI* web_ui, { "braveNewsNoContentActionLabel", IDS_BRAVE_NEWS_NO_CONTENT_ACTION_LABEL}, // NOLINT { "braveNewsPopularTitle", IDS_BRAVE_NEWS_POPULAR_TITLE}, { "braveNewsNewsPeek", IDS_BRAVE_NEWS_NEWS_PEEK}, - { "braveNewsMyFeedHeading", IDS_BRAVE_NEWS_MY_FEED_HEADING}, { "braveNewsForYouFeed",IDS_BRAVE_NEWS_FOR_YOU_FEED}, { "braveNewsFollowingFeed", IDS_BRAVE_NEWS_FOLLOWING_FEED}, - { "braveNewsAddChannelsOrPublishers",IDS_BRAVE_NEWS_ADD_CHANNELS_OR_PUBLISHERS}, { "braveNewsPublishersHeading", IDS_BRAVE_NEWS_PUBLISHERS_HEADING}, { "braveNewsShowAll", IDS_BRAVE_NEWS_SHOW_ALL}, { "braveNewsShowLess", IDS_BRAVE_NEWS_SHOW_LESS}, diff --git a/components/brave_new_tab_ui/components/default/braveNews/FeedV2.tsx b/components/brave_new_tab_ui/components/default/braveNews/FeedV2.tsx index 405192205b63..a823019b97bf 100644 --- a/components/brave_new_tab_ui/components/default/braveNews/FeedV2.tsx +++ b/components/brave_new_tab_ui/components/default/braveNews/FeedV2.tsx @@ -4,19 +4,26 @@ // You can obtain one at https://mozilla.org/MPL/2.0/. import Flex from '$web-common/Flex' import { getLocale } from '$web-common/locale' -import Button from '@brave/leo/react/button' import Icon from '@brave/leo/react/icon' import { radius, spacing } from '@brave/leo/tokens/css' import * as React from 'react' import styled from 'styled-components' import Feed from '../../../../brave_news/browser/resources/Feed' -import FeedNavigation from '../../../../brave_news/browser/resources/FeedNavigation' import NewsButton from '../../../../brave_news/browser/resources/NewsButton' import Variables from '../../../../brave_news/browser/resources/Variables' import { useBraveNews } from '../../../../brave_news/browser/resources/shared/Context' import { CLASSNAME_PAGE_STUCK } from '../page' +import SettingsButton from '../../../../brave_news/browser/resources/SettingsButton' +import useMediaQuery from '$web-common/useMediaQuery' + +const SidebarMenu = React.lazy(() => import('./SidebarMenu')) +const FeedNavigation = React.lazy(() => import('../../../../brave_news/browser/resources/FeedNavigation')) + +const isSmallQuery = '(max-width: 1024px)' const Root = styled(Variables)` + --bn-top-bar-height: 78px; + padding-top: ${spacing.xl}; display: grid; @@ -50,17 +57,30 @@ const ButtonsContainer = styled.div` visibility: visible; } - display: flex; - gap: ${spacing.m}; padding: ${spacing.m}; background: var(--bn-glass-container); + backdrop-filter: blur(64px); + + @media ${isSmallQuery} { + height: var(--bn-top-bar-height); + + inset: 0; + bottom: unset; + padding: ${spacing['2Xl']} ${spacing.xl}; + border-radius: 0; + } ` -const SettingsButton = styled(Button)` - --leo-button-color: var(--bn-glass-50); - --leo-button-radius: ${radius.s}; - --leo-button-padding: ${spacing.s}; +const ButtonSpacer = styled.div` + max-width: min(540px, 100vw); + + display: flex; + justify-content: flex-end; + gap: ${spacing.m}; + + margin-left: auto; + margin-right: auto; ` const LoadNewContentButton = styled(NewsButton)` @@ -69,9 +89,15 @@ const LoadNewContentButton = styled(NewsButton)` top: ${spacing['3Xl']}; flex-grow: 0; + + @media ${isSmallQuery} { + top: calc(var(--bn-top-bar-height) + var(--leo-spacing-m)); + } ` export default function FeedV2() { + const isSmall = useMediaQuery(isSmallQuery) + const { feedV2, setCustomizePage, refreshFeedV2, feedV2UpdatesAvailable } = useBraveNews() const ref = React.useRef() @@ -88,7 +114,7 @@ export default function FeedV2() { return - + {!isSmall && } {feedV2UpdatesAvailable && @@ -98,12 +124,15 @@ export default function FeedV2() { - setCustomizePage('news')} title={getLocale('braveNewsCustomizeFeed')}> - - - { - refreshFeedV2() - }}> + + {isSmall && } + setCustomizePage('news')} title={getLocale('braveNewsCustomizeFeed')}> + + + { + refreshFeedV2() + }}> + } diff --git a/components/brave_new_tab_ui/components/default/braveNews/SidebarMenu.tsx b/components/brave_new_tab_ui/components/default/braveNews/SidebarMenu.tsx new file mode 100644 index 000000000000..29228f361cfa --- /dev/null +++ b/components/brave_new_tab_ui/components/default/braveNews/SidebarMenu.tsx @@ -0,0 +1,60 @@ +// Copyright (c) 2024 The Brave Authors. All rights reserved. +// 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 https://mozilla.org/MPL/2.0/. + +import * as React from 'react'; +import styled from 'styled-components'; +import FeedNavigation from '../../../../brave_news/browser/resources/FeedNavigation'; +import SettingsButton from '../../../../brave_news/browser/resources/SettingsButton'; +import Icon from '@brave/leo/react/icon'; + +const Container = styled.dialog` + top: var(--bn-top-bar-height); + height: calc(100vh - var(--bn-top-bar-height)); + + overflow: hidden; + + margin-left: 0; + margin-top: 0; + padding: 0; + + position: fixed; + display: flex; + + transition: transform 0.2s ease-in-out; + transform: translateX(-100%); + + background: var(--bn-glass-card); + backdrop-filter: blur(64px); + border: none; + outline: none; + + &[open] { + transform: translateX(0); + } + + &> div { + background: unset; + } +` + +const MenuButton = styled(SettingsButton)` + margin-right: auto; +` + +export default function SidebarMenu() { + const dialogRef = React.useRef() + return dialogRef.current?.showModal()}> + + { + // Close the menu on click outside. + const bounds = e.currentTarget.getBoundingClientRect() + if (e.clientX < bounds.x || e.clientY < bounds.y || e.clientX > bounds.right || e.clientY > bounds.bottom) { + e.currentTarget.close() + } + }}> + + + +} diff --git a/components/brave_news/browser/combined_feed_parsing.cc b/components/brave_news/browser/combined_feed_parsing.cc index b57c4cf22fa9..88200ac75eae 100644 --- a/components/brave_news/browser/combined_feed_parsing.cc +++ b/components/brave_news/browser/combined_feed_parsing.cc @@ -9,6 +9,7 @@ #include #include +#include "base/feature_list.h" #include "base/logging.h" #include "base/notreached.h" #include "base/strings/strcat.h" @@ -16,9 +17,10 @@ #include "base/time/time.h" #include "base/types/expected.h" #include "brave/components/brave_news/api/combined_feed.h" +#include "brave/components/brave_news/browser/channel_migrator.h" #include "brave/components/brave_news/common/brave_news.mojom-forward.h" -#include "brave/components/brave_news/common/brave_news.mojom-shared.h" #include "brave/components/brave_news/common/brave_news.mojom.h" +#include "brave/components/brave_news/common/features.h" #include "third_party/abseil-cpp/absl/types/optional.h" #include "ui/base/l10n/time_format.h" #include "url/gurl.h" @@ -49,9 +51,13 @@ base::expected ParseFeedItem( base::StrCat({"Item url was not HTTP or HTTPS: url=", url.spec()})); } - if (feed_item.padded_img.empty()) { - return base::unexpected(base::StrCat( - {"Found feed item with missing image. url=", feed_item.url})); + // FeedV2 supports articles with no images, such as the ones from Brave Blog. + if (!base::FeatureList::IsEnabled( + brave_news::features::kBraveNewsFeedUpdate)) { + if (feed_item.padded_img.empty()) { + return base::unexpected(base::StrCat( + {"Found feed item with missing image. url=", feed_item.url})); + } } if (feed_item.publisher_id.empty()) { @@ -70,7 +76,7 @@ base::expected ParseFeedItem( } auto metadata = mojom::FeedItemMetadata::New(); - metadata->category_name = feed_item.category; + metadata->category_name = GetMigratedChannel(feed_item.category); metadata->title = feed_item.title; metadata->description = feed_item.description; metadata->publisher_id = feed_item.publisher_id; diff --git a/components/brave_news/browser/resources/FeedNavigation.tsx b/components/brave_news/browser/resources/FeedNavigation.tsx index 8620f11c95af..2cc12e13ecc7 100644 --- a/components/brave_news/browser/resources/FeedNavigation.tsx +++ b/components/brave_news/browser/resources/FeedNavigation.tsx @@ -12,6 +12,7 @@ import { useBraveNews } from './shared/Context'; import { isPublisherEnabled } from './shared/api'; import { FeedView } from './shared/useFeedV2'; import { getLocale } from '$web-common/locale'; +import SettingsButton from './SettingsButton'; const DEFAULT_SHOW_COUNT = 4; @@ -32,15 +33,7 @@ const Container = styled(Card)` scrollbar-color: var(--bn-glass-10) var(--bn-glass-10); ` -const Heading = styled.h3` - font: ${font.default.semibold}; - color: var(--bn-glass-25); - margin: 0; - - padding-left: ${PAD_LEFT}; -` - -const CustomButton = styled.button <{ selected?: boolean, faint?: boolean, bold?: boolean }>` +const CustomButton = styled.button <{ selected?: boolean, faint?: boolean, large?: boolean, bold?: boolean }>` padding: ${spacing.m}; padding-left: ${PAD_LEFT}; @@ -52,8 +45,8 @@ const CustomButton = styled.button <{ selected?: boolean, faint?: boolean, bold? text-align: left; width: 100%; - color: ${p => p.faint ? `var(--bn-glass-25)` : `var(--bn-glass-70)`}; - font: ${p => font.small[p.bold ? 'semibold' : 'regular']}; + color: ${p => p.faint ? `var(--bn-glass-50)` : `var(--bn-glass-100)`}; + font: ${p => font[p.large ? 'default' : 'small'][p.bold ? 'semibold' : 'regular']}; cursor: pointer; &:hover { @@ -79,7 +72,7 @@ const Section = styled.details` align-items: center; gap: ${spacing.m}; list-style: none; - font: ${font.small.semibold}; + font: ${font.default.semibold}; cursor: pointer; @@ -87,12 +80,7 @@ const Section = styled.details` box-shadow: ${effect.focusState}; } - ${CustomButton} { - padding: 0; - flex: 0; - display: flex; - gap: ${spacing.m}; - align-items: center; + ${SettingsButton} { margin-left: auto; } } @@ -118,11 +106,12 @@ function usePersistedState(name: string, defaultValue: T) { } const Marker = +const PlaceholderMarker = export function Item(props: { id: FeedView, name: string }) { const { feedView, setFeedView } = useBraveNews() - - return setFeedView(props.id)} bold={props.id === 'all'}> + const topLevel = ['all', 'following'].includes(props.id) + return setFeedView(props.id)} bold={topLevel}> {props.name} } @@ -147,17 +136,18 @@ export default function Sidebar() { .slice(0, showingMoreChannels ? undefined : DEFAULT_SHOW_COUNT), [subscribedChannels, showingMoreChannels]) return - {getLocale('braveNewsMyFeedHeading')} {!!subscribedChannels.length &&
- {Marker} + {subscribedChannels.length ? Marker : PlaceholderMarker} {getLocale('braveNewsChannelsHeader')} - setCustomizePage('news')}> + { + setCustomizePage('news') + e.stopPropagation() + }}> - {getLocale('braveNewsAddChannelsOrPublishers')} - + {slicedChannelIds.map(c => )} {subscribedChannels.length > DEFAULT_SHOW_COUNT @@ -169,12 +159,14 @@ export default function Sidebar() {
} {!!subscribedPublisherIds.length &&
- {Marker} + {subscribedPublisherIds.length ? Marker : PlaceholderMarker} {getLocale('braveNewsPublishersHeading')} - setCustomizePage('popular')}> + { + setCustomizePage('popular') + e.stopPropagation() + }}> - {getLocale('braveNewsAddChannelsOrPublishers')} - + {slicedPublisherIds.map(p => )} {subscribedPublisherIds.length > DEFAULT_SHOW_COUNT diff --git a/components/brave_news/browser/resources/Peek.tsx b/components/brave_news/browser/resources/Peek.tsx index 2a6b1695847f..09cbae3ecc2e 100644 --- a/components/brave_news/browser/resources/Peek.tsx +++ b/components/brave_news/browser/resources/Peek.tsx @@ -3,17 +3,17 @@ // License, v. 2.0. If a copy of the MPL was not distributed with this file, // You can obtain one at https://mozilla.org/MPL/2.0/. +import { getLocale } from '$web-common/locale'; import Icon from '@brave/leo/react/icon'; -import { color, effect, gradient, radius, spacing } from '@brave/leo/tokens/css'; +import { color, effect, font, radius, spacing } from '@brave/leo/tokens/css'; import * as React from 'react'; import styled, { keyframes } from 'styled-components'; import { NEWS_FEED_CLASS } from './Feed'; +import Variables from './Variables'; import { MetaInfo } from './feed/ArticleMetaRow'; import Card, { SmallImage, Title } from './feed/Card'; import { useBraveNews } from './shared/Context'; import { useUnpaddedImageUrl } from './shared/useUnpaddedImageUrl'; -import Variables from './Variables'; -import { getLocale } from '$web-common/locale' const NewsButton = styled.button` cursor: pointer; @@ -27,10 +27,7 @@ const NewsButton = styled.button` backdrop-filter: blur(40px); color: ${color.white}; - - & > leo-icon[name="news-default"] { - --leo-icon-color: ${gradient.iconsActive}; - } + font: ${font.default.semibold}; & > leo-icon[name="carat-down"] { --leo-icon-color: rgba(255, 255, 255, 0.25); @@ -114,7 +111,7 @@ export default function Peek() { return isShowOnNTPPrefEnabled ? - {(!isOptInPrefEnabled || data) && + {(!isOptInPrefEnabled || feedV2) && {getLocale('braveNewsNewsPeek')} diff --git a/components/brave_news/browser/resources/SettingsButton.tsx b/components/brave_news/browser/resources/SettingsButton.tsx new file mode 100644 index 000000000000..5b4a3d7f2d24 --- /dev/null +++ b/components/brave_news/browser/resources/SettingsButton.tsx @@ -0,0 +1,24 @@ +// Copyright (c) 2024 The Brave Authors. All rights reserved. +// 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 https://mozilla.org/MPL/2.0/. + +import Button from "@brave/leo/react/button"; +import { radius, spacing } from "@brave/leo/tokens/css"; +import styled from "styled-components"; + + +const SettingsButton = styled(Button)` + --leo-button-color: var(--bn-glass-50); + --leo-button-radius: ${radius.s}; + --leo-button-padding: ${spacing.s}; + + flex: 0; +` + +SettingsButton.defaultProps = { + fab: true, + kind: 'outline' +} + +export default SettingsButton diff --git a/components/brave_news/browser/resources/feed/Ad.tsx b/components/brave_news/browser/resources/feed/Ad.tsx index 0475b6a20a37..2f6132bb16c7 100644 --- a/components/brave_news/browser/resources/feed/Ad.tsx +++ b/components/brave_news/browser/resources/feed/Ad.tsx @@ -114,7 +114,7 @@ export default function Advert(props: Props) { return - e.stopPropagation()} href="brave://rewards">{getLocale('braveNewsAdvertBadge')} + e.stopPropagation()} href="chrome://rewards">{getLocale('braveNewsAdvertBadge')} • {' ' + advert.description} diff --git a/components/brave_news/browser/resources/shared/Icons.tsx b/components/brave_news/browser/resources/shared/Icons.tsx index 4fb4df02b456..f7a96f5f67d7 100644 --- a/components/brave_news/browser/resources/shared/Icons.tsx +++ b/components/brave_news/browser/resources/shared/Icons.tsx @@ -15,32 +15,34 @@ export const ArrowRight = , - 'Business': , - 'Cars': , - 'Crypto': , - 'Culture': , - 'Entertainment': , - 'Entertainment News': , - 'Fashion': , - 'Film and TV': , - 'Food': , - 'Fun': , - 'Gaming': , - 'Health': , - 'Home': , - 'Music': , - 'Politics': , - 'Regional News': , - 'Science': , - 'Sports': , - 'Travel': , - 'Technology': , - 'Tech News': , - 'Tech Reviews': , - 'Top News': , - 'US News': , - 'Weather': , + 'default': , + 'Brave': + + , + 'Business': , + 'Cars': , + 'Crypto': , + 'Culture': , + 'Entertainment': , + 'Entertainment News': , + 'Fashion': , + 'Film and TV': , + 'Food': , + 'Fun': , + 'Gaming': , + 'Health': , + 'Home': , + 'Music': , + 'Politics': , + 'Regional News': , + 'Science': , + 'Sports': , + 'Travel': , + 'Technology': , + 'Tech News': , + 'Tech Reviews': , + 'Top News': , + 'US News': , + 'Weather': , 'World News': } diff --git a/components/common/useMediaQuery.ts b/components/common/useMediaQuery.ts new file mode 100644 index 000000000000..b719573c4dcf --- /dev/null +++ b/components/common/useMediaQuery.ts @@ -0,0 +1,23 @@ +// Copyright (c) 2024 The Brave Authors. All rights reserved. +// 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 https://mozilla.org/MPL/2.0/. + +import { useEffect, useState } from "react"; + +export default function useMediaQuery(query: string) { + const [result, setResult] = useState(() => window.matchMedia(query).matches) + + useEffect(() => { + const media = window.matchMedia(query) + const handler = () => setResult(media.matches) + media.addEventListener('change', handler) + setResult(media.matches) + + return () => { + media.removeEventListener('change', handler) + } + }, [query]) + + return result +} diff --git a/components/resources/brave_news_strings.grdp b/components/resources/brave_news_strings.grdp index fedd12a8dab3..33336eae8057 100644 --- a/components/resources/brave_news_strings.grdp +++ b/components/resources/brave_news_strings.grdp @@ -183,18 +183,12 @@ News - - My Feed - For You Following - - Add - Publishers diff --git a/ui/webui/resources/BUILD.gn b/ui/webui/resources/BUILD.gn index 0e15debedfd6..c9eb8b115f4e 100644 --- a/ui/webui/resources/BUILD.gn +++ b/ui/webui/resources/BUILD.gn @@ -206,6 +206,7 @@ leo_icons = [ "fullscreen-on.svg", "graph.svg", "grid04.svg", + "hamburger-menu.svg", "help-outline.svg", "history.svg", "image-off.svg",