実際の現場で使えるstyled-componentsのデザインパターンを紹介します。
なお、styled-componentsのみで完結するパターンについて記述しており、他のライブラリと組み合わせるようなパターンについては紹介しません。
随時更新・追加していきます。

:nail_care: 基本パターン

styled-componentsは、reactのコンポーネントに与えられたpropsを参照し、propsに応じてstyleを出し分けることが可能です。

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

  font-size: 1em;
  margin: 1em;
  padding: 0.25em 1em;
  border: 2px solid palevioletred;
  border-radius: 3px;
`

公式サイトでも紹介されている基本的なやりかたですね。

でも実際のプロダクトでは、色々なUIパターンや例外が出てきたりとこんな簡単にはいきません。この記事では、styled-componentsをプロダクションコードで何度か使ってきた経験から、実際のUI実装で使えるデザインパターン的なものを紹介します。

:nail_care: propsによって多くのプロパティが変わる時

primaryかどうかでbackground,color,padding…といくつものプロパティが変わるような場合です。
css関数を使うことで複数のプロパティが変わるパターンを楽に書けます。
※ただし、あまりに多くのプロパティが変わる場合は別コンポーネントとみなして分けることも考えましょう。

const Button = styled.button`
  font-size: 1em;
  margin: 1em;
  border: 2px solid palevioletred;
  border-radius: 3px;

  ${props => props.primary ? css`
    background: 'palevioletred';
    color: 'white';
    padding: 0.5em 2em;
  ` : css`
    background: 'white';
    color: 'palevioletred';
    padding: 0.25em 1em;
  `}
`

:nail_care: 例外パターンに対応する拡張

うまい具合にデザインシステムができてきたと思ったら、突然変異のような例外コンポーネントが出てくるときってありますよね。
そういうときは、例外に元のコンポーネントでは対応せず、使う場所でstyled.extendで拡張しましょう。

import Button from '../atoms/Button'

const ExtendedButton = Button.extend`
  background: 'blue';
  padding : 3em;
  border-radius: 4px;
`

// StyledComponentクラスでない場合
const ExtendedButton = styled(Button)`
  background: 'blue';
  padding : 3em;
  border-radius: 4px;
`

なお、extendはStyledComponentクラスのインスタンスに対してしか使えないので、functionalコンポーネント等の場合はstyld(Button)とすることで同様の拡張ができます。

:nail_care: バリエーションが多い時

タグのようなコンポーネントは5色7色とバリエーションが多くなることがあると思います。
そのような場合、幾つかの解決方法があります。

functionを作って切り出す

propsを受け取ってバリエーションを出し分ける関数を作る方法です。

const Tag = styled.span`
  font-size: 1em;
  border: 1px solid #ddd;

  ${props => getTagColor(props)}
`

const getTagColor = props => {
  if (props.caseA) {
    return `
      color: red;
    `
  } else if (props.caseB) {
    return `
      color: blue;
    `
  } else if (props.caseC) {
    return `
      color: yellow;
    `
  }
}

// usage
<Tag caseA/>
<Tag caseB/>
<Tag caseC/>

カラーパレットをオブジェクトとして定義する

propsに応じて影響するプロパティが1つに定まる場合、propsに対応するvalueを定義するオブジェクトをつくることでエレガントに書くことができます。

const Tag = styled.span`
  font-size: 1em;
  border: 1px solid #ddd;
    color: ${colors[props.type]};
`

const colors = {
  caseA: 'red',
  caseB: 'blue',
  caseC: 'yellow'
}

// usage
<Tag type='caseA'>
<Tag type='caseB'>
<Tag type='caseC'>

:nail_care: 共通するスタイルをmixinで定義する

sassなどのmixinと同じようなことを css関数を使ってできます
ちなみに、styled-componentsチームでメンテナンスしているpolishedというライブラリはmixinそのものです。

// 赤い下線を引くmixin
const underLine = styled.css`
  background: linear-gradient(transparent 50%, red 50%);
`

// usage
const Text = styled.p`
  font-size: 12px

  ${underLine()}
`