[4725] Inverted Variants of buttons (#5671)

Resolves #4725

---------

Co-authored-by: Félix Malfait <felix.malfait@gmail.com>
This commit is contained in:
Hinson Chan
2024-06-06 07:41:22 -07:00
committed by GitHub
parent 9567103d5f
commit c76bc4729d
5 changed files with 222 additions and 102 deletions

View File

@ -16,6 +16,7 @@ export type ButtonProps = {
title?: string; title?: string;
fullWidth?: boolean; fullWidth?: boolean;
variant?: ButtonVariant; variant?: ButtonVariant;
inverted?: boolean;
size?: ButtonSize; size?: ButtonSize;
position?: ButtonPosition; position?: ButtonPosition;
accent?: ButtonAccent; accent?: ButtonAccent;
@ -36,6 +37,7 @@ const StyledButton = styled('button', {
ButtonProps, ButtonProps,
| 'fullWidth' | 'fullWidth'
| 'variant' | 'variant'
| 'inverted'
| 'size' | 'size'
| 'position' | 'position'
| 'accent' | 'accent'
@ -46,83 +48,112 @@ const StyledButton = styled('button', {
> >
>` >`
align-items: center; align-items: center;
${({ theme, variant, accent, disabled, focus }) => { ${({ theme, variant, inverted, accent, disabled, focus }) => {
switch (variant) { switch (variant) {
case 'primary': case 'primary':
switch (accent) { switch (accent) {
case 'default': case 'default':
return css` return css`
background: ${theme.background.secondary}; background: ${!inverted
border-color: ${!disabled ? theme.background.secondary
: theme.background.primary};
border-color: ${!inverted
? focus ? focus
? theme.color.blue ? theme.color.blue
: theme.background.transparent.light : theme.background.transparent.light
: 'transparent'}; : theme.background.transparent.light};
border-width: ${!disabled && focus ? '1px 1px !important' : 0}; border-width: 1px 1px 1px 1px !important;
opacity: ${disabled ? 0.24 : 1};
box-shadow: ${!disabled && focus box-shadow: ${!disabled && focus
? `0 0 0 3px ${theme.accent.tertiary}` ? `0 0 0 3px ${
!inverted
? theme.accent.tertiary
: theme.background.transparent.medium
}`
: 'none'}; : 'none'};
color: ${!disabled color: ${!inverted
? theme.font.color.secondary ? !disabled
: theme.font.color.extraLight}; ? theme.font.color.secondary
: theme.font.color.extraLight
: theme.font.color.secondary};
&:hover { &:hover {
background: ${!disabled background: ${!inverted
? theme.background.tertiary ? theme.background.tertiary
: theme.background.secondary}; : theme.background.secondary};
} }
&:active { &:active {
background: ${!disabled background: ${!inverted
? theme.background.quaternary ? theme.background.quaternary
: theme.background.secondary}; : theme.background.tertiary};
} }
`; `;
case 'blue': case 'blue':
return css` return css`
background: ${theme.color.blue}; background: ${!inverted
border-color: ${!disabled ? theme.color.blue
: theme.background.primary};
border-color: ${!inverted
? focus ? focus
? theme.color.blue ? theme.color.blue
: theme.background.transparent.light : theme.background.transparent.light
: 'transparent'}; : theme.background.transparent.light};
border-width: ${!disabled && focus ? '1px 1px !important' : 0}; border-width: 1px 1px 1px 1px !important;
box-shadow: ${!disabled && focus box-shadow: ${!disabled && focus
? `0 0 0 3px ${theme.accent.tertiary}` ? `0 0 0 3px ${
!inverted
? theme.accent.tertiary
: theme.background.transparent.medium
}`
: 'none'}; : 'none'};
color: ${theme.grayScale.gray0}; color: ${!inverted ? theme.grayScale.gray0 : theme.color.blue};
opacity: ${disabled ? 0.24 : 1}; opacity: ${disabled ? 0.24 : 1};
${disabled ${disabled
? '' ? ''
: css` : css`
&:hover { &:hover {
background: ${theme.color.blue50}; background: ${!inverted
? theme.color.blue50
: theme.background.secondary};
} }
&:active { &:active {
background: ${theme.color.blue60}; background: ${!inverted
? theme.color.blue60
: theme.background.tertiary};
} }
`} `}
`; `;
case 'danger': case 'danger':
return css` return css`
background: ${theme.color.red}; background: ${!inverted
border-color: ${!disabled ? theme.color.red
: theme.background.primary};
border-color: ${!inverted
? focus ? focus
? theme.color.red ? theme.color.red
: theme.background.transparent.light : theme.background.transparent.light
: 'transparent'}; : theme.background.transparent.light};
border-width: ${!disabled && focus ? '1px 1px !important' : 0}; border-width: 1px 1px !important;
box-shadow: ${!disabled && focus box-shadow: ${!disabled && focus
? `0 0 0 3px ${theme.color.red10}` ? `0 0 0 3px ${
!inverted
? theme.color.red10
: theme.background.transparent.medium
}`
: 'none'}; : 'none'};
color: ${theme.grayScale.gray0}; color: ${!inverted ? theme.background.primary : theme.color.red};
opacity: ${disabled ? 0.24 : 1}; opacity: ${disabled ? 0.24 : 1};
${disabled ${disabled
? '' ? ''
: css` : css`
&:hover, &:hover {
background: ${!inverted
? theme.color.red40
: theme.background.secondary};
}
&:active { &:active {
background: ${theme.color.red50}; background: ${!inverted
? theme.color.red50
: theme.background.tertiary};
} }
`} `}
`; `;
@ -133,88 +164,143 @@ const StyledButton = styled('button', {
switch (accent) { switch (accent) {
case 'default': case 'default':
return css` return css`
background: ${focus background: transparent;
? theme.background.transparent.primary border-color: ${!inverted
: 'transparent'}; ? variant === 'secondary'
border-color: ${variant === 'secondary' ? !disabled && focus
? !disabled && focus ? theme.color.blue
? theme.color.blue : theme.background.transparent.medium
: theme.background.transparent.medium : focus
: focus ? theme.color.blue
? theme.color.blue : 'transparent'
: 'transparent'}; : variant === 'secondary'
border-width: ${!disabled && focus ? '1px 1px !important' : 0}; ? focus || disabled
? theme.grayScale.gray0
: theme.background.transparent.primary
: focus
? theme.grayScale.gray0
: 'transparent'};
border-width: 1px 1px 1px 1px !important;
box-shadow: ${!disabled && focus box-shadow: ${!disabled && focus
? `0 0 0 3px ${theme.accent.tertiary}` ? `0 0 0 3px ${
!inverted
? theme.accent.tertiary
: theme.background.transparent.medium
}`
: 'none'}; : 'none'};
color: ${!disabled opacity: ${disabled ? 0.24 : 1};
? theme.font.color.secondary color: ${!inverted
: theme.font.color.extraLight}; ? !disabled
? theme.font.color.secondary
: theme.font.color.extraLight
: theme.font.color.inverted};
&:hover { &:hover {
background: ${!disabled background: ${!inverted
? theme.background.transparent.light ? !disabled
: 'transparent'}; ? theme.background.transparent.light
: 'transparent'
: theme.background.transparent.light};
} }
&:active { &:active {
background: ${!disabled background: ${!inverted
? theme.background.transparent.light ? !disabled
: 'transparent'}; ? theme.background.transparent.light
: 'transparent'
: theme.background.transparent.medium};
} }
`; `;
case 'blue': case 'blue':
return css` return css`
background: ${focus background: transparent;
? theme.background.transparent.primary border-color: ${!inverted
: 'transparent'}; ? variant === 'secondary'
border-color: ${variant === 'secondary' ? focus
? focus ? theme.color.blue
? theme.color.blue : theme.accent.primary
: theme.accent.primary : focus
: focus ? theme.color.blue
? theme.color.blue : 'transparent'
: 'transparent'}; : variant === 'secondary'
border-width: ${!disabled && focus ? '1px 1px !important' : 0}; ? focus || disabled
? theme.grayScale.gray0
: theme.background.transparent.primary
: focus
? theme.grayScale.gray0
: 'transparent'};
border-width: 1px 1px 1px 1px !important;
box-shadow: ${!disabled && focus box-shadow: ${!disabled && focus
? `0 0 0 3px ${theme.accent.tertiary}` ? `0 0 0 3px ${
!inverted
? theme.accent.tertiary
: theme.background.transparent.medium
}`
: 'none'}; : 'none'};
color: ${!disabled ? theme.color.blue : theme.accent.accent4060}; opacity: ${disabled ? 0.24 : 1};
color: ${!inverted
? !disabled
? theme.color.blue
: theme.accent.accent4060
: theme.font.color.inverted};
&:hover { &:hover {
background: ${!disabled background: ${!inverted
? theme.accent.tertiary ? !disabled
: 'transparent'}; ? theme.accent.tertiary
: 'transparent'
: theme.background.transparent.light};
} }
&:active { &:active {
background: ${!disabled background: ${!inverted
? theme.accent.secondary ? !disabled
: 'transparent'}; ? theme.accent.secondary
: 'transparent'
: theme.background.transparent.medium};
} }
`; `;
case 'danger': case 'danger':
return css` return css`
background: transparent; background: transparent;
border-color: ${variant === 'secondary' border-color: ${!inverted
? focus ? variant === 'secondary'
? theme.color.red ? focus
: theme.border.color.danger ? theme.color.red
: focus : theme.border.color.danger
? theme.color.red : focus
: 'transparent'}; ? theme.color.red
border-width: ${!disabled && focus ? '1px 1px !important' : 0}; : 'transparent'
: variant === 'secondary'
? focus || disabled
? theme.grayScale.gray0
: theme.background.transparent.primary
: focus
? theme.grayScale.gray0
: 'transparent'};
border-width: 1px 1px 1px 1px !important;
box-shadow: ${!disabled && focus box-shadow: ${!disabled && focus
? `0 0 0 3px ${theme.color.red10}` ? `0 0 0 3px ${
!inverted
? theme.color.red10
: theme.background.transparent.medium
}`
: 'none'}; : 'none'};
color: ${!disabled opacity: ${disabled ? 0.24 : 1};
? theme.font.color.danger color: ${!inverted
: theme.border.color.danger}; ? !disabled
? theme.font.color.danger
: theme.color.red20
: theme.font.color.inverted};
&:hover { &:hover {
background: ${!disabled background: ${!inverted
? theme.background.danger ? !disabled
: 'transparent'}; ? theme.background.danger
: 'transparent'
: theme.background.transparent.light};
} }
&:active { &:active {
background: ${!disabled background: ${!inverted
? theme.background.danger ? !disabled
: 'transparent'}; ? theme.background.danger
: 'transparent'
: theme.background.transparent.medium};
} }
`; `;
} }
@ -277,6 +363,7 @@ export const Button = ({
title, title,
fullWidth = false, fullWidth = false,
variant = 'primary', variant = 'primary',
inverted = false,
size = 'medium', size = 'medium',
accent = 'default', accent = 'default',
position = 'standalone', position = 'standalone',
@ -294,6 +381,7 @@ export const Button = ({
<StyledButton <StyledButton
fullWidth={fullWidth} fullWidth={fullWidth}
variant={variant} variant={variant}
inverted={inverted}
size={size} size={size}
position={position} position={position}
disabled={soon || disabled} disabled={soon || disabled}

View File

@ -30,6 +30,7 @@ export const Default: Story = {
title: 'Button', title: 'Button',
size: 'small', size: 'small',
variant: 'primary', variant: 'primary',
inverted: false,
accent: 'danger', accent: 'danger',
disabled: false, disabled: false,
focus: false, focus: false,

View File

@ -19,16 +19,16 @@ html {
padding: 0 !important; padding: 0 !important;
} }
*::-webkit-scrollbar { *::-webkit-scrollbar {
height: 4px; height: 4px;
width: 4px; width: 4px;
} }
*::-webkit-scrollbar-corner { *::-webkit-scrollbar-corner {
background-color: transparent; background-color: transparent;
} }
*::-webkit-scrollbar-thumb { *::-webkit-scrollbar-thumb {
background-color: transparent; background-color: transparent;
border-radius: 2px; border-radius: 2px;
} }
</style> </style>

View File

@ -1,7 +1,11 @@
import styled from '@emotion/styled'; import styled from '@emotion/styled';
const StyledLayout = styled.div<{ width?: number }>` const StyledLayout = styled.div<{
background: ${({ theme }) => theme.background.primary}; width?: number;
backgroundColor?: string | undefined;
}>`
background: ${({ theme, backgroundColor }) =>
backgroundColor ?? theme.background.primary};
border: 1px solid ${({ theme }) => theme.border.color.light}; border: 1px solid ${({ theme }) => theme.border.color.light};
border-radius: 5px; border-radius: 5px;
@ -17,12 +21,16 @@ const StyledLayout = styled.div<{ width?: number }>`
type ComponentStorybookLayoutProps = { type ComponentStorybookLayoutProps = {
width?: number; width?: number;
backgroundColor?: string | undefined;
children: JSX.Element; children: JSX.Element;
}; };
export const ComponentStorybookLayout = ({ export const ComponentStorybookLayout = ({
width, width,
backgroundColor,
children, children,
}: ComponentStorybookLayoutProps) => ( }: ComponentStorybookLayoutProps) => (
<StyledLayout width={width}>{children}</StyledLayout> <StyledLayout width={width} backgroundColor={backgroundColor}>
{children}
</StyledLayout>
); );

View File

@ -1,12 +1,35 @@
import { Decorator } from '@storybook/react'; import { Decorator } from '@storybook/react';
import { GRAY_SCALE, MAIN_COLORS } from '@ui/theme';
import { ComponentStorybookLayout } from '../ComponentStorybookLayout'; import { ComponentStorybookLayout } from '../ComponentStorybookLayout';
const getBackgroundColor = (inverted: boolean, accent: string) => {
if (!inverted) return undefined;
switch (accent) {
case 'default':
return GRAY_SCALE.gray50;
case 'danger':
return MAIN_COLORS.red;
case 'blue':
return MAIN_COLORS.blue;
default:
return undefined;
}
};
export const ComponentDecorator: Decorator = (Story, context) => { export const ComponentDecorator: Decorator = (Story, context) => {
const { container } = context.parameters; const { container } = context.parameters;
const inverted = context.args.inverted as boolean;
const accent = context.args.accent as string;
const backgroundColor = getBackgroundColor(inverted, accent);
return ( return (
<ComponentStorybookLayout width={container?.width}> <ComponentStorybookLayout
width={container?.width}
backgroundColor={backgroundColor}
>
<Story /> <Story />
</ComponentStorybookLayout> </ComponentStorybookLayout>
); );