[React] Use react styled system with styled components

In this lesson we’ll improve a generic button primitive component by refactoring it with Styled System to simplify the implementation.

The naïve styled-component implementation has styles like this:

import styled from 'styled-components'

export const Button = styled.button`
  width: ${(props) => (props.fullWidth ? '100%' : undefined)};
  padding: 8px 16px;
  background-color: ${(props) =>
    props.variant === 'primary'
      ? props.theme.colors.primary
      : props.theme.colors.secondary};
  color: snow;
  border: 0;
  border-radius: 0.2rem;
  font-size: 1rem;
  cursor: pointer;

  &:hover,
  &:active {
    background-color: ${(props) => props.theme.colors.accent};
  }

  &:focus {
    outline: 0;
    box-shadow: 0 0 0 2px white, 0 0 0 4px salmon;
  }

  @media (max-width: 550px) {
    width: 100%;
  }
`
Button.propTypes = {
  variant: PropTypes.oneOf(['secondary', 'primary']),
}
Button.defaultProps = {
  variant: 'secondary',
}

 

Convert to Style system:

import styled, { ThemeProvider } from 'styled-components'
import css from '@styled-system/css'
import { variant, space } from 'styled-system'

const variants = {
  primary: {
    color: 'background',
    backgroundColor: 'primary',
  },
  secondary: {
    color: 'primary',
    backgroundColor: 'background',
  },
}

const Button = styled.button(
  css({
    boxSizing: 'border-box',
    display: 'inline-block',
    textAlign: 'center',
    px: 4,
    py: 3,
    color: (props) => (props.variant === 'primary' ? 'background' : 'primary'),
    backgroundColor: (props) =>
      props.variant === 'primary' ? 'primary' : 'background',
    border: '1px solid',
    borderColor: 'primary',
    borderRadius: 'round',
    fontFamily: 'body',
    fontSize: 'm',
    textDecoration: 'none',

    '&:hover:not(:disabled),&:active:not(:disabled),&:focus': {
      outline: 0,
      color: 'background',
      borderColor: 'accent',
      backgroundColor: 'accent',
      cursor: 'pointer',
    },

    '&:disabled': {
      opacity: 0.6,
      filter: 'saturate(60%)',
    },
  }),
  variant({ variants }),
  space,
)

export default Button

 

Use:

        <Button p="10 20" fullWidth variant="primary">
          Click Me
        </Button>

 

posted @ 2020-08-23 03:02  Zhentiw  阅读(354)  评论(0编辑  收藏  举报