testokur/testokur-ui

View on GitHub
src/components/Button/styled.ts

Summary

Maintainability
D
2 days
Test Coverage
import styled, { FlattenSimpleInterpolation, css } from 'styled-components';
import { Sizes, getSize, getSpacing, SpacingsAfter } from '../../modules';
import getIconSpacing from './getIconSpacing';
import getColor from './getColor';
import getWidth from './getWidth';
import { Tokens, Types, ButtonStates } from './const';
import getSizeToken from './getSizeToken';
import { StyledSpinner } from '../Loading';
import getFocus from './getFocus';
import getButtonBoxShadow from './getButtonBoxShadow';
import getButtonSpacing from './getButtonSpacing';

type IconContainerProps = {
  readonly size: Sizes;
  readonly type: Types;
  readonly onlyIcon: boolean;
  readonly bordered?: boolean;
};

export const IconContainer = styled.span<IconContainerProps>`
  display: flex;
  flex-direction: row;
  align-items: center;
  justify-content: center;
  transition: background ${(props): string => props.theme.duration.durationFast} ease-in-out,
    box-shadow ${(props): string => props.theme.duration.durationFast} ease-in-out;
  color: ${(props): string =>
    props.bordered
      ? getColor(Tokens.colorTextButtonBordered, props.type, props.theme)
      : getColor(Tokens.colorTextButton, props.type, props.theme)};
  margin: ${(props): string => getIconSpacing(props.size, props.onlyIcon, props.theme)};

  > svg {
    width: ${(props): string => getSize(props.theme)(props.size)};
    height: ${(props): string => getSize(props.theme)(props.size)};
  }
`;

type StyledButtonContentProps = {
  readonly loading?: boolean;
};

export const StyledButtonContent = styled.span<StyledButtonContentProps>`
  visibility: ${(props): string => (props.loading ? 'hidden' : 'inherirt')};
  height: 100%;
  display: flex;
  flex-basis: 100%;
  justify-content: center;
  align-items: center;
`;

export const StyledButtonContentChildren = styled.span`
  display: inline-block;
`;

export type StyledButtonProps = {
  readonly buttonType: Types;
  readonly size: Sizes;
  readonly fullWidth?: boolean;
  readonly width?: string;
  readonly onlyIcon: boolean;
  readonly bordered: boolean;
  readonly circled?: boolean;
  readonly disabled: boolean;
  readonly spaceAfter: SpacingsAfter;
  readonly hasRightIcon: boolean;
  readonly hasLeftIcon: boolean;
};

export const StyledButton = styled.button<StyledButtonProps>`
  position: relative;
  display: flex;
  justify-content: center;
  align-items: center;
  box-sizing: border-box;
  appearance: none;
  text-decoration: none;
  width: ${(props): string => getWidth(props.size, props.theme, props.fullWidth, props.width, props.onlyIcon)};
  flex: ${(props): string => (props.fullWidth ? '1 1 auto' : '0 0 auto')};
  max-width: 100%;
  height: ${(props): string => getSizeToken(Tokens.heightButton, props.size, props.theme)};
  background: ${(props): string =>
    props.bordered
      ? getColor(Tokens.backgroundButtonBordered, props.buttonType, props.theme)
      : getColor(Tokens.backgroundButton, props.buttonType, props.theme)};
  color: ${(props): string =>
    props.bordered
      ? getColor(Tokens.colorTextButtonBordered, props.buttonType, props.theme)
      : getColor(Tokens.colorTextButton, props.buttonType, props.theme)};
  border: 0;
  border-radius: ${(props): string =>
    props.circled ? getSizeToken(Tokens.heightButton, props.size, props.theme) : props.theme.border.borderRadiusNormal};
  min-width: ${(props): string => (props.circled ? getSizeToken(Tokens.heightButton, props.size, props.theme) : 'initial')};
  font-family: ${(props): string => props.theme.fontFamily};
  font-weight: ${(props): string => `${props.theme.font.fontWeightBold}`};
  font-size: ${(props): string => getSizeToken(Tokens.fontSizeButton, props.size, props.theme)};
  line-height: 1.4;
  cursor: ${(props): string => (props.disabled ? 'not-allowed' : 'pointer')};
  transition: all 0.15s ease-in-out !important;
  outline: 0;
  opacity: ${(props): string => (props.disabled ? props.theme.opacity.buttonDisabled.toString() : 'initial')};
  margin-bottom: ${(props): string => getSpacing(props.theme)(props.spaceAfter)};
  padding: ${(props): string => getButtonSpacing(props.theme, props.onlyIcon, props.hasRightIcon, props.hasLeftIcon, props.size)};
  ${(props): FlattenSimpleInterpolation | null =>
    getButtonBoxShadow(ButtonStates.Default, props.buttonType, props.bordered, props.disabled, props.theme)};

  &:hover {
    ${(props): FlattenSimpleInterpolation | undefined =>
    !props.disabled
      ? css`
            background: ${props.bordered
    ? getColor(Tokens.backgroundButtonBorderedHover, props.buttonType, props.theme)
    : getColor(Tokens.backgroundButtonHover, props.buttonType, props.theme)};
            color: ${props.bordered
    ? getColor(Tokens.colorTextButtonBorderedHover, props.buttonType, props.theme)
    : getColor(Tokens.colorTextButton, props.buttonType, props.theme)}!important;
            ${getButtonBoxShadow(ButtonStates.Hover, props.buttonType, props.bordered, props.disabled, props.theme)};
            & ${/* sc-selector */ IconContainer} {
              color: ${props.bordered
    ? getColor(Tokens.colorTextButtonBorderedHover, props.buttonType, props.theme)
    : getColor(Tokens.colorTextButton, props.buttonType, props.theme)};
            }
          `
      : undefined};
  }

  &:active {
    ${(props): FlattenSimpleInterpolation | undefined =>
    !props.disabled
      ? css`
            background: ${props.bordered
    ? getColor(Tokens.backgroundButtonBorderedActive, props.buttonType, props.theme)
    : getColor(Tokens.backgroundButtonActive, props.buttonType, props.theme)};
            color: ${props.bordered
    ? getColor(Tokens.colorTextButtonBorderedActive, props.buttonType, props.theme)
    : getColor(Tokens.colorTextButton, props.buttonType, props.theme)}!important;
            ${getButtonBoxShadow(ButtonStates.Active, props.buttonType, props.bordered, props.disabled, props.theme)};
            & ${/* sc-selector */ IconContainer} {
              color: ${props.bordered
    ? getColor(Tokens.colorTextButtonBorderedActive, props.buttonType, props.theme)
    : getColor(Tokens.colorTextButton, props.buttonType, props.theme)};
            }
          `
      : undefined};
  }
  ${(props): FlattenSimpleInterpolation => getFocus(props.buttonType, props.bordered, props.disabled, props.theme)};
  ${/* sc-selector */ StyledSpinner} {
    width: ${(props): string => getSizeToken(Tokens.loadingWidth, props.size, props.theme)};
    height: ${(props): string => getSizeToken(Tokens.loadingHeight, props.size, props.theme)};
  }
`;