🙆

マイベストのデザインシステムで使用しているレイアウトコンポーネントを紹介

2024/04/26に公開

はじめに

株式会社マイベストでフロントエンドエンジニアをしているyamadaです。
近年、企業やプロダクトチームでデザインシステムを導入する動きが加速しています。
弊社でもデザインシステムの構築に力を入れており、Material UIやChakra UIのようなUIライブラリを参考にしながら独自のデザインシステムの開発を進めています。
今回はその独自のデザインシステムの重要な構成要素であるレイアウトコンポーネントを紹介したいと思います。

レイアウトコンポーネントとは

弊社ではアプリケーションの構造やレイアウトを構築するのに使われるコンポーネントのことをレイアウトコンポーネントと呼んでいます。
主なレイアウトコンポーネントには以下のようなものがあります。

フレックスボックスコンポーネント

  • Flexboxのプロパティを使ってレイアウトを構築
  • 代表例: Material UIのBox・Stack、Chakra UIのFlex・Stack

グリッドコンポーネント

  • グリッドレイアウトを構築するためのコンポーネント
  • 代表例: Material UIのGrid、Bootstrap のrowとcol

コンテナコンポーネント

  • 他のコンポーネントを格納するための領域を提供
  • 代表例: Material UIのContainer

これらのコンポーネントを使うことで開発者はアプリケーションのレイアウトを迅速に作成し、さまざまな画面サイズやデバイスにわたって一貫したユーザーエクスペリエンスを確保できます。

マイベストのレイアウトコンポーネント

マイベストのデザインシステムは大きく分けてBase、Elements、Patternsの3つの要素で構成されています。

  • Base: コンポーネントを作る素材的な要素
  • Elements: 最小単位として存在できるコンポーネント
  • Patterns: 2つ以上のElementsで構成されたコンポーネント

この中でレイアウトコンポーネントはBaseとして位置付けておりBaseStackBaseBoxというコンポーネントを用意しております。
Baseには約10種類ほどのコンポーネントを用意していますがレイアウトに使用する主なコンポーネントはこの2つになります。

BaseStack

Flexboxレイアウトを構築するためのコンポーネントです。
Material UIやChakra UIのStackに近いものとなっており、主に子要素を垂直または水平に並べたい場合に使用します。
Material UIやChakra UIは複雑なレイアウトのためにStackより高機能なBoxやFlexコンポーネントも用意されていますが、マイベストでは下記の理由からBaseStackのみ用意しています。
(ここでは全てFlexboxレイアウトを構築するためのコンポーネントとして捉えてます)

  • 似たようなコンポーネントが複数あるとどちらを使ったら良いか悩む
  • 単純で直感的な使い方をできた方が良さそう
  • mybestのデザインパターンだとBaseStackのみでカバーできそう

BaseStackは下記のpropsを持ち、レスポンシブデザインに対応したプロパティ値を指定可能としています。また、gapやdividerColorの値はデザイントークンで定義された値のみを受け付けるようになっています。

  • gap
  • gapVertical
  • direction
  • alignItems
  • justifyContent
  • wrap
  • grow
  • shrink
  • noBasis
  • divider
  • dividerSize
  • dividerColor
  • as(HTML要素の変更)

使用例

// p12はデザイントークンで12pxとして定義されている値
<BaseStack gap="p12" alignItems="center">
  <div>Lorem, ipsum dolor.</div>
  <div>Lorem, ipsum dolor.</div>
  <div>Lorem, ipsum dolor.</div>
</BaseStack>
// レスポンシブでgapの値や配置の変更を可能
<BaseStack gap={{ sp: "p12", pc: "p24"}} alignItems={{ sp: "center", pc: "end"}}>
  <div>Lorem, ipsum dolor.</div>
  <div>Lorem, ipsum dolor.</div>
  <div>Lorem, ipsum dolor.</div>
</BaseStack>

表示

[余談]gapでの余白について

BaseStackでのgapの多用は階層が複雑になりコードの可読性が損なわれることが多々ありました。そのためgapを特定の用途に限定して使用しています。それ以外の場合はBaseBoxのmarginTop(この後に説明)を使用する事としています。

  • 3つ以上同じ余白で要素が並ぶ時
  • 2要素のうち、前者が非表示なケースがあり、それと余白も消える時

使用例

// 入れ子が多くなるとどこのgapなのか分かりにくくなる
<BaseStack gap="p12" direction="column">
  <BaseStack gap="p24" direction="column">
    <BaseStack gap="p36" direction="column">
      <div>Lorem, ipsum dolor.</div>
      <div>Lorem, ipsum dolor.</div>
    </BaseStack>
    <div>Lorem, ipsum dolor.</div>
    <div>Lorem, ipsum dolor.</div>
  </BaseStack>
  <div>Lorem, ipsum dolor.</div>
  <div>Lorem, ipsum dolor.</div>
</BaseStack>

表示

Material UIとChakra UIのStackには下記のようなpropsが用意されておりBaseStackも似たようなものだとお分かり頂けるかと思います。

Material UI

  • alignItems
  • direction
  • justifyContent
  • flexWrap
  • divider
  • component(HTML要素の変更)
  • spacing
  • sx(インラインでstyleを設定)
  • useFlexGap

https://mui.com/material-ui/react-stack/

Chakra UI

  • align
  • direction
  • justify
  • wrap
  • divider
  • isInline
  • shouldWrapChildren
  • spacing

https://v2.chakra-ui.com/docs/components/stack

この2つのライブラリでは余白のpropsをspacingとしていますがマイベストではgapとしています。これはデザイナーとの協議の結果、こちらの方が双方分かりやすいという事になりこの命名を採用しています。
また、BaseStackではgrow、shrink、noBasisというBooleanのpropsを用意して子要素にflex-grow(0か1)、flex-shirink(0か1)、flex-basis(0かauto)が当たるようにしています。

BaseBox

要素を格納する箱としての機能がメインのコンポーネントで背景色や境界線を設定することができます。レイアウト用途としては上方向のみ余白を取ることが許されています。

BaseBoxは下記のpropsを持ち、こちらもレスポンシブデザインに対応したプロパティ値を指定可能とし、paddingとmarginTopはデザイントークンで定義された値のみを受け付けるようになっています。

  • backgroundColor
  • borderColor
  • borderStyle
  • borderRadius
  • borderWidth
  • padding
  • paddingVertical
  • paddingHorizontal
  • paddingTop
  • paddingRight
  • paddingBottom
  • paddingLeft
  • marginTop
  • as(HTML要素の変更)

使用例

<BaseBox marginTop={{sp: "p12", pc: "p24"}} backgroundColor="background.primary.normal">
  <div>Lorem, ipsum dolor.</div>
</BaseBox>

表示

Material UIとChakra UIのBoxには下記のようなpropsが用意されており、多用途で柔軟性のあるコンポーネントとして作られてます。
一方、BaseBoxはこれらよりシンプルな設計のコンポーネントとしています。

Material UIとChakra UI(共通してるものを抜粋)

  • display
  • flexDirection
  • alignItems
  • justifyContent
  • width、height、maxWidth、maxHeight、minWidth、minHeight
  • margin、padding
  • backgroundColor
  • color
  • border
  • boxShadow
  • position
  • top、right、bottom、left
  • zIndex
  • ...

https://mui.com/material-ui/api/box/
https://v2.chakra-ui.com/docs/components/box

BaseStackとBaseBoxを使うと

今のところmybestではこの2つのコンポーネントで大抵のレイアウトは実現できています。

さいごに

簡単ではありましたが、マイベストの独自デザインシステムの重要な構成要素であるBaseStackとBaseBoxを紹介させて頂きました。
この2つのコンポーネントを組み合わせることで、ほとんどのレイアウトを容易に作成できるようになり、フロントエンドエンジニアやバックエンドエンジニアを問わず、誰もが素早く効果的なレイアウトを実装できるようになりました。

また、Material UIやChakra UIを参考にしつつも独自実装することでデザインへの制約の少なさとシンプルな実装であるが故のメンテナンス性の高さといったメリットを実感しています。

Discussion