All files / components/Button Button.tsx

100% Statements 15/15
77.77% Branches 7/9
100% Functions 4/4
100% Lines 15/15

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116                          2x                 2x 7x   2x           2x             3x               2x 7x   3x                                 4x                         2x 7x             2x                   2x             7x                      
import { css } from '@emotion/css';
import { cssVariables } from '../../styles/theme';
 
interface ButtonStyledProps {
  size?: 'small' | 'default' | 'large';
  color?: 'primary' | 'secondary';
}
interface ButtonProps extends ButtonStyledProps {
  label: string;
  icon?: React.ReactNode;
  onClick?: () => void;
}
 
const cssClassName = css`
  cursor: pointer;
  display: inline-block;
  border: none;
  display: flex;
  align-items: center;
  justify-content: center;
`;
 
const getCssClassNameForSize = ({ size }: ButtonStyledProps): string => {
  switch (size) {
    case 'small':
      return css`
        ${cssVariables.topdoneComponentsTypographyButtonMd}
        padding: ${`${cssVariables.topdoneComponentsPaddingButtonSmallVertical} ${cssVariables.topdoneComponentsPaddingButtonSmallHorizontal}`};
        border-radius: ${cssVariables.topdoneComponentsRadiusButton};
      `;
    case 'large':
      return css`
        ${cssVariables.topdoneComponentsTypographyButtonLg}
        padding: ${`${cssVariables.topdoneComponentsPaddingButtonLargeVertical} ${cssVariables.topdoneComponentsPaddingButtonLargeHorizontal}`};
        border-radius: ${cssVariables.topdoneComponentsRadiusButton};
      `;
    case 'default':
    default:
      return css`
        ${cssVariables.topdoneComponentsTypographyButtonMd}
        padding: ${`${cssVariables.topdoneComponentsPaddingButtonMediumVertical} ${cssVariables.topdoneComponentsPaddingButtonMediumHorizontal}`};
        border-radius: ${cssVariables.topdoneComponentsRadiusButton};
      `;
  }
};
 
const getCssClassNameForColor = ({ color }: ButtonStyledProps): string => {
  switch (color) {
    case 'secondary':
      return css`
        box-shadow: ${`inset 0px 0px 0px  ${cssVariables.topdoneComponentsBorderButtonSecondaryDefault}  ${cssVariables.topdoneComponentsColorBorderButtonSecondaryDefault}`};
        color: ${cssVariables.topdoneComponentsColorTextButtonSecondaryDefault};
        background-color: ${cssVariables.topdoneComponentsColorBackgroundButtonSecondaryDefault};
        .topdone-icon path {
          fill: ${cssVariables.topdoneComponentsColorTextButtonSecondaryDefault};
        }
        &:hover {
          color: ${cssVariables.topdoneComponentsColorTextButtonSecondaryHover};
          background-color: ${cssVariables.topdoneComponentsColorBackgroundButtonSecondaryHover};
          .topdone-icon path {
            fill: ${cssVariables.topdoneComponentsColorTextButtonSecondaryHover};
          }
        }
      `;
    case 'primary':
    default:
      return css`
        color: ${cssVariables.topdoneComponentsColorTextButtonPrimaryDefault};
        background-color: ${cssVariables.topdoneComponentsColorBackgroundButtonPrimaryDefault};
        &:hover {
          background-color: ${cssVariables.topdoneComponentsColorBackgroundButtonPrimaryHover};
        }
        .topdone-icon path {
          fill: ${cssVariables.topdoneComponentsColorTextButtonPrimaryDefault};
        }
      `;
  }
};
 
const getStyledClassNames = (props: ButtonStyledProps): string =>
  [
    cssClassName,
    getCssClassNameForSize(props),
    getCssClassNameForColor(props),
    'topdone-button',
  ].join(' ');
 
const cssIconClassName = css`
  justify-self: flex-start;
  width: ${cssVariables.topdoneCoreSpacing05};
  margin-right: ${cssVariables.topdoneComponentsMarginButtonLabelIconBefore};
  .topdone-icon {
    position: absolute;
    transform: translateY(-50%);
  }
`;
 
const Button = ({
  icon,
  label,
  size,
  color,
  onClick,
}: ButtonProps): JSX.Element => (
  <button
    className={getStyledClassNames({ color, size })}
    onClick={onClick}
    type="button"
  >
    {icon && <span className={cssIconClassName}>{icon}</span>}
    {label}
  </button>
);
 
export default Button;