mcpField
B
bootstrap-component

bootstrap-component

github.com/twbs设计与 UI175.0k355 次安装今天更新
代码仓库

关于 bootstrap-component

用于编写 Bootstrap 6 组件 CSS 和标记的 Skill,不涵盖 JavaScript 行为。它指导开发者设置 Sass 令牌映射、基础类与修饰类,并处理主题、无障碍、文档和验证。

主要功能

  1. 01定义可覆盖的 Sass 令牌映射
  2. 02构建基础类与修饰类
  3. 03使用主题令牌和回退值
  4. 04编写无障碍且兼容 RTL 的标记
  5. 05注册并编写组件文档

适用场景

  1. 01为 Bootstrap 6 添加组件
  2. 02创建组件变体与尺寸
  3. 03让组件适配主题颜色
  4. 04基于 Bootstrap 构建自定义组件

安装

复制下面的命令,在终端中运行。

$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 前,先确定组件需要什么:
    • 仅令牌 — 一种外观,通过 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 会完全移除该令牌。
  • 第二次赋值需要添加 stylelint-disable-next-line scss/dollar-variable-default 注释,因为这是有意在不使用 !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),然后编写声明,最后编写嵌套规则。声明通过 var(--widget-*) 读取值,绝不直接读取 Sass 映射。
  • 使用 @include border-radius() 和 @include transition(),不要直接使用原生属性——stylelint 会禁止直接使用,因为这些混入会遵循 $enable-rounded、$enable-transitions 和 prefers-reduced-motion。
  • 使用逻辑属性(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:注册局部文件

在组件区块中从 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);
  }
}

使用 custom 层,它位于 components 之后、helpers 和 utilities 之前。这样一来,你的样式会覆盖组件默认样式,而工具类仍可覆盖你的样式。调整现有 Bootstrap 组件无需做这些操作——在运行时覆盖其 CSS 变量,或在编译时通过 with () 传入其 $*-tokens 映射。

评论

支持 Markdown