14
9

More than 3 years have passed since last update.

[React & TS] styled-componentsで動的にスタイルを変更する

Posted at

やりたいこと

よくみるこれをReact & TypeScript とstyled-componentsで実装したい

animation.gif

作ったもの

今回はstyled-componentsに真偽値を渡しておき、値を変更する形としました。

styled-components本家にやり方が記載されています。

hamburgerIcon.tsx
import React from 'react'
import styled, { css } from 'styled-components'

const Hamburger = styled.div<{ isOpen: boolean }>`
  position: absolute;
  top: 16px;
  right: 30px;
  width: 22px;
  height: 18px;
  transition: all 0.4s;

  span {
    :nth-of-type(2) {
      top: 50%;
      left: 50%;
      -webkit-transform: translate3d(-50%, -50%, 0);
      transform: translate3d(-50%, -50%, 0);
    }
  }

  ${(props) =>
    props.isOpen
      ? css`
          span {
            :nth-of-type(1) {
              -webkit-transform: translateY(20px) rotate(-45deg) scale(0.8);
              transform: translateY(8px) rotate(-45deg) scale(0.8);
            }

            :nth-of-type(2) {
              opacity: 0;
            }

            :nth-of-type(3) {
              -webkit-transform: translateY(-20px) rotate(45deg) scale(0.8);
              transform: translateY(-7px) rotate(45deg) scale(0.8);
            }
          }
        `
      : ''}
`

const HamburgerLine = styled.span`
  position: absolute;
  width: 100%;
  height: 3px;
  background-color: #707070;
  transition: all 0.4s;

  &:nth-of-type(1) {
    top: 0;
  }
  &:nth-of-type(2) {
    top: 8px;
  }
  &:nth-of-type(3) {
    bottom: 0;
  }
`

type PropsType = {
  isOpen: boolean
  toggleIsOpen
}

export const MenuHamburger: React.FC<PropsType> = ({
  isOpen,
  toggleIsOpen,
}) => {
  return (
    <Hamburger isOpen={isOpen} onClick={toggleIsOpen}>
      <HamburgerLine />
      <HamburgerLine />
      <HamburgerLine />
    </Hamburger>
  )
}

特別にやったこと

本家を見ると以下の様に書かれています。

import React from 'react'
import styled, { css } from 'styled-components'

const Button = styled.button`
  color: ${(props) => (props.primary ? 'white' : 'palevioletred')};
`

export const MenuHamburger: React.FC<any> = () => {
  return <Button primary>Primary</Button>
}

しかしTypeScriptだと、型解決が出来ずにIDEなどに怒られてしまいます。
image.png

以下の通り、styleの生成時に型を設定してあげましょう。

import React from 'react'
import styled, { css } from 'styled-components'

const Button = styled.button<{ primary: boolean }>`
  color: ${(props) => (props.primary ? 'white' : 'palevioletred')};
`

export const MenuHamburger: React.FC<any> = () => {
  return <Button primary>Primary</Button>
}

数が多い場合は、typeにまとめてもよいですね!

import React from 'react'
import styled, { css } from 'styled-components'

type ButtonProps = {
  primary: boolean
}

const Button = styled.button<ButtonProps>`
  color: ${(props) => (props.primary ? 'white' : 'palevioletred')};
`

export const MenuHamburger: React.FC<any> = () => {
  return <Button primary>Primary</Button>
}
14
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
9