classNameをpropsとして受け取るかどうか
LoginButtonがclassNameを受け取るというのは「どんなスタイルが来ても対応します!」という宣言であり、非常に大言壮語です。上の例のcolorのように、自分で責任を持てる範囲で拡張可能性を持たせるべきであるというのが筆者の考えです
↑にするとcolor、size.....等propsが増えるんでは?に対する解決策
これに対する根本的な解決策はデザインシステムを整備することです。デザインのパターンを現実的にメンテナンス可能な形に抑えて制御することにより、その実装にかかる責任も自ずと制御されるでしょう。
厳密なことを言えば、classNameを渡さなくても、CSSには子要素セレクタ(>)などもあるため親コンポーネントから子コンポーネント(が描画するDOM要素)にスタイルを注入することは可能です。これも明らかに子コンポーネントの内部構造に依存しているため避けるべきですが、子コンポーネントから取れる防御策は多くなく、人間の良心で防がなければならないのが残念なところです。
この前提(親要素から子要素にスタイルを注入できちゃう)はあるものの、
基本的にはclassNameに頼らずに明示的にprops(size, colorなど)として分けたい
親要素から子要素の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>
)
classNameをpropsとして持っていなくても、親から子要素のCSSを指定すると簡単に拡張されてしまう
厳密なことを言えば、classNameを渡さなくても、CSSには子要素セレクタ(>)などもあるため親コンポーネントから子コンポーネント(が描画するDOM要素)にスタイルを注入することは可能です。これも明らかに子コンポーネントの内部構造に依存しているため避けるべきですが、子コンポーネントから取れる防御策は多くなく、人間の良心で防がなければならないのが残念なところです。
のことを言ってる感じかな
ほんの少しのスタイル多様性の受け入れに「1・2」は釣り合いが取れているでしょうか? 「ここだけちょっと」が複数回発生するのであれば、コンポーネントの I/F として備えて然るべきですが、CSS だけで簡単に解決できる要件の場合、バンドルサイズに優しくないのは明らかです。
特別な理由があって、いつものあのボタン、ここだけちょっと小さくしたい」 という要望がデザイナーさんからあがってくることがあります
起こりそうなことに対して、classNameを受け取るようにしとけばCSSの修正だけですむよ