フロントエンドにstyled-systemを導入した話 - YOUTRUST Tech Blog

フロントエンドにstyled-systemを導入した話

はじめに

こんにちは、YOUTRUSTでWebエンジニアをしている石井です。

入社直後に一回目のTech Blogを書いたのですが、あっという間に時間は過ぎ、来月で入社してから半年になります。

一応過去記事のリンクを張っておくので興味のある方は覗いてみてください!

tech.youtrust.co.jp

今回は、今年の夏頃チームで取り組んできたユーザー詳細ページのリニューアルに関連した話をします。

リニューアルの全体に関しては、チームメンバーのめろたんさんがこちらのブログを書いてくださっているので、よかったら参照ください。

tech.youtrust.co.jp

実施したリニューアルプロジェクトでは、ユーザー詳細ページの改修というプロダクト側の開発だけでなく、デザイナーとエンジニアが協業してDoveというデザインシステムを構築しています。そしてリニューアルプロジェクト自体が終了した後でもDoveは継続的に開発、運用をしています。

基本的に新規のフロントエンドの開発では、Doveで定義されているコンポーネントを利用して開発を進める体制になっています。

今回は、そのDoveに styled-system というライブラリを導入した話について述べようと思います。

styled-system とは

styled-system.com

styled-system とは、ReactコンポーネントにスタイルPropsを追加するユーティリティ関数のコレクションを提供しているライブラリになります。

styled-systemはユーティリティPropsを採用しており、Tailwind CSSが提唱しているユーティリティファーストに通じるものがあります、

違う点といえば、Tailwind CSS はユーティリティクラスを提供するのに対し、styled-system はユーティリティPropsというPropsとしてスタイリングを指定できる機構を使っている点です。

同じくユーティリティPropsを使用している代表的なライブラリにChakra UIがありますが、 styled-system との違いとしては、Chakra UIはコンポーネントカタログのような一定UIの情報をもつコンポーネントを提供しているのに対し、styled-systemではユーティリティPropsの機構とその周辺拡張機構のみを提供してくれます。 そのため emotionstyled-components などのCSS-in-JSライブラリと組み合わせて使うことができるのに加えて既存のコンポーネントの拡張も容易に実現できます。

YOUTRUSTではDoveというデザインシステムを構築し、将来的には外部公開も視野に入れつつ開発を進めています。

もともとDoveはユーティリティPropsの思想を一定受け継ぎ設計されており、同じ思想のライブラリを導入しやすいという背景があるのに加えて、今も大部分で利用している mui をリプレイスするという目的もあり、現状カスタムスタイル適用に makeStyles を使用している箇所を少しづつユーティリティPropsで完結できるようにするため styled-system を導入しました。

どう使うのか?

styled-system はグローバルテーマに定義されているユーティリティ関数をimportすることで使用することができます。 例えば、自前で作った Box というコンポーネントにスタイルを設定できるようにするためには、以下のコードになります。

今回は styled-components と一緒に使う想定で記述をします。

import styled from 'styled-components';
import { color } from 'styled-system';

export const Box = styled('div')(
  {
    width: '200px',
    height: '200px',
  },
  color
)

colorという中に組まれているユーティリティ関数を使用することで、以下のユーティリティPropsを使うことができるようになります。

<Box color='blue' />
<Box bg='blue' />
<Box backgroundColor='blue' />

グローバルテーマに定義されているユーティリティ関数の一覧は以下のリンクから見れます。

https://styled-system.com/api/

ここまでシンプルに導入できる理由としては、以下のコードのようなスタイルオブジェクトを返却するというシンプルな実装によるものが大きいです。

import styled from 'styled-components';
 
 const getColor = props => ({
   color: props.color,
 })
 
 const Box = styled.div`
   ${getColor}
 `

また、グローバルテーマで定義されていないプロパティに対するユーティリティPropsを提供したい場合にカスタムPropsを作る低レベルの関数が用意されていたり、variantを定義することができる関数も存在します。

そのため、すべてのCSSプロパティをユーティリティPropsで表現できるのと、テーマで制約を設けることで一貫したスタイルを適用させることができる土台を作ることができたり、Figmaで構築されているデザインシステムと同じvariantの定義をコンポーネントに対して使用できると言ったメリットがあります。

// variantの例
const Button = styled('button')(
  {
    width: '240px',
    height: '80px',
    appearance: 'none',
    fontFamily: 'inherit',
  },
  variant({
    variants: {
      primary: {
        color: 'white',
        bg: 'black',
      },
      secondary: {
        color: 'white',
        bg: 'blue',
      },
    },
  }),
);

<Button variant="primary">PrimaryButton</Button>
<Button variant="secondary">SecondaryButton</Button>

導入後の効果と課題

実際に導入していくつかの成果とメリットを感じることができました

  • importするグローバルテーマによってコンポーネントごとに適用させるべきスタイルとそうでないスタイルを制限するためのルールを設けることができた。
  • classNameなどの命名のブレの削減と同じ命名で違うスタイルが定義されているオブジェクトを削減するための土台作りができた。
  • Doveで使用するコンポーネントは今後ユーティリティPropsでのスタイル拡張に統一するための土台作りができた。
  • makeStylesを使用してカスタムスタイルを適用させている箇所を削減できた。

逆に現在も残っている課題は以下です。

  • まだすべてのDoveのコンポーネントに導入できているわけではないこと。
  • まだまだ多くのコンポーネントmui ベースのものになっていること。
  • まだグローバルテーマなどの一部機能しか使えていないので、今後フロントエンドを含むデザインシステムを構築する場合、どの程度 styled-system を活用する方針でいくのか、またいかないのかは議論の余地があること

まとめ

今回は、 Doveにおける styled-system 導入について述べました。

YOUTRUSTは一緒に働いてくれるメンバーを絶賛募集しています。 Web/モバイル開発に興味がある方は一度お話しできればと思っています。まずはカジュアル面談からでもご応募いただけると嬉しいです!

herp.careers