关于 canvas-styling-conventions
为 Drupal Canvas 项目提供 React 与 Tailwind CSS 4 样式约定的技能,供实现或维护 Canvas 组件的开发者参考。内容涵盖主题令牌、类名合并和变体用法,并区分 Canvas Headless 与 React 项目规则。
主要功能
- 01识别 Canvas Headless 与 React 项目
- 02使用 Tailwind 主题令牌
- 03通过 cn() 合并样式类
- 04用 CVA 定义颜色变体
- 05避免组件使用原始颜色值
适用场景
- 01为 Canvas 组件编写一致样式
- 02将重复颜色值整理为主题令牌
- 03为组件定义受控的颜色方案
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ drupal-canvas/ skills --skill canvas-styling-conventions安装后在 Claude Code 中输入/canvas-styling-conventions确认已加载。
详细介绍
项目类型
应用此技能前,请检查 package.json 中是否有名为
@drupal-canvas/headless 或以 @drupal-canvas/headless- 开头的依赖。如果有,
这是一个 Canvas Headless 代码库——请先阅读
canvas-headless;其中的指导优先于下方
针对 React 的说明。本技能中关于 Tailwind 4 主题令牌的指导同样适用于
无头项目;cn() 和 className 部分仅针对 React。如果没有此类依赖,
则这是一个 Canvas 渲染的 React 代码库:组件采用 React(index.jsx/.tsx),
本技能中的所有内容均按原样适用。项目类型仅有这两种。
技术栈
| 技术 | 用途 |
|---|---|
| Tailwind CSS 4.1+ | 样式 |
| class-variance-authority (CVA) | 组件变体 |
通过 cn() 使用 clsx + tailwind-merge | 类名合并 |
样式仅使用这些依赖。不要添加第三方 CSS 库,也不要创建新的样式工具。
在 Canvas Headless 代码库中,不支持 drupal-canvas 包(及其 cn())。
只要项目安装了 CVA,它仍可用于任何框架;合并类名时,请使用框架自身的类组合惯例——参见
canvas-headless。
样式约定
- 使用
global.css中定义的 Tailwind 主题颜色(primary-*、gray-*)。 - 避免使用硬编码颜色值,改用主题令牌。
- 遵循示例中已有的焦点、悬停和激活状态样式模式。
cn() 工具
使用 cn() 合并 Tailwind 类。它将 clsx 用于条件类,并使用
tailwind-merge 解决冲突的工具类。可从以下任一来源导入:
import { cn } from '@/lib/utils';
// or
import { cn } from 'drupal-canvas';
用法示例:
const Button = ({ variant, className, children }) => (
<button
className={cn(
'rounded px-4 py-2',
variant === 'primary' && 'bg-primary-600 text-white',
variant === 'secondary' && 'bg-gray-200 text-gray-800',
className,
)}
>
{children}
</button>
);
接受 className 以自定义样式
此规则仅针对 React;在 Vue 和 Astro 组件中,如果使用方需要覆盖样式,
请依赖框架自身的类传递方式(Vue 中的属性透传,Astro 中的 class 属性)。
每个 React 组件都应接受 className 属性,以便覆盖样式。
将其作为最后一个参数传给 cn(),这样使用方的类就具有优先级。
const Card = ({ colorScheme, className, children }) => (
<div className={cn(cardVariants({ colorScheme }), className)}>{children}</div>
);
className 是实现/组合属性,不是编辑器属性。不要将 className 添加到
component.yml,不要将其标记为必填,也不要在 Canvas 元数据中公开它。
Tailwind 4 主题变量
Canvas 项目使用 Tailwind CSS 4 的 @theme 指令在 global.css 中定义设计令牌。
在 @theme { } 中定义的变量会自动成为可用的 Tailwind 工具类。
务必检查 global.css 中可用的设计令牌。 @theme 块是颜色、字体、
断点及其他设计令牌的唯一事实来源。
主题变量如何映射到工具类
在 @theme 中定义 CSS 变量时,Tailwind 4 会根据变量的命名空间前缀自动生成
对应的工具类:
@theme 中的 CSS 变量 | 生成的工具类 |
|---|---|
--color-primary-600: #xxx | bg-primary-600、text-primary-600、border-primary-600 |
--color-gray-100: #xxx | bg-gray-100、text-gray-100、border-gray-100 |
--font-sans: ... | font-sans |
--breakpoint-md: 48rem | md: 响应式前缀 |
规则是:--{namespace}-{name} 会变为 {utility}-{name}。
示例
在 global.css 中有以下定义:
@theme {
--color-primary-600: #1899cb;
--color-primary-700: #1487b4;
}
你可以将这些颜色用于任何接受颜色的工具类:
// Correct
<button className="bg-primary-600 hover:bg-primary-700 text-white">
Click me
</button>
// Wrong
<button className="bg-[#1899cb] text-white hover:bg-[#1487b4]">Click me</button>
对于罕见的一次性场景,可以使用任意值(例如 bg-[#xxx]),因为这类情况添加主题变量显得过于繁琐。不过,如果某种颜色在多个地方出现,或代表品牌/设计系统的值,请将其添加到 @theme 中。
语义别名
主题变量可以引用其他变量,以创建语义别名:
@theme {
--color-primary-700: #1487b4;
--color-primary-dark: var(--color-primary-700);
}
bg-primary-700 和 bg-primary-dark 都可以使用。当语义别名能更好地表达意图时(例如,用 primary-dark 表示较深的品牌变体),请使用语义别名。
添加或更新主题变量
当设计需要主题中尚未定义的颜色、字体或其他值时,请将其添加到 global.css 中的 @theme 区块,而不是在组件中硬编码该值。
何时添加新的主题变量:
- 设计引入了新的品牌颜色或色阶
- 需要为现有值创建语义别名(例如
--color-accent) - 设计反复使用特定的间距、字体或断点值
何时更新现有主题变量:
- 品牌颜色发生变化(更新十六进制值)
- 需要调整整个系统中的设计令牌
示例 - 添加新颜色:
@theme {
/* Existing tokens */
--color-primary-600: #1899cb;
/* New token for a success state */
--color-success: #22c55e;
--color-success-dark: #16a34a;
}
添加后,你可以立即使用 bg-success、text-success-dark 等。
保持主题井然有序。 将相关令牌归类,并添加注释说明其用途。遵循 global.css 中现有的命名约定(例如,从 primary-100 到 primary-900 的编号色阶,以及 primary-dark 这类语义名称)。
颜色属性必须使用变体,而非颜色代码
切勿创建允许用户传入颜色代码的属性(十六进制值、RGB、HSL 或任何原始颜色字符串)。应使用 CVA 定义一小组易于理解的变体,并将其映射到 global.css 中的设计令牌。
始终检查 global.css 中可用的设计令牌。 其中定义的令牌(例如 primary-*、gray-* 等)是颜色值的唯一依据。
错误 - 允许使用原始颜色值:
# Wrong
props:
properties:
backgroundColor:
title: Background Color
type: string
examples:
- '#3b82f6'
// Wrong
const Card = ({ backgroundColor }) => (
<div style={{ backgroundColor }}>{/* ... */}</div>
);
正确 - 使用带有设计令牌的 CVA 变体:
# Correct
props:
properties:
colorScheme:
title: Color Scheme
type: string
enum:
- default
- primary
- muted
- dark
meta:enum:
default: Default (White)
primary: Primary (Blue)
muted: Muted (Light Gray)
dark: Dark
examples:
- default
// Correct
import { cva } from 'class-variance-authority';
const cardVariants = cva('rounded-lg p-6', {
variants: {
colorScheme: {
default: 'bg-white text-black',
primary: 'bg-primary-600 text-white',
muted: 'bg-gray-100 text-gray-700',
dark: 'bg-gray-900 text-white',
},
},
defaultVariants: {
colorScheme: 'default',
},
});
const Card = ({ colorScheme, children }) => (
<div className={cardVariants({ colorScheme })}>{children}</div>
);
这种方法可以确保:
- 整个设计系统中的颜色保持一致
- 用户从经过精选且有意义的选项中进行选择,而不是使用任意值
- 只需修改
global.css中的令牌,即可轻松更新主题 - 通过经过测试的颜色组合,提升可访问性