styled-components로 조건부mixin을 진행하는 방법

개시하다


스타일드-components를 사용하여 조건부 렌더링을 할 때 다음과 같은 항목별 상황에 따라 구분된 예를 자주 볼 수 있다
기본적으로 이 정도면 문제없지만 장소별 종류가 늘어나면 관리가 번거로워진다.
이 경우 상황에 따라 클라스처럼 스타일링을 정리하는 것이 자연스럽다.
그래서 여러 항목을 단숨에 클라스가 있는지 없는지 몰라서 조사를 해봤어요.
const Wrapper = styled.div.attrs((props) => ({
  ...props,
}))`
background: ${(props) => (props.hoge ? '#fff' : '#000')};
`

하고 싶은 일


우리는 다음과 같이 프로포즈의 조건이 하나만 있으면 조형에 큰 변화가 있을 것이라고 생각한다.
목표는 위와 아래에서 각각 css를 관리하는 것이다.

우선 기본 상태 준비


우선,props.type이 지정한 애니메이션 상태가 없습니다.
import React, { VFC } from "react";
import styled from "styled-components";

export type ButtonProps = {
  className?: string;
  type?: "bgleft" | "bgright";
};

const Button: VFC<ButtonProps> = ({ className, type }: ButtonProps) => {
  return (
    <WrapperButton className={className} type={type}>
      <span>ボタン</span>
    </WrapperButton>
  );
};

const WrapperButton = styled.a.attrs((props) => ({ ...props }))`
  /* default */
  position: relative;
  overflow: hidden;

  text-decoration: none;
  display: inline-block;

  border: 1px solid #555;
  padding: 10px 30px;
  text-align: center;
  outline: none;
  transition: ease 0.2s;

  span {
    position: relative;
    z-index: 3;
    color: #333;
  }
  :hover {
    span {
      color: #fff;
    }
  }
`;

export default Button;

MixIn의 정의


그런 다음 MixIn에서 좌우 동작에 대한 애니메이션을 정의합니다.
우선 스타일드-componenst에서 css를 가져옵니다.
import React, { VFC } from "react";
import styled, { css } from "styled-components"; //ここ
그런 다음 MixIn을 정의합니다.
각각 좌우 동작 부분의 css입니다.
const MixInBgLeft = css`
  &:before {
    content: "";
    position: absolute;
    top: 0;
    left: 0;
    z-index: 2;
    background-color: #333;
    width: 100%;
    height: 100%;
    transition: transform 0.6s cubic-bezier(0.8, 0, 0.2, 1) 0s;
    transform: scale(0, 1);
    transform-origin: right top;
  }

  &:hover:before {
    transform-origin: left top;
    transform: scale(1, 1);
  }
`;

const MixInBgRight = css`
  &:before {
    content: "";
    position: absolute;
    top: 0;
    left: 0;
    z-index: 2;
    background-color: #333;
    width: 100%;
    height: 100%;
    transition: transform 0.6s cubic-bezier(0.8, 0, 0.2, 1) 0s;
    transform: scale(0, 1);
    transform-origin: left top;
  }

  &:hover:before {
    transform-origin: right top;
    transform: scale(1, 1);
  }
`;

조건부 렌더링


마지막.를 참고하십시오.
const WrapperButton = styled.a.attrs((props) => ({ ...props }))`
   //....省略

  /* typeにbgleftを選択した場合 */
  ${(props) => props.type === "bgleft" && MixInBgLeft}

  /* typeにbgrightを選択した場合 */
  ${(props) => props.type === "bgright" && MixInBgRight}
`;


이 button을 사용하는 쪽은 다음과 같습니다.
import Button from '***'


<Button type="bgleft" />
// or
<Button type="bgright" />

최후


이번 예에서 최초로 소개한 항목별 상황도 괜찮다.증가하는 상황을 감안하면 이런 실시 방식도 괜찮을 것이다.
더 좋은 방법이 있다면 꼭 나눠주세요.
마지막으로 모든 집합 코드를 붙여넣습니다.
import React, { VFC } from "react";
import styled, { css } from "styled-components";

export type ButtonProps = {
  className?: string;
  type?: "bgleft" | "bgright";
};

const Button: VFC<ButtonProps> = ({ className, type }: ButtonProps) => {
  return (
    <WrapperButton className={className} type={type}>
      <span>ボタン</span>
    </WrapperButton>
  );
};

const MixInBgLeft = css`
  &:before {
    content: "";
    position: absolute;
    top: 0;
    left: 0;
    z-index: 2;
    background-color: #333;
    width: 100%;
    height: 100%;
    transition: transform 0.6s cubic-bezier(0.8, 0, 0.2, 1) 0s;
    transform: scale(0, 1);
    transform-origin: right top;
  }

  &:hover:before {
    transform-origin: left top;
    transform: scale(1, 1);
  }
`;

const MixInBgRight = css`
  &:before {
    content: "";
    position: absolute;
    top: 0;
    left: 0;
    z-index: 2;
    background-color: #333;
    width: 100%;
    height: 100%;
    transition: transform 0.6s cubic-bezier(0.8, 0, 0.2, 1) 0s;
    transform: scale(0, 1);
    transform-origin: left top;
  }

  &:hover:before {
    transform-origin: right top;
    transform: scale(1, 1);
  }
`;

const WrapperButton = styled.a.attrs((props) => ({ ...props }))`
  /* default */
  position: relative;
  overflow: hidden;

  text-decoration: none;
  display: inline-block;

  border: 1px solid #555;
  padding: 10px 30px;
  text-align: center;
  outline: none;
  transition: ease 0.2s;

  span {
    position: relative;
    z-index: 3;
    color: #333;
  }
  :hover {
    span {
      color: #fff;
    }
  }

  /* typeにbgleftを選択した場合 */
  ${(props) => props.type === "bgleft" && MixInBgLeft}

  /* typeにbgrightを選択した場合 */
  ${(props) => props.type === "bgright" && MixInBgRight}
`;

export default Button;

좋은 웹페이지 즐겨찾기