Skip to content

Commit

Permalink
Added select theme UI to the new onboarding flow (#16326)
Browse files Browse the repository at this point in the history
  • Loading branch information
nullhook committed Dec 23, 2022
1 parent be4cb81 commit 9bffe3e
Show file tree
Hide file tree
Showing 10 changed files with 357 additions and 16 deletions.
9 changes: 8 additions & 1 deletion browser/ui/webui/brave_welcome_ui.cc
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,14 @@ constexpr webui::LocalizedString kLocalizedStrings[] = {
{"braveWelcomeSetupCompleteLabel", IDS_BRAVE_WELCOME_SETUP_COMPLETE_LABEL},
{"braveWelcomeChangeSettingsNote", IDS_BRAVE_WELCOME_CHANGE_SETTINGS_NOTE},
{"braveWelcomePrivacyPolicyNote", IDS_BRAVE_WELCOME_PRIVACY_POLICY_NOTE},
};
{"braveWelcomeSelectThemeLabel", IDS_BRAVE_WELCOME_SELECT_THEME_LABEL},
{"braveWelcomeSelectThemeNote", IDS_BRAVE_WELCOME_SELECT_THEME_NOTE},
{"braveWelcomeSelectThemeSystemLabel",
IDS_BRAVE_WELCOME_SELECT_THEME_SYSTEM_LABEL},
{"braveWelcomeSelectThemeLightLabel",
IDS_BRAVE_WELCOME_SELECT_THEME_LIGHT_LABEL},
{"braveWelcomeSelectThemeDarkLabel",
IDS_BRAVE_WELCOME_SELECT_THEME_DARK_LABEL}};

void OpenJapanWelcomePage(Profile* profile) {
DCHECK(profile);
Expand Down
12 changes: 1 addition & 11 deletions components/brave_welcome_ui/components/loader/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,20 +26,10 @@ const Graphic = styled('div')`
`

export default function Loader () {
const [show, setShow] = React.useState(false)

React.useEffect(() => {
const timerId = setTimeout(() => setShow(true), 100)

return () => {
clearTimeout(timerId)
}
}, [])

return (
<Loading aria-busy='true'>
<Graphic aria-label='Loading'>
{ show ? <LoaderIcon /> : null }
<LoaderIcon />
</Graphic>
</Loading>
)
Expand Down
132 changes: 132 additions & 0 deletions components/brave_welcome_ui/components/select-theme/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
// 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 https://mozilla.org/MPL/2.0/.

import * as React from 'react'
import * as S from './style'

import { getLocale } from '$web-common/locale'
import classnames from '$web-common/classnames'
import Button from '$web-components/button'

import DataContext from '../../state/context'
import { ViewType } from '../../state/component_types'

interface ThemeModeItemProps {
themeType: chrome.braveTheme.ThemeType
title: string
isActive: boolean
onChange?: (themeType: chrome.braveTheme.ThemeType) => void
}

const themeList = [
{ themeType: 'System', title: getLocale('braveWelcomeSelectThemeSystemLabel') },
{ themeType: 'Light', title: getLocale('braveWelcomeSelectThemeLightLabel') },
{ themeType: 'Dark', title: getLocale('braveWelcomeSelectThemeDarkLabel') }
]

function ThemeModeItem (props: ThemeModeItemProps) {
const handleClick = () => {
props.onChange?.(props.themeType)
}

const buttonClass = classnames({
'theme-item': true,
'is-selected': props.isActive
})

const logoBoxClass = classnames({
'logo': true,
'dark-mode': props.themeType === 'Dark',
'system-mode': props.themeType === 'System'
})

return (
<button onClick={handleClick}
className={buttonClass}
>
<i className="check-icon-box">
{props.isActive && (
<svg viewBox="0 0 16 12" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M14.9558.9327c-.2259-.2134-.5083-.2667-.7907-.2667s-.5648.16-.7907.3733l-7.06 7.68-3.7276-3.4666c-.4518-.4267-1.186-.4267-1.5814 0-.226.2133-.3389.48-.3389.7466 0 .2667.113.5334.3389.7467l4.5748 4.2667c.1695.2133.4519.32.7907.32h.0565c.3389 0 .6213-.16.7907-.3734l7.8507-8.5333c.3953-.4267.3389-1.12-.113-1.4933Z" fill="#4C54D2"/>
</svg>
)}
</i>
<div className="logo-box">
<div className={logoBoxClass} />
<p className="theme-name">{props.title}</p>
</div>
</button>
)
}

function SelectTheme () {
const { setViewType, scenes } = React.useContext(DataContext)
const [currentSelectedTheme, setCurrentTheme] = React.useState<chrome.braveTheme.ThemeType>('System')

const handleSelectionChange = (themeType: chrome.braveTheme.ThemeType) => {
setCurrentTheme?.(themeType)
}

const handleSkip = () => {
setViewType(ViewType.HelpImprove)
scenes?.s2.play()
}

const handleNext = () => {
chrome.braveTheme.setBraveThemeType(currentSelectedTheme)
setViewType(ViewType.HelpImprove)
scenes?.s2.play()
}

return (
<S.Box>
<div className="view-header-box">
<div className="view-header-actions">
</div>
<div className="view-details">
<h1 className="view-title">{getLocale('braveWelcomeSelectThemeLabel')}</h1>
</div>
</div>
<S.ThemeListBox>
<div className={classnames({
'theme-list': true,
'is-selected-dark': currentSelectedTheme === 'Dark',
'is-selected-light': currentSelectedTheme === 'Light'
})}>
{themeList.map((entry, id) => {
return (
<ThemeModeItem
key={id}
themeType={entry.themeType as chrome.braveTheme.ThemeType}
title={entry.title}
isActive={entry.themeType === currentSelectedTheme}
onChange={handleSelectionChange}
/>
)
})}
</div>
</S.ThemeListBox>
<div className="view-note">{getLocale('braveWelcomeSelectThemeNote')}</div>
<S.ActionBox>
<Button
isTertiary={true}
onClick={handleSkip}
scale="jumbo"
>
{getLocale('braveWelcomeSkipButtonLabel')}
</Button>
<Button
isPrimary={true}
onClick={handleNext}
scale="jumbo"
>
{getLocale('braveWelcomeNextButtonLabel')}
</Button>
</S.ActionBox>
</S.Box>
)
}

export default SelectTheme
168 changes: 168 additions & 0 deletions components/brave_welcome_ui/components/select-theme/style.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
// 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 https://mozilla.org/MPL/2.0/.

import styled from 'styled-components'

export const Box = styled.div`
background: rgba(255, 255, 255, 0.1);
backdrop-filter: blur(15px);
border-radius: 30px;
max-width: 800px;
color: white;
font-family: ${(p) => p.theme.fontFamily.heading};
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
.view-header-box {
display: grid;
grid-template-columns: 0.2fr 1fr 0.2fr;
padding: 40px;
text-align: center;
}
.view-details {
grid-column: 2;
}
.view-title {
font-weight: 600;
font-size: 36px;
margin: 0 0 18px 0;
}
.view-desc {
font-weight: 400;
font-size: 16px;
margin: 0;
}
.view-note {
font-weight: 400;
font-size: 16px;
margin-bottom: 48px;
}
`

export const ThemeListBox = styled.div`
--background-color: white;
--text-color: #212529;
--background-color-light: white;
--background-color-dark: #495057;
@media (prefers-color-scheme: dark) {
--background-color: #1E2029;
--text-color: white;
--background-color-light: white;
--background-color-dark: #495057;
}
.theme-list {
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 56px;
grid-gap: 15px;
flex-wrap: wrap;
&.is-selected-light {
--background-color: white;
--text-color: #212529;
--background-color-light: white;
--background-color-dark: #495057;
}
&.is-selected-dark {
--background-color: #1E2029;
--text-color: white;
--background-color-light: white;
--background-color-dark: #495057;
}
}
.theme-item {
--border-color: transparent;
background: var(--background-color);
border-radius: 20px;
width: 132px;
height: 155px;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
color: var(--text-color);
border: 0;
box-shadow: 0 0 0 4px var(--border-color);
position: relative;
&.is-selected {
--border-color: #737ADE;
}
}
.theme-name {
font-weight: 400;
font-size: 14px;
line-height: 1.2;
margin: 0;
min-height: calc(2 * 14px * 1.2); // A min height of 2 lines
}
.logo-box {
display: grid;
grid-template-rows: 50px 1fr;
gap: 10px;
width: 100%;
}
.logo {
width: 48px;
height: 48px;
border-radius: 48px;
background: var(--background-color-light);
border: 1px solid #C2C4CF;
position: relative;
margin: 0 auto;
&.dark-mode {
background: var(--background-color-dark);
}
&.system-mode {
&::after {
content: '';
position: absolute;
left: 0;
width: 40px;
height: 40px;
border: 23px solid var(--background-color-dark);
border-radius: 50%;
border-bottom-color: transparent;
border-left-color: transparent;
transform: rotate(90deg);
}
}
}
.check-icon-box {
width: 16px;
height: 16px;
position: absolute;
top: 14px;
right: 14px;
}
`

export const ActionBox = styled.div`
display: flex;
grid-gap: 10px;
margin-bottom: 40px;
button {
color: white;
}
`
14 changes: 11 additions & 3 deletions components/brave_welcome_ui/components/welcome/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,27 @@ import { shouldPlayAnimations } from '../../state/hooks'
import braveLogoUrl from '../../assets/brave_logo_3d@2x.webp'

function Welcome () {
const { setViewType, scenes } = React.useContext(DataContext)
const { setViewType, scenes, browserProfiles } = React.useContext(DataContext)
const ref = React.useRef<HTMLDivElement>(null)

const goToImportThemeOrBrowser = () => {
if (!browserProfiles || browserProfiles.length === 0) {
setViewType(ViewType.ImportSelectTheme)
return
}
setViewType(ViewType.ImportSelectBrowser)
}

const handleSetAsDefaultBrowser = () => {
WelcomeBrowserProxyImpl.getInstance().recordP3A({ currentScreen: ViewType.DefaultBrowser, isFinished: false, isSkipped: false })
DefaultBrowserBrowserProxyImpl.getInstance().setAsDefaultBrowser()
setViewType(ViewType.ImportSelectBrowser)
goToImportThemeOrBrowser()
scenes?.s1.play()
}

const handleSkip = () => {
WelcomeBrowserProxyImpl.getInstance().recordP3A({ currentScreen: ViewType.DefaultBrowser, isFinished: false, isSkipped: true })
setViewType(ViewType.ImportSelectBrowser)
goToImportThemeOrBrowser()
scenes?.s1.play()
}

Expand Down
5 changes: 5 additions & 0 deletions components/brave_welcome_ui/main_container.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import Loader from './components/loader'

const SelectBrowser = React.lazy(() => import('./components/select-browser'))
const SelectProfile = React.lazy(() => import('./components/select-profile'))
const SelectTheme = React.lazy(() => import('./components/select-theme'))
const SetupComplete = React.lazy(() => import('./components/setup-complete'))

function MainContainer () {
Expand All @@ -32,6 +33,10 @@ function MainContainer () {
mainEl = <SelectProfile />
}

if (viewType === ViewType.ImportSelectTheme) {
mainEl = <SelectTheme />
}

if (viewType === ViewType.ImportInProgress) {
mainEl = <ImportInProgress />
}
Expand Down
1 change: 1 addition & 0 deletions components/brave_welcome_ui/state/component_types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import WebAnimationPlayer from '../api/web_animation_player'
export enum ViewType {
DefaultBrowser, // the welcome ui
ImportSelectBrowser,
ImportSelectTheme,
ImportSelectProfile,
ImportInProgress,
ImportSucceeded,
Expand Down
Loading

0 comments on commit 9bffe3e

Please sign in to comment.