From a90a5cba08fdf6c0ceb95101c275108a152a3aed Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 12 Jun 2024 07:35:37 +0200 Subject: Merging upstream version 127.0. Signed-off-by: Daniel Baumann --- .../newtab/content-src/components/Base/Base.jsx | 24 +- .../ContentSection/ContentSection.jsx | 20 +- .../components/CustomizeMenu/CustomizeMenu.jsx | 15 +- .../components/CustomizeMenu/_CustomizeMenu.scss | 15 +- .../DiscoveryStreamAdmin/DiscoveryStreamAdmin.jsx | 57 +++ .../DiscoveryStreamAdmin/DiscoveryStreamAdmin.scss | 12 + .../DiscoveryStreamComponents/DSCard/DSCard.jsx | 77 ++-- .../DiscoveryStreamComponents/DSCard/_DSCard.scss | 32 +- .../Highlights/_Highlights.scss | 18 + .../content-src/components/TopSites/_TopSites.scss | 28 +- .../WallpapersSection/WallpapersSection.jsx | 19 + .../content-src/components/Weather/Weather.jsx | 350 ++++++++++++++++++ .../content-src/components/Weather/_Weather.scss | 393 +++++++++++++++++++++ .../newtab/content-src/lib/link-menu-options.mjs | 64 ++++ .../content-src/styles/_activity-stream.scss | 1 + .../newtab/content-src/styles/_icons.scss | 10 +- .../newtab/content-src/styles/_theme.scss | 21 ++ .../newtab/content-src/styles/_variables.scss | 27 +- 18 files changed, 1106 insertions(+), 77 deletions(-) create mode 100644 browser/components/newtab/content-src/components/Weather/Weather.jsx create mode 100644 browser/components/newtab/content-src/components/Weather/_Weather.scss (limited to 'browser/components/newtab/content-src') diff --git a/browser/components/newtab/content-src/components/Base/Base.jsx b/browser/components/newtab/content-src/components/Base/Base.jsx index 1738f8f51a..61722fd418 100644 --- a/browser/components/newtab/content-src/components/Base/Base.jsx +++ b/browser/components/newtab/content-src/components/Base/Base.jsx @@ -12,6 +12,7 @@ import { CustomizeMenu } from "content-src/components/CustomizeMenu/CustomizeMen import React from "react"; import { Search } from "content-src/components/Search/Search"; import { Sections } from "content-src/components/Sections/Sections"; +import { Weather } from "content-src/components/Weather/Weather"; const VISIBLE = "visible"; const VISIBILITY_CHANGE_EVENT = "visibilitychange"; @@ -235,7 +236,7 @@ export class BaseContent extends React.PureComponent { return (

@@ -393,6 +407,13 @@ export class BaseContent extends React.PureComponent { {wallpapersEnabled && this.renderWallpaperAttribution()} +

); @@ -410,4 +431,5 @@ export const Base = connect(state => ({ DiscoveryStream: state.DiscoveryStream, Search: state.Search, Wallpapers: state.Wallpapers, + Weather: state.Weather, }))(_Base); 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 1dd13fc965..494d506da9 100644 --- a/browser/components/newtab/content-src/components/CustomizeMenu/ContentSection/ContentSection.jsx +++ b/browser/components/newtab/content-src/components/CustomizeMenu/ContentSection/ContentSection.jsx @@ -28,7 +28,7 @@ export class ContentSection extends React.PureComponent { } onPreferenceSelect(e) { - // eventSource: TOP_SITES | TOP_STORIES | HIGHLIGHTS + // eventSource: TOP_SITES | TOP_STORIES | HIGHLIGHTS | WEATHER const { preference, eventSource } = e.target.dataset; let value; if (e.target.nodeName === "SELECT") { @@ -97,6 +97,7 @@ export class ContentSection extends React.PureComponent { pocketRegion, mayHaveSponsoredStories, mayHaveRecentSaves, + mayHaveWeather, openPreferences, spocMessageVariant, wallpapersEnabled, @@ -107,6 +108,7 @@ export class ContentSection extends React.PureComponent { topSitesEnabled, pocketEnabled, highlightsEnabled, + weatherEnabled, showSponsoredTopSitesEnabled, showSponsoredPocketEnabled, showRecentSavesEnabled, @@ -269,6 +271,22 @@ export class ContentSection extends React.PureComponent { + {mayHaveWeather && ( +
+ +
+ )} + {pocketRegion && mayHaveSponsoredStories && spocMessageVariant === "variant-c" && ( diff --git a/browser/components/newtab/content-src/components/CustomizeMenu/CustomizeMenu.jsx b/browser/components/newtab/content-src/components/CustomizeMenu/CustomizeMenu.jsx index f1c723fed2..035e84af58 100644 --- a/browser/components/newtab/content-src/components/CustomizeMenu/CustomizeMenu.jsx +++ b/browser/components/newtab/content-src/components/CustomizeMenu/CustomizeMenu.jsx @@ -55,12 +55,14 @@ export class _CustomizeMenu extends React.PureComponent { role="dialog" data-l10n-id="newtab-personalize-dialog-label" > - + + + + + ); + } + + return ( +
+
+ {" "} + +
+
+ ); + } +} + +export const Weather = connect(state => ({ + Weather: state.Weather, + Prefs: state.Prefs, + IntersectionObserver: globalThis.IntersectionObserver, + document: globalThis.document, +}))(_Weather); diff --git a/browser/components/newtab/content-src/components/Weather/_Weather.scss b/browser/components/newtab/content-src/components/Weather/_Weather.scss new file mode 100644 index 0000000000..0616530f98 --- /dev/null +++ b/browser/components/newtab/content-src/components/Weather/_Weather.scss @@ -0,0 +1,393 @@ +// Custom font sizing for weather widget +:root { + --newtab-weather-content-font-size: 11px; + --newtab-weather-sponsor-font-size: 8px; +} + +.weather { + font-size: var(--font-size-root); + position: absolute; + left: var(--space-xlarge); + top: var(--space-xlarge); + z-index: 1; +} + +// Unavailable / Error State +.weatherNotAvailable { + font-size: var(--newtab-weather-content-font-size); + color: var(--text-color-error); + display: flex; + align-items: center; + + .icon { + fill: var(--icon-color-critical); + -moz-context-properties: fill; + } +} + +.weatherCard { + margin-block-end: var(--space-xsmall); + display: flex; + flex-wrap: nowrap; + align-items: stretch; + border-radius: var(--border-radius-medium); + overflow: hidden; + + &:hover, &:focus-within { + ~ .weatherSponsorText { + visibility: visible; + } + } + + &:focus-within { + overflow: visible; + } + + &:hover { + box-shadow: var(--box-shadow-10); + background: var(--background-color-box); + } + + a { + color: var(--text-color); + } + +} + +.weatherSponsorText { + visibility: hidden; + font-size: var(--newtab-weather-sponsor-font-size); + color: var(--text-color-deemphasized); +} + +.weatherInfoLink, .weatherButtonContextMenuWrapper { + appearance: none; + background-color: var(--background-color-ghost); + border: 0; + padding: var(--space-small); + cursor: pointer; + + &:hover { + // TODO: Add Wallpaper Background Color Fix + background-color: var(--button-background-color-ghost-hover); + + &::after { + background-color: transparent + } + + &:active { + // TODO: Add Wallpaper Background Color Fix + background-color: var(--button-background-color-ghost-active); + } + } + + &:focus-visible { + outline: var(--focus-outline); + } + + // Contrast fix for users who have wallpapers set + .hasWallpaperDark & { + @media (prefers-color-scheme: dark) { + // TODO: Replace with token + background-color: rgba(35, 34, 43, 70%); + + &:hover { + background-color: var(--newtab-button-static-hover-background); + } + + &:hover:active { + background-color: var(--newtab-button-static-active-background); + } + } + + @media (prefers-contrast) and (prefers-color-scheme: dark) { + background-color: var(--background-color-box); + } + } + + .hasWallpaperLight & { + @media (prefers-color-scheme: light) { + // TODO: Replace with token + background-color: rgba(255, 255, 255, 70%); + + &:hover { + background-color: var(--newtab-button-static-hover-background); + } + + &:hover:active { + background-color: var(--newtab-button-static-active-background); + } + } + + @media (prefers-contrast) and (prefers-color-scheme: light) { + background-color: var(--background-color-box); + } + } + +} + +.weatherInfoLink { + display: flex; + gap: var(--space-medium); + padding: var(--space-small) var(--space-medium); + border-radius: var(--border-radius-medium) 0 0 var(--border-radius-medium); + text-decoration: none; + color: var(--text-color);; + min-width: 130px; + max-width: 190px; + text-overflow: ellipsis; + + @media(min-width: $break-point-medium) { + min-width: unset; + } + + &:hover ~.weatherButtonContextMenuWrapper { + &::after { + background-color: transparent + } + } + + &:focus-visible { + border-radius: var(--border-radius-medium); + + ~ .weatherButtonContextMenuWrapper { + &::after { + background-color: transparent + } + } + } +} + +.weatherButtonContextMenuWrapper { + position: relative; + cursor: pointer; + border-radius: 0 var(--border-radius-medium) var(--border-radius-medium) 0; + display: flex; + align-items: stretch; + width: 50px; + padding: 0; + + &::after { + content: ''; + left: 0; + top: 10px; + height: calc(100% - 20px); + width: 1px; + background-color: var(--newtab-button-static-background); + display: block; + position: absolute; + z-index: 0; + } + + @media (prefers-color-scheme: dark) { + &::after { + background-color: var(--color-gray-70); + } + } + + &:hover { + &::after { + background-color: transparent + } + } + + &:focus-visible { + border-radius: var(--border-radius-medium); + + &::after { + background-color: transparent + } + } +} + +.weatherButtonContextMenu { + background-image: url('chrome://global/skin/icons/more.svg'); + background-repeat: no-repeat; + background-size: var(--size-item-small) auto; + background-position: center; + background-color: transparent; + cursor: pointer; + fill: var(--icon-color); + -moz-context-properties: fill; + width: 100%; + height: 100%; + border: 0; + appearance: none; + min-width: var(--size-item-large); +} + +.weatherText { + height: min-content; +} + +.weatherCityRow, .weatherForecastRow, .weatherDetailedSummaryRow { + display: flex; + justify-content: space-between; + align-items: center; + gap: var(--space-small); +} + +.weatherForecastRow { + text-transform: uppercase; + font-weight: var(--font-weight-bold); +} + +.weatherCityRow { + color: var(--text-color-deemphasized); +} + +.weatherCity { + text-overflow: ellipsis; + font-size: var(--font-size-small); +} + +// Add additional margin if detailed summary is in view +.weatherCityRow + .weatherDetailedSummaryRow { + margin-block-start: var(--space-xsmall); +} + +.weatherDetailedSummaryRow { + font-size: var(--newtab-weather-content-font-size); + gap: var(--space-large); +} + +.weatherHighLowTemps { + display: flex; + gap: var(--space-xxsmall); + text-transform: uppercase; + word-spacing: var(--space-xxsmall); +} + +.weatherTextSummary { + text-align: center; + max-width: 90px; +} + +.weatherTemperature { + font-size: var(--font-size-large); +} + +// Weather Symbol Icons +.weatherIconCol { + width: var(--size-item-large); + height: var(--size-item-large); + aspect-ratio: 1; + display: flex; + align-items: center; + justify-content: center; + align-self: center; +} + +.weatherIcon { + width: var(--size-item-large); + height: auto; + vertical-align: middle; + + @media (prefers-contrast) { + -moz-context-properties: fill, stroke; + fill: currentColor; + stroke: currentColor; + } + + &.iconId1 { + content: url('chrome://browser/skin/weather/sunny.svg'); + // height: var(--size-item-large); + } + + &.iconId2 { + content: url('chrome://browser/skin/weather/mostly-sunny.svg'); + // height: var(--size-item-large); + } + + &:is(.iconId3, .iconId4, .iconId6) { + content: url('chrome://browser/skin/weather/partly-sunny.svg'); + // height: var(--size-item-large); + } + + &.iconId5 { + content: url('chrome://browser/skin/weather/hazy-sunshine.svg'); + // height: var(--size-item-large); + } + + &:is(.iconId7, .iconId8) { + content: url('chrome://browser/skin/weather/cloudy.svg'); + } + + &.iconId11 { + content: url('chrome://browser/skin/weather/fog.svg'); + } + + &.iconId12 { + content: url('chrome://browser/skin/weather/showers.svg'); + } + + &:is(.iconId13, .iconId14) { + content: url('chrome://browser/skin/weather/mostly-cloudy-with-showers.svg'); + // height: var(--size-item-large); + } + + &.iconId15 { + content: url('chrome://browser/skin/weather/thunderstorms.svg'); + } + + &:is(.iconId16, .iconId17) { + content: url('chrome://browser/skin/weather/mostly-cloudy-with-thunderstorms.svg'); + } + + &.iconId18 { + content: url('chrome://browser/skin/weather/rain.svg'); + } + + &:is(.iconId19, .iconId20, .iconId25) { + content: url('chrome://browser/skin/weather/flurries.svg'); + } + + &.iconId21 { + content: url('chrome://browser/skin/weather/partly-sunny-with-flurries.svg'); + } + + &:is(.iconId22, .iconId23) { + content: url('chrome://browser/skin/weather/snow.svg'); + } + + &:is(.iconId24, .iconId31) { + content: url('chrome://browser/skin/weather/ice.svg'); + } + + &:is(.iconId26, .iconId29) { + content: url('chrome://browser/skin/weather/freezing-rain.svg'); + } + + &.iconId30 { + content: url('chrome://browser/skin/weather/hot.svg'); + } + + &.iconId32 { + content: url('chrome://browser/skin/weather/windy.svg'); + } + + &.iconId33 { + content: url('chrome://browser/skin/weather/night-clear.svg'); + } + + &:is(.iconId34, .iconId35, .iconId36, .iconId38) { + content: url('chrome://browser/skin/weather/night-mostly-clear.svg'); + } + + &.iconId37 { + content: url('chrome://browser/skin/weather/night-hazy-moonlight.svg'); + } + + &:is(.iconId39, .iconId40) { + content: url('chrome://browser/skin/weather/night-partly-cloudy-with-showers.svg'); + height: var(--size-item-large); + } + + &:is(.iconId41, .iconId42) { + content: url('chrome://browser/skin/weather/night-partly-cloudy-with-thunderstorms.svg'); + } + + &:is(.iconId43, .iconId44) { + content: url('chrome://browser/skin/weather/night-mostly-cloudy-with-flurries.svg'); + } +} diff --git a/browser/components/newtab/content-src/lib/link-menu-options.mjs b/browser/components/newtab/content-src/lib/link-menu-options.mjs index f10a5e34c6..23dcf8b050 100644 --- a/browser/components/newtab/content-src/lib/link-menu-options.mjs +++ b/browser/components/newtab/content-src/lib/link-menu-options.mjs @@ -306,4 +306,68 @@ export const LinkMenuOptions = { : LinkMenuOptions.EmptyItem(), OpenInPrivateWindow: (site, index, eventSource, isEnabled) => isEnabled ? _OpenInPrivateWindow(site) : LinkMenuOptions.EmptyItem(), + ChangeWeatherLocation: () => ({ + id: "newtab-weather-menu-change-location", + action: ac.OnlyToMain({ + type: at.CHANGE_WEATHER_LOCATION, + data: { url: "https://mozilla.org" }, + }), + }), + ChangeWeatherDisplaySimple: () => ({ + id: "newtab-weather-menu-change-weather-display-simple", + action: ac.OnlyToMain({ + type: at.SET_PREF, + data: { + name: "weather.display", + value: "simple", + }, + }), + }), + ChangeWeatherDisplayDetailed: () => ({ + id: "newtab-weather-menu-change-weather-display-detailed", + action: ac.OnlyToMain({ + type: at.SET_PREF, + data: { + name: "weather.display", + value: "detailed", + }, + }), + }), + ChangeTempUnitFahrenheit: () => ({ + id: "newtab-weather-menu-change-temperature-units-fahrenheit", + action: ac.OnlyToMain({ + type: at.SET_PREF, + data: { + name: "weather.temperatureUnits", + value: "f", + }, + }), + }), + ChangeTempUnitCelsius: () => ({ + id: "newtab-weather-menu-change-temperature-units-celsius", + action: ac.OnlyToMain({ + type: at.SET_PREF, + data: { + name: "weather.temperatureUnits", + value: "c", + }, + }), + }), + HideWeather: () => ({ + id: "newtab-weather-menu-hide-weather", + action: ac.OnlyToMain({ + type: at.SET_PREF, + data: { + name: "showWeather", + value: false, + }, + }), + }), + OpenLearnMoreURL: site => ({ + id: "newtab-weather-menu-learn-more", + action: ac.OnlyToMain({ + type: at.OPEN_LINK, + data: { url: site.url }, + }), + }), }; diff --git a/browser/components/newtab/content-src/styles/_activity-stream.scss b/browser/components/newtab/content-src/styles/_activity-stream.scss index d2e66667b2..580f35416e 100644 --- a/browser/components/newtab/content-src/styles/_activity-stream.scss +++ b/browser/components/newtab/content-src/styles/_activity-stream.scss @@ -149,6 +149,7 @@ input { @import '../components/ConfirmDialog/ConfirmDialog'; @import '../components/CustomizeMenu/CustomizeMenu'; @import '../components/WallpapersSection/WallpapersSection'; +@import '../components/Weather/Weather'; @import '../components/Card/Card'; @import '../components/CollapsibleSection/CollapsibleSection'; @import '../components/DiscoveryStreamAdmin/DiscoveryStreamAdmin'; diff --git a/browser/components/newtab/content-src/styles/_icons.scss b/browser/components/newtab/content-src/styles/_icons.scss index 8be97ad9ae..39879b2b44 100644 --- a/browser/components/newtab/content-src/styles/_icons.scss +++ b/browser/components/newtab/content-src/styles/_icons.scss @@ -4,7 +4,7 @@ background-size: $icon-size; -moz-context-properties: fill; display: inline-block; - color: var(--newtab-text-primary-color); + color: var(--icon-color); fill: currentColor; height: $icon-size; vertical-align: middle; @@ -70,6 +70,10 @@ background-image: url('chrome://global/skin/icons/info.svg'); } + &.icon-info-critical { + background-image: url('chrome://activity-stream/content/data/content/assets/glyph-info-critical-16.svg'); + } + &.icon-help { background-image: url('chrome://global/skin/icons/help.svg'); } @@ -167,6 +171,10 @@ background-image: url('chrome://activity-stream/content/data/content/assets/glyph-webextension-16.svg'); } + &.icon-weather { + background-image: url('chrome://browser/skin/weather/sunny.svg'); + } + &.icon-highlights { background-image: url('chrome://global/skin/icons/highlights.svg'); } diff --git a/browser/components/newtab/content-src/styles/_theme.scss b/browser/components/newtab/content-src/styles/_theme.scss index 6b097ae93e..78b54f4f8e 100644 --- a/browser/components/newtab/content-src/styles/_theme.scss +++ b/browser/components/newtab/content-src/styles/_theme.scss @@ -38,6 +38,21 @@ $shadow-image-inset: inset 0 0 0 0.5px $black-15; --newtab-element-hover-color: color-mix(in srgb, var(--newtab-background-color) 90%, #{$black}); --newtab-element-active-color: color-mix(in srgb, var(--newtab-background-color) 80%, #{$black}); + // --newtab-button-*-color is used on all new page card/top site options buttons + --newtab-button-background: var(--button-background-color); + --newtab-button-focus-background: var(--newtab-button-background); + --newtab-button-focus-border: var(--focus-outline-color); + --newtab-button-hover-background: var(--button-background-color-hover); + --newtab-button-active-background: var(--button-background-color-active); + --newtab-button-text: var(--button-text-color); + + // --newtab-button-static*-color is used on pocket cards and require a + // static color unit due to transparency issues with `color-mix` + --newtab-button-static-background: #F0F0F4; + --newtab-button-static-focus-background: var(--newtab-button-static-background); + --newtab-button-static-hover-background: #E0E0E6; + --newtab-button-static-active-background: #CFCFD8; + // --newtab-element-secondary*-color is used when an element needs to be set // off from the secondary background color. --newtab-element-secondary-color: color-mix(in srgb, currentColor 5%, transparent); @@ -87,6 +102,12 @@ $shadow-image-inset: inset 0 0 0 0.5px $black-15; --newtab-primary-element-text-color: #{$primary-text-color-dark}; --newtab-wordmark-color: #{$newtab-wordmark-darktheme-color}; --newtab-status-success: #{$status-dark-green}; + + // --newtab-button-static*-color is used on pocket cards and require a + // static color unit due to transparency issues with `color-mix` + --newtab-button-static-background: #2B2A33; + --newtab-button-static-hover-background: #52525E; + --newtab-button-static-active-background: #5B5B66; } } diff --git a/browser/components/newtab/content-src/styles/_variables.scss b/browser/components/newtab/content-src/styles/_variables.scss index 9fd0083841..43672c7796 100644 --- a/browser/components/newtab/content-src/styles/_variables.scss +++ b/browser/components/newtab/content-src/styles/_variables.scss @@ -157,14 +157,17 @@ $customize-menu-border-tint: 1px solid rgba(0, 0, 0, 15%); @mixin context-menu-button { .context-menu-button { background-clip: padding-box; - background-color: var(--newtab-background-color-secondary); + background-color: var(--newtab-button-background); background-image: url('chrome://global/skin/icons/more.svg'); background-position: 55%; - border: $border-primary; + border: 0; + outline: $border-primary; + outline-width: 0; border-radius: 100%; box-shadow: $context-menu-button-boxshadow; cursor: pointer; - fill: var(--newtab-text-primary-color); + color: var(--button-text-color); + fill: var(--newtab-button-text); height: $context-menu-button-size; inset-inline-end: math.div(-$context-menu-button-size, 2); opacity: 0; @@ -175,10 +178,26 @@ $customize-menu-border-tint: 1px solid rgba(0, 0, 0, 15%); transition-property: transform, opacity; width: $context-menu-button-size; - &:is(:active, :focus) { + &:is(:active, :focus-visible, :hover) { opacity: 1; transform: scale(1); } + + &:is(:hover) { + background-color: var(--newtab-button-hover-background); + } + + &:is(:focus-visible) { + outline-color: var(--newtab-button-focus-border); + background-color: var(--newtab-button-focus-background); + outline-width: 4px; + } + + &:is(:active) { + background-color: var(--newtab-button-active-background); + } + + } } -- cgit v1.2.3