import React from "react"; import { CommonComponentProps, hexToRgba, ThemeProp } from "./common"; import styled from "styled-components"; import Icon, { IconName } from "./Icon"; import Spinner from "./Spinner"; import { mediumButton, smallButton, largeButton, } from "../../constants/DefaultTheme"; export enum Category { primary = "primary", secondary = "secondary", tertiary = "tertiary", } export enum Variant { success = "success", info = "info", warning = "warning", danger = "danger", } export enum Size { small = "small", medium = "medium", large = "large", } type stateStyleType = { bgColorPrimary: string; borderColorPrimary: string; txtColorPrimary: string; bgColorSecondary: string; borderColorSecondary: string; txtColorSecondary: string; bgColorTertiary: string; borderColorTertiary: string; txtColorTertiary: string; }; type BtnColorType = { bgColor: string; txtColor: string; border: string; }; type BtnFontType = { buttonFont: any; padding: string; }; type ButtonProps = CommonComponentProps & { onClick?: (event: React.MouseEvent) => void; text?: string; category?: Category; variant?: Variant; icon?: IconName; size?: Size; }; const stateStyles = ( props: ThemeProp & ButtonProps, state: string, ): stateStyleType => { let bgColorPrimary, borderColorPrimary, txtColorPrimary, bgColorSecondary, borderColorSecondary, txtColorSecondary, bgColorTertiary, borderColorTertiary, txtColorTertiary; if (props.isLoading || props.disabled) { switch (props.category) { case Category.primary: if (props.variant) { bgColorPrimary = props.theme.colors[props.variant].darkest; borderColorPrimary = props.theme.colors[props.variant].darkest; } txtColorPrimary = props.theme.colors.blackShades[6]; break; case Category.secondary: if (props.variant) { bgColorSecondary = props.theme.colors[props.variant].darkest; borderColorSecondary = props.theme.colors[props.variant].darker; } txtColorSecondary = props.theme.colors.blackShades[6]; break; case Category.tertiary: bgColorTertiary = props.theme.colors.tertiary.darker; borderColorTertiary = props.theme.colors.tertiary.dark; txtColorTertiary = props.theme.colors.blackShades[6]; break; } } else if (state === "main") { switch (props.category) { case Category.primary: if (props.variant) { bgColorPrimary = props.theme.colors[props.variant].main; borderColorPrimary = props.theme.colors[props.variant].main; } txtColorPrimary = props.theme.colors.blackShades[9]; break; case Category.secondary: if (props.variant) { borderColorSecondary = props.theme.colors[props.variant].main; txtColorSecondary = props.theme.colors[props.variant].main; } bgColorSecondary = "transparent"; break; case Category.tertiary: bgColorTertiary = "transparent"; borderColorTertiary = props.theme.colors.tertiary.main; txtColorTertiary = props.theme.colors.tertiary.main; break; } } else if (state === "hover") { switch (props.category) { case Category.primary: if (props.variant) { bgColorPrimary = props.theme.colors[props.variant].dark; borderColorPrimary = props.theme.colors[props.variant].dark; } txtColorPrimary = props.theme.colors.blackShades[9]; break; case Category.secondary: if (props.variant) { bgColorSecondary = hexToRgba( props.theme.colors[props.variant].main, 0.1, ); txtColorSecondary = props.theme.colors[props.variant].main; borderColorSecondary = props.theme.colors[props.variant].main; } break; case Category.tertiary: bgColorTertiary = hexToRgba(props.theme.colors.tertiary.main, 0.1); borderColorTertiary = props.theme.colors.tertiary.main; txtColorTertiary = props.theme.colors.tertiary.main; break; } } else if (state === "active") { switch (props.category) { case Category.primary: if (props.variant) { bgColorPrimary = props.theme.colors[props.variant].dark; borderColorPrimary = props.theme.colors[props.variant].main; } txtColorPrimary = props.theme.colors.blackShades[9]; break; case Category.secondary: if (props.variant) { bgColorSecondary = hexToRgba( props.theme.colors[props.variant].main, 0.1, ); txtColorSecondary = props.theme.colors[props.variant].light; borderColorSecondary = props.theme.colors[props.variant].light; } break; case Category.tertiary: bgColorTertiary = hexToRgba(props.theme.colors.tertiary.main, 0.1); borderColorTertiary = props.theme.colors.tertiary.light; txtColorTertiary = props.theme.colors.tertiary.light; break; } } return { bgColorPrimary, borderColorPrimary, txtColorPrimary, bgColorSecondary, borderColorSecondary, txtColorSecondary, bgColorTertiary, borderColorTertiary, txtColorTertiary, }; }; const btnColorStyles = ( props: ThemeProp & ButtonProps, state: string, ): BtnColorType => { let bgColor = "", txtColor = "", border = ""; switch (props.category) { case Category.primary: bgColor = stateStyles(props, state).bgColorPrimary; txtColor = stateStyles(props, state).txtColorPrimary; border = `2px solid ${stateStyles(props, state).borderColorPrimary}`; break; case Category.secondary: bgColor = stateStyles(props, state).bgColorSecondary; txtColor = stateStyles(props, state).txtColorSecondary; border = `2px solid ${stateStyles(props, state).borderColorSecondary}`; break; case Category.tertiary: bgColor = stateStyles(props, state).bgColorTertiary; txtColor = stateStyles(props, state).txtColorTertiary; border = `2px solid ${stateStyles(props, state).borderColorTertiary}`; break; } return { bgColor, txtColor, border }; }; const btnFontStyles = (props: ThemeProp & ButtonProps): BtnFontType => { let buttonFont, padding = ""; switch (props.size) { case Size.small: buttonFont = smallButton; padding = !props.text && props.icon ? `${props.theme.spaces[1]}px ${props.theme.spaces[1]}px` : `${props.theme.spaces[1]}px ${props.theme.spaces[6]}px ${props.theme .spaces[1] - 1}px`; break; case Size.medium: buttonFont = mediumButton; padding = !props.text && props.icon ? `${props.theme.spaces[2]}px ${props.theme.spaces[2]}px` : `${props.theme.spaces[3] - 1}px ${props.theme.spaces[7]}px`; break; case Size.large: buttonFont = largeButton; padding = !props.text && props.icon ? `${props.theme.spaces[3]}px` : `${props.theme.spaces[5] - 1}px ${props.theme.spaces[12] - 4}px`; break; } return { buttonFont, padding }; }; const StyledButton = styled("button")` border: none; outline: none; text-transform: uppercase; background-color: ${props => btnColorStyles(props, "main").bgColor}; color: ${props => btnColorStyles(props, "main").txtColor}; border: ${props => btnColorStyles(props, "main").border}; border-radius: ${props => props.theme.radii[0]}; ${props => btnFontStyles(props).buttonFont}; padding: ${props => btnFontStyles(props).padding}; .ads-icon { margin-right: ${props => props.text && props.icon ? `${props.theme.spaces[4]}px` : `0`} path { fill: ${props => btnColorStyles(props, "main").txtColor}; } } &:hover { background-color: ${props => btnColorStyles(props, "hover").bgColor}; color: ${props => btnColorStyles(props, "hover").txtColor}; border: ${props => btnColorStyles(props, "hover").border}; cursor: ${props => props.isLoading || props.disabled ? `not-allowed` : `pointer`}; .ads-icon { margin-right: ${props => props.text && props.icon ? `${props.theme.spaces[4]}px` : `0`} path { fill: ${props => btnColorStyles(props, "hover").txtColor}; } } } font-style: normal; &:active { background-color: ${props => btnColorStyles(props, "active").bgColor}; color: ${props => btnColorStyles(props, "active").txtColor}; border: ${props => btnColorStyles(props, "active").border}; cursor: ${props => props.isLoading || props.disabled ? `not-allowed` : `pointer`}; .ads-icon { path { fill: ${props => btnColorStyles(props, "active").txtColor}; } } } display: flex; position: relative; .new-spinner { position: absolute; left: 0; right: 0; margin-left: auto; margin-right: auto; } `; Button.defaultProps = { category: Category.primary, variant: Variant.success, size: Size.small, isLoading: false, disabled: false, }; export const VisibilityWrapper = styled.div` visibility: hidden; `; function Button(props: ButtonProps) { const IconLoadingState = ( ); const TextLoadingState = {props.text}; return ( ) => props.onClick && props.onClick(e) } > {props.icon ? ( props.isLoading ? ( IconLoadingState ) : ( ) ) : null} {props.text ? (props.isLoading ? TextLoadingState : props.text) : null} {props.isLoading ? : null} ); } export default Button;