Kumiki コンポーネント SCSS 再利用ルール

Kumiki の data-as コンポーネントを SCSS で書くときの三層再利用ルール。卒業(data-as→FLOCSS)に乗る、grep 可能なクラス名規律を保つための約束。

0. 原則

再利用は 3 層で構成する。各層は機能ではなく思想で役割が決まる。

実体役割厚み
第1層@mixinコンポーネントの外側で決まる条件を @content で内側に掛ける機構極薄
第2層%placeholderdata-as 語彙 1 件に対応する、自己完結したコンポーネント定義厚い(ここに実質を全部置く)
第3層[data-as="…"]第2層を claim する公開語彙極薄

第1層と第3層は外との境界であり、責務を盛ると複雑性が外へ漏れる。実質はすべて、変更が内部に閉じる第2層に置く。

1. 判定の基準(迷ったらこの一問)

その条件は、コンポーネントの「外側」で決まるか?

@content を取れることは第1層の必要条件にすぎない。十分条件は「外部条件への応答」であること。

2. & の規則(三層共通・最重要)

& には性質の異なる 2 種類があり、層ごとに扱いを変える。

層ごとの確定規則

3. 第1層 — @mixin(外部条件ラッパ)

書くもの

コンポーネントの外側の状態に応答する、@content ラッパのみ。

書かないもの

記法の制約

4. 第2層 — %placeholder(名前付きコンポーネント)

書くもの

data-as 語彙 1 件に対応する、コンポーネントの実体すべて。

書かないもの

記法の制約

5. 第3層 — [data-as="…"](公開語彙)

書くもの

対応する第2層を claim する @extend 一行のみ

[data-as="prose"] { @extend %kumiki-prose; }

書かないもの

記法の制約

6. 横断する記法の制約(集約)

  1. @extend@media の中に書かない。 コンポーネントは内部 MQ ごとルートで定義し、ルートからのみ claim する。
  2. & の三層規則(§2)。 第1層は User Action Pseudo-Classes(:hover/:active/:focus/:focus-visible/:focus-within)に限り許可、第2層・第3層は禁止。連結 &__/&-- は全層禁止。
  3. 第3層は @extend だけ。 第1層を直接 @include しない。
  4. 画面幅差は語彙化しない。 card-sp のような語彙を作らず、% 内部に @include sp で畳み込む。語彙化するのは意味として独立したバリアントだけ。
  5. % が固有宣言ゼロ = プロキシ化の警告灯。 レビュー/リンタの検出ポイント。

7. 正規パターン

// ── 第1層:外部条件ラッパのみ。──
// 環境ラッパ(& なし)
@mixin sp         { @media (max-width: 600px)        { @content; } }
@mixin tablet     { @media (max-width: 1024px)       { @content; } }
@mixin container($w) { @container (min-width: #{$w}) { @content; } }

// 相互作用ラッパ(& は User Action Pseudo-Classes に限り許可)
@mixin hover { @media (hover: hover) { &:hover { @content; } } }
@mixin focus { &:focus-visible { @content; } }

// grid($cols) / truncate / 単なる囲い はここに無い

// ── 第2層:実質を全部持つ。固有宣言は直書き。& は使わず完全修飾。──
%kumiki-prose {
  max-width: 65ch;
  font-size: 1.6rem;
  line-height: 1.8;
  overflow: hidden;                 // truncate 相当を切り出さず直書き
  text-overflow: ellipsis;
  white-space: nowrap;

  @include sp { font-size: 1.4rem; }     // viewport 応答(第1層経由)
  @include hover { opacity: 0.7; }       // 相互作用応答。& は hover mixin の内部にあり、ここには出ない
}

// 子要素は完全修飾の別 % として書く(&__title は使わない)
%kumiki-prose__lead {
  font-size: 1.8rem;
  font-weight: bold;
}

// ── 第3層:extend 一行のみ。──
[data-as="prose"]      { @extend %kumiki-prose; }
[data-as="prose-lead"] { @extend %kumiki-prose__lead; }

8. 境界事例の扱い

9. 一行サマリ

第1層は外部条件(環境+相互作用)を @content で掛けるラッパだけ& は User Action Pseudo-Classes に限り許可、固定塊・引数は不可。第2層は data-as 語彙に対応する % に実質を全部持ち、応答を内側へ畳み込み、固有宣言は重複を恐れず直書きし、& は使わず完全修飾で書く。第3層は @extend 一行だけ(ルート位置、宣言・@include@media& 不可)。連結 &__/&-- は全層禁止。両境界(第1・第3層)は薄く保ち、太らせるのは第2層に限る。