mcpField
F
faststore-theming

faststore-theming

github.com/vtex设计与 UI4782 次安装2 周前更新
代码仓库

关于 faststore-theming

faststore-theming 是用于定制 FastStore 店面的设计主题技能,面向调整颜色、字体、间距、边框及组件样式的开发者。它以设计令牌和组件数据属性为核心,并规定主题文件位置与样式选择方式。

主要功能

  1. 01使用全局与局部设计令牌
  2. 02通过 data-fs-* 属性定位组件
  3. 03在指定目录配置主题 SCSS
  4. 04为自定义组件使用 CSS Modules
  5. 05区分主题调整与行为覆盖

适用场景

  1. 01设置店面品牌颜色与字体
  2. 02调整特定组件的外观
  3. 03创建或维护 FastStore 主题
  4. 04判断是否需要组件覆盖

安装

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

$npx skills add https://github.com/vtex/skills --skill faststore-theming

安装后在 Claude Code 中输入/faststore-theming确认已加载。

详细介绍

FastStore 主题与设计令牌

适用场景

在以下情况下使用此技能:

  • 需要更改 FastStore 店面的视觉外观,例如颜色、字体、间距、边框或组件专属样式。
  • 正在处理 src/themes/ 中的文件,或创建 custom-theme.scss。
  • 需要使用本地令牌和 [data-fs-*] 数据属性自定义单个组件的样式。
  • 需要在 Brandless 默认主题的基础上设置品牌形象。

以下情况不要使用此技能:

  • 需要替换组件、注入逻辑或修改行为时,请使用 faststore-overrides 技能。
  • 管理客户端状态时,请使用 faststore-state-management 技能。
  • 获取数据或扩展 API 时,请使用 faststore-data-fetching 技能。

决策规则

  • 优先使用主题设置,再考虑覆盖——这种方式更轻量,也更易维护。
  • 当更改应应用于整个店面时(例如品牌颜色、字体系列),使用全局令牌(:root 作用域)。
  • 当更改仅适用于单个组件时(例如按钮背景色),使用本地令牌([data-fs-*] 作用域)。
  • 使用 [data-fs-*] 数据属性定位组件——切勿使用 .fs-* 类名或通用标签选择器。
  • 将所有主题文件放在 src/themes/ 中,并以 custom-theme.scss 作为入口文件——其他位置的文件不会被发现。
  • 通过 var(--fs-*) 引用设计令牌,而不是硬编码十六进制颜色、像素尺寸或字体值。
  • 自定义(非 FastStore)组件应使用 CSS 模块,以避免与 FastStore 的结构样式冲突。

严格约束

约束:使用设计令牌,而非内联样式

必须使用设计令牌(全局或本地)设置 FastStore 组件的样式。不得为了主题设置而在 FastStore 组件上使用内联 style={} 属性。

重要原因 内联样式会绕过设计令牌层级,无法被主题覆盖,也不会参与响应式断点,还会造成维护难题。此外,由于样式嵌入 HTML 中,它们也会破坏 CSS 缓存。设计令牌可确保一致性,并允许从单个文件更改整个店面的样式。

检测方法 如果在 FastStore 原生组件(从 @faststore/ui 或 @faststore/core 导入的组件)上看到 style={{ 或 style={ → 提醒这会绕过主题系统,并建议改用设计令牌或 CSS 模块。例外:对于不属于 FastStore UI 库的完全自定义组件,可以使用内联样式。

正确

// src/themes/custom-theme.scss
// Override the BuyButton's primary background color using design tokens
[data-fs-buy-button] {
  --fs-button-primary-bkg-color: #e31c58;
  --fs-button-primary-bkg-color-hover: #c4174d;
  --fs-button-primary-text-color: var(--fs-color-text-inverse);

  [data-fs-button-wrapper] {
    border-radius: var(--fs-border-radius-pill);
  }
}

错误

// WRONG: Using inline styles on a FastStore component
import { BuyButton } from '@faststore/ui'

function ProductActions() {
  return (
    <BuyButton
      style={{ backgroundColor: '#e31c58', color: 'white', borderRadius: '999px' }}
    >
      Add to Cart
    </BuyButton>
  )
  // Inline styles bypass the design token hierarchy.
  // They cannot be changed store-wide from the theme file.
  // They do not respond to dark mode or other theme variants.
}

约束:将主题文件放在 src/themes/ 中

必须将自定义主题 SCSS 文件放在 src/themes/ 目录中。主主题文件必须命名为 custom-theme.scss。

重要原因 FastStore 的构建系统会从 src/themes/custom-theme.scss 导入主题文件。放在其他位置的文件不会被构建流程读取,因此令牌覆盖不会生效。此时不会出现错误,而是显示默认的 Brandless 主题。

检测方法 如果在 src/themes/ 之外的 SCSS 文件中看到令牌覆盖声明(以 --fs- 开头的变量)→ 提醒这些声明可能不会生效。如果项目中不存在 src/themes/custom-theme.scss 文件 → 提醒当前没有启用自定义主题。

正确

// src/themes/custom-theme.scss
// Global token overrides — applied store-wide
:root {
  --fs-color-main-0: #003232;
  --fs-color-main-1: #004c4c;
  --fs-color-main-2: #006666;
  --fs-color-main-3: #008080;
  --fs-color-main-4: #00b3b3;

  --fs-color-accent-0: #e31c58;
  --fs-color-accent-1: #c4174d;
  --fs-color-accent-2: #a51342;

  --fs-text-face-body: 'Inter', -apple-system, system-ui, BlinkMacSystemFont, sans-serif;
  --fs-text-face-title: 'Poppins', var(--fs-text-face-body);

  --fs-text-size-title-huge: 3.5rem;
  --fs-text-size-title-page: 2.25rem;
}

// Component-specific token overrides
[data-fs-price] {
  --fs-price-listing-color: #cb4242;
}

错误

// src/styles/my-theme.scss
// WRONG: This file is in src/styles/, not src/themes/
// FastStore will NOT import this file. Token overrides will be ignored.
:root {
  --fs-color-main-0: #003232;
  --fs-color-accent-0: #e31c58;
}

// Also WRONG: Creating a theme in the project root
// ./theme.scss — this will not be discovered by the build system

约束:使用数据属性定位组件

必须在主题 SCSS 文件中使用 FastStore 的 data-fs-* 数据属性定位组件。不得使用类名或标签选择器定位 FastStore 原生组件。

为何这很重要 FastStore 组件使用数据属性作为公开的样式 API(例如 data-fs-button、data-fs-price、data-fs-hero)。类名属于实现细节,可能会在不同版本间变更。使用数据属性可确保主题在 FastStore 更新后仍能正常使用。每个组件都会在其文档的自定义部分说明可用的数据属性。

检测 如果看到 CSS 选择器使用 .fs-* 类名或通用标签选择器(button、h1、div)来设置 FastStore 组件的样式 → 提醒其存在脆弱性。建议改用 [data-fs-*] 选择器。

正确

// src/themes/custom-theme.scss
// Target the Hero section using its data attribute
[data-fs-hero] {
  --fs-hero-text-size: var(--fs-text-size-title-huge);
  --fs-hero-heading-weight: var(--fs-text-weight-bold);

  [data-fs-hero-heading] {
    text-transform: uppercase;
    letter-spacing: 0.05em;
  }

  [data-fs-hero-image] {
    border-radius: var(--fs-border-radius);
    filter: brightness(0.9);
  }
}

错误

// src/themes/custom-theme.scss
// WRONG: Targeting by class names — these are internal and may change
.fs-hero {
  font-size: 3.5rem;
}

.fs-hero h1 {
  text-transform: uppercase;
}

// WRONG: Using generic tag selectors
section > div > h1 {
  font-weight: bold;
}
// These are fragile selectors that break when FastStore restructures its HTML.

推荐模式

推荐的文件布局:

src/
└── themes/
    └── custom-theme.scss    ← main entry point (auto-imported by FastStore)

最精简的自定义主题:

// src/themes/custom-theme.scss
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=Poppins:wght@600;700;800&display=swap');

// Global Token Overrides
:root {
  --fs-color-main-0: #003232;
  --fs-color-main-1: #004c4c;
  --fs-color-accent-0: #e31c58;
  --fs-color-accent-1: #c4174d;

  --fs-text-face-body: 'Inter', -apple-system, system-ui, sans-serif;
  --fs-text-face-title: 'Poppins', var(--fs-text-face-body);
}

// Component-specific overrides
[data-fs-button] {
  --fs-button-border-radius: var(--fs-border-radius-pill);

  &[data-fs-button-variant="primary"] {
    --fs-button-primary-bkg-color: var(--fs-color-accent-0);
    --fs-button-primary-bkg-color-hover: var(--fs-color-accent-1);
    --fs-button-primary-text-color: var(--fs-color-text-inverse);
  }
}

[data-fs-price] {
  --fs-price-listing-color: #cb4242;
  --fs-price-listing-text-decoration: line-through;
}

[data-fs-navbar] {
  --fs-navbar-bkg-color: var(--fs-color-main-0);
  --fs-navbar-text-color: var(--fs-color-text-inverse);
}

对于自定义(非 FastStore)组件,请使用 CSS modules 以避免冲突:

// src/components/CustomBanner.module.scss
.customBanner {
  display: flex;
  align-items: center;
  gap: var(--fs-spacing-3); // Still reference FastStore tokens for consistency
  padding: var(--fs-spacing-4);
  background-color: var(--fs-color-main-0);
  color: var(--fs-color-text-inverse);
  border-radius: var(--fs-border-radius);
}

常见失败模式

  • 使用 !important 声明——会造成特异性死局,破坏设计令牌的层叠特性。应在正确的选择器特异性下使用正确的令牌。
  • 在组件样式中直接硬编码十六进制颜色、像素尺寸和字体值,而不是引用 var(--fs-*) 令牌。更改无法在整个商店中生效。
  • 创建与 FastStore 结构样式冲突且会使 CSS 负载翻倍的平行 CSS 系统(Tailwind、Bootstrap、自定义全局样式表)。
  • 将主题文件放在 src/themes/ 之外——构建系统将无法发现这些文件。
  • 使用 .fs-* 类名或通用标签选择器,而不是 [data-fs-*] 数据属性来定位 FastStore 组件。

审查清单

  • 主题文件是否位于 src/themes/custom-theme.scss?
  • 全局令牌覆盖是否放在 :root 作用域中?
  • 组件级覆盖是否使用 [data-fs-*] 数据属性选择器?
  • 所有值是否都通过 var(--fs-*) 引用设计令牌,而非使用硬编码值?
  • 是否未使用 !important 声明?
  • 是否可以不使用覆盖来实现此更改(主题设置是否足够)?
  • 自定义组件样式是否使用 CSS modules 进行作用域限定,以避免冲突?

参考

评论

支持 Markdown