【问题标题】:Approach to creating variants with styled components使用样式化组件创建变体的方法
【发布时间】:2020-08-31 01:07:04
【问题描述】:

使用样式化组件创建变体的最佳方法是什么?这是我目前正在做的事情。

  const ButtonStyle = styled.button`
  padding:8px 20px;
  border:none;
  outline:none;
  font-weight:${props => props.theme.font.headerFontWeight};
  font-size:${props => props.theme.font.headerFontSize};
  display:block;
  &:hover{
    cursor:pointer;
  }
  ${({ variant }) =>
    variant == 'header' && css`
    background-color:${props => props.theme.colors.lightblue};
    color:${({ theme }) => theme.colors.white};
    &:active{
      background-color:${props => props.theme.colors.blue}
    }
    `
  }
  ${({ variant }) =>
    variant == 'white' && css`
    background-color:white;
    color:${({ theme }) => theme.colors.lightblue};
    &:active{
      color:${props => props.theme.colors.blue}
    }
    `
  }
`;

我不知道这是否是标准的做事方式。 我也一直在使用其他组件作为基础来创建其他组件,同时更改一些内容

例如

  const InnerDiv = styled(otherComponent)`
  position: unset;
  background-color: red;
  overflow-x: hidden;
  display: flex;
`;

哪种方法更好?有没有更好的选择?

【问题讨论】:

    标签: css reactjs styled-components


    【解决方案1】:

    这只是我的看法:

    我不认为我们可以做任何与你完全不同的事情。

    我认为另一种方法是创建一个选项对象来映射变体的可能性,如下所示:

    const variantOptions = {
      header: {
        backgroundColor: theme.colors.lightblue,
        color: theme.colors.white,
        active: theme.colors.blue,
      },
      white: {
        backgroundColor: "white",
        color: theme.colors.lightblue,
        active: theme.colors.blue,
      },
    };
    

    并像这样在你的样式组件中使用它:

    const ButtonStyle = styled.button`
      padding: 8px 20px;
      border: none;
      outline: none;
      font-weight: ${(props) => props.theme.font.headerFontWeight};
      font-size: ${(props) => props.theme.font.headerFontSize};
      display: block;
      &:hover {
        cursor: pointer;
      }
    
      ${({ variant }) =>
        variant &&
        variantOptions[variant] &&
        css`
           background-color: ${variantOptions[variant].backgroundColor};
           color: ${variantOptions[variant].color};
           &:active {
              color: ${variantOptions[variant].active};
           }
       `}
    `;
    

    所有这些按钮都可以使用:

    <ButtonStyle variant="*wrong*">Button</ButtonStyle>
    <ButtonStyle variant="header">Button</ButtonStyle>
    <ButtonStyle variant="white">Button</ButtonStyle>
    <ButtonStyle>Button</ButtonStyle>
    

    【讨论】:

      【解决方案2】:

      受之前解决方案的启发,我想分享一下我的想法:

      import styled, { css, DefaultTheme } from 'styled-components';
      
      const variantStyles = (theme: DefaultTheme, variant = 'primary') =>
        ({
          primary: css`
            color: ${theme.colors.light};
            background: ${theme.colors.primary};
            border: 1px solid ${theme.colors.primary};
          `,
        }[variant]);
      
      const Button = styled.button<{ variant: string }>`
        padding: 1rem;
        font-size: 0.875rem;
        transition: all 0.3s;
        cursor: pointer;
      
        ${({ theme, variant }) => variantStyles(theme, variant)}
      
        &:active {
          transform: translateY(1.5px);
        }
      `;
      
      export default Button;
      
      

      目前它只包含主要的和默认的,您可以通过向variantStyles 对象添加新对象来添加更多变体

      然后您可以通过将变体作为道具传递来使用它,或者通过不传递任何变体来保持默认值。

      import { Button } from './HeroSection.styles';
      
      <Button variant="primary">Start Learning</Button>
      

      【讨论】:

      • 太棒了,我喜欢这个解决方案
      【解决方案3】:

      在处理样式化组件变体时,我喜欢这样做以保持事物的组织性和可扩展性。

      如果变体存储在同一个文件中,我将使用继承属性:

      const DefaultButton = styled.button`
          color: ${(props) => props.theme.primary};
      `;
      
      const ButtonFlashy = styled(DefaultButton)`
          color: fuchsia;
      `;
      
      const ButtonDisabled = styled(DefaultButton)`
          color: ${(props) => props.theme.grey};
      `;
      

      如果我们谈论的是可重用组件,我会使用这种技术:

      import styled from 'styled-components';
      
      // Note that having a default class is important
      const StyledCTA = ({ className = 'default', children }) => {
          return <Wrapper className={className}>{children}</Wrapper>;
      };
      
      /*
       * Default Button styles
       */
      const Wrapper = styled.button`
          color: #000;
      `;
      
      /*
       * Custom Button Variant 1
       */
      export const StyledCTAFushia = styled(StyledCTA)`
          && {
              color: fuchsia;
          }
      `;
      
      /*
       * Custom Button Variant 2
       */
      export const StyledCTADisabled = styled(StyledCTA)`
          && {
              color: ${(props) => props.theme.colors.grey.light};
          }
      `;
      
      export default StyledCTA;
      

      用法:

      import StyledCTA, { StyledCTADisabled, StyledCTAFushia } from 'components/StyledCTA';
      
      const Page = () => {
          return (
              <>
                  <StyledCTA>Default CTA</StyledCTA>
                  <StyledCTADisabled>Disable CTA</StyledCTADisabled>
                  <StyledCTAFushia>Fuchsia CTA</StyledCTAFushia>
              </>
          )
      };
      

      在我创建的主题为 herethere 的博客文章中了解更多信息。

      【讨论】:

        【解决方案4】:

        有很多方法可以做到这一点。一种简单的方法是使用名为 Styled-components-modifiers 的包。文档简单明了。

        https://www.npmjs.com/package/styled-components-modifiers

        简单使用示例:

        import { applyStyleModifiers } from 'styled-components-modifiers';
        
        export const TEXT_MODIFIERS = {
          success: () => `
          color: #118D4E;
         `,
         warning: () => `
         color: #DBC72A;
         `,
        
         error: () => `
         color: #DB2A30;
         `,
        };
        
        export const Heading = styled.h2`
        color: #28293d;
        font-weight: 600;
        ${applyStyleModifiers(TEXT_MODIFIERS)};
        `;
        

        在组件中 - 导入 Heading 并使用修饰符道具选择变体。

         <Heading modifiers='success'>
            Hello Buddy!!
         </Heading>
        

        【讨论】:

          【解决方案5】:

          样式化组件通常与样式化系统一起使用,该系统支持变体和其他增强样式化组件的好功能。在下面的示例中,Button prop 变体自动映射到 variants 对象的键:

          const buttonVariant = ({ theme }) =>
            variant({
              variants: {
                header: {
                  backgroundColor: theme.colors.lightblue,
                  color: theme.colors.white,
                  active: theme.colors.blue,
                },
                white: {
                  backgroundColor: 'white',
                  color: theme.colors.lightblue,
                  active: theme.colors.blue,
                },
              },
            })
          
          const Button = styled.button`
            ${(props) => buttonVariant(props)}
          `
          

          样式系统变体:https://styled-system.com/variants

          【讨论】:

          猜你喜欢
          • 2020-12-24
          • 1970-01-01
          • 1970-01-01
          • 2021-10-11
          • 2021-10-09
          • 2019-11-17
          • 1970-01-01
          • 2020-09-26
          • 2020-09-22
          相关资源
          最近更新 更多