diff --git a/components/brave_new_tab_ui/components/default/grid/index.ts b/components/brave_new_tab_ui/components/default/grid/index.ts index 731c2f904a94..12a7c3e69706 100644 --- a/components/brave_new_tab_ui/components/default/grid/index.ts +++ b/components/brave_new_tab_ui/components/default/grid/index.ts @@ -7,37 +7,45 @@ import styled from 'brave-ui/theme' export const Header = styled<{}, 'header'>('header')` box-sizing: border-box; display: grid; - height: 100%; - margin: 70px 0 0; - grid-template-columns: 1fr auto auto; - grid-template-rows: 100px; - grid-gap: 30px 0; + margin: 46px 0 0; + grid-template-columns: fit-content(100%) auto fit-content(100%); + grid-template-rows: fit-content(100%) fit-content(100%) fit-content(100%) fit-content(100%); grid-template-areas: - "stats clock" - "topsites topsites"; + "stats . clock" + ". . clock" + "topsites topsites topsites" + "notification notification notification"; - > *:first-child { + > *:nth-child(1) { grid-area: stats; - margin: 0 70px 0 70px; + margin: 0 46px 0 46px; } - > *:nth-child(2) { grid-area: clock; - margin: 0 70px 0 70px; + margin: 0 46px 0 46px; } > *:nth-child(3) { grid-area: topsites; + margin: 0 46px 0 46px; + justify-self: start; + } + + > *:nth-child(4) { + grid-area: notification; + justify-self: center; } @media screen and (max-width: 1150px) { - grid-template-rows: 1fr; + grid-row-gap: 4px; grid-template-areas: - "clock" - "stats" - "topsites"; + "clock clock clock" + "stats stats stats" + "topsites topsites topsites" + "notification notification notification"; - > *:first-child { + + > *:nth-child(1) { margin: auto; text-align: center; } @@ -48,11 +56,11 @@ export const Header = styled<{}, 'header'>('header')` } > *:nth-child(3) { + margin: auto; justify-content: center; } } ` - export const Main = styled<{}, 'main'>('main')` box-sizing: border-box; ` diff --git a/components/brave_new_tab_ui/components/default/index.ts b/components/brave_new_tab_ui/components/default/index.ts index 952dae8399da..a60a46772ffb 100644 --- a/components/brave_new_tab_ui/components/default/index.ts +++ b/components/brave_new_tab_ui/components/default/index.ts @@ -6,7 +6,7 @@ import { StatsContainer, StatsItem } from './stats' import { Header, Main, Footer } from './grid' import { SettingsMenu, SettingsRow, SettingsText, SettingsTitle, SettingsWrapper } from './settings' -import { List, ListWidget, Tile, TileActionsContainer, TileAction, TileFavicon } from './topSites' +import { ListWidget, Tile, TileActionsContainer, TileAction, TileFavicon } from './topSites' import { SiteRemovalNotification, SiteRemovalText, SiteRemovalAction } from './notification' import { ClockWidget } from './clock' import createWidget from './widget' @@ -19,7 +19,6 @@ export { Header, Main, Footer, - List, ListWidget, Tile, TileActionsContainer, diff --git a/components/brave_new_tab_ui/components/default/notification/index.ts b/components/brave_new_tab_ui/components/default/notification/index.ts index 18d36e032d65..a69324ced313 100644 --- a/components/brave_new_tab_ui/components/default/notification/index.ts +++ b/components/brave_new_tab_ui/components/default/notification/index.ts @@ -13,7 +13,7 @@ export const SiteRemovalNotification = styled<{}, 'header'>('header')` height: 100px; align-items: center; padding: 30px 60px; - margin: 80px auto 0; + margin: 80px 0 0 0; display: flex; justify-content: space-between; ` 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 f52a977eac1e..5435d6e915df 100644 --- a/components/brave_new_tab_ui/components/default/stats/style.ts +++ b/components/brave_new_tab_ui/components/default/stats/style.ts @@ -7,7 +7,7 @@ import styled from 'brave-ui/theme' export const StyledStatsItemContainer = styled<{}, 'ul'>('ul')` -webkit-font-smoothing: antialiased; display: grid; - grid-template-columns: repeat(4, fit-content(100%)); + grid-template-columns: repeat(3, fit-content(100%)); grid-gap: 25px 50px; font-weight: 400; margin: 0; @@ -16,7 +16,7 @@ export const StyledStatsItemContainer = styled<{}, 'ul'>('ul')` font-size: inherit; font-family: inherit; - @media screen and (max-width: 630px) { + @media screen and (max-width: 700px) { grid-template-columns: repeat(2, fit-content(100%)); } diff --git a/components/brave_new_tab_ui/components/default/topSites/index.ts b/components/brave_new_tab_ui/components/default/topSites/index.ts index 28c25d90ea65..4f35f5deb988 100644 --- a/components/brave_new_tab_ui/components/default/topSites/index.ts +++ b/components/brave_new_tab_ui/components/default/topSites/index.ts @@ -5,23 +5,25 @@ import styled from 'brave-ui/theme' import createWidget from '../widget' -export const List = styled<{}, 'div'>('div')` - padding: 0 70px; +interface ListProps { + blockNumber: number +} + +export const List = styled('div')` height: 100%; display: grid; - grid-template-columns: repeat(6, 92px); + grid-template-columns: repeat(${p => Math.min(p.blockNumber, 6).toString()}, 92px); @media screen and (max-width: 1150px) { justify-content: center; - padding: 40px; } - @media screen and (max-width: 630px) { - grid-template-columns: repeat(3, 92px); + @media screen and (max-width: 700px) { + grid-template-columns: repeat(${p => Math.min(p.blockNumber, 3).toString()}, 92px); } @media screen and (max-width: 390px) { - grid-template-columns: repeat(2, 92px); + grid-template-columns: repeat(${p => Math.min(p.blockNumber, 2).toString()}, 92px); } ` 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 7f961dcef617..fcdc8cbbb090 100644 --- a/components/brave_new_tab_ui/components/default/widget/index.tsx +++ b/components/brave_new_tab_ui/components/default/widget/index.tsx @@ -3,21 +3,57 @@ * You can obtain one at http://mozilla.org/MPL/2.0/. */ import * as React from 'react' -import { StyledWidgetContainer } from './styles' +import { StyledWidget, StyledWidgetContainer } from './styles' +import WidgetMenu from './widgetMenu' export interface WidgetProps { showWidget: boolean + menuPosition: 'right' | 'left' + hideWidget: () => void + textDirection: string +} + +export interface WidgetState { + widgetMenuPersist: boolean } const createWidget =

(WrappedComponent: React.ComponentType

) => - class Widget extends React.Component

{ + class Widget extends React.Component

{ + constructor (props: P & WidgetProps) { + super(props) + this.state = { + widgetMenuPersist: false + } + } + + toggleWidgetHover = () => { + this.setState({ widgetMenuPersist: !this.state.widgetMenuPersist }) + } + + unpersistWidgetHover = () => { + this.setState({ widgetMenuPersist: false }) + } + render () { - const { showWidget } = this.props + const { showWidget, menuPosition, hideWidget, textDirection } = this.props + const { widgetMenuPersist } = this.state return ( - + + + + ) } diff --git a/components/brave_new_tab_ui/components/default/widget/styles.ts b/components/brave_new_tab_ui/components/default/widget/styles.ts index 1de22fe6081a..11ec58fc60c0 100644 --- a/components/brave_new_tab_ui/components/default/widget/styles.ts +++ b/components/brave_new_tab_ui/components/default/widget/styles.ts @@ -3,8 +3,123 @@ * You can obtain one at http://mozilla.org/MPL/2.0/. */ import styled from 'styled-components' -import { WidgetProps } from './index' -export const StyledWidgetContainer = styled('div')` - display: ${p => p.showWidget ? 'initial' : 'none'}; +interface WidgetContainerProps { + showWidget: boolean + menuPosition: 'right' | 'left' + textDirection: string +} + +export const StyledWidgetContainer = styled('div')` + display: ${p => p.showWidget ? 'flex' : 'none'}; + align-items: center; + flex-direction: ${p => p.menuPosition === 'right' ? 'row' : 'row-reverse'} + + @media screen and (max-width: 1150px) { + flex-direction: row; + padding: ${p => p.textDirection === 'ltr' + ? `0 0 0 48px` + : `0 48px 0 0`} + } +` + +interface WidgetVisibilityProps { + widgetMenuPersist: boolean +} + +export const StyledWidget = styled('div')` + padding: 24px; + + ${StyledWidgetContainer}:hover & { + border-radius: 16px; + background: rgba(33, 37, 41, 0.48); + } + + // Also hover when menu button has been clicked + ${ p => p.widgetMenuPersist && ` + border-radius: 16px; + background: rgba(33, 37, 41, 0.48); + `} + +` + +export const StyledWidgetMenuContainer = styled('div')` + visibility: hidden; + pointer-events: none; + position: relative; + + ${StyledWidgetContainer}:hover & { + visibility: visible; + pointer-events: auto; + } + + // Also hover when menu button has been clicked + ${ p => p.widgetMenuPersist && ` + visibility: visible; + pointer-events: auto; + `} + +` + +interface WidgetMenuProps { + menuPosition: 'right' | 'left' + textDirection: string +} + +export const StyledWidgetMenu = styled('div')` + position absolute; + width: 166px; + padding: 8px 0; + background: white; + box-shadow: 0px 0px 6px 0px rgba(0, 0, 0, 0.3); + border-radius: 4px; + top: 48px; + + @media screen and (min-width: 1150px) { + ${p => (p.menuPosition === 'right' && p.textDirection === 'ltr') || (p.menuPosition === 'left' && p.textDirection === 'rtl') + ? 'left: 8px' + : 'right: 8px'} + } + + @media screen and (min-width: 950px) and (max-width: 1150px) { + ${p => p.textDirection === 'ltr' + ? 'left: 8px' + : 'right: 8px'} + } + + @media screen and (max-width: 950px) { + ${p => p.textDirection === 'ltr' + ? 'right: 8px' + : 'left: 8px'} + } +` + +interface WidgetButtonProps { + onClick: () => void +} +export const StyledWidgetButton = styled('button')` + border-style: none; + blackground: white; + padding: 0; + display: flex; + height: 30px; + width: 100%; + flex-direction: row; + align-items: center; + justify-content: flex-start; + outline-color: #FF7654; + outline-width: 2px; + outline-offset: -3px; + &:hover { + background: rgb(217, 221, 254); + } +` + +export const StyledWidgetIcon = styled<{}, 'div'>('div')` + height: 13px; + width: 13px; + margin: 0 10px 0 18px; +` +export const StyledSpan = styled<{}, 'span'>('span')` + height: 13px; ` diff --git a/components/brave_new_tab_ui/components/default/widget/widgetMenu.tsx b/components/brave_new_tab_ui/components/default/widget/widgetMenu.tsx new file mode 100644 index 000000000000..6b749985a1b8 --- /dev/null +++ b/components/brave_new_tab_ui/components/default/widget/widgetMenu.tsx @@ -0,0 +1,88 @@ +// Copyright (c) 2019 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 React from 'react' + +import { StyledWidgetMenuContainer, StyledWidgetMenu, StyledWidgetButton, StyledWidgetIcon, StyledSpan } from './styles' +import { IconButton } from '../../default' +import { CaratCircleODownIcon, CloseStrokeIcon } from 'brave-ui/components/icons' + +interface Props { + menuPosition: 'right' | 'left' + hideWidget: () => void + textDirection: string + toggleWidgetHover: () => void + widgetMenuPersist: boolean + unpersistWidgetHover: () => void +} + +interface State { + showMenu: boolean +} + +export default class WidgetMenu extends React.PureComponent { + settingsMenuRef: React.RefObject + constructor (props: Props) { + super(props) + this.settingsMenuRef = React.createRef() + this.state = { + showMenu: false + } + } + + handleClickOutsideMenu = (event: Event) => { + if (this.settingsMenuRef && !this.settingsMenuRef.current.contains(event.target)) { + this.props.unpersistWidgetHover() + this.closeMenu() + } + } + + componentDidMount () { + document.addEventListener('mousedown', this.handleClickOutsideMenu) + } + + componentWillUnmount () { + document.removeEventListener('mousedown', this.handleClickOutsideMenu) + } + + toggleMenu = () => { + this.props.toggleWidgetHover() + this.setState({ showMenu: !this.state.showMenu }) + } + + closeMenu = () => { + this.setState({ showMenu: false }) + } + + unmountWidget = () => { + this.props.hideWidget() + this.props.unpersistWidgetHover() + this.closeMenu() + } + + render () { + const { menuPosition, textDirection, widgetMenuPersist } = this.props + const { showMenu } = this.state + return ( + + + {showMenu && + + + Remove + + } + + ) + } +} diff --git a/components/brave_new_tab_ui/containers/newTab/index.tsx b/components/brave_new_tab_ui/containers/newTab/index.tsx index 30dc803f8fe1..2e1bc8c62ae7 100644 --- a/components/brave_new_tab_ui/containers/newTab/index.tsx +++ b/components/brave_new_tab_ui/containers/newTab/index.tsx @@ -9,7 +9,6 @@ import { Page, Header, ClockWidget as Clock, - Main, ListWidget as List, Footer, App, @@ -162,36 +161,51 @@ class NewTabPage extends React.Component { }

- - -
- - { - this.props.newTabData.gridSites.map((site: NewTab.Site) => - - ) - } - + + + {this.props.newTabData.gridSites.length && { - this.props.newTabData.showSiteRemovalNotification - ? - : null + this.props.newTabData.gridSites.map((site: NewTab.Site) => + + ) } -
+ } + { + this.props.newTabData.showSiteRemovalNotification + ? + : null + }