Skip to content
This repository has been archived by the owner on May 13, 2024. It is now read-only.

Use new button styles #541

Draft
wants to merge 7 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 26 additions & 19 deletions src/components/buttonsIndicators/button/__snapshots__/spec.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@

exports[`Button tests basic tests matches the snapshot 1`] = `
.c1 {
--button-main-color: #3b3e4f;
--button-main-color-hover: #1E2029;
--button-main-color-active: #5e6175;
--button-state-color: var(--button-main-color);
--brand-color-subtle: #fb542b1a;
--brand-color-hover: #ff977d;
--brand-color-main: #ff7654;
--brand-color-pressed: #FB542B;
--brand-style-focus-shadow: 0 0 0 4px #ff765466;
--icon-size: 16px;
--icon-spacing: 6px;
--webkit-appearance: none;
Expand All @@ -28,31 +29,39 @@ exports[`Button tests basic tests matches the snapshot 1`] = `
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
font-family: Poppins,sans-serif;
font-family: Muli,sans-serif;
cursor: pointer;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
font-size: 13px;
font-size: 14px;
border-radius: 20px;
width: auto;
min-width: 104px;
padding: 11px 15px;
min-width: 82px;
padding: 9px 16px;
opacity: none;
}

.c1:hover:enabled {
--button-state-color: var(--button-main-color-hover);
.c0 {
color: #3b3e4f;
border: 1px solid #c2c4cf;
}

.c1:active:enabled {
--button-state-color: var(--button-main-color-active);
.c0:hover:enabled {
color: var(--brand-color-main);
border-color: var(--brand-color-main);
}

.c0 {
color: #fff;
background: var(--button-state-color);
border: 1px solid var(--button-state-color);
.c0:focus:enabled {
border-color: var(--brand-color-main);
box-shadow: var(--brand-style-focus-shadow);
}

.c0:active:enabled {
color: var(--brand-color-main);
border-color: var(--brand-color-main);
box-shadow: var(--brand-style-focus-shadow);
}

.c2 {
Expand All @@ -70,7 +79,7 @@ exports[`Button tests basic tests matches the snapshot 1`] = `
-moz-letter-spacing: 0;
-ms-letter-spacing: 0;
letter-spacing: 0;
font-weight: 500;
font-weight: 600;
text-transform: none;
line-height: 1;
}
Expand All @@ -79,12 +88,10 @@ exports[`Button tests basic tests matches the snapshot 1`] = `
className="c0 c1"
id="button"
size="medium"
type="default"
>
<div
className="c2"
size="medium"
type="default"
>
test
</div>
Expand Down
12 changes: 5 additions & 7 deletions src/components/buttonsIndicators/button/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import * as React from 'react'
import {
DefaultButton,
PrimaryButton,
SecondaryButton,
TertiaryButton,
Expand All @@ -14,19 +15,16 @@ import {
export interface Props {
text: string
size?: Size
type?: Type
brand?: Brand
level?: Level
main?: boolean
onClick?: () => void
id?: string
disabled?: boolean
icon?: {image: React.ReactNode, position: 'before' | 'after'}
className?: string
}

export type Level = 'primary' | 'secondary' | 'tertiary'
export type Type = 'default' | 'accent' | 'warn' | 'subtle'
export type Level = 'default' | 'primary' | 'secondary' | 'tertiary'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure it's clear to me that we should have a default value here - it's not understandable how this semantically fits in between the hierarchy of primary / secondary / tertiary

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just took that directly from abstract, cc @karenkliu

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@karenkliu @antonok-edm we should probably sync-up as it seems that whilst this has removed some variations, it seems more complicated to use. Right now we have properties that easily allow a developer or designer to know when to use which button:

  • 'level' which indicates the importance of the button (most important in the UI vs one of many equal actions) and affects the style of the button,

image

  • 'type' which indicates the type of action (positive, negative, primary brand action) and just really affects the color

image

These two properties are independent and could allow for all combinations.

In this new version we have a single property called 'Levels' in which I would expect the values to be hierarchical and has 4 variations - primary, secondary, tertiary and default. I wouldn't know when to use 'default' vs the hierarchical values. I would expect most buttons which aren't Primary actions to be Secondary actions, but now I'm guessing they should be Default actions and it's unclear when to use Secondary vs Tertiary.

image

IMO we shouldn't mix metaphors here - either keep the semantic definitions (and ideally backwards-compatible) or choose new ones.

As another aside, these new button styles are slightly different to the other new button styles that Ross implemented in brave-core's WebUI at brave/brave-core#2778. Those ones have a slight hover effect on 'pressed' and also a nicer focus outline style (that last one we should definitely adopt).

export type Brand = 'brave' | 'rewards'
export type Size = 'call-to-action' | 'large' | 'medium' | 'small'

Expand All @@ -36,13 +34,13 @@ export default class ThemedButton extends React.PureComponent<Props, {}> {
static defaultProps = {
brand: 'brave',
size: 'medium',
type: 'default',
level: 'primary',
main: false
level: 'default'
}

getButtonComponent () {
switch (this.props.level) {
case 'default':
return DefaultButton
case 'primary':
return PrimaryButton
case 'secondary':
Expand Down
136 changes: 85 additions & 51 deletions src/components/buttonsIndicators/button/style.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,51 +21,35 @@ function largeMediumSmall (largeValue: any, mediumValue: any, smallValue: any, c
}

const getThemeColors = (p: ThemedStyledProps<Props>) => {
let mainColor
let subtleBackgroundColor
let hoverColor
let activeColor
if (p.disabled) {
mainColor = hoverColor = activeColor = p.theme.color.disabled
} else {
switch (p.type) {
case 'accent':
if (p.brand === 'brave') {
mainColor = p.theme.color.brandBrave
hoverColor = p.theme.color.brandBraveInteracting
activeColor = p.theme.color.brandBraveActive
} else if (p.brand === 'rewards') {
mainColor = p.theme.color.brandBat
hoverColor = p.theme.color.brandBatInteracting
activeColor = p.theme.color.brandBatActive
}
break
case 'default':
mainColor = p.theme.color.defaultControl
hoverColor = p.theme.color.defaultControlInteracting
activeColor = p.theme.color.defaultControlActive
break
case 'warn':
mainColor = p.theme.color.warn
hoverColor = p.theme.color.warnInteracting
activeColor = p.theme.color.warnActive
break
case 'subtle':
mainColor = p.theme.color.subtle
hoverColor = p.theme.color.subtleInteracting
activeColor = p.theme.color.subtleActive
break
}
let mainColor
let pressedColor
let outlineColor
if (p.brand === 'brave') {
subtleBackgroundColor = p.theme.color.brandBraveSubtleBackground
hoverColor = p.theme.color.brandBraveHover
mainColor = p.theme.color.brandBraveMain
pressedColor = p.theme.color.brandBravePressed
outlineColor = p.theme.color.brandBraveOutline
} else if (p.brand === 'rewards') {
subtleBackgroundColor = p.theme.color.brandBatSubtleBackground
hoverColor = p.theme.color.brandBatHover
mainColor = p.theme.color.brandBatMain
pressedColor = p.theme.color.brandBatPressed
outlineColor = p.theme.color.brandBatOutline
}
return css`
--button-main-color: ${mainColor};
--button-main-color-hover: ${hoverColor};
--button-main-color-active: ${activeColor};
--brand-color-subtle: ${subtleBackgroundColor};
--brand-color-hover: ${hoverColor};
--brand-color-main: ${mainColor};
--brand-color-pressed: ${pressedColor};
--brand-style-focus-shadow: 0 0 0 4px ${outlineColor};
`
}

const StyledButton = styled<Props, 'button'>('button')`
${getThemeColors}
--button-state-color: var(--button-main-color);
--icon-size: ${largeMediumSmall('18px', '16px', '14px')};
--icon-spacing: ${largeMediumSmall('6px', '6px', '6px')};
--webkit-appearance: none;
Expand All @@ -77,37 +61,87 @@ const StyledButton = styled<Props, 'button'>('button')`
flex-direction: ${p => p.icon && p.icon.position === 'after' ? 'row' : 'row-reverse'};
justify-content: center;
align-items: center;
font-family: Poppins, sans-serif;
font-family: Muli, sans-serif;
cursor: ${p => p.disabled ? 'default' : 'pointer'};
user-select: none;
font-size: ${largeMediumSmall('14px', '13px', '11px')};
font-size: ${largeMediumSmall('16px', '14px', '13px')};
border-radius: ${largeMediumSmall('24px', '20px', '16px', '28px')};
width: ${p => p.size === 'call-to-action' ? '100%' : 'auto'};
min-width: ${largeMediumSmall('116px', '104px', '88px', '235px')};
padding: ${largeMediumSmall('14px 15px', '11px 15px', '7px 10px', '19px 15px')};
min-width: ${largeMediumSmall('85px', '82px', '68px', '235px')};
padding: ${largeMediumSmall('13px 20px', '9px 16px', '5px 16px', '19px 15px')};
opacity: ${p => p.disabled ? '0.4' : 'none'};
`

export default StyledButton

export const DefaultButton = styled(StyledButton)`
color: ${p => p.theme.color.defaultControl};
border: 1px solid ${p => p.theme.color.defaultButtonBorder};
:hover:enabled {
--button-state-color: var(--button-main-color-hover);
color: var(--brand-color-main);
border-color: var(--brand-color-main);
}
:focus:enabled {
border-color: var(--brand-color-main);
box-shadow: var(--brand-style-focus-shadow);
}
:active:enabled {
--button-state-color: var(--button-main-color-active);
color: var(--brand-color-main);
border-color: var(--brand-color-main);
box-shadow: var(--brand-style-focus-shadow);
}
`

export default StyledButton

export const PrimaryButton = styled(StyledButton)`
color: #fff;
background: var(--button-state-color);
border: 1px solid var(--button-state-color);
background: var(--brand-color-main);
:hover:enabled {
background: var(--brand-color-hover);
}
:focus:enabled {
background: var(--brand-color-main);
box-shadow: var(--brand-style-focus-shadow);
}
:active:enabled {
background: var(--brand-color-main);
box-shadow: var(--brand-style-focus-shadow);
}
`

export const SecondaryButton = styled(StyledButton)`
border: 1px solid;
color: var(--button-state-color);
color: var(--brand-color-main);
:hover:enabled {
background: var(--brand-color-subtle);
color: var(--brand-color-main);
}
:focus:enabled {
background: var(--brand-color-subtle);
color: var(--brand-color-main);
box-shadow: var(--brand-style-focus-shadow);
}
:active:enabled {
background: var(--brand-color-subtle);
color: var(--brand-color-pressed);
box-shadow: var(--brand-style-focus-shadow);
}
`

export const TertiaryButton = styled(StyledButton)`
color: var(--button-state-color);
color: ${p => p.theme.color.defaultControl};
:hover:enabled {
background: var(--brand-color-subtle);
color: var(--brand-color-main);
}
:focus:enabled {
background: var(--brand-color-subtle);
color: var(--brand-color-main);
box-shadow: var(--brand-style-focus-shadow);
}
:active:enabled {
background: var(--brand-color-subtle);
color: var(--brand-color-pressed);
box-shadow: var(--brand-style-focus-shadow);
}
`

export const StyledText = styled<Props, 'div'>('div')`
Expand All @@ -117,7 +151,7 @@ export const StyledText = styled<Props, 'div'>('div')`
align-items: center;
text-align: center;
letter-spacing: 0;
font-weight: 500;
font-weight: ${p => p.level === 'primary' ? 700 : 600};
text-transform: ${p => p.size === 'call-to-action' ? 'uppercase' : 'none'};
line-height: 1;
`
Expand Down
10 changes: 3 additions & 7 deletions src/components/popupModals/alertBox/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,12 @@ export interface Props {
onClickOk?: () => void
cancelString?: string
okString: string
colorType: 'default' | 'accent' | 'warn' | 'subtle'
}

export default class AlertBox extends React.PureComponent<Props, {}> {
static defaultProps = {
colorType: 'accent'
}
render () {
const { testId, children, ...buttonProps } = this.props
const { colorType, onClickCancel, cancelString, onClickOk, okString } = buttonProps
const { onClickCancel, cancelString, onClickOk, okString } = buttonProps
return (
<StyledDialogWrapper>
<StyledDialog data-test-id={testId}>
Expand All @@ -31,11 +27,11 @@ export default class AlertBox extends React.PureComponent<Props, {}> {
<StyledCancelContainer>
{
cancelString
? <Button type={colorType} level='secondary' onClick={onClickCancel} text={cancelString} />
? <Button onClick={onClickCancel} text={cancelString} />
: null
}
</StyledCancelContainer>
<Button type={colorType} onClick={onClickOk} text={okString} />
<Button level='primary' onClick={onClickOk} text={okString} />
</StyledFooter>
</StyledDialog>
</StyledDialogWrapper>
Expand Down
2 changes: 1 addition & 1 deletion src/features/rewards/boxAlert/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ export default class BoxAlert extends React.PureComponent<Props, State> {
<Button
text={getLocale('ok')}
size={'call-to-action'}
type={'accent'}
level={'primary'}
onClick={this.toggleModalDisplay}
/>
</StyledButton>
Expand Down
Loading