From fa9393cddd282b12aa8cb7618d69bdffa70e00ff Mon Sep 17 00:00:00 2001 From: "sangwoo.ko" Date: Tue, 27 Sep 2022 22:45:47 +0900 Subject: [PATCH 1/6] Invert foreground color when background is light For readability, the foreground color is inverted when the background is light. This is based on WCGA2.0 spec. --- .../components/default/braveToday/hint.tsx | 12 +- .../components/default/clock/index.tsx | 8 +- .../components/default/clock/style.ts | 8 +- .../default/footer/braveTalkItem.tsx | 4 +- .../footer/braveTalkTooltip/braveTalkIcon.tsx | 1 - .../components/default/footer/footer.tsx | 14 +- .../components/default/page/index.tsx | 21 ++- .../components/default/stats/index.tsx | 7 +- .../components/default/stats/style.ts | 24 +-- .../default/widget/assets/ellipsis.ts | 9 +- .../components/default/widget/index.tsx | 10 +- .../components/default/widget/widgetMenu.tsx | 10 +- .../containers/newTab/index.tsx | 15 +- .../containers/newTab/stats.tsx | 10 +- .../helpers/colorUtil.test.ts | 128 +++++++++++++ .../brave_new_tab_ui/helpers/colorUtil.ts | 173 ++++++++++++++++++ .../reducers/new_tab_reducer.ts | 14 +- .../default/data/backgroundWallpaper.ts | 26 ++- .../stories/default/data/storybookState.ts | 17 +- components/definitions/newTab.d.ts | 2 + components/web-components/app.global.scss | 7 +- 21 files changed, 442 insertions(+), 78 deletions(-) create mode 100644 components/brave_new_tab_ui/helpers/colorUtil.test.ts create mode 100644 components/brave_new_tab_ui/helpers/colorUtil.ts diff --git a/components/brave_new_tab_ui/components/default/braveToday/hint.tsx b/components/brave_new_tab_ui/components/default/braveToday/hint.tsx index c81761357668..8c4561919d97 100644 --- a/components/brave_new_tab_ui/components/default/braveToday/hint.tsx +++ b/components/brave_new_tab_ui/components/default/braveToday/hint.tsx @@ -8,14 +8,18 @@ import styled from 'styled-components' import { CaratStrongDownIcon } from 'brave-ui/components/icons' import { getLocale } from '../../../../common/locale' -const Hint = styled('div')` +interface Props { + color: string +} + +const Hint = styled('div')` display: flex; flex-direction: column; align-items: center; gap: 12px; text-align: center; font-size: 15px; - color: white; + color: ${p => p.color}; > p { margin: 0; } @@ -26,9 +30,9 @@ const Graphic = styled('div')` height: 16px; ` -export default function BraveTodayHint () { +export default function BraveTodayHint (props: Props) { return ( - +

{getLocale('braveTodayScrollHint')}

diff --git a/components/brave_new_tab_ui/components/default/clock/index.tsx b/components/brave_new_tab_ui/components/default/clock/index.tsx index c9f77f794e72..312cfc211bd1 100644 --- a/components/brave_new_tab_ui/components/default/clock/index.tsx +++ b/components/brave_new_tab_ui/components/default/clock/index.tsx @@ -7,9 +7,13 @@ import { useNewTabPref } from '../../../hooks/usePref' import { StyledClock, StyledTime } from './style' +interface Props { + color: string +} + // Tick once every two seconds. const TICK_RATE = 2000 -export function Clock () { +export function Clock ({ color }: Props) { const [now, setNow] = React.useState() const [clockFormat, setClockFormat] = useNewTabPref('clockFormat') const toggleClockFormat = () => { @@ -42,7 +46,7 @@ export function Clock () { ? null : t.value), [formatter, now]) - return + return {formattedTime} } diff --git a/components/brave_new_tab_ui/components/default/clock/style.ts b/components/brave_new_tab_ui/components/default/clock/style.ts index 3f083c8e03e6..819e12e73809 100644 --- a/components/brave_new_tab_ui/components/default/clock/style.ts +++ b/components/brave_new_tab_ui/components/default/clock/style.ts @@ -5,8 +5,12 @@ import styled from 'styled-components' -export const StyledClock = styled('div')<{}>` - color: #FFFFFF; +interface ClockProps { + color: string +} + +export const StyledClock = styled('div')` + color: ${p => p.color}; box-sizing: border-box; line-height: 1; user-select: none; diff --git a/components/brave_new_tab_ui/components/default/footer/braveTalkItem.tsx b/components/brave_new_tab_ui/components/default/footer/braveTalkItem.tsx index 6832ee873427..a3dc7da6a0c3 100644 --- a/components/brave_new_tab_ui/components/default/footer/braveTalkItem.tsx +++ b/components/brave_new_tab_ui/components/default/footer/braveTalkItem.tsx @@ -39,7 +39,7 @@ function BraveTalkTooltipItem (props: Props) { } return ( - + @@ -51,7 +51,7 @@ export default function BraveTalkItem (props: Props) { return } return ( - + ) diff --git a/components/brave_new_tab_ui/components/default/footer/braveTalkTooltip/braveTalkIcon.tsx b/components/brave_new_tab_ui/components/default/footer/braveTalkTooltip/braveTalkIcon.tsx index 91b59afe14b0..c7e55e1ef80c 100644 --- a/components/brave_new_tab_ui/components/default/footer/braveTalkTooltip/braveTalkIcon.tsx +++ b/components/brave_new_tab_ui/components/default/footer/braveTalkTooltip/braveTalkIcon.tsx @@ -9,7 +9,6 @@ export default function Icon () { return ( any onDismissBraveTalkPrompt: OnDismissBraveTalkPrompt + color: string } export default class FooterInfo extends React.PureComponent { @@ -48,7 +49,8 @@ export default class FooterInfo extends React.PureComponent { supportsBraveTalk, backgroundImageInfo, showPhotoInfo, - onClickSettings + onClickSettings, + color } = this.props return ( @@ -68,21 +70,21 @@ export default class FooterInfo extends React.PureComponent { } - + - + {getLocale('customize')} - + - + - + {supportsBraveTalk && diff --git a/components/brave_new_tab_ui/components/default/page/index.tsx b/components/brave_new_tab_ui/components/default/page/index.tsx index a82c151709b8..2d520cb28e70 100644 --- a/components/brave_new_tab_ui/components/default/page/index.tsx +++ b/components/brave_new_tab_ui/components/default/page/index.tsx @@ -382,18 +382,22 @@ export const Navigation = styled('nav')<{}>` align-items: center; ` +interface ColorButtonProps { + color: string +} + interface IconButtonProps { clickDisabled?: boolean isClickMenu?: boolean } -export const IconLink = styled('a')<{}>` +export const IconLink = styled('a')` display: block; width: 24px; height: 24px; margin: 8px; cursor: pointer; - color: #ffffff; + color: ${p => p.color}; opacity: 0.7; transition: opacity 0.15s ease, filter 0.15s ease; @@ -402,7 +406,7 @@ export const IconLink = styled('a')<{}>` } ` -export const IconButton = styled('button')` +export const IconButton = styled('button')` pointer-events: ${p => p.clickDisabled && 'none'}; display: flex; width: 24px; @@ -412,7 +416,7 @@ export const IconButton = styled('button')` outline: none; margin: ${p => p.isClickMenu ? '7' : '0 12'}px; cursor: pointer; - color: #ffffff; + color: ${p => p.color}; background-color: transparent; opacity: 0.7; transition: opacity 0.15s ease, filter 0.15s ease; @@ -461,19 +465,20 @@ export const IconButtonSideText = styled('label')` interface IconButtonContainerProps { textDirection: string + color: string } export const IconButtonContainer = styled('div')` font-family: ${p => p.theme.fontFamily.heading}; font-size: 13px; font-weight: 600; - color: rgba(255,255,255,0.8); + color: ${p => p.color + 'CC' /* == 0.8 */}; margin-right: ${p => p.textDirection === 'ltr' && '8px'}; margin-left: ${p => p.textDirection === 'rtl' && '8px'}; - border-right: ${p => p.textDirection === 'ltr' && '1px solid rgba(255, 255, 255, 0.6)'}; - border-left: ${p => p.textDirection === 'rtl' && '1px solid rgba(255, 255, 255, 0.6)'}; + border-right: ${p => p.textDirection === 'ltr' && `1px solid ${p.color + '99' /* == 0.6 */}`}; + border-left: ${p => p.textDirection === 'rtl' && `1px solid ${p.color + '99' /* == 0.6 */}`}; &:hover { - color: #ffffff; + color: ${p => p.color}; } ` diff --git a/components/brave_new_tab_ui/components/default/stats/index.tsx b/components/brave_new_tab_ui/components/default/stats/index.tsx index f72d3e0d6d54..e897b21ba575 100644 --- a/components/brave_new_tab_ui/components/default/stats/index.tsx +++ b/components/brave_new_tab_ui/components/default/stats/index.tsx @@ -31,6 +31,7 @@ export interface StatsItemProps { counter: string | number text?: string description: string + overriddenTextColor?: string } /** @@ -40,10 +41,10 @@ export interface StatsItemProps { * @prop {string} text - descriptive text that goes along the stat * @prop {string} description - describes what the counter is showing */ -export function StatsItem ({ testId, counter, text, description }: StatsItemProps) { - return +export function StatsItem ({ testId, counter, text, description, overriddenTextColor }: StatsItemProps) { + return {counter} {text && {text}} - {description} + {description} } diff --git a/components/brave_new_tab_ui/components/default/stats/style.ts b/components/brave_new_tab_ui/components/default/stats/style.ts index 3ad4d66cfdbc..63e6cc1852e4 100644 --- a/components/brave_new_tab_ui/components/default/stats/style.ts +++ b/components/brave_new_tab_ui/components/default/stats/style.ts @@ -2,7 +2,7 @@ * 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 styled from 'styled-components' +import styled, { css } from 'styled-components' export const StyledStatsItemContainer = styled('ul')<{}>` -webkit-font-smoothing: antialiased; @@ -18,22 +18,18 @@ export const StyledStatsItemContainer = styled('ul')<{}>` font-family: inherit; ` -export const StyledStatsItem = styled('li')<{}>` +export const StyledStatsItem = styled('li')<{overriddenTextColor?: string}>` list-style-type: none; font-size: inherit; font-family: inherit; margin: 10px 16px; + &:last-child { margin-right: 0; } - &:first-child { - color: #FB542B; - } - &:nth-child(2) { - color: #A0A5EB; - } - &:last-child { - color: #FFFFFF; - margin-right: 0; - } + ${p => p.overriddenTextColor + ? css`color: ${p.overriddenTextColor};` + : css`&:first-child { color: var(--interactive2); } + &:nth-child(2) { color: var(--interactive9); } + &:last-child { color: #FFFFFF; }`} ` export const StyledStatsItemCounter = styled('span')<{}>` @@ -56,10 +52,10 @@ export const StyledStatsItemText = styled('span')<{}>` letter-spacing: 0; ` -export const StyledStatsItemDescription = styled('div')<{}>` +export const StyledStatsItemDescription = styled('div')<{overriddenTextColor?: string}>` font-size: 16px; font-weight: 500; - color: #FFFFFF; + ${p => !p.overriddenTextColor && css`color: #FFFFFF;`} margin-top: 8px; font-family: ${p => p.theme.fontFamily.heading}; ` diff --git a/components/brave_new_tab_ui/components/default/widget/assets/ellipsis.ts b/components/brave_new_tab_ui/components/default/widget/assets/ellipsis.ts index 24426ec3c46f..300650363a07 100644 --- a/components/brave_new_tab_ui/components/default/widget/assets/ellipsis.ts +++ b/components/brave_new_tab_ui/components/default/widget/assets/ellipsis.ts @@ -3,13 +3,6 @@ // 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 styled from 'styled-components' import EllipsisIcon from '../../../popupMenu/ellipsisIcon' -interface Props { - lightWidget?: boolean -} - -export default styled(EllipsisIcon)` - color: ${p => p.lightWidget ? '#495057' : '#ffffff'}; -` +export default EllipsisIcon diff --git a/components/brave_new_tab_ui/components/default/widget/index.tsx b/components/brave_new_tab_ui/components/default/widget/index.tsx index 98e5d43c115b..b2d038f44587 100644 --- a/components/brave_new_tab_ui/components/default/widget/index.tsx +++ b/components/brave_new_tab_ui/components/default/widget/index.tsx @@ -18,8 +18,8 @@ export interface WidgetProps { widgetTitle?: string hideMenu?: boolean isForeground?: boolean - lightWidget?: boolean paddingType: 'none' | 'right' | 'default' + color?: string onLearnMore?: () => void onDisconnect?: () => void onRefreshData?: () => void @@ -42,7 +42,6 @@ export function Widget ({ widgetTitle, hideMenu, isForeground, - lightWidget, paddingType, onLearnMore, onDisconnect, @@ -50,7 +49,8 @@ export function Widget ({ onAddSite, customLinksEnabled, onToggleCustomLinksEnabled, - children + children, + color }: WidgetProps & { children: React.ReactNode }) { const [widgetMenuPersist, setWidgetMenuPersist] = React.useState(!!isForeground) return @@ -78,8 +78,8 @@ export function Widget ({ hideWidget={hideWidget} persistWidget={() => setWidgetMenuPersist(true)} unpersistWidget={() => setWidgetMenuPersist(false)} - lightWidget={lightWidget} - paddingType={paddingType} />} + paddingType={paddingType} + color={color} />} } diff --git a/components/brave_new_tab_ui/components/default/widget/widgetMenu.tsx b/components/brave_new_tab_ui/components/default/widget/widgetMenu.tsx index 1f70c32ee178..fd7fbaf2809a 100644 --- a/components/brave_new_tab_ui/components/default/widget/widgetMenu.tsx +++ b/components/brave_new_tab_ui/components/default/widget/widgetMenu.tsx @@ -32,8 +32,8 @@ interface Props { onAddSite?: () => void customLinksEnabled?: boolean onToggleCustomLinksEnabled?: () => void - lightWidget?: boolean paddingType: 'none' | 'right' | 'default' + color?: string } interface State { @@ -100,14 +100,14 @@ export default class WidgetMenu extends React.PureComponent { widgetMenuPersist, widgetTitle, isForeground, - lightWidget, paddingType, onLearnMore, onDisconnect, onRefreshData, onAddSite, onToggleCustomLinksEnabled, - customLinksEnabled + customLinksEnabled, + color } = this.props const { showMenu } = this.state const hideString = widgetTitle ? `${getLocale('hide')} ${widgetTitle}` : getLocale('hide') @@ -115,8 +115,8 @@ export default class WidgetMenu extends React.PureComponent { return ( - - + + {showMenu && { cryptoContent = null } + let overriddenForegroundColor: string | undefined + if (!newTabData.brandedWallpaper && newTabData.backgroundWallpaper?.type === 'color') { + overriddenForegroundColor = newTabData.backgroundWallpaper.overriddenForegroundColor + } + return ( { paddingType={'right'} widgetTitle={getLocale('statsTitle')} textDirection={newTabData.textDirection} - menuPosition={'right'}> - + menuPosition={'right'} + color={overriddenForegroundColor ?? '#ffffff'}> + { widgetTitle={getLocale('clockTitle')} textDirection={newTabData.textDirection} menuPosition='left'> - + { showTopSites @@ -1247,12 +1253,13 @@ class NewTabPage extends React.Component { showPhotoInfo={!isShowingBrandedWallpaper && hasWallpaperInfo && newTabData.showBackgroundImage} onClickSettings={this.openSettings} onDismissBraveTalkPrompt={this.props.actions.dismissBraveTalkPrompt} + color={overriddenForegroundColor ?? '#ffffff'} /> {newTabData.showToday && - + } diff --git a/components/brave_new_tab_ui/containers/newTab/stats.tsx b/components/brave_new_tab_ui/containers/newTab/stats.tsx index 50862ee82ae7..f27e519d8ac5 100644 --- a/components/brave_new_tab_ui/containers/newTab/stats.tsx +++ b/components/brave_new_tab_ui/containers/newTab/stats.tsx @@ -10,6 +10,7 @@ import { getLocale } from '../../../common/locale' interface Props { stats: NewTab.Stats + overriddenTextColor?: string } const MILLISECONDS_PER_ITEM = 50 @@ -88,16 +89,19 @@ export default function Stats (props: Props) { return + counter={adblockCount.toLocaleString()} + overriddenTextColor={props.overriddenTextColor} /> {bandwidthSaved && + description={getLocale('estimatedBandwidthSaved')} + overriddenTextColor={props.overriddenTextColor} /> } + description={getLocale('estimatedTimeSaved')} + overriddenTextColor={props.overriddenTextColor} /> } diff --git a/components/brave_new_tab_ui/helpers/colorUtil.test.ts b/components/brave_new_tab_ui/helpers/colorUtil.test.ts new file mode 100644 index 000000000000..9a18add89c41 --- /dev/null +++ b/components/brave_new_tab_ui/helpers/colorUtil.test.ts @@ -0,0 +1,128 @@ +// Copyright (c) 2022 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 http://mozilla.org/MPL/2.0/. + +import * as ColorUtil from './colorUtil' + +describe('ColorData', () => { + describe('constructor', () => { + it('can be constructed from HEX color', () => { + const color = new ColorUtil.ColorData('#123456') + expect(color.type).toBe(ColorUtil.ColorType.HEX) + expect(color.r).toBe(0x12) + expect(color.g).toBe(0x34) + expect(color.b).toBe(0x56) + }) + + it('can be constructed from HEX shorthand color', () => { + const color = new ColorUtil.ColorData('#123') + expect(color.type).toBe(ColorUtil.ColorType.HEX) + expect(color.r).toBe(0x11) + expect(color.g).toBe(0x22) + expect(color.b).toBe(0x33) + }) + + it('can be constructed from rgb()', () => { + let color = new ColorUtil.ColorData('rgb(1, 2, 3)') + expect(color.type).toBe(ColorUtil.ColorType.RGB) + expect(color.r).toBe(1) + expect(color.g).toBe(2) + expect(color.b).toBe(3) + + color = new ColorUtil.ColorData('rgb(0, 0, 0)') + expect(color.type).toBe(ColorUtil.ColorType.RGB) + expect(color.r).toBe(0) + expect(color.g).toBe(0) + expect(color.b).toBe(0) + + color = new ColorUtil.ColorData('rgb(255, 255, 255)') + expect(color.type).toBe(ColorUtil.ColorType.RGB) + expect(color.r).toBe(255) + expect(color.g).toBe(255) + expect(color.b).toBe(255) + }) + }) + + describe('getRelativeLuminance()', () => { + // Can cross check values from https://planetcalc.com/7779/?color=%23FFFFFF + // (modify |color| query value) + it('returns 0.0 for black', () => { expect(new ColorUtil.ColorData('rgb(0, 0, 0)').getRelativeLuminance()).toBe(0) }) + it('returns 1.0 for white', () => { expect(new ColorUtil.ColorData('rgb(255, 255, 255)').getRelativeLuminance()).toBe(1) }) + it('returns 0.2126 for red', () => { expect(new ColorUtil.ColorData('rgb(255, 0, 0)').getRelativeLuminance()).toBe(0.2126) }) + it('returns 0.7152 for green', () => { expect(new ColorUtil.ColorData('rgb(0, 255, 0)').getRelativeLuminance()).toBe(0.7152) }) + it('returns 0.0722 for blue', () => { expect(new ColorUtil.ColorData('rgb(0, 0, 255)').getRelativeLuminance()).toBe(0.0722) }) + }) + + describe('luminanceCache', () => { + beforeEach(() => { ColorUtil.ColorData.clearCacheForTesting() }) + + it('has L for rgb(255, 255, 255) in the beginning', () => { expect(new ColorUtil.ColorData('rgb(255, 255, 255)').hasCachedLuminance()).toBeTruthy() }) + it('has L for #ffffff in the beginning', () => { expect(new ColorUtil.ColorData('#ffffff').hasCachedLuminance()).toBeTruthy() }) + it('has L for rgb(0, 0, 0) in the beginning', () => { expect(new ColorUtil.ColorData('rgb(0, 0, 0)').hasCachedLuminance()).toBeTruthy() }) + it('has L for #000 in the beginning', () => { expect(new ColorUtil.ColorData('#000').hasCachedLuminance()).toBeTruthy() }) + it('caches L once a L is calculated', () => { + const color = new ColorUtil.ColorData('rgb(255, 0, 0)') + expect(color.hasCachedLuminance()).toBeFalsy() + + // Calculate L and make cache hot + color.getRelativeLuminance() + expect(color.hasCachedLuminance()).toBeTruthy() + + // Equivalent color should use the same cache + expect(new ColorUtil.ColorData('#ff0000').hasCachedLuminance).toBeTruthy() + }) + }) +}) + +describe('getContrastRatio()', () => { + // Can cross check values from https://planetcalc.com/7779/?color1=%23FFFFFF&color2=%23000000 + // (modify |color1| and |color2| query value) + it('returns 1.0 for same color', () => { + expect(ColorUtil.getContrastRatio(new ColorUtil.ColorData('rgb(0, 0, 0)'), + new ColorUtil.ColorData('#000'))).toBe(1) + }) + + it('returns 21 for black and white', () => { + expect(ColorUtil.getContrastRatio(new ColorUtil.ColorData('#fff'), + new ColorUtil.ColorData('#000'))).toBe(21) + }) + + it('returns 2.91 for red and green', () => { + expect(ColorUtil.getContrastRatio(new ColorUtil.ColorData('#f00'), + new ColorUtil.ColorData('#0f0'))).toBe(2.9139375476009137) + }) + + it('returns 6.26 for green and blue', () => { + expect(ColorUtil.getContrastRatio(new ColorUtil.ColorData('#0f0'), + new ColorUtil.ColorData('#00f'))).toBe(6.261865793780687) + }) + + it('returns 2.14 for blue and red', () => { + expect(ColorUtil.getContrastRatio(new ColorUtil.ColorData('#00f'), + new ColorUtil.ColorData('#f00'))).toBe(2.148936170212766) + }) +}) + +describe('isReadable()', () => { + describe('When background is black, stats are visible', () => { + const background = new ColorUtil.ColorData('#000') + it('returns true for tracker stat color', () => { expect(ColorUtil.isReadable(background, new ColorUtil.ColorData('#FB542B'/* --interactive2 */))).toBeTruthy() }) + it('returns false for bandwidth saved stat color', () => { expect(ColorUtil.isReadable(background, new ColorUtil.ColorData('#A0A5EB'/* --interactive9 */))).toBeTruthy() }) + it('returns false for time saved stat color', () => { expect(ColorUtil.isReadable(background, new ColorUtil.ColorData('#FFFFFF'))).toBeTruthy() }) + }) + + describe('When background is #F0CB44, stats are not visible', () => { + const background = new ColorUtil.ColorData('#F0CB44') + it('returns true for tracker stat color', () => { expect(ColorUtil.isReadable(background, new ColorUtil.ColorData('#FB542B'/* --interactive2 */))).toBeTruthy() }) + it('returns false for bandwidth saved stat color', () => { expect(ColorUtil.isReadable(background, new ColorUtil.ColorData('#A0A5EB'/* --interactive9 */))).toBeFalsy() }) + it('returns false for time saved stat color', () => { expect(ColorUtil.isReadable(background, new ColorUtil.ColorData('#FFFFFF'))).toBeFalsy() }) + }) + + describe('When background is #2197F9 stats are not visible', () => { + const background = new ColorUtil.ColorData('#2197F9') + it('returns true for tracker stat color', () => { expect(ColorUtil.isReadable(background, new ColorUtil.ColorData('#FB542B'/* --interactive2 */))).toBeFalsy() }) + it('returns false for bandwidth saved stat color', () => { expect(ColorUtil.isReadable(background, new ColorUtil.ColorData('#A0A5EB'/* --interactive9 */))).toBeFalsy() }) + it('returns false for time saved stat color', () => { expect(ColorUtil.isReadable(background, new ColorUtil.ColorData('#FFFFFF'))).toBeTruthy() }) + }) +}) diff --git a/components/brave_new_tab_ui/helpers/colorUtil.ts b/components/brave_new_tab_ui/helpers/colorUtil.ts new file mode 100644 index 000000000000..28f3b81c520b --- /dev/null +++ b/components/brave_new_tab_ui/helpers/colorUtil.ts @@ -0,0 +1,173 @@ +// Copyright (c) 2022 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 http://mozilla.org/MPL/2.0/. + +/** enums for types of background color */ +export enum ColorType { + NONE, + HEX, + RGB, + LINEAR_GRADIENT, + RADIAL_GRADIENT +} + +/** ColorData class takes a color string, parses it, and returns the luminance of the color */ +export class ColorData { + static #luminanceCache = new Map([[0 /* black */, 0.0], [255255255 /* white */, 1.0]]) + + static clearCacheForTesting () { ColorData.#luminanceCache = new Map([[0 /* black */, 0.0], [255255255 /* white */, 1.0]]) } + + static rgbMatcher = /rgb\((\d+),\s*(\d+),\s*(\d+)\)/ + static hexMatcher = /#([0-9a-f]{6}|[0-9a-f]{3})/i + + type: ColorType + value: string + r: number + g: number + b: number + + constructor (value: string) { + this.value = value + + const rgb = this.value.match(ColorData.rgbMatcher) + if (rgb) { + this.type = ColorType.RGB; + [this.r, this.g, this.b] = [rgb[1], rgb[2], rgb[3]].map((v) => parseInt(v, 10)) + return + } + + const hex = this.value.match(ColorData.hexMatcher) + if (hex) { + this.type = ColorType.HEX + if (hex[0].length === 7) { + [this.r, this.g, this.b] = [hex[1].substring(0, 2), hex[1].substring(2, 4), hex[1].substring(4, 6)].map((v) => parseInt(v, 16)) + } else if (hex[0].length === 4) { + // short-hand hex + [this.r, this.g, this.b] = [hex[1].substring(0, 1), hex[1].substring(1, 2), hex[1].substring(2, 3)].map((v) => parseInt(v + v, 16)) + } + return + } + + // TODO(sko) linear-gradient, radial-gradient + this.type = ColorType.NONE + } + + toString = () => { + return `ColorData{${this.value}}` + } + + isValid = () => { + return this.type !== ColorType.NONE + } + + get luminanceCacheKey () { + return this.r * 1000000 + this.g * 1000 + this.b + } + + get cachedLuminance () { + return ColorData.#luminanceCache.get(this.luminanceCacheKey) + } + + hasCachedLuminance = () => { + return ColorData.#luminanceCache.has(this.luminanceCacheKey) + } + + // Returns luminance of value of given |color| based on a definition from + // https://www.w3.org/TR/WCAG20/#relativeluminancedef + getRelativeLuminance = () => { + if (!this.isValid()) { + console.error(`Invalid color value: ${this}`) + return 0.0 + } + + let r = this.r + let g = this.g + let b = this.b + if (r === undefined || g === undefined || b === undefined) { + console.error(`Couldn't extract RGB of: ${this}`) + return 0.0 + } + + const cachedLuminance = this.cachedLuminance + if (cachedLuminance) { + return cachedLuminance + } + + // Step 1. Lerp each channel to a value between 0 and 1. + [r, g, b] = [r, g, b].map(v => v / 255); + + // Step 2. Adjust each channel's value. + [r, g, b] = [r, g, b].map(v => { + if (v <= 0.03928) { + v /= 12.92 + } else { + v = ((v + 0.055) / 1.055) ** 2.4 + } + return v + }) + + // Step 3. Get Luminance. + const cacheKey = this.luminanceCacheKey + ColorData.#luminanceCache.set(cacheKey, 0.2126 * r + 0.7152 * g + 0.0722 * b) + return ColorData.#luminanceCache.get(cacheKey)! + } +} + +/** + * Returns contrast ratio of two colors based on a definition from +// https://www.w3.org/TR/WCAG20/#contrast-ratiodef + * @param {ColorData} a - ColorData + * @param {ColorData} b - ColorData + * @returns Contrast ratio of two colors + */ +export function getContrastRatio (a: ColorData, b: ColorData): number { + const [lighter, darker] = a.getRelativeLuminance() > b.getRelativeLuminance() ? [a, b] : [b, a] + return (lighter.getRelativeLuminance() + 0.05) / (darker.getRelativeLuminance() + 0.05) +} + +// This value is much lower than that of WCAG 2.0. https://www.w3.org/WAI/WCAG21/quickref/?versions=2.0#qr-visual-audio-contrast-contrast +// The value was decided by our UX team. +let thresholdForReadability = 1.5 + +export function setThresholdForReadability (threshold: number) { + thresholdForReadability = threshold +} + +export function getThresholdForReadability () { + return thresholdForReadability +} + +// Determines if . The threshold we use +/** + * It returns true if |foreground| is readable on |background|. + * @param {ColorData} background - The background color + * @param {ColorData} foreground - The foreground color. + * @returns {boolean} - True if the contrast ratio is greater than or equal to the threshold for readability + */ +export function isReadable (background: ColorData, foreground: ColorData) { + return getContrastRatio(background, foreground) >= thresholdForReadability +} + +/** + * Convenient function to get readability for our background type + * @param {NewTab.BackgroundWallpaper | undefined} background - + * NewTab.BackgroundWallpaper | undefined + * @returns {boolean} - true if background is readable + */ +export default function isReadableOnBackground (background: NewTab.BackgroundWallpaper | undefined) { + if (!background || background.type !== 'color') { + // Consider other cases readable. We can't determine the color from images. + return true + } + + const backgroundData = new ColorData(background.wallpaperColor) + if (!backgroundData.isValid()) { + console.error(`Invalid background color: ${backgroundData}`) + return true + } + + return isReadable(backgroundData, new ColorData('#fff')) && + isReadable(backgroundData, new ColorData('#FB542B'/* --interactive2 */)) && + isReadable(backgroundData, new ColorData('#A0A5EB'/* --interactive9 */)) +} diff --git a/components/brave_new_tab_ui/reducers/new_tab_reducer.ts b/components/brave_new_tab_ui/reducers/new_tab_reducer.ts index d45c2e934e19..85615c5dd593 100644 --- a/components/brave_new_tab_ui/reducers/new_tab_reducer.ts +++ b/components/brave_new_tab_ui/reducers/new_tab_reducer.ts @@ -23,6 +23,7 @@ import { setMostVisitedSettings } from '../api/topSites' import { handleWidgetPrefsChange } from './stack_widget_reducer' import { NewTabAdsData } from '../api/newTabAdsData' import { Background } from '../api/background' +import isReadableOnBackground from '../helpers/colorUtil' let sideEffectState: NewTab.State = storage.load() @@ -59,8 +60,14 @@ export const newTabReducer: Reducer = (state: NewTab.S if (initialDataPayload.wallpaperData) { let backgroundWallpaper = initialDataPayload.wallpaperData.backgroundWallpaper - if (backgroundWallpaper?.type === 'color' && backgroundWallpaper.random) { - backgroundWallpaper = backgroundAPI.randomColorBackground(backgroundWallpaper.wallpaperColor) + if (backgroundWallpaper?.type === 'color') { + if (backgroundWallpaper.random) { + backgroundWallpaper = backgroundAPI.randomColorBackground(backgroundWallpaper.wallpaperColor) + } + + if (!isReadableOnBackground(backgroundWallpaper)) { + (backgroundWallpaper as NewTab.ColorBackground).overriddenForegroundColor = '#000000' + } } state = { @@ -137,6 +144,9 @@ export const newTabReducer: Reducer = (state: NewTab.S state.backgroundWallpaper = { type: 'image', wallpaperImageUrl: url } } else if (color) { state.backgroundWallpaper = random ? backgroundAPI.randomColorBackground(color) : { type: 'color', wallpaperColor: color, random } + if (!isReadableOnBackground(state.backgroundWallpaper)) { + (state.backgroundWallpaper as NewTab.ColorBackground).overriddenForegroundColor = '#000000' + } } } diff --git a/components/brave_new_tab_ui/stories/default/data/backgroundWallpaper.ts b/components/brave_new_tab_ui/stories/default/data/backgroundWallpaper.ts index b9cec5a3e1d5..08dfe66371c1 100644 --- a/components/brave_new_tab_ui/stories/default/data/backgroundWallpaper.ts +++ b/components/brave_new_tab_ui/stories/default/data/backgroundWallpaper.ts @@ -8,11 +8,15 @@ import { addons } from '@storybook/addons' import { images, solidColorsForBackground, gradientColorsForBackground } from '../../../data/backgrounds' +import isReadableOnBackground from '../../../helpers/colorUtil' + const addonsChannel = addons.getChannel() -export const backgroundWallpapers = (function (images: NewTab.BackgroundWallpaper[], - solidColors: NewTab.ColorBackground[], - gradientColors: NewTab.ColorBackground[]) { +export let backgroundWallpapers: any + +const generateWallpapers = function (images: NewTab.BackgroundWallpaper[], + solidColors: NewTab.ColorBackground[], + gradientColors: NewTab.ColorBackground[]) { let staticImages = { defaultImage: undefined } for (const image of images) { // author is optional field. @@ -23,7 +27,8 @@ export const backgroundWallpapers = (function (images: NewTab.BackgroundWallpape Object.assign(staticImages, { [image.author]: { ...image, - wallpaperImageUrl: require('../../../../img/newtab/backgrounds/' + image.wallpaperImageUrl) + // wallpaperImageUrl: require('../../../../img/newtab/backgrounds/' + image.wallpaperImageUrl) + wallpaperImageUrl: '' } }) @@ -33,6 +38,12 @@ export const backgroundWallpapers = (function (images: NewTab.BackgroundWallpape } const reducer = (prev: any, colorBackground: NewTab.ColorBackground) => { + if (isReadableOnBackground(colorBackground)) { + colorBackground.overriddenForegroundColor = undefined + } else { + colorBackground.overriddenForegroundColor = '#000000' + } + return { ...prev, [colorBackground.wallpaperColor]: colorBackground @@ -43,7 +54,12 @@ export const backgroundWallpapers = (function (images: NewTab.BackgroundWallpape staticImages = gradientColors.reduce(reducer, staticImages) return staticImages -})(images, solidColorsForBackground, gradientColorsForBackground) +}.bind(null, images, solidColorsForBackground, gradientColorsForBackground) + +export const resetWallpapers = () => { + backgroundWallpapers = generateWallpapers() +} +resetWallpapers() /** * Mock handler for colored backgrounds. Emits a change event to knobs diff --git a/components/brave_new_tab_ui/stories/default/data/storybookState.ts b/components/brave_new_tab_ui/stories/default/data/storybookState.ts index 6855ca54d914..83b160cf7a9e 100644 --- a/components/brave_new_tab_ui/stories/default/data/storybookState.ts +++ b/components/brave_new_tab_ui/stories/default/data/storybookState.ts @@ -6,9 +6,10 @@ import { defaultState } from '../../../storage/new_tab_storage' import { initialGridSitesState } from '../../../storage/grid_sites_storage' import { TabType as SettingsTabType } from '../../../containers/newTab/settings' import dummyBrandedWallpaper from './brandedWallpaper' -import { backgroundWallpapers } from './backgroundWallpaper' +import * as Background from './backgroundWallpaper' import { newTabPrefManager } from '../../../hooks/usePref' import { useEffect } from 'react' +import isReadableOnBackground, * as ColorUtil from '../../../helpers/colorUtil' const addonsChannel = addons.getChannel() @@ -70,9 +71,10 @@ export const useNewTabData = (state: NewTab.State = defaultState) => { brandedWallpaperOptIn: boolean('Show branded background image?', true), backgroundWallpaper: select( 'Background', - backgroundWallpapers, - backgroundWallpapers.defaultImage + Background.backgroundWallpapers, + Background.backgroundWallpapers.defaultImage ), + readabilityThreshold: number('Readability threshold', ColorUtil.getThresholdForReadability(), { range: true, min: 0, max: 10, step: 0.1 }), customLinksEnabled: boolean('CustomLinks Enabled?', false), featureFlagBraveNTPSponsoredImagesWallpaper: true, featureCustomBackgroundEnabled: true, @@ -113,6 +115,15 @@ export const useNewTabData = (state: NewTab.State = defaultState) => { widgetStackOrder: getWidgetStackOrder(select('First widget', ['braveTalk', 'rewards'], 'rewards')) } + if (state.readabilityThreshold !== result.readabilityThreshold) { + ColorUtil.setThresholdForReadability(result.readabilityThreshold!) + Background.resetWallpapers() + if (result.backgroundWallpaper?.type === 'color') { + result.backgroundWallpaper.overriddenForegroundColor = isReadableOnBackground(result.backgroundWallpaper) + ? undefined : '#000000' + } + } + // On all updates, notify that the prefs might've changed. Listeners are // only notified when the setting they're interested in updates anyway. useEffect(() => { diff --git a/components/definitions/newTab.d.ts b/components/definitions/newTab.d.ts index fe546e7abf96..6e9210fb5025 100644 --- a/components/definitions/newTab.d.ts +++ b/components/definitions/newTab.d.ts @@ -9,6 +9,7 @@ declare namespace NewTab { type: 'color' wallpaperColor: string random?: boolean + overriddenForegroundColor?: string } // Backgrounds based on image. Custom image background or Brave background. @@ -315,6 +316,7 @@ declare namespace NewTab { interface StorybookStateExtras { forceSettingsTab?: string // SettingsTabType + readabilityThreshold?: number } // In-memory state is a superset of PersistentState diff --git a/components/web-components/app.global.scss b/components/web-components/app.global.scss index c006d2e1ae64..13cf240e0b9f 100644 --- a/components/web-components/app.global.scss +++ b/components/web-components/app.global.scss @@ -1,3 +1,8 @@ +/* Copyright (c) 2022 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 http://mozilla.org/MPL/2.0/. */ + :root { --brave-font-family-default: Poppins, sans-serif; --brave-font-family-non-serif: Poppins, normal; @@ -14,6 +19,7 @@ --interactive6: #737ADE; --interactive7: #212529; --interactive8: #AEB1C2; + --interactive9: #A0A5EB; --focus-border: #A0A5EB; --disabled: #DADCE8; --blurple300: #A0A5EB; @@ -28,7 +34,6 @@ --text1: #F0F2FF; --text2: #C2C4CF; --text3: #84889C; - --interactive2: #FB542B; --interactive7: #F0F2FF; --interactive8: #5E6175; --disabled: #343A40; From 27a0d34e36d85962ef0b7d71d98762f57421151a Mon Sep 17 00:00:00 2001 From: "sangwoo.ko" Date: Tue, 27 Sep 2022 22:45:47 +0900 Subject: [PATCH 2/6] Address code review: remove prop drilling --- .../components/default/braveToday/hint.tsx | 12 ++--- .../components/default/clock/index.tsx | 8 +--- .../components/default/clock/style.ts | 8 +--- .../default/footer/braveTalkItem.tsx | 4 +- .../components/default/footer/footer.tsx | 14 +++--- .../components/default/page/index.tsx | 19 +++----- .../components/default/stats/style.ts | 17 ++++--- .../components/default/widget/index.tsx | 7 +-- .../components/default/widget/widgetMenu.tsx | 7 ++- .../containers/newTab/index.tsx | 44 ++++++++++++++----- .../containers/newTab/stats.tsx | 9 ++-- .../helpers/colorUtil.test.ts | 10 ++--- .../default/data/backgroundWallpaper.ts | 15 +------ .../stories/default/data/storybookState.ts | 11 +---- ui/webui/resources/css/reset.css | 2 +- 15 files changed, 80 insertions(+), 107 deletions(-) diff --git a/components/brave_new_tab_ui/components/default/braveToday/hint.tsx b/components/brave_new_tab_ui/components/default/braveToday/hint.tsx index 8c4561919d97..279a1b5583e6 100644 --- a/components/brave_new_tab_ui/components/default/braveToday/hint.tsx +++ b/components/brave_new_tab_ui/components/default/braveToday/hint.tsx @@ -8,18 +8,14 @@ import styled from 'styled-components' import { CaratStrongDownIcon } from 'brave-ui/components/icons' import { getLocale } from '../../../../common/locale' -interface Props { - color: string -} - -const Hint = styled('div')` +const Hint = styled('div')<{}>` display: flex; flex-direction: column; align-items: center; gap: 12px; text-align: center; font-size: 15px; - color: ${p => p.color}; + color: var(--override-readability-color, #FFFFFF); > p { margin: 0; } @@ -30,9 +26,9 @@ const Graphic = styled('div')` height: 16px; ` -export default function BraveTodayHint (props: Props) { +export default function BraveTodayHint () { return ( - +

{getLocale('braveTodayScrollHint')}

diff --git a/components/brave_new_tab_ui/components/default/clock/index.tsx b/components/brave_new_tab_ui/components/default/clock/index.tsx index 312cfc211bd1..838ee63497f6 100644 --- a/components/brave_new_tab_ui/components/default/clock/index.tsx +++ b/components/brave_new_tab_ui/components/default/clock/index.tsx @@ -7,13 +7,9 @@ import { useNewTabPref } from '../../../hooks/usePref' import { StyledClock, StyledTime } from './style' -interface Props { - color: string -} - // Tick once every two seconds. const TICK_RATE = 2000 -export function Clock ({ color }: Props) { +export function Clock () { const [now, setNow] = React.useState() const [clockFormat, setClockFormat] = useNewTabPref('clockFormat') const toggleClockFormat = () => { @@ -46,7 +42,7 @@ export function Clock ({ color }: Props) { ? null : t.value), [formatter, now]) - return + return {formattedTime} } diff --git a/components/brave_new_tab_ui/components/default/clock/style.ts b/components/brave_new_tab_ui/components/default/clock/style.ts index 819e12e73809..e884169420c2 100644 --- a/components/brave_new_tab_ui/components/default/clock/style.ts +++ b/components/brave_new_tab_ui/components/default/clock/style.ts @@ -5,12 +5,8 @@ import styled from 'styled-components' -interface ClockProps { - color: string -} - -export const StyledClock = styled('div')` - color: ${p => p.color}; +export const StyledClock = styled('div')<{}>` + color: var(--override-readability-color-rgb, #FFFFFF); box-sizing: border-box; line-height: 1; user-select: none; diff --git a/components/brave_new_tab_ui/components/default/footer/braveTalkItem.tsx b/components/brave_new_tab_ui/components/default/footer/braveTalkItem.tsx index a3dc7da6a0c3..6832ee873427 100644 --- a/components/brave_new_tab_ui/components/default/footer/braveTalkItem.tsx +++ b/components/brave_new_tab_ui/components/default/footer/braveTalkItem.tsx @@ -39,7 +39,7 @@ function BraveTalkTooltipItem (props: Props) { } return ( - + @@ -51,7 +51,7 @@ export default function BraveTalkItem (props: Props) { return } return ( - + ) diff --git a/components/brave_new_tab_ui/components/default/footer/footer.tsx b/components/brave_new_tab_ui/components/default/footer/footer.tsx index fd7510e95ee9..44976e7cd0df 100644 --- a/components/brave_new_tab_ui/components/default/footer/footer.tsx +++ b/components/brave_new_tab_ui/components/default/footer/footer.tsx @@ -39,7 +39,6 @@ export interface Props { showPhotoInfo: boolean onClickSettings: () => any onDismissBraveTalkPrompt: OnDismissBraveTalkPrompt - color: string } export default class FooterInfo extends React.PureComponent { @@ -49,8 +48,7 @@ export default class FooterInfo extends React.PureComponent { supportsBraveTalk, backgroundImageInfo, showPhotoInfo, - onClickSettings, - color + onClickSettings } = this.props return ( @@ -70,21 +68,21 @@ export default class FooterInfo extends React.PureComponent { } - + - + {getLocale('customize')} - + - + - + {supportsBraveTalk && diff --git a/components/brave_new_tab_ui/components/default/page/index.tsx b/components/brave_new_tab_ui/components/default/page/index.tsx index 2d520cb28e70..e7136884d82f 100644 --- a/components/brave_new_tab_ui/components/default/page/index.tsx +++ b/components/brave_new_tab_ui/components/default/page/index.tsx @@ -382,22 +382,18 @@ export const Navigation = styled('nav')<{}>` align-items: center; ` -interface ColorButtonProps { - color: string -} - interface IconButtonProps { clickDisabled?: boolean isClickMenu?: boolean } -export const IconLink = styled('a')` +export const IconLink = styled('a')<{}>` display: block; width: 24px; height: 24px; margin: 8px; cursor: pointer; - color: ${p => p.color}; + color: var(--override-readability-color, #ffffff); opacity: 0.7; transition: opacity 0.15s ease, filter 0.15s ease; @@ -406,7 +402,7 @@ export const IconLink = styled('a')` } ` -export const IconButton = styled('button')` +export const IconButton = styled('button')` pointer-events: ${p => p.clickDisabled && 'none'}; display: flex; width: 24px; @@ -416,7 +412,7 @@ export const IconButton = styled('button')` outline: none; margin: ${p => p.isClickMenu ? '7' : '0 12'}px; cursor: pointer; - color: ${p => p.color}; + color: var(--override-readability-color, #ffffff); background-color: transparent; opacity: 0.7; transition: opacity 0.15s ease, filter 0.15s ease; @@ -465,18 +461,17 @@ export const IconButtonSideText = styled('label')` interface IconButtonContainerProps { textDirection: string - color: string } export const IconButtonContainer = styled('div')` font-family: ${p => p.theme.fontFamily.heading}; font-size: 13px; font-weight: 600; - color: ${p => p.color + 'CC' /* == 0.8 */}; + color: rgba(var(--override-readability-color-rgb, 255, 255, 255), 0.8); margin-right: ${p => p.textDirection === 'ltr' && '8px'}; margin-left: ${p => p.textDirection === 'rtl' && '8px'}; - border-right: ${p => p.textDirection === 'ltr' && `1px solid ${p.color + '99' /* == 0.6 */}`}; - border-left: ${p => p.textDirection === 'rtl' && `1px solid ${p.color + '99' /* == 0.6 */}`}; + border-right: ${p => p.textDirection === 'ltr' && 'rgba(var(--override-readability-color-rgb, 255, 255, 255), 0.6)'}; + border-left: ${p => p.textDirection === 'rtl' && 'rgba(var(--override-readability-color-rgb, 255, 255, 255), 0.6)'}; &:hover { color: ${p => p.color}; diff --git a/components/brave_new_tab_ui/components/default/stats/style.ts b/components/brave_new_tab_ui/components/default/stats/style.ts index 63e6cc1852e4..be7d5e8cf07c 100644 --- a/components/brave_new_tab_ui/components/default/stats/style.ts +++ b/components/brave_new_tab_ui/components/default/stats/style.ts @@ -2,7 +2,7 @@ * 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 styled, { css } from 'styled-components' +import styled from 'styled-components' export const StyledStatsItemContainer = styled('ul')<{}>` -webkit-font-smoothing: antialiased; @@ -23,13 +23,12 @@ export const StyledStatsItem = styled('li')<{overriddenTextColor?: string}>` font-size: inherit; font-family: inherit; margin: 10px 16px; - &:last-child { margin-right: 0; } - - ${p => p.overriddenTextColor - ? css`color: ${p.overriddenTextColor};` - : css`&:first-child { color: var(--interactive2); } - &:nth-child(2) { color: var(--interactive9); } - &:last-child { color: #FFFFFF; }`} + &:first-child { color: var(--override-readability-color-rgb, var(--interactive2)); } + &:nth-child(2) { color: var(--override-readability-color-rgb, var(--interactive9)); } + &:last-child { + color: var(--override-readability-color-rgb, #FFFFFF); + margin-right: 0; + } ` export const StyledStatsItemCounter = styled('span')<{}>` @@ -55,7 +54,7 @@ export const StyledStatsItemText = styled('span')<{}>` export const StyledStatsItemDescription = styled('div')<{overriddenTextColor?: string}>` font-size: 16px; font-weight: 500; - ${p => !p.overriddenTextColor && css`color: #FFFFFF;`} + color: var(--override-readability-color-rgb, #FFFFFF); margin-top: 8px; font-family: ${p => p.theme.fontFamily.heading}; ` diff --git a/components/brave_new_tab_ui/components/default/widget/index.tsx b/components/brave_new_tab_ui/components/default/widget/index.tsx index b2d038f44587..ac3ff813f2db 100644 --- a/components/brave_new_tab_ui/components/default/widget/index.tsx +++ b/components/brave_new_tab_ui/components/default/widget/index.tsx @@ -19,7 +19,6 @@ export interface WidgetProps { hideMenu?: boolean isForeground?: boolean paddingType: 'none' | 'right' | 'default' - color?: string onLearnMore?: () => void onDisconnect?: () => void onRefreshData?: () => void @@ -49,8 +48,7 @@ export function Widget ({ onAddSite, customLinksEnabled, onToggleCustomLinksEnabled, - children, - color + children }: WidgetProps & { children: React.ReactNode }) { const [widgetMenuPersist, setWidgetMenuPersist] = React.useState(!!isForeground) return @@ -78,8 +76,7 @@ export function Widget ({ hideWidget={hideWidget} persistWidget={() => setWidgetMenuPersist(true)} unpersistWidget={() => setWidgetMenuPersist(false)} - paddingType={paddingType} - color={color} />} + paddingType={paddingType} />} } diff --git a/components/brave_new_tab_ui/components/default/widget/widgetMenu.tsx b/components/brave_new_tab_ui/components/default/widget/widgetMenu.tsx index fd7fbaf2809a..8bf94ae9d097 100644 --- a/components/brave_new_tab_ui/components/default/widget/widgetMenu.tsx +++ b/components/brave_new_tab_ui/components/default/widget/widgetMenu.tsx @@ -7,7 +7,7 @@ import * as React from 'react' import { StyledWidgetMenuContainer, StyledWidgetMenu, StyledWidgetButton, StyledWidgetIcon, StyledSpan, StyledWidgetLink, StyledEllipsis } from './styles' import { IconButton } from '../../default' -import EllipsisIcon from './assets/ellipsis' +import EllipsisIcon from '../../popupMenu/ellipsisIcon' import HideIcon from './assets/hide' import AddSiteIcon from './assets/add-site' import FrecencyIcon from './assets/frecency' @@ -106,8 +106,7 @@ export default class WidgetMenu extends React.PureComponent { onRefreshData, onAddSite, onToggleCustomLinksEnabled, - customLinksEnabled, - color + customLinksEnabled } = this.props const { showMenu } = this.state const hideString = widgetTitle ? `${getLocale('hide')} ${widgetTitle}` : getLocale('hide') @@ -115,7 +114,7 @@ export default class WidgetMenu extends React.PureComponent { return ( - + diff --git a/components/brave_new_tab_ui/containers/newTab/index.tsx b/components/brave_new_tab_ui/containers/newTab/index.tsx index d7c6bace68b4..d09bb7a70f23 100644 --- a/components/brave_new_tab_ui/containers/newTab/index.tsx +++ b/components/brave_new_tab_ui/containers/newTab/index.tsx @@ -40,6 +40,7 @@ import { fetchCryptoDotComSupportedPairs } from '../../api/cryptoDotCom' import { generateQRData } from '../../binance-utils' +import * as ColorUtil from '../../helpers/colorUtil' // Types import { GeminiAssetAddress } from '../../actions/gemini_actions' @@ -54,6 +55,7 @@ import { FTXState } from '../../widgets/ftx/ftx_state' import Settings, { TabType as SettingsTabType } from './settings' import { MAX_GRID_SIZE } from '../../constants/new_tab_ui' import GridWidget from './gridWidget' +import isReadableOnBackground from '../../helpers/colorUtil' interface Props { newTabData: NewTab.State @@ -185,6 +187,8 @@ class NewTabPage extends React.Component { forceToHideWidget: GetShouldForceToHideWidget(this.props, searchPromotionEnabled) }) window.addEventListener('resize', this.handleResize.bind(this)) + + this.updateOverrideReadabilityColor() } componentWillUnmount () { @@ -192,6 +196,9 @@ class NewTabPage extends React.Component { window.clearTimeout(this.braveNewsPromptTimerId) } window.removeEventListener('resize', this.handleResize.bind(this)) + + document.documentElement.style.removeProperty('--override-readability-color-rgb') + document.documentElement.style.removeProperty('--override-readability-color') } componentDidUpdate (prevProps: Props) { @@ -215,6 +222,28 @@ class NewTabPage extends React.Component { !GetShouldShowBrandedWallpaperNotification(this.props)) { this.stopWaitingForBrandedWallpaperNotificationAutoDismiss() } + + if (prevProps.newTabData.readabilityThreshold !== this.props.newTabData.readabilityThreshold || + this.shouldOverrideReadabilityColor(prevProps.newTabData) !== this.shouldOverrideReadabilityColor(this.props.newTabData)) { + if (this.props.newTabData.readabilityThreshold) { + ColorUtil.setThresholdForReadability(this.props.newTabData.readabilityThreshold) + } + this.updateOverrideReadabilityColor() + } + } + + shouldOverrideReadabilityColor (newTabData: NewTab.State) { + return !newTabData.brandedWallpaper && newTabData.backgroundWallpaper?.type === 'color' && !isReadableOnBackground(newTabData.backgroundWallpaper) + } + + updateOverrideReadabilityColor () { + if (this.shouldOverrideReadabilityColor(this.props.newTabData)) { + document.body.style.setProperty('--override-readability-color-rgb', '0, 0, 0') + document.body.style.setProperty('--override-readability-color', 'rgb(0, 0, 0)') + } else { + document.body.style.removeProperty('--override-readability-color-rgb') + document.body.style.removeProperty('--override-readability-color') + } } handleResize () { @@ -1158,11 +1187,6 @@ class NewTabPage extends React.Component { cryptoContent = null } - let overriddenForegroundColor: string | undefined - if (!newTabData.brandedWallpaper && newTabData.backgroundWallpaper?.type === 'color') { - overriddenForegroundColor = newTabData.backgroundWallpaper.overriddenForegroundColor - } - return ( { paddingType={'right'} widgetTitle={getLocale('statsTitle')} textDirection={newTabData.textDirection} - menuPosition={'right'} - color={overriddenForegroundColor ?? '#ffffff'}> - + menuPosition={'right'}> + { widgetTitle={getLocale('clockTitle')} textDirection={newTabData.textDirection} menuPosition='left'> - + { showTopSites @@ -1253,13 +1276,12 @@ class NewTabPage extends React.Component { showPhotoInfo={!isShowingBrandedWallpaper && hasWallpaperInfo && newTabData.showBackgroundImage} onClickSettings={this.openSettings} onDismissBraveTalkPrompt={this.props.actions.dismissBraveTalkPrompt} - color={overriddenForegroundColor ?? '#ffffff'} /> {newTabData.showToday && - + } diff --git a/components/brave_new_tab_ui/containers/newTab/stats.tsx b/components/brave_new_tab_ui/containers/newTab/stats.tsx index f27e519d8ac5..131cab0e4217 100644 --- a/components/brave_new_tab_ui/containers/newTab/stats.tsx +++ b/components/brave_new_tab_ui/containers/newTab/stats.tsx @@ -89,19 +89,16 @@ export default function Stats (props: Props) { return + counter={adblockCount.toLocaleString()}/> {bandwidthSaved && + description={getLocale('estimatedBandwidthSaved')}/> } + description={getLocale('estimatedTimeSaved')}/> } diff --git a/components/brave_new_tab_ui/helpers/colorUtil.test.ts b/components/brave_new_tab_ui/helpers/colorUtil.test.ts index 9a18add89c41..e9f32b8197fc 100644 --- a/components/brave_new_tab_ui/helpers/colorUtil.test.ts +++ b/components/brave_new_tab_ui/helpers/colorUtil.test.ts @@ -108,21 +108,21 @@ describe('isReadable()', () => { describe('When background is black, stats are visible', () => { const background = new ColorUtil.ColorData('#000') it('returns true for tracker stat color', () => { expect(ColorUtil.isReadable(background, new ColorUtil.ColorData('#FB542B'/* --interactive2 */))).toBeTruthy() }) - it('returns false for bandwidth saved stat color', () => { expect(ColorUtil.isReadable(background, new ColorUtil.ColorData('#A0A5EB'/* --interactive9 */))).toBeTruthy() }) - it('returns false for time saved stat color', () => { expect(ColorUtil.isReadable(background, new ColorUtil.ColorData('#FFFFFF'))).toBeTruthy() }) + it('returns true for bandwidth saved stat color', () => { expect(ColorUtil.isReadable(background, new ColorUtil.ColorData('#A0A5EB'/* --interactive9 */))).toBeTruthy() }) + it('returns true for time saved stat color', () => { expect(ColorUtil.isReadable(background, new ColorUtil.ColorData('#FFFFFF'))).toBeTruthy() }) }) describe('When background is #F0CB44, stats are not visible', () => { const background = new ColorUtil.ColorData('#F0CB44') it('returns true for tracker stat color', () => { expect(ColorUtil.isReadable(background, new ColorUtil.ColorData('#FB542B'/* --interactive2 */))).toBeTruthy() }) it('returns false for bandwidth saved stat color', () => { expect(ColorUtil.isReadable(background, new ColorUtil.ColorData('#A0A5EB'/* --interactive9 */))).toBeFalsy() }) - it('returns false for time saved stat color', () => { expect(ColorUtil.isReadable(background, new ColorUtil.ColorData('#FFFFFF'))).toBeFalsy() }) + it('returns true for time saved stat color', () => { expect(ColorUtil.isReadable(background, new ColorUtil.ColorData('#FFFFFF'))).toBeTruthy() }) }) describe('When background is #2197F9 stats are not visible', () => { const background = new ColorUtil.ColorData('#2197F9') - it('returns true for tracker stat color', () => { expect(ColorUtil.isReadable(background, new ColorUtil.ColorData('#FB542B'/* --interactive2 */))).toBeFalsy() }) + it('returns false for tracker stat color', () => { expect(ColorUtil.isReadable(background, new ColorUtil.ColorData('#FB542B'/* --interactive2 */))).toBeFalsy() }) it('returns false for bandwidth saved stat color', () => { expect(ColorUtil.isReadable(background, new ColorUtil.ColorData('#A0A5EB'/* --interactive9 */))).toBeFalsy() }) - it('returns false for time saved stat color', () => { expect(ColorUtil.isReadable(background, new ColorUtil.ColorData('#FFFFFF'))).toBeTruthy() }) + it('returns true for time saved stat color', () => { expect(ColorUtil.isReadable(background, new ColorUtil.ColorData('#FFFFFF'))).toBeTruthy() }) }) }) diff --git a/components/brave_new_tab_ui/stories/default/data/backgroundWallpaper.ts b/components/brave_new_tab_ui/stories/default/data/backgroundWallpaper.ts index 08dfe66371c1..5bea1cc5d13b 100644 --- a/components/brave_new_tab_ui/stories/default/data/backgroundWallpaper.ts +++ b/components/brave_new_tab_ui/stories/default/data/backgroundWallpaper.ts @@ -8,12 +8,8 @@ import { addons } from '@storybook/addons' import { images, solidColorsForBackground, gradientColorsForBackground } from '../../../data/backgrounds' -import isReadableOnBackground from '../../../helpers/colorUtil' - const addonsChannel = addons.getChannel() -export let backgroundWallpapers: any - const generateWallpapers = function (images: NewTab.BackgroundWallpaper[], solidColors: NewTab.ColorBackground[], gradientColors: NewTab.ColorBackground[]) { @@ -38,12 +34,6 @@ const generateWallpapers = function (images: NewTab.BackgroundWallpaper[], } const reducer = (prev: any, colorBackground: NewTab.ColorBackground) => { - if (isReadableOnBackground(colorBackground)) { - colorBackground.overriddenForegroundColor = undefined - } else { - colorBackground.overriddenForegroundColor = '#000000' - } - return { ...prev, [colorBackground.wallpaperColor]: colorBackground @@ -56,10 +46,7 @@ const generateWallpapers = function (images: NewTab.BackgroundWallpaper[], return staticImages }.bind(null, images, solidColorsForBackground, gradientColorsForBackground) -export const resetWallpapers = () => { - backgroundWallpapers = generateWallpapers() -} -resetWallpapers() +export const backgroundWallpapers = generateWallpapers() /** * Mock handler for colored backgrounds. Emits a change event to knobs diff --git a/components/brave_new_tab_ui/stories/default/data/storybookState.ts b/components/brave_new_tab_ui/stories/default/data/storybookState.ts index 83b160cf7a9e..2f4b9af29a9c 100644 --- a/components/brave_new_tab_ui/stories/default/data/storybookState.ts +++ b/components/brave_new_tab_ui/stories/default/data/storybookState.ts @@ -9,7 +9,7 @@ import dummyBrandedWallpaper from './brandedWallpaper' import * as Background from './backgroundWallpaper' import { newTabPrefManager } from '../../../hooks/usePref' import { useEffect } from 'react' -import isReadableOnBackground, * as ColorUtil from '../../../helpers/colorUtil' +import * as ColorUtil from '../../../helpers/colorUtil' const addonsChannel = addons.getChannel() @@ -115,15 +115,6 @@ export const useNewTabData = (state: NewTab.State = defaultState) => { widgetStackOrder: getWidgetStackOrder(select('First widget', ['braveTalk', 'rewards'], 'rewards')) } - if (state.readabilityThreshold !== result.readabilityThreshold) { - ColorUtil.setThresholdForReadability(result.readabilityThreshold!) - Background.resetWallpapers() - if (result.backgroundWallpaper?.type === 'color') { - result.backgroundWallpaper.overriddenForegroundColor = isReadableOnBackground(result.backgroundWallpaper) - ? undefined : '#000000' - } - } - // On all updates, notify that the prefs might've changed. Listeners are // only notified when the setting they're interested in updates anyway. useEffect(() => { diff --git a/ui/webui/resources/css/reset.css b/ui/webui/resources/css/reset.css index 007267d1820c..acc43bf86065 100644 --- a/ui/webui/resources/css/reset.css +++ b/ui/webui/resources/css/reset.css @@ -179,4 +179,4 @@ summary { [aria-disabled] { cursor: default; -} \ No newline at end of file +} From 473a4bc93c6b42aab3b3acd14ebce90a893c2072 Mon Sep 17 00:00:00 2001 From: "sangwoo.ko" Date: Wed, 28 Sep 2022 18:14:40 +0900 Subject: [PATCH 3/6] Use styled-component's createGlobalStyle to avoid a bug When we use setProperty(), a color value defined in reset.css wins over our css variables. In order to avoid this, use createGlobalStyle and override color value in resets.css when we need more readable color --- .../components/default/page/index.tsx | 15 ++++++++++- .../containers/newTab/index.tsx | 27 +++---------------- 2 files changed, 18 insertions(+), 24 deletions(-) diff --git a/components/brave_new_tab_ui/components/default/page/index.tsx b/components/brave_new_tab_ui/components/default/page/index.tsx index e7136884d82f..3ab1e4a0ccf6 100644 --- a/components/brave_new_tab_ui/components/default/page/index.tsx +++ b/components/brave_new_tab_ui/components/default/page/index.tsx @@ -3,7 +3,7 @@ * You can obtain one at http://mozilla.org/MPL/2.0/. */ import * as React from 'react' -import styled, { css } from 'styled-components' +import styled, { createGlobalStyle, css } from 'styled-components' import { requestAnimationFrameThrottle } from '../../../../common/throttle' const breakpointLargeBlocks = '980px' @@ -477,3 +477,16 @@ export const IconButtonContainer = styled('div')` color: ${p => p.color}; } ` + +export const OverrideReadabilityColor = createGlobalStyle<{override: boolean}>` + body { + ${p => p.override && css` + --override-readability-color-rgb: 0, 0, 0; + --override-readability-color: rgb(0, 0, 0); + + // override color property in resets.css. Not sure why this happens but, + // the value in the stylesheet wins over variables above. + color: inherit + `} + } +` diff --git a/components/brave_new_tab_ui/containers/newTab/index.tsx b/components/brave_new_tab_ui/containers/newTab/index.tsx index d09bb7a70f23..ee4b91303a2a 100644 --- a/components/brave_new_tab_ui/containers/newTab/index.tsx +++ b/components/brave_new_tab_ui/containers/newTab/index.tsx @@ -19,7 +19,8 @@ import { CryptoDotComWidget as CryptoDotCom, EditTopSite, SearchPromotion, - EditCards + EditCards, + OverrideReadabilityColor } from '../../components/default' import { FTXWidget as FTX } from '../../widgets/ftx/components' import * as Page from '../../components/default/page' @@ -40,7 +41,7 @@ import { fetchCryptoDotComSupportedPairs } from '../../api/cryptoDotCom' import { generateQRData } from '../../binance-utils' -import * as ColorUtil from '../../helpers/colorUtil' +import isReadableOnBackground from '../../helpers/colorUtil' // Types import { GeminiAssetAddress } from '../../actions/gemini_actions' @@ -55,7 +56,6 @@ import { FTXState } from '../../widgets/ftx/ftx_state' import Settings, { TabType as SettingsTabType } from './settings' import { MAX_GRID_SIZE } from '../../constants/new_tab_ui' import GridWidget from './gridWidget' -import isReadableOnBackground from '../../helpers/colorUtil' interface Props { newTabData: NewTab.State @@ -187,8 +187,6 @@ class NewTabPage extends React.Component { forceToHideWidget: GetShouldForceToHideWidget(this.props, searchPromotionEnabled) }) window.addEventListener('resize', this.handleResize.bind(this)) - - this.updateOverrideReadabilityColor() } componentWillUnmount () { @@ -222,30 +220,12 @@ class NewTabPage extends React.Component { !GetShouldShowBrandedWallpaperNotification(this.props)) { this.stopWaitingForBrandedWallpaperNotificationAutoDismiss() } - - if (prevProps.newTabData.readabilityThreshold !== this.props.newTabData.readabilityThreshold || - this.shouldOverrideReadabilityColor(prevProps.newTabData) !== this.shouldOverrideReadabilityColor(this.props.newTabData)) { - if (this.props.newTabData.readabilityThreshold) { - ColorUtil.setThresholdForReadability(this.props.newTabData.readabilityThreshold) - } - this.updateOverrideReadabilityColor() - } } shouldOverrideReadabilityColor (newTabData: NewTab.State) { return !newTabData.brandedWallpaper && newTabData.backgroundWallpaper?.type === 'color' && !isReadableOnBackground(newTabData.backgroundWallpaper) } - updateOverrideReadabilityColor () { - if (this.shouldOverrideReadabilityColor(this.props.newTabData)) { - document.body.style.setProperty('--override-readability-color-rgb', '0, 0, 0') - document.body.style.setProperty('--override-readability-color', 'rgb(0, 0, 0)') - } else { - document.body.style.removeProperty('--override-readability-color-rgb') - document.body.style.removeProperty('--override-readability-color') - } - } - handleResize () { this.setState({ forceToHideWidget: GetShouldForceToHideWidget(this.props, this.state.showSearchPromotion) @@ -1195,6 +1175,7 @@ class NewTabPage extends React.Component { imageHasLoaded={this.state.backgroundHasLoaded} colorForBackground={colorForBackground} data-show-news-prompt={((this.state.backgroundHasLoaded || colorForBackground) && this.state.isPromptingBraveToday) ? true : undefined}> + Date: Wed, 28 Sep 2022 18:34:44 +0900 Subject: [PATCH 4/6] Override text color in GridSites --- .../brave_new_tab_ui/components/default/gridSites/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/brave_new_tab_ui/components/default/gridSites/index.ts b/components/brave_new_tab_ui/components/default/gridSites/index.ts index e0da98895ee1..95f97cd60e44 100644 --- a/components/brave_new_tab_ui/components/default/gridSites/index.ts +++ b/components/brave_new_tab_ui/components/default/gridSites/index.ts @@ -13,7 +13,7 @@ export const TileTitle = styled('p')<{}>` line-height: 17px; max-width: 100%; height: 17px; - color: white; + color: var(--override-readability-color, white); padding: 0 2px; overflow: hidden; white-space: nowrap; From 46371b67012d56c89834f09f92f88df81ef362cd Mon Sep 17 00:00:00 2001 From: "sangwoo.ko" Date: Wed, 28 Sep 2022 18:52:37 +0900 Subject: [PATCH 5/6] Clean up --- .../components/default/clock/index.tsx | 2 +- .../components/default/stats/index.tsx | 7 +++---- .../components/default/stats/style.ts | 4 ++-- .../components/default/widget/assets/ellipsis.ts | 8 -------- .../brave_new_tab_ui/containers/newTab/index.tsx | 5 +---- .../brave_new_tab_ui/containers/newTab/stats.tsx | 7 +++---- .../brave_new_tab_ui/reducers/new_tab_reducer.ts | 14 ++------------ .../stories/default/data/backgroundWallpaper.ts | 3 +-- components/definitions/newTab.d.ts | 1 - 9 files changed, 13 insertions(+), 38 deletions(-) delete mode 100644 components/brave_new_tab_ui/components/default/widget/assets/ellipsis.ts diff --git a/components/brave_new_tab_ui/components/default/clock/index.tsx b/components/brave_new_tab_ui/components/default/clock/index.tsx index 838ee63497f6..c9f77f794e72 100644 --- a/components/brave_new_tab_ui/components/default/clock/index.tsx +++ b/components/brave_new_tab_ui/components/default/clock/index.tsx @@ -42,7 +42,7 @@ export function Clock () { ? null : t.value), [formatter, now]) - return + return {formattedTime} } diff --git a/components/brave_new_tab_ui/components/default/stats/index.tsx b/components/brave_new_tab_ui/components/default/stats/index.tsx index e897b21ba575..f72d3e0d6d54 100644 --- a/components/brave_new_tab_ui/components/default/stats/index.tsx +++ b/components/brave_new_tab_ui/components/default/stats/index.tsx @@ -31,7 +31,6 @@ export interface StatsItemProps { counter: string | number text?: string description: string - overriddenTextColor?: string } /** @@ -41,10 +40,10 @@ export interface StatsItemProps { * @prop {string} text - descriptive text that goes along the stat * @prop {string} description - describes what the counter is showing */ -export function StatsItem ({ testId, counter, text, description, overriddenTextColor }: StatsItemProps) { - return +export function StatsItem ({ testId, counter, text, description }: StatsItemProps) { + return {counter} {text && {text}} - {description} + {description} } diff --git a/components/brave_new_tab_ui/components/default/stats/style.ts b/components/brave_new_tab_ui/components/default/stats/style.ts index be7d5e8cf07c..b07ab346d396 100644 --- a/components/brave_new_tab_ui/components/default/stats/style.ts +++ b/components/brave_new_tab_ui/components/default/stats/style.ts @@ -18,7 +18,7 @@ export const StyledStatsItemContainer = styled('ul')<{}>` font-family: inherit; ` -export const StyledStatsItem = styled('li')<{overriddenTextColor?: string}>` +export const StyledStatsItem = styled('li')<{}>` list-style-type: none; font-size: inherit; font-family: inherit; @@ -51,7 +51,7 @@ export const StyledStatsItemText = styled('span')<{}>` letter-spacing: 0; ` -export const StyledStatsItemDescription = styled('div')<{overriddenTextColor?: string}>` +export const StyledStatsItemDescription = styled('div')<{}>` font-size: 16px; font-weight: 500; color: var(--override-readability-color-rgb, #FFFFFF); diff --git a/components/brave_new_tab_ui/components/default/widget/assets/ellipsis.ts b/components/brave_new_tab_ui/components/default/widget/assets/ellipsis.ts deleted file mode 100644 index 300650363a07..000000000000 --- a/components/brave_new_tab_ui/components/default/widget/assets/ellipsis.ts +++ /dev/null @@ -1,8 +0,0 @@ -// Copyright (c) 2021 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 http://mozilla.org/MPL/2.0/. - -import EllipsisIcon from '../../../popupMenu/ellipsisIcon' - -export default EllipsisIcon diff --git a/components/brave_new_tab_ui/containers/newTab/index.tsx b/components/brave_new_tab_ui/containers/newTab/index.tsx index ee4b91303a2a..7a65e80498d6 100644 --- a/components/brave_new_tab_ui/containers/newTab/index.tsx +++ b/components/brave_new_tab_ui/containers/newTab/index.tsx @@ -194,9 +194,6 @@ class NewTabPage extends React.Component { window.clearTimeout(this.braveNewsPromptTimerId) } window.removeEventListener('resize', this.handleResize.bind(this)) - - document.documentElement.style.removeProperty('--override-readability-color-rgb') - document.documentElement.style.removeProperty('--override-readability-color') } componentDidUpdate (prevProps: Props) { @@ -1195,7 +1192,7 @@ class NewTabPage extends React.Component { widgetTitle={getLocale('statsTitle')} textDirection={newTabData.textDirection} menuPosition={'right'}> - + + counter={adblockCount.toLocaleString()} /> {bandwidthSaved && + description={getLocale('estimatedBandwidthSaved')} /> } + description={getLocale('estimatedTimeSaved')} /> } diff --git a/components/brave_new_tab_ui/reducers/new_tab_reducer.ts b/components/brave_new_tab_ui/reducers/new_tab_reducer.ts index 85615c5dd593..d45c2e934e19 100644 --- a/components/brave_new_tab_ui/reducers/new_tab_reducer.ts +++ b/components/brave_new_tab_ui/reducers/new_tab_reducer.ts @@ -23,7 +23,6 @@ import { setMostVisitedSettings } from '../api/topSites' import { handleWidgetPrefsChange } from './stack_widget_reducer' import { NewTabAdsData } from '../api/newTabAdsData' import { Background } from '../api/background' -import isReadableOnBackground from '../helpers/colorUtil' let sideEffectState: NewTab.State = storage.load() @@ -60,14 +59,8 @@ export const newTabReducer: Reducer = (state: NewTab.S if (initialDataPayload.wallpaperData) { let backgroundWallpaper = initialDataPayload.wallpaperData.backgroundWallpaper - if (backgroundWallpaper?.type === 'color') { - if (backgroundWallpaper.random) { - backgroundWallpaper = backgroundAPI.randomColorBackground(backgroundWallpaper.wallpaperColor) - } - - if (!isReadableOnBackground(backgroundWallpaper)) { - (backgroundWallpaper as NewTab.ColorBackground).overriddenForegroundColor = '#000000' - } + if (backgroundWallpaper?.type === 'color' && backgroundWallpaper.random) { + backgroundWallpaper = backgroundAPI.randomColorBackground(backgroundWallpaper.wallpaperColor) } state = { @@ -144,9 +137,6 @@ export const newTabReducer: Reducer = (state: NewTab.S state.backgroundWallpaper = { type: 'image', wallpaperImageUrl: url } } else if (color) { state.backgroundWallpaper = random ? backgroundAPI.randomColorBackground(color) : { type: 'color', wallpaperColor: color, random } - if (!isReadableOnBackground(state.backgroundWallpaper)) { - (state.backgroundWallpaper as NewTab.ColorBackground).overriddenForegroundColor = '#000000' - } } } diff --git a/components/brave_new_tab_ui/stories/default/data/backgroundWallpaper.ts b/components/brave_new_tab_ui/stories/default/data/backgroundWallpaper.ts index 5bea1cc5d13b..006d28bce969 100644 --- a/components/brave_new_tab_ui/stories/default/data/backgroundWallpaper.ts +++ b/components/brave_new_tab_ui/stories/default/data/backgroundWallpaper.ts @@ -23,8 +23,7 @@ const generateWallpapers = function (images: NewTab.BackgroundWallpaper[], Object.assign(staticImages, { [image.author]: { ...image, - // wallpaperImageUrl: require('../../../../img/newtab/backgrounds/' + image.wallpaperImageUrl) - wallpaperImageUrl: '' + wallpaperImageUrl: require('../../../../img/newtab/backgrounds/' + image.wallpaperImageUrl) } }) diff --git a/components/definitions/newTab.d.ts b/components/definitions/newTab.d.ts index 6e9210fb5025..b626b25527c8 100644 --- a/components/definitions/newTab.d.ts +++ b/components/definitions/newTab.d.ts @@ -9,7 +9,6 @@ declare namespace NewTab { type: 'color' wallpaperColor: string random?: boolean - overriddenForegroundColor?: string } // Backgrounds based on image. Custom image background or Brave background. From 323660987ddc04ff9f1fdff60d0f6d08485820cf Mon Sep 17 00:00:00 2001 From: "sangwoo.ko" Date: Thu, 29 Sep 2022 16:55:10 +0900 Subject: [PATCH 6/6] More clean up and fix wrong variable usage --- .../components/default/clock/style.ts | 2 +- .../components/default/page/index.tsx | 13 ++++--------- .../components/default/stats/style.ts | 6 +++--- .../components/default/widget/widgetMenu.tsx | 1 - 4 files changed, 8 insertions(+), 14 deletions(-) diff --git a/components/brave_new_tab_ui/components/default/clock/style.ts b/components/brave_new_tab_ui/components/default/clock/style.ts index e884169420c2..6bed6d14801e 100644 --- a/components/brave_new_tab_ui/components/default/clock/style.ts +++ b/components/brave_new_tab_ui/components/default/clock/style.ts @@ -6,7 +6,7 @@ import styled from 'styled-components' export const StyledClock = styled('div')<{}>` - color: var(--override-readability-color-rgb, #FFFFFF); + color: var(--override-readability-color, #FFFFFF); box-sizing: border-box; line-height: 1; user-select: none; diff --git a/components/brave_new_tab_ui/components/default/page/index.tsx b/components/brave_new_tab_ui/components/default/page/index.tsx index 3ab1e4a0ccf6..7c3592879424 100644 --- a/components/brave_new_tab_ui/components/default/page/index.tsx +++ b/components/brave_new_tab_ui/components/default/page/index.tsx @@ -470,8 +470,8 @@ export const IconButtonContainer = styled('div')` color: rgba(var(--override-readability-color-rgb, 255, 255, 255), 0.8); margin-right: ${p => p.textDirection === 'ltr' && '8px'}; margin-left: ${p => p.textDirection === 'rtl' && '8px'}; - border-right: ${p => p.textDirection === 'ltr' && 'rgba(var(--override-readability-color-rgb, 255, 255, 255), 0.6)'}; - border-left: ${p => p.textDirection === 'rtl' && 'rgba(var(--override-readability-color-rgb, 255, 255, 255), 0.6)'}; + border-right: ${p => p.textDirection === 'ltr' && '1px solid rgba(var(--override-readability-color-rgb, 255, 255, 255), 0.6)'}; + border-left: ${p => p.textDirection === 'rtl' && '1px solid rgba(var(--override-readability-color-rgb, 255, 255, 255), 0.6)'}; &:hover { color: ${p => p.color}; @@ -479,14 +479,9 @@ export const IconButtonContainer = styled('div')` ` export const OverrideReadabilityColor = createGlobalStyle<{override: boolean}>` - body { + :root { ${p => p.override && css` --override-readability-color-rgb: 0, 0, 0; - --override-readability-color: rgb(0, 0, 0); - - // override color property in resets.css. Not sure why this happens but, - // the value in the stylesheet wins over variables above. - color: inherit - `} + --override-readability-color: rgb(0, 0, 0);`} } ` diff --git a/components/brave_new_tab_ui/components/default/stats/style.ts b/components/brave_new_tab_ui/components/default/stats/style.ts index b07ab346d396..cecaf16929e7 100644 --- a/components/brave_new_tab_ui/components/default/stats/style.ts +++ b/components/brave_new_tab_ui/components/default/stats/style.ts @@ -23,10 +23,10 @@ export const StyledStatsItem = styled('li')<{}>` font-size: inherit; font-family: inherit; margin: 10px 16px; - &:first-child { color: var(--override-readability-color-rgb, var(--interactive2)); } - &:nth-child(2) { color: var(--override-readability-color-rgb, var(--interactive9)); } + &:first-child { color: var(--override-readability-color, var(--interactive2)); } + &:nth-child(2) { color: var(--override-readability-color, var(--interactive9)); } &:last-child { - color: var(--override-readability-color-rgb, #FFFFFF); + color: var(--override-readability-color, #FFFFFF); margin-right: 0; } ` diff --git a/components/brave_new_tab_ui/components/default/widget/widgetMenu.tsx b/components/brave_new_tab_ui/components/default/widget/widgetMenu.tsx index 8bf94ae9d097..bc256c0539a5 100644 --- a/components/brave_new_tab_ui/components/default/widget/widgetMenu.tsx +++ b/components/brave_new_tab_ui/components/default/widget/widgetMenu.tsx @@ -33,7 +33,6 @@ interface Props { customLinksEnabled?: boolean onToggleCustomLinksEnabled?: () => void paddingType: 'none' | 'right' | 'default' - color?: string } interface State {