💅

styled-componentsの理解

2023/06/30に公開

styled-componentsを採用することになりました、勉強していきます

styled-components

Reactアプリケーションで使用される、コンポーネントベースのCSS-in-JSライブラリ

導入

本体
https://styled-components.com/docs/basics#installation

TypeScriptで使いたいので、型定義ファイルもインストール
https://www.npmjs.com/package/@types/styled-components

$ yarn add styled-components
$ yarn add --dev @types/styled-components

使い方

import styled from 'styled-components';

// スタイルを書く
// StyledXXXにすることが一般的
const StyledButton = styled.button`
  padding: 4px 10px;
  color: #fff;
  background-color: blue;
  border-radius: 5px;

  &:disabled {
    background-color: gray;
  }
`;

// そのままexport可能
export default StyledButton;

組み合わせて使うことも可能

const StyledGroup = styled.div`
 border: 1px solid #cccccc;
 border-radius: 8px;
`;

// コンポーネントからpropsを受け取ることが可能
const StyledLabel = styled.label<{ $type: 'correct' | 'wrong' }>`
  background-color: ${(props) =>
    props.$type === 'correct' 
    ? '#d4edda' 
    : '#fff'};
`;

function Group({ isAnswer }: Props){
 return (
  <StyledGroup>
   <StyledLabel $type={ isAnswer ? "correct" : "wrong"}>
   {isAnswer ? '正解' : '不正解'}
   </StyledLabel>
  </StyledGroup>
 )
}

Theming

次にコンポーネントにテーマを用いてスタイルを適用していく
https://styled-components.com/docs/advanced#theming

Themingとは

<ThemeProvider>でラッパーすると、
それ自身の下にあるすべてのReactコンポーネントにテーマが提供され、すべての styled-componentsはテーマにアクセスすることができる

導入

ベースファイル

config/theme.tsを作る
(ファイルを作るかどうかや、ファイル名、ファイルの置き場所はプロジェクトによる)
ここにスタイルの定義を書く

export const theme = {
 pallet: {
   primary: {
     light: '#42a5f5',
     main: '#1976d2',
     dark: '#1565c0',
     contrastText: '#ffffff',
   },
   secondary: {
     light: '#ba68c8',
     main: '#9c27b0',
     dark: '#7b1fa2',
     contrastText: '#ffffff',
   }
 },
 offset: {
  gap: 8,
 }
}

型定義

styled-components用の型定義ファイルを作成

styled-components.d.ts
import 'styled-components';
import { theme } from '@/config/theme';

type Theme = typeof theme;

declare module 'styled-components' {
  // config/theme.ts で定義したもので DefaultTheme を上書きする
  export interface DefaultTheme extends Theme {}
}

これで型解決します!
(props.themeの補完や、静的型チェックが有効になる)

プロバイダーの設置

アプリケーションルートを <ThemeProvider>でラップする
themeプロパティに使用したいthemeを設定(ここではベースファイルを使用)

import { theme } from '@/config/theme';

export default function App({ Component, pageProps }: AppProps) {
  return (
    <ThemeProvider theme={theme}>
      <Component {...pageProps} />
    </ThemeProvider>
  );
}

あとはコンポーネント内で使いまわす

type ThemeType = 'primary' | 'secondary';

type StyledButtonProps = {
  readonly $theme: ThemeType;
};

const StyledButton = styled.button<StyledButtonProps>`
  &:disabled {
    background-color: ${(props) => props.theme.pallet.disabled.main};
  }
  
  /* こんな感じでも使える */
  background-color: ${(props) => props.theme.pallet[props.$theme].main};
`;
// 青いボタン
<Button $theme="primary">click me</Button>
// 紫のボタン
<Button $theme="secondary">click me</Button>

Discussion