|
@@ -4,45 +4,76 @@ import styled from '@emotion/styled'
|
|
|
|
|
|
import { colors, sizes, transitions } from '../../theme'
|
|
|
|
|
|
-export type ButtonVariant = 'primary' | 'secondary' | 'tertiary'
|
|
|
+export type ButtonVariant =
|
|
|
+ | 'primary'
|
|
|
+ | 'secondary'
|
|
|
+ | 'tertiary'
|
|
|
+ | 'destructive'
|
|
|
+ | 'destructive-secondary'
|
|
|
+ | 'warning'
|
|
|
+ | 'warning-secondary'
|
|
|
export type ButtonSize = 'large' | 'medium' | 'small'
|
|
|
export type ButtonBaseStyleProps = {
|
|
|
variant: ButtonVariant
|
|
|
size: ButtonSize
|
|
|
clickable?: boolean
|
|
|
+ textOnly: boolean
|
|
|
+ iconOnly: boolean
|
|
|
}
|
|
|
|
|
|
-const variantStyles = ({ variant }: ButtonBaseStyleProps): SerializedStyles => {
|
|
|
+const variantStyles = ({ variant, textOnly, iconOnly }: ButtonBaseStyleProps): SerializedStyles => {
|
|
|
switch (variant) {
|
|
|
case 'primary':
|
|
|
return css`
|
|
|
background-color: ${colors.blue[500]};
|
|
|
+ color: ${textOnly ? colors.blue[300] : colors.gray[50]};
|
|
|
|
|
|
- &:hover {
|
|
|
+ path {
|
|
|
+ fill: ${textOnly && colors.blue[300]};
|
|
|
+ }
|
|
|
+
|
|
|
+ &:hover,
|
|
|
+ &:focus {
|
|
|
background-color: ${colors.blue[700]};
|
|
|
}
|
|
|
|
|
|
&:active {
|
|
|
background-color: ${colors.blue[900]};
|
|
|
+ color: ${textOnly && colors.blue[400]};
|
|
|
+
|
|
|
+ path {
|
|
|
+ fill: ${textOnly && colors.blue[400]};
|
|
|
+ }
|
|
|
}
|
|
|
`
|
|
|
case 'secondary':
|
|
|
return css`
|
|
|
/* 1px inset border */
|
|
|
box-shadow: inset 0 0 0 1px ${colors.gray[500]};
|
|
|
+ color: ${colors.gray[50]};
|
|
|
|
|
|
- &:hover {
|
|
|
- box-shadow: inset 0 0 0 1px ${colors.gray[50]};
|
|
|
+ &:hover,
|
|
|
+ &:focus {
|
|
|
+ box-shadow: inset 0 0 0 2px ${colors.gray[300]};
|
|
|
+ border-color: ${colors.gray[300]};
|
|
|
}
|
|
|
|
|
|
&:active {
|
|
|
- box-shadow: inset 0 0 0 1px ${colors.gray[50]};
|
|
|
- background-color: ${colors.blue[500]};
|
|
|
+ box-shadow: inset 0 0 0 2px ${colors.gray[50]};
|
|
|
+ color: ${textOnly && colors.gray[300]};
|
|
|
+
|
|
|
+ path {
|
|
|
+ fill: ${textOnly && colors.gray[300]};
|
|
|
+ }
|
|
|
}
|
|
|
`
|
|
|
case 'tertiary':
|
|
|
return css`
|
|
|
- &:hover {
|
|
|
+ color: ${colors.gray[50]};
|
|
|
+ ${iconOnly && `border-radius: 50%`};
|
|
|
+
|
|
|
+ &:hover,
|
|
|
+ &:focus {
|
|
|
background-color: ${colors.transparentPrimary[12]};
|
|
|
}
|
|
|
|
|
@@ -50,6 +81,84 @@ const variantStyles = ({ variant }: ButtonBaseStyleProps): SerializedStyles => {
|
|
|
background-color: ${colors.transparentPrimary[6]};
|
|
|
}
|
|
|
`
|
|
|
+ case 'destructive':
|
|
|
+ return css`
|
|
|
+ background-color: ${colors.secondary.alert[100]};
|
|
|
+ color: ${colors.gray[50]};
|
|
|
+
|
|
|
+ &:hover,
|
|
|
+ &:focus {
|
|
|
+ background-color: ${colors.secondary.alert[200]};
|
|
|
+ }
|
|
|
+
|
|
|
+ &:active {
|
|
|
+ background-color: ${colors.secondary.alert[300]};
|
|
|
+ }
|
|
|
+ `
|
|
|
+ case 'destructive-secondary':
|
|
|
+ return css`
|
|
|
+ box-shadow: inset 0 0 0 1px ${colors.gray[400]};
|
|
|
+ color: ${colors.secondary.alert[50]};
|
|
|
+
|
|
|
+ path {
|
|
|
+ fill: ${colors.secondary.alert[50]};
|
|
|
+ }
|
|
|
+
|
|
|
+ &:hover,
|
|
|
+ &:focus {
|
|
|
+ box-shadow: inset 0 0 0 2px ${colors.gray[300]};
|
|
|
+ }
|
|
|
+
|
|
|
+ &:active {
|
|
|
+ box-shadow: inset 0 0 0 2px ${colors.gray[50]};
|
|
|
+ color: ${textOnly && colors.secondary.alert[100]};
|
|
|
+
|
|
|
+ path {
|
|
|
+ fill: ${textOnly && colors.secondary.alert[100]};
|
|
|
+ }
|
|
|
+ }
|
|
|
+ `
|
|
|
+ case 'warning':
|
|
|
+ return css`
|
|
|
+ background-color: ${colors.secondary.warning[100]};
|
|
|
+ color: ${colors.gray[900]};
|
|
|
+
|
|
|
+ path {
|
|
|
+ fill: ${colors.gray[900]};
|
|
|
+ }
|
|
|
+
|
|
|
+ &:hover,
|
|
|
+ &:focus {
|
|
|
+ background-color: ${colors.secondary.warning[200]};
|
|
|
+ }
|
|
|
+
|
|
|
+ &:active {
|
|
|
+ background-color: ${colors.secondary.warning[300]};
|
|
|
+ }
|
|
|
+ `
|
|
|
+ case 'warning-secondary':
|
|
|
+ return css`
|
|
|
+ color: ${colors.secondary.warning[100]};
|
|
|
+ box-shadow: inset 0 0 0 1px ${colors.gray[400]};
|
|
|
+
|
|
|
+ path {
|
|
|
+ fill: ${colors.secondary.warning[100]};
|
|
|
+ }
|
|
|
+
|
|
|
+ &:hover,
|
|
|
+ &:focus {
|
|
|
+ box-shadow: inset 0 0 0 2px ${colors.gray[300]};
|
|
|
+ }
|
|
|
+
|
|
|
+ &:active {
|
|
|
+ color: ${textOnly && colors.secondary.warning[300]};
|
|
|
+ box-shadow: inset 0 0 0 2px ${colors.gray[50]};
|
|
|
+
|
|
|
+ path {
|
|
|
+ fill: ${textOnly && colors.secondary.warning[300]};
|
|
|
+ }
|
|
|
+ }
|
|
|
+ `
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -70,6 +179,46 @@ const sizeStyles = ({ size }: ButtonBaseStyleProps): SerializedStyles => {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+const textOnlyStyles = ({ textOnly }: ButtonBaseStyleProps): SerializedStyles | null =>
|
|
|
+ textOnly
|
|
|
+ ? css`
|
|
|
+ background-color: ${colors.transparent};
|
|
|
+ box-shadow: none;
|
|
|
+ padding: 0;
|
|
|
+
|
|
|
+ &:hover,
|
|
|
+ &:focus {
|
|
|
+ background-color: ${colors.transparent};
|
|
|
+ box-shadow: none;
|
|
|
+ }
|
|
|
+
|
|
|
+ &:active {
|
|
|
+ background-color: ${colors.transparent};
|
|
|
+ box-shadow: none;
|
|
|
+ }
|
|
|
+ `
|
|
|
+ : null
|
|
|
+
|
|
|
+export const BorderWrapper = styled.div<Pick<ButtonBaseStyleProps, 'textOnly'>>`
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ box-sizing: border-box;
|
|
|
+ margin-top: -0.5px;
|
|
|
+ margin-bottom: -0.5px;
|
|
|
+ height: 100%;
|
|
|
+ visibility: hidden;
|
|
|
+ border-bottom-width: ${({ textOnly }) => textOnly && '1px'};
|
|
|
+ border-bottom-style: ${({ textOnly }) => textOnly && 'solid'};
|
|
|
+
|
|
|
+ &:hover {
|
|
|
+ visibility: visible;
|
|
|
+ }
|
|
|
+
|
|
|
+ * {
|
|
|
+ visibility: visible;
|
|
|
+ }
|
|
|
+`
|
|
|
+
|
|
|
export const StyledButtonBase = styled('button', { shouldForwardProp: isPropValid })<ButtonBaseStyleProps>`
|
|
|
display: inline-flex;
|
|
|
align-items: center;
|
|
@@ -91,4 +240,9 @@ export const StyledButtonBase = styled('button', { shouldForwardProp: isPropVali
|
|
|
|
|
|
${variantStyles};
|
|
|
${sizeStyles};
|
|
|
+ ${textOnlyStyles};
|
|
|
+
|
|
|
+ :focus ${BorderWrapper} {
|
|
|
+ visibility: visible;
|
|
|
+ }
|
|
|
`
|