mcpField
B
bootstrap-component

bootstrap-component

github.com/twbsデザイン・UI175.0k355 回インストール今日更新
リポジトリ

bootstrap-component について

JavaScript の動作を除く Bootstrap 6 のコンポーネント CSS とマークアップを作成するスキルです。Sass トークン、基本クラスと修飾クラス、テーマ対応、アクセシビリティ、文書化、検証を案内します。

主な機能

  1. 01上書き可能な Sass トークンマップの定義
  2. 02基本クラスと修飾クラスの作成
  3. 03テーマトークンとフォールバックの利用
  4. 04アクセシブルで RTL 対応のマークアップ
  5. 05コンポーネントの登録と文書化

活用シーン

  1. 01Bootstrap 6 へのコンポーネント追加
  2. 02コンポーネントのバリアントとサイズ作成
  3. 03テーマカラーへのコンポーネント対応
  4. 04Bootstrap 上でのカスタムコンポーネント開発

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/twbs/bootstrap --skill bootstrap-component

インストール後、Claude Code で/bootstrap-componentを入力して読み込まれたか確認します。

詳細

Bootstrap 6 コンポーネント CSS

コンポーネントのスタイルとマークアップ、つまり JavaScript 以外の部分を作成します。Bootstrap 6 のコンポーネントは、CSS カスタムプロパティの Sass マップ(トークンマップ)、それらのトークンを出力する基本クラス、およびトークンを上書きする修飾クラスで構成されます。

インタラクティブな動作については、bootstrap-component-js スキルを参照してください。パレット、テーマカラー、カラーモードについては、bootstrap-color-system スキルを参照してください。

ワークフロー

  • ステップ 1:コンポーネントを計画する
  • ステップ 2:パーシャルとトークンマップを作成する
  • ステップ 3:基本クラスを記述する
  • ステップ 4:修飾子、バリエーション、サイズを追加する
  • ステップ 5:テーマカラーを連携する
  • ステップ 6:マークアップとアクセシビリティ
  • ステップ 7:パーシャルを登録する
  • ステップ 8:コンポーネントをドキュメント化する
  • ステップ 9:検証する

ステップ 1:コンポーネントを計画する

  1. 単数形の kebab-case 名を選びます。この名前を基にすべてが決まります。パーシャルは scss/_<name>.scss、基本クラスは .<name>、トークンのプレフィックスは --<name>-*、マップは $<name>-tokens です。
  2. CSS を記述する前に、コンポーネントに必要なものを決めます。
    • トークンのみ — 1 つの外観を CSS 変数でカスタマイズします。scss/_alert.scss を参考にしてください。
    • バリエーション — .badge-subtle のような、コンテキストに応じた色のスタイルです。scss/_badge.scss を参考にしてください。
    • バリエーションとサイズ — scss/buttons/_button.scss を参考にしてください。
  3. 既存のコンポーネントで要件を満たせないか確認します。よく似たコンポーネントを追加するより、修飾子で既存のものを拡張するほうが望ましいです。

dist/、js/dist/、_site/ 内の生成物は編集しないでください。ソースは scss/ と js/src/ にあります。


ステップ 2:パーシャルとトークンマップを作成する

scss/_<name>.scss を作成します。まず空のマップを宣言し、その後 defaults() で値を設定します。

@use "config" as *;
@use "functions" as *;
@use "mixins/border-radius" as *;
@use "mixins/tokens" as *;

$widget-tokens: () !default;

// scss-docs-start widget-tokens
// stylelint-disable-next-line scss/dollar-variable-default
$widget-tokens: defaults(
  (
    --widget-gap: var(--spacer-2),
    --widget-padding-x: var(--spacer-4),
    --widget-padding-y: var(--spacer-2),
    --widget-color: var(--theme-fg, inherit),
    --widget-bg: var(--theme-bg-subtle, var(--bg-1)),
    --widget-border-color: var(--theme-border, var(--border-color)),
    --widget-border-radius: var(--radius-5),
  ),
  $widget-tokens
);
// scss-docs-end widget-tokens

ここで重要なルールは次のとおりです。

  • $widget-tokens: () !default; の行によって、マップを上書きできるようになります。@use "bootstrap/scss/bootstrap" with ($widget-tokens: (…)) で値を設定し、defaults() がその上書き値をデフォルト値にマージします。キーに null を渡すと、そのトークンが完全に削除されます。
  • 2 つ目の代入には、意図的に !default なしで再代入するため、stylelint-disable-next-line scss/dollar-variable-default コメントが必要です。
  • トークン名にはコンポーネントの名前空間を付け、プレフィックスなしで記述します。Bootstrap の dist および CDN の CSS では、PostCSS が --bs- プレフィックス(--bs-widget-bg)を付けます。ソースを自分でコンパイルする場合は、プレフィックスなしのままです。
  • ハードコードした長さではなく、var(--spacer-3)、var(--radius-5)、var(--border-width)、var(--font-weight-semibold) などの既存のグローバルトークンを使って値を作成し、コンポーネントがフレームワーク全体に合わせて拡縮するようにします。
  • scss-docs-start / scss-docs-end マーカーは必須です。ドキュメントページでは <ScssDocs> を使ってマップを表示するため、マーカーがないとビルド時にエラーになります。

ステップ 3:基本クラスを記述する

宣言はカスケードレイヤー内に記述し、トークンマップをルートセレクターに出力します。

@layer components {
  .widget {
    @include tokens($widget-tokens);

    display: flex;
    gap: var(--widget-gap);
    align-items: center;
    padding: var(--widget-padding-y) var(--widget-padding-x);
    color: var(--widget-color);
    background-color: var(--widget-bg);
    border: var(--border-width) solid var(--widget-border-color);
    @include border-radius(var(--widget-border-radius));
  }
}
  • 適切なレイヤーを選びます。コンポーネントには @layer components、フォームコントロールには @layer forms、ヘルパーには @layer helpers を使います。順序は scss/_root.scss で一度だけ宣言されています。colors, config, root, reboot, layout, content, forms, components, custom, helpers, utilities。
  • まず @include tokens($widget-tokens) を記述し、次に宣言、最後にネストしたルールを記述します。宣言では Sass マップを直接参照せず、var(--widget-*) を読み込みます。
  • 生のプロパティの代わりに @include border-radius() と @include transition() を使います。これらのミックスインは $enable-rounded、$enable-transitions、prefers-reduced-motion に対応しており、生のプロパティは stylelint によって禁止されています。
  • 論理プロパティ(padding-inline-start、margin-block-end、inset-inline-start)を使い、上書きなしで RTL に対応できるようにします。
  • lighten() / darken() は使わず、color-mix()、相対 oklch()、または light-dark() を使います。border: none / outline: none は使わず、0 を使います。

ステップ 4:モディファイア、バリアント、サイズを追加する

モディファイアはトークンだけを上書きし、ベースの宣言を繰り返さないようにします。

.widget-lg {
  --widget-padding-x: var(--spacer-6);
  --widget-padding-y: var(--spacer-3);
  --widget-border-radius: var(--radius-7);
}

コンポーネントに複数のコンテキスト別スタイルがある場合は、値にテーマのサブキーを使う、上書き可能なマップから適用し、ループ処理します。これは scss/_badge.scss のパターンです。

// scss-docs-start widget-variants
$widget-variants: () !default;
$widget-variants: defaults(
  (
    "subtle": (
      "color": "fg",
      "bg": "bg-subtle",
      "border-color": "transparent"
    ),
    "outline": (
      "color": "fg",
      "bg": "transparent",
      "border-color": "border"
    )
  ),
  $widget-variants
);
// scss-docs-end widget-variants

@layer components {
  // scss-docs-start widget-variant-loop
  @each $variant, $properties in $widget-variants {
    .widget-#{$variant} {
      @each $property, $value in $properties {
        @if $value == "transparent" {
          --widget-#{$property}: transparent;
        } @else {
          --widget-#{$property}: var(--theme-#{$value});
        }
      }
    }
  }
  // scss-docs-end widget-variant-loop
}

色のリテラル値ではなくテーマのサブキーにマッピングすることで、色ごとにバリアントを大量に作ることなく、.widget-outline.theme-success が機能します。

サイズにはボタンのパターンを使います。リストに defaults() を適用し、ループ処理して、コンポーネントのトークンを共有の --btn-input-<size>-* スケールに再割り当てするクラスを生成します。

$widget-sizes: () !default;
$widget-sizes: defaults(
  ("sm", "lg"),
  $widget-sizes
);

defaults() はリストをマップに変換するため、プロジェクト側で $widget-sizes: ("sm": null) を指定してサイズを削除したり、独自のサイズを追加したりできます。


ステップ 5:テーマカラーを接続する

テーマクラス(.theme-primary、.theme-danger など)は $theme-colors から生成され、決まった一連の変数を設定します:--theme-base、--theme-fg、--theme-fg-emphasis、--theme-bg、--theme-bg-subtle、--theme-bg-muted、--theme-border、--theme-focus-ring、--theme-contrast。

ニュートラルなフォールバックを指定してこれらの変数を読み取るだけで、コンポーネントはテーマに対応できます。そのため、ステップ 2 のデフォルト値は次のようになります。

--widget-color: var(--theme-fg, inherit),
--widget-bg: var(--theme-bg-subtle, var(--bg-1)),
--widget-border-color: var(--theme-border, var(--border-color)),

テーマを指定していないマークアップではフォールバックが使われます。テーマクラスを追加すると、追加の CSS なしでコンポーネントの色が変わります。

<div class="widget theme-danger">…</div>

ネストされたサブツリーに .theme-reset を使うと、継承された --theme-* トークンを解除し、フォールバックに戻せます。

コンポーネントのトークンで var(--red-500) や特定のテーマカラーをハードコードしないでください。テーマカラー自体の追加や上書きについては、bootstrap-color-system スキルで扱います。


ステップ 6:マークアップとアクセシビリティ

  • セマンティックな要素から始めます。マークアップだけでは意味を伝えられない場合に限り、ARIA を追加します。たとえば、ライブメッセージには role="alert"、開閉トリガーには aria-expanded を指定します。
  • インタラクティブな要素にはキーボードでアクセスでき、フォーカスリングが視認できるようにします。.focus-ring ヘルパーは :focus-visible に対して outline: var(--focus-ring-width) solid var(--theme-focus-ring, var(--focus-ring-color)) を適用します。テーマに対応したコンポーネントには、適切な色が自動的に継承されます。
  • アイコンのみのコントロールには、.visually-hidden のテキストまたは aria-label でアクセシブルな名前を付けます。
  • 色だけで状態を示さないでください。テキスト、アイコン、または ARIA 属性を併用します。
  • マークアップは RTL に対応できるようにします。CSS では論理プロパティを使い、DOM の順序で左右を前提にしないでください。

ステップ 7:パーシャルを登録する

既存の順序を維持しながら、components ブロック内で scss/bootstrap.scss からパーシャルをフォワードします。

@forward "widget";

サブディレクトリ(scss/buttons/、scss/forms/、scss/helpers/)にあるコンポーネントは、そのディレクトリの index.scss バレルからフォワードし、さらにそのバレルを scss/bootstrap.scss からフォワードします。その場合、新しいファイルは bootstrap.scss ではなくバレルに追加します。


ステップ 8:コンポーネントをドキュメント化する

  1. site/src/content/docs/components/<name>.mdx を追加します。

    ---
    title: Widget
    description: Documentation and examples for Bootstrap’s widget component.
    toc: true
    css_layer: components
    ---
    

    コンポーネントに JavaScript プラグインが含まれる場合は、js: optional(または js: required)を追加します。

  2. Components セクションの下に、site/data/sidebar.yml の項目を追加します。サイドバーはナビゲーション、ページの順序、llms.txt への収録を制御するため、項目がないページは実質的に表示されません。

    - title: Widget
      meta:
        - added: 6.0.0
    
  3. ライブデモには <Example> を使って使用方法を示し、### Variables セクションの下にトークンマップを表示します。

    <CSSVariables component="Widgets" className="widget" />
    
    <ScssDocs name="widget-tokens" file="scss/_widget.scss" />
    
  4. 内部リンクには、バージョンをハードコードしたパスではなく [[docsref:/components/widget/]] を使います。


ステップ 9:検証

  1. npm run css-lint — 使用が許可されていないプロパティ、宣言の順序の誤り、論理プロパティの不足を検出します。
  2. npm run css — コンパイル、プレフィックスの付与、最小化を行います。トークンが --bs- プレフィックス付きで dist/css/bootstrap.css に出力されることを確認します。
  3. npm run docs-build — docsref のリンク切れ、サイドバー項目の不足、scss-docs マーカーの不足があると失敗します。
  4. ブラウザーでコンポーネントを確認します。テーマクラスの有無、両方のカラーモード、<html> の dir="rtl"(v6 には RTL 専用スタイルシートはありません。論理プロパティが処理します)、アニメーションする場合は動きを抑える設定を有効にした状態で確認してください。

独自のプロジェクトで使う

Bootstrap をベースにした独自のコンポーネントにも、同じパターンを使用できます。custom.scss で必要な要素を @use し、ステップ 2〜6 をそのまま実行します。

@use "bootstrap/scss/config" as *;
@use "bootstrap/scss/mixins/tokens" as *;
@use "bootstrap/scss/bootstrap";

$widget-tokens: () !default;
$widget-tokens: defaults(
  (
    --widget-bg: var(--theme-bg-subtle, var(--bg-1)),
  ),
  $widget-tokens
);

@layer custom {
  .widget {
    @include tokens($widget-tokens);
    background-color: var(--widget-bg);
  }
}

components の後、helpers と utilities の前に配置される custom レイヤーを使用します。これにより、コンポーネントのデフォルトよりも独自のスタイルが優先されつつ、ユーティリティは独自のスタイルを上書きできます。既存の Bootstrap コンポーネントの設定を調整する場合、これらは必要ありません。実行時に CSS 変数を上書きするか、コンパイル時に with () を使って $*-tokens マップを渡してください。

コメント