canvas-styling-conventions

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Technology stack

技术栈

TechnologyPurpose
Tailwind CSS 4.1+Styling
class-variance-authority (CVA)Component variants
clsx
+
tailwind-merge
via
cn()
Class name merging
Only use these dependencies for styling. Do not add third-party CSS libraries or create new styling utilities.
技术用途
Tailwind CSS 4.1+样式设置
class-variance-authority (CVA)组件变体
clsx
+
tailwind-merge
via
cn()
类名合并
仅使用这些依赖项进行样式设置。请勿添加第三方CSS库或创建新的样式工具。

Styling conventions

样式设置规范

  • Use Tailwind's theme colors (
    primary-*
    ,
    gray-*
    ) defined in
    global.css
    .
  • Avoid hardcoded color values; use theme tokens instead.
  • Follow the existing focus, hover, and active state patterns from examples.
  • 使用在
    global.css
    中定义的Tailwind主题颜色(
    primary-*
    gray-*
    )。
  • 避免硬编码颜色值;请改用主题令牌。
  • 遵循示例中的现有焦点、悬停和激活状态模式。

The cn() utility

cn()工具函数

Use
cn()
to merge Tailwind classes. It combines
clsx
for conditional classes with
tailwind-merge
to resolve conflicting utilities. Import from either source:
jsx
import { cn } from "@/lib/utils";
// or
import { cn } from "drupal-canvas";
Example usage:
jsx
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>
);
使用
cn()
合并Tailwind类。它结合了
clsx
用于条件类,以及
tailwind-merge
用于解决工具类冲突。可从以下任一来源导入:
jsx
import { cn } from "@/lib/utils";
// or
import { cn } from "drupal-canvas";
示例用法:
jsx
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>
);

Accept className for style customization

接受className以自定义样式

Every component should accept a
className
prop to allow style overrides. Pass it to
cn()
as the last argument so consumer classes take precedence.
jsx
const Card = ({ colorScheme, className, children }) => (
  <div className={cn(cardVariants({ colorScheme }), className)}>{children}</div>
);
className
is an implementation/composition prop, not an editor prop. Do not add
className
to
component.yml
, do not mark it as required, and do not surface it in Canvas metadata.
每个组件都应接受
className
属性以允许样式覆盖。将其作为最后一个参数传递给
cn()
,以便使用者的类优先生效。
jsx
const Card = ({ colorScheme, className, children }) => (
  <div className={cn(cardVariants({ colorScheme }), className)}>{children}</div>
);
className
是实现/组合属性,而非编辑器属性。请勿将
className
添加到
component.yml
中,请勿将其标记为必填,也请勿在Canvas元数据中显示它。

Tailwind 4 theme variables

Tailwind 4主题变量

Canvas projects use Tailwind CSS 4's
@theme
directive to define design tokens in
global.css
. Variables defined inside
@theme { }
automatically become available as Tailwind utility classes.
Always check
global.css
for available design tokens.
The
@theme
block is the source of truth for colors, fonts, breakpoints, and other design tokens.
Canvas项目使用Tailwind CSS 4的
@theme
指令在
global.css
中定义设计令牌。
@theme { }
内定义的变量会自动成为可用的Tailwind工具类。
请务必查看
global.css
中的可用设计令牌。
@theme
块是颜色、字体、断点及其他设计令牌的唯一可信来源。

How theme variables map to utility classes

主题变量如何映射到工具类

When you define a CSS variable in
@theme
, Tailwind 4 automatically generates corresponding utility classes based on the variable's namespace prefix:
CSS Variable in
@theme
Generated Utility Classes
--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:
responsive prefix
The pattern is:
--{namespace}-{name}
becomes
{utility}-{name}
.
当您在
@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}

Examples

示例

Given this definition in
global.css
:
css
@theme {
  --color-primary-600: #1899cb;
  --color-primary-700: #1487b4;
}
You can use these colors with any color-accepting utility:
jsx
// 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>
Arbitrary values (e.g.,
bg-[#xxx]
) are acceptable for rare, one-off cases where adding a theme variable would be overkill. However, if a color appears in multiple places or represents a brand/design system value, add it to
@theme
instead.
假设在
global.css
中有以下定义:
css
@theme {
  --color-primary-600: #1899cb;
  --color-primary-700: #1487b4;
}
您可以将这些颜色用于任何接受颜色的工具类:
jsx
// 正确
<button className="bg-primary-600 hover:bg-primary-700 text-white">
  点击我
</button>

// 错误
<button className="bg-[#1899cb] text-white hover:bg-[#1487b4]">点击我</button>
对于罕见的一次性场景,添加主题令牌过于繁琐时,可使用任意值(如
bg-[#xxx]
)。但如果某颜色出现在多个位置,或代表品牌/设计系统值,请改为将其添加到
@theme
中。

Semantic aliases

语义别名

Theme variables can reference other variables to create semantic aliases:
css
@theme {
  --color-primary-700: #1487b4;
  --color-primary-dark: var(--color-primary-700);
}
Both
bg-primary-700
and
bg-primary-dark
will work. Use semantic aliases when they better express intent (e.g.,
primary-dark
for a darker brand variant).
主题变量可以引用其他变量以创建语义别名:
css
@theme {
  --color-primary-700: #1487b4;
  --color-primary-dark: var(--color-primary-700);
}
bg-primary-700
bg-primary-dark
均可使用。当语义别名能更好地表达意图时(例如,用
primary-dark
表示更深的品牌变体),请使用语义别名。

Adding or updating theme variables

添加或更新主题变量

When a design requires a color, font, or other value not yet defined in the theme, add it to the
@theme
block in
global.css
rather than hardcoding the value in a component.
When to add new theme variables:
  • A design introduces a new brand color or shade
  • You need a semantic alias for an existing value (e.g.,
    --color-accent
    )
  • The design uses a specific spacing, font, or breakpoint value repeatedly
When to update existing theme variables:
  • The brand colors change (update the hex values)
  • Design tokens need adjustment across the system
Example - adding a new color:
css
@theme {
  /* Existing tokens */
  --color-primary-600: #1899cb;

  /* New token for a success state */
  --color-success: #22c55e;
  --color-success-dark: #16a34a;
}
After adding, you can immediately use
bg-success
,
text-success-dark
, etc.
Keep the theme organized. Group related tokens together with comments explaining their purpose. Follow the existing naming conventions in
global.css
(e.g., numbered shades like
primary-100
through
primary-900
, semantic names like
primary-dark
).
当设计需要主题中尚未定义的颜色、字体或其他值时,请将其添加到
global.css
@theme
块中,而非在组件中硬编码值。
何时添加新主题变量:
  • 设计引入了新的品牌颜色或色调
  • 您需要为现有值创建语义别名(例如
    --color-accent
  • 设计重复使用特定的间距、字体或断点值
何时更新现有主题变量:
  • 品牌颜色变更(更新十六进制值)
  • 设计令牌需要在整个系统中调整
示例 - 添加新颜色:
css
@theme {
  /* 现有令牌 */
  --color-primary-600: #1899cb;

  /* 为成功状态添加的新令牌 */
  --color-success: #22c55e;
  --color-success-dark: #16a34a;
}
添加后,您即可立即使用
bg-success
text-success-dark
等工具类。
保持主题的条理性。 将相关令牌分组,并添加注释说明其用途。遵循
global.css
中的现有命名规范(例如,从
primary-100
primary-900
的编号色调,
primary-dark
等语义名称)。

Color props must use variants, not color codes

颜色属性必须使用变体,而非颜色代码

Never create props that allow users to pass color codes (hex values, RGB, HSL, or any raw color strings). Instead, define a small set of human-readable variants using CVA that map to the design tokens in
global.css
.
Always check
global.css
for available design tokens.
The tokens defined there (such as
primary-*
,
gray-*
, etc.) are the source of truth for color values.
Wrong - allowing raw color values:
yaml
undefined
切勿创建允许用户传递颜色代码(十六进制值、RGB、HSL或任何原始颜色字符串)的属性。 相反,请使用CVA定义一组少量的易读变体,映射到
global.css
中的设计令牌。
请务必查看
global.css
中的可用设计令牌。
其中定义的令牌(如
primary-*
gray-*
等)是颜色值的唯一可信来源。
错误示例 - 允许原始颜色值:
yaml
undefined

Wrong

错误

props: properties: backgroundColor: title: Background Color type: string examples: - "#3b82f6"

```jsx
// Wrong
const Card = ({ backgroundColor }) => (
  <div style={{ backgroundColor }}>{/* ... */}</div>
);
Correct - using CVA variants with design tokens:
yaml
undefined
props: properties: backgroundColor: title: 背景颜色 type: string examples: - "#3b82f6"

```jsx
// 错误
const Card = ({ backgroundColor }) => (
  <div style={{ backgroundColor }}>{/* ... */}</div>
);
正确示例 - 使用带设计令牌的CVA变体:
yaml
undefined

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

```jsx
// 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>
);
This approach ensures:
  • Consistent colors across the design system
  • Users select from curated, meaningful options (not arbitrary values)
  • Easy theme updates by modifying
    global.css
    tokens
  • Better accessibility through tested color combinations
props: properties: colorScheme: title: 配色方案 type: string enum: - default - primary - muted - dark meta:enum: default: 默认(白色) primary: 主色(蓝色) muted: 柔和色(浅灰) dark: 深色 examples: - default

```jsx
// 正确
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
    令牌即可轻松更新主题
  • 通过经过测试的颜色组合提升可访问性