Closed11

classNameをpropsとして受け取るかどうか

nus3nus3
nus3nus3

LoginButtonがclassNameを受け取るというのは「どんなスタイルが来ても対応します!」という宣言であり、非常に大言壮語です。上の例のcolorのように、自分で責任を持てる範囲で拡張可能性を持たせるべきであるというのが筆者の考えです

↑にするとcolor、size.....等propsが増えるんでは?に対する解決策

これに対する根本的な解決策はデザインシステムを整備することです。デザインのパターンを現実的にメンテナンス可能な形に抑えて制御することにより、その実装にかかる責任も自ずと制御されるでしょう。

nus3nus3

厳密なことを言えば、classNameを渡さなくても、CSSには子要素セレクタ(>)などもあるため親コンポーネントから子コンポーネント(が描画するDOM要素)にスタイルを注入することは可能です。これも明らかに子コンポーネントの内部構造に依存しているため避けるべきですが、子コンポーネントから取れる防御策は多くなく、人間の良心で防がなければならないのが残念なところです。

この前提(親要素から子要素にスタイルを注入できちゃう)はあるものの、
基本的にはclassNameに頼らずに明示的にprops(size, colorなど)として分けたい

nus3nus3

親要素から子要素のmarginを操作したい時が結構あるんよなぁ。。

classNameを使う場合

export const Foo = () => (
  <div>
    <Button className="ml-1" />
    <Button className="ml-1" />
  </div>
)

classNameを使わない場合

flexやgrid使ってる場合の子要素全体に対してのmarginはgapで対応できる

export const Foo = () => (
  <div className="flex gap-1">
    <Button />
    <Button />
  </div>
)

子要素個別に対応したい場合
個別にdivやspanで囲む?

export const Foo = () => (
  <div>
    <div className="ml-1">
      <Button />
    </div>
    <Button />
  </div>
)
nus3nus3
nus3nus3

classNameをpropsとして持っていなくても、親から子要素のCSSを指定すると簡単に拡張されてしまう

厳密なことを言えば、classNameを渡さなくても、CSSには子要素セレクタ(>)などもあるため親コンポーネントから子コンポーネント(が描画するDOM要素)にスタイルを注入することは可能です。これも明らかに子コンポーネントの内部構造に依存しているため避けるべきですが、子コンポーネントから取れる防御策は多くなく、人間の良心で防がなければならないのが残念なところです。

のことを言ってる感じかな

nus3nus3

ほんの少しのスタイル多様性の受け入れに「1・2」は釣り合いが取れているでしょうか? 「ここだけちょっと」が複数回発生するのであれば、コンポーネントの I/F として備えて然るべきですが、CSS だけで簡単に解決できる要件の場合、バンドルサイズに優しくないのは明らかです。

特別な理由があって、いつものあのボタン、ここだけちょっと小さくしたい」 という要望がデザイナーさんからあがってくることがあります

起こりそうなことに対して、classNameを受け取るようにしとけばCSSの修正だけですむよ

nus3nus3

今回はclassNameをpropsとして受け取らない方針にしたい

  • チームメンバーの習熟度的にもclassNameを使わずpropsでコンポーネントのスタイルの変更が明示的になるようにしたい
  • 受け取るpropsはcolor, size?
  • marginは親要素で指定
    • 子要素に共通するものはgapなどで対応
    • 特定の子要素に個別にスタイルを当てたい場合はdivやspanでラップし、divやspanに親要素でスタイルを当てる
nus3nus3

classNameを使わずとも親要素からスタイルをいじれるのはルールとしてダメって感じにするしかないかなぁ
人間の良心で防がなければならないのが残念なところです

このスクラップは2021/03/02にクローズされました