颜色 Colors
@cloudflare/kumo

用法

请始终使用语义令牌,而不是原始的 Tailwind 颜色。这能确保你的 UI 自动适配浅色与深色模式,并让组件在各主题间保持一致。

正确

<div className="bg-kumo-base text-kumo-default border-kumo-hairline">
  <button className="bg-kumo-brand text-white">Primary</button>
  <button className="bg-kumo-control text-kumo-default">Secondary</button>
</div>

错误

{
  /* 切勿使用原始的 Tailwind 颜色 */
}
<div className="bg-white dark:bg-gray-900 text-black dark:text-white">
  <button className="bg-blue-500">Primary</button>
</div>;

Lint 规则会强制这一点:no-primitive-colors 规则会标记任何类似 bg-blue-500 的原始 Tailwind 颜色。

模式

在父元素上设置 data-mode 来控制浅色/深色模式。切勿使用 Tailwind 的 dark: 变体——语义令牌会通过 CSS light-dark() 自动处理深色模式。

// 在 html 或 body 上设置模式
<html data-mode="light">  // 浅色模式
<html data-mode="dark">   // 深色模式

// 组件会自动适配 —— 无需 dark: 变体
<div className="bg-kumo-base text-kumo-default" />

主题

主题会覆盖语义令牌的值,同时保留相同的令牌名称。在父元素上设置 data-theme 即可应用主题。

可用主题

  • kumo — 默认主题 (无需任何属性)
  • fedramp — 政府合规样式
// 将主题应用到某个区块或整个应用
<div data-theme="fedramp">
  {/* 内部所有 Kumo 组件都使用 fedramp 令牌覆盖 */}
  <Button>FedRAMP Styled</Button>
</div>

// 主题同时适用于浅色和深色模式
<html data-mode="dark" data-theme="fedramp">

主题生成器

主题在集中式配置中定义,并生成为 CSS 文件。主题生成器确保所有主题之间的一致性。


# 列出所有令牌及其主题覆盖

pnpm --filter @cloudflare/kumo codegen:themes --list

# 生成主题 CSS 文件

pnpm --filter @cloudflare/kumo codegen:themes

# 预览更改但不写入文件

pnpm --filter @cloudflare/kumo codegen:themes --dry-run

主题配置:packages/kumo/scripts/theme-generator/config.ts

创建新主题

在配置文件中添加主题覆盖。只需覆盖需要更改的令牌——其余所有令牌都会从基础 kumo 主题继承。

// 在 scripts/theme-generator/config.ts 中
export const THEME_CONFIG: ThemeConfig = {
  color: {
    "kumo-base": {
      newName: "",
      theme: {
        kumo: {
          light: "var(--color-white, #fff)",
          dark: "var(--color-black, #000)",
        },
        // 添加你自己的主题覆盖
        myTheme: {
          light: "#f0f4f8",
          dark: "#1a1f2e",
        },
      },
    },
    // ... 其他令牌
  },
};

// 添加到可用主题列表
export const AVAILABLE_THEMES = ["kumo", "fedramp", "myTheme"] as const;

然后运行 pnpm codegen:themes 生成 CSS。

语义令牌

我们使用语义令牌按用途对颜色分组。请选择与元素角色相匹配的令牌,而不是你想要呈现的颜色。

语义令牌按角色命名,而非色相。像 bg-kumo-danger 这样的令牌传达的是意图——它并不暗示某种特定的红色深浅,其具体值可以随主题或颜色模式变化,而无需改动你的组件代码。

表面层级

表面用于在 UI 中建立深度与层次。请从最外层背景向内按顺序使用它们。

令牌用途
bg-kumo-canvas最外层的页面背景——位于所有内容之下
bg-kumo-base组件默认背景
bg-kumo-elevated略微抬升的表面,例如 LayerCard.Secondary
bg-kumo-recessed下沉式表面,填充色略深,例如分段式 Tabs 的背景
bg-kumo-tint带细微色调的背景,适用于表格或悬停状态
bg-kumo-contrast高对比度的反色背景

品牌色

令牌用途
bg-kumo-brand主品牌背景
bg-kumo-brand-hover品牌背景的悬停状态

语义状态色

每种状态色都有两种变体:一种是用于图标和指示器的实色,另一种是 -tint 变体,用于内容背后的背景填充 (即 Badge 或 Banner)。

令牌用途
bg-kumo-info信息指示器
bg-kumo-success成功指示器
bg-kumo-warning警告指示器
bg-kumo-danger错误/破坏性操作指示器

状态点使用实色令牌 bg-kumo-*,图标使用 fill-kumo-*,边框和轮廓使用 border-kumo-*、ring-kumo-*。Banner 和 Badge 使用 -tint 变体,并配合不同的透明度值。

Something went wrong.
import { WarningIcon } from "@phosphor-icons/react";

export function StatusBannerDemo() {
  return (
    <div className="flex items-center gap-2 rounded-lg bg-kumo-danger-tint/70 p-4">
      <WarningIcon weight="fill" className="fill-kumo-danger" />
      <span className="text-sm text-kumo-danger">Something went wrong.</span>
    </div>
  );
}

文本颜色

令牌用途
text-kumo-default正文主文本
text-kumo-strong对比度比默认值更强的文本,用于标题和重要标签
text-kumo-subtle弱化文本,用于描述、说明文字或次要标签
text-kumo-inactive禁用或非活动状态的文本
text-kumo-placeholder输入框中的占位文本
text-kumo-inverse用于高对比度或反色背景上的文本
text-kumo-link链接文本
text-kumo-info信息色文本
text-kumo-success成功色文本
text-kumo-warning警告色文本
text-kumo-danger错误/破坏性文本

语义文本色 (即 text-kumo-success) 默认更深,以便在 tint-* 背景上获得更好的对比度和可读性。

边框与轮廓

令牌用途
kumo-hairline用于区分没有阴影的平面表面的边框/轮廓颜色 (即 LayerCard)。
kumo-line更粗的边框/轮廓颜色,与阴影一起勾勒出抬升表面的边缘。

令牌参考

在页头切换主题,即可查看令牌如何适配。标记为「全局」的令牌是显式选择加入的类,不依赖主题始终可用。

Colors

Displaying 54 tokens

Text Colors (12)

--text-color-kumo-default
Lightvar(--color-neutral-900, oklch(21% 0.006 285.885))
Darkvar(--color-neutral-100, oklch(97% 0 0))
--text-color-kumo-inverse
Lightvar(--color-neutral-100, oklch(97% 0 0))
Darkvar(--color-neutral-900, oklch(20.5% 0 0))
--text-color-kumo-strong
Lightvar(--color-neutral-950, oklch(14.5% 0 0))
Darkvar(--color-neutral-50, oklch(98.5% 0 0))
--text-color-kumo-subtle
Lightvar(--color-neutral-500, oklch(55.6% 0 0))
Darkvar(--color-neutral-400, oklch(70.8% 0 0))
--text-color-kumo-inactive
Lightvar(--color-neutral-300, oklch(87% 0 0))
Darkvar(--color-neutral-600, oklch(43.9% 0 0))
--text-color-kumo-placeholder
Lightvar(--color-neutral-400, oklch(70.8% 0 0))
Darkvar(--color-neutral-500, oklch(55.6% 0 0))
--text-color-kumo-brand
Light#f6821f
Dark#f6821f
--text-color-kumo-link
Lightvar(--color-blue-800, oklch(42.4% 0.199 265.638))
Darkvar(--color-blue-400, oklch(70.7% 0.165 254.624))
--text-color-kumo-info
Lightvar(--color-blue-800, oklch(42.4% 0.199 265.638))
Darkvar(--color-blue-400, oklch(70.7% 0.165 254.624))
--text-color-kumo-success
Lightvar(--color-emerald-800, oklch(43.2% 0.095 166.913))
Darkvar(--color-emerald-200, oklch(90.5% 0.093 164.15))
--text-color-kumo-danger
Lightvar(--color-red-700, oklch(50.5% 0.213 27.518))
Darkvar(--color-red-400, oklch(70.4% 0.191 22.216))
--text-color-kumo-warning
Lightoklch(59.7% 0.144 57.5)
Darkvar(--color-orange-400, oklch(75% 0.183 55.934))

Surface, State & Theme Colors (28)

--color-kumo-canvas
Lightvar(--color-kumo-neutral-25, oklch(98.75% 0 0))
Darkvar(--color-kumo-neutral-1000, oklch(10% 0 0))
--color-kumo-elevated
Lightvar(--color-kumo-neutral-75, oklch(98% 0 0))
Darkvar(--color-kumo-neutral-975, oklch(12% 0 0))
--color-kumo-recessed
Lightvar(--color-kumo-neutral-125, oklch(96% 0 0))
Darkvar(--color-kumo-neutral-950, oklch(15% 0 0))
--color-kumo-base
Lightvar(--color-white, #fff)
Darkvar(--color-kumo-neutral-925, oklch(17% 0 0))
--color-kumo-tint
Lightvar(--color-neutral-100, oklch(97% 0 0))
Darkvar(--color-kumo-neutral-800, oklch(26.9% 0 0))
--color-kumo-contrast
Lightvar(--color-kumo-neutral-975, oklch(8.5% 0 0))
Darkvar(--color-kumo-neutral-25, oklch(98.5% 0 0))
--color-kumo-overlay
Lightvar(--color-kumo-neutral-50, oklch(97.5% 0 0))
Darkvar(--color-neutral-800, oklch(26.9% 0 0))
--color-kumo-control
Lightvar(--color-white, #fff)
Darkvar(--color-neutral-900, oklch(21% 0.006 285.885))
--color-kumo-interact
Lightvar(--color-neutral-300, oklch(87% 0 0))
Darkvar(--color-neutral-700, oklch(37.1% 0 0))
--color-kumo-fill
Lightvar(--color-neutral-200, oklch(92.2% 0 0))
Darkvar(--color-neutral-800, oklch(26.9% 0 0))
--color-kumo-fill-hover
Lightvar(--color-kumo-neutral-125, oklch(96.5% 0 0))
Darkvar(--color-neutral-800, oklch(37.1% 0 0))
--color-kumo-brand
Lightoklch(0.5772 0.2324 260)
Darkcolor-mix(in oklch, oklch(0.5772 0.2324 260), black 10%)
--color-kumo-brand-hover
Lightvar(--color-blue-700, oklch(48.8% 0.243 264.376))
Darkvar(--color-blue-700, oklch(48.8% 0.243 264.376))
--color-kumo-line
Lightoklch(14.5% 0 0 / 0.1)
Darkvar(--color-kumo-neutral-750, oklch(32% 0 0))
--color-kumo-hairline
Lightvar(--color-kumo-neutral-150, oklch(93.5% 0 0))
Darkvar(--color-neutral-800, oklch(26.9% 0 0))
--color-kumo-focus
Lightvar(--color-kumo-neutral-950, oklch(15% 0 0))
Darkvar(--color-kumo-neutral-150, oklch(93.5% 0 0))
--color-kumo-shadow-edge
Lightoklch(0% 0 0 / 0.12)
Darkoklch(100% 0 0 / 0.1)
--color-kumo-shadow-drop
Lightoklch(0% 0 0 / 0.08)
Darkoklch(0% 0 0 / 0.3)
--color-kumo-arrow-edge
Lightoklch(14.5% 0 0 / 0.1)
Darktransparent
--color-kumo-arrow-stroke
Lighttransparent
Darkvar(--color-kumo-neutral-750, oklch(32% 0 0))
--color-kumo-info-tint
Lightoklch(93.2% 0.032 255.6 / 0.45)
Darkoklch(38.0% 0.145 265.5 / 0.22)
--color-kumo-info
Lightvar(--color-blue-500, oklch(68.5% 0.169 237.323))
Darkvar(--color-blue-500, oklch(68.5% 0.169 237.323))
--color-kumo-warning-tint
Lightoklch(93.1% 0.107 94.6 / 0.20)
Darkoklch(35.3% 0.079 65.0 / 0.37)
--color-kumo-warning
Lightoklch(73.9% 0.177 58.2)
Darkoklch(64.5% 0.168 50.0)
--color-kumo-danger-tint
Lightoklch(93.6% 0.032 17.7 / 0.42)
Darkoklch(42.9% 0.176 28.7 / 0.17)
--color-kumo-danger
Lightvar(--color-red-500, oklch(63.7% 0.237 25.331))
Darkvar(--color-red-600, oklch(57.7% 0.245 27.325))
--color-kumo-success-tint
Lightoklch(96.2% 0.043 156.7 / 0.57)
Darkoklch(39.3% 0.096 152.3 / 0.20)
--color-kumo-success
Lightvar(--color-emerald-600, oklch(59.6% 0.145 163.225))
Darkvar(--color-emerald-400, oklch(76.5% 0.177 163.223))

Component Colors (14)

Badge (12)

--text-color-kumo-badge-orange-subtle
Lightvar(--color-orange-800, oklch(47% 0.157 37.304))
Darkvar(--color-orange-200, oklch(90.1% 0.076 70.697))
--text-color-kumo-badge-teal-subtle
Lightvar(--color-teal-800, oklch(43.7% 0.078 188.216))
Darkvar(--color-teal-200, oklch(91% 0.096 180.426))
--text-color-kumo-badge-neutral-subtle
Lightvar(--color-neutral-800, oklch(26.9% 0 0))
Darkvar(--color-neutral-200, oklch(92.2% 0 0))
--text-color-kumo-badge-inverted
Lightvar(--color-white, #fff)
Darkvar(--color-black, #000)
--color-kumo-badge-red
Lightvar(--color-red-600, oklch(57.7% 0.245 27.325))
Darkvar(--color-red-700, oklch(50.5% 0.213 27.518))
--color-kumo-badge-green
Lightvar(--color-emerald-600, oklch(59.6% 0.145 163.225))
Darkvar(--color-emerald-700, oklch(50.8% 0.118 165.612))
--color-kumo-badge-orange
Lightvar(--color-orange-650, oklch(81.5% 0.197 76))
Darkvar(--color-orange-650, oklch(81.5% 0.197 76))
--color-kumo-badge-purple
Lightvar(--color-purple-600, oklch(55.8% 0.288 302.321))
Darkvar(--color-purple-700, oklch(49.6% 0.265 301.924))
--color-kumo-badge-teal
Lightvar(--color-teal-650, oklch(54.9% 0.096 184.565))
Darkvar(--color-teal-700, oklch(51.1% 0.096 186.391))
--color-kumo-badge-blue
Lightvar(--color-blue-600, oklch(54.6% 0.245 262.881))
Darkvar(--color-blue-700, oklch(48.8% 0.243 264.376))
--color-kumo-badge-neutral
Lightvar(--color-neutral-500, oklch(55.6% 0 0))
Darkvar(--color-neutral-600, oklch(43.9% 0 0))
--color-kumo-badge-inverted
Lightvar(--color-neutral-950, oklch(14.5% 0 0))
Darkvar(--color-white, #fff)

Banner (2)

--color-kumo-banner-info
Lightoklch(93.2% 0.032 255.585 / 0.7)
Darkoklch(37.9% 0.146 265.522 / 0.5)
--color-kumo-banner-warning
Lightvar(--color-yellow-100, oklch(97.3% 0.071 103.193))
Darkoklch(55.4% 0.135 66.442 / 0.5)