← Croprix 品牌手册 · 源文件 tokens/README.md

Croprix design tokens

品牌视觉系统的设计 token:色彩、字体、间距、圆角、阴影、网格、断点、动效、层级。 唯一事实来源是 tokens.json(W3C Design Tokens / DTCG 格式),其余全部由 build.mjs 生成。 上游决策见 brand/decisions.md(§3 色彩、§4 字体、§5 间距等、§8 命名契约); 改动顺序:先改 decisions.md,再改 tokens.json,再跑 build。 不要手改 dist/

brand/tokens/
  tokens.json            源(DTCG)
  build.mjs              Node ≥ 24,零依赖;生成 dist/,并做 WCAG 对比度核验
  test.mjs               冒烟测试:跑 build、校验 dist 文件与抽样值
  README.md              本文
  dist/
    tokens.css           :root 变量(亮色)+ [data-theme="dark"] + prefers-color-scheme 暗色 + 基础规则
    tokens.scss          $cx-* 变量与 $cx-colors / $cx-colors-dark map
    tailwind.css         Tailwind v4 @theme
    tokens.figma.json    Tokens Studio(global / light / dark 三个 set)
    Tokens.swift         iOS / macOS(SwiftUI)
    tokens.xml           Android values(colors + dimens + integers + strings)
    tokens-night.xml     Android values-night(语义色暗色覆盖)
    contrast-report.md   WCAG 对比度核验结果

生成与测试

node brand/tokens/build.mjs      # 生成 dist/;任何门槛对比度不达标 → 非零退出并打印原因
node brand/tokens/test.mjs       # 跑 build + 校验(CI 用这一条即可)

package.json 不含任何相关依赖;两个脚本只用 Node 内置模块。

tokens.json 结构

顶层分组:color(原始 7 族 × 11 阶 + white/black;语义 bg/fg/brand/accent/border/link/success/warning/danger/info/chart)、 font.{family,size,weight,lineHeight,letterSpacing}spaceradiusshadowborder.widthcontainerbreakpointzmotion.{duration,ease}。版本在 $extensions.cx.version

命名规则

CSS:--cx-<组>-<名>[-<阶>],camelCase 转 kebab;font.lineHeight.*--cx-line-height-*font.letterSpacing.*--cx-letter-spacing-*(其余 font.* 保留 font- 前缀)。

tokens.json CSS SCSS Tailwind v4 Swift Android
color.navy.900 --cx-color-navy-900 $cx-color-navy-900 --color-navy-900bg-navy-900 CXColor.navy900 @color/cx_navy_900
color.bg.DEFAULT --cx-color-bg $cx-color-bg --color-bgbg-bg CXColor.bg @color/cx_bg
color.fg.muted --cx-color-fg-muted $cx-color-fg-muted --color-fg-muted CXColor.fgMuted @color/cx_fg_muted
color.chart.1 --cx-color-chart-1 $cx-color-chart-1 --color-chart-1 CXColor.chart1 @color/cx_chart_1
font.family.cjk --cx-font-family-cjk $cx-font-family-cjk --font-cjkfont-cjk CXFont.familyCjk @string/cx_font_family_cjk
font.size.md --cx-font-size-md $cx-font-size-md --text-mdtext-md CXFont.sizeMd @dimen/cx_font_size_md
font.lineHeight.cjk.md --cx-line-height-cjk-md $cx-line-height-cjk-md --leading-cjk-md CXFont.lineHeightCjkMd @dimen/cx_line_height_cjk_md
font.letterSpacing.caps --cx-letter-spacing-caps $cx-letter-spacing-caps --tracking-caps CXFont.letterSpacingCaps @dimen/cx_letter_spacing_caps
space.4 --cx-space-4 $cx-space-4 --spacing-4p-4 CXSpace.s4 @dimen/cx_space_4
radius.md --cx-radius-md $cx-radius-md --radius-mdrounded-md CXRadius.md @dimen/cx_radius_md
shadow.md --cx-shadow-md $cx-shadow-md --shadow-mdshadow-md
motion.ease.standard --cx-motion-ease-standard $cx-motion-ease-standard --ease-standard @string/cx_motion_ease_standard

单位

接入

官网 / Next.js

/* app/globals.css */
@import "../../brand/tokens/dist/tokens.css";

tokens.css 已含基础规则:html { font-family: var(--cx-font-family-sans); font-variant-numeric: tabular-nums }:lang(zh|ja|ko|ar|fa|hi|th) 按文字系统切换字体族,code/kbd/pre/samp 用等宽, prefers-reduced-motion 时所有 --cx-motion-duration-* 归零。暗色两条路径: <html data-theme="dark"> 显式切换;无 data-theme 时跟随系统 prefers-color-scheme: darkdata-theme="light" 强制亮色。字体文件(@font-face)不在此,由 brand/assets/fonts/ 与官网 public/fonts/ 负责。

CJK 行高与字重不在基础规则里自动切换(会覆盖组件级行高):组件在 :lang(zh) 下自行取 --cx-line-height-cjk-*,标题字重取 500/600。

Tailwind v4

@import "tailwindcss";
@import "../../brand/tokens/dist/tailwind.css";

tailwind.css 内部 @import "./tokens.css",所以不必再单独引 tokens.css。原始色在 @theme(静态 hex), 语义色在 @theme inline 里指向 var(--cx-color-*),因此 bg-bg text-fg border-border 会随主题切换。 字号 text-md 自带行高(--text-md--line-height)。--spacing-* 只声明 §5 的 14 档, 但 Tailwind v4 默认的 --spacing: 0.25rem 乘数与 4px 基准一致,其它数字仍可用。 Tailwind 命名与 --cx-* 不同:--color-*--font-*--text-*--font-weight-*--leading-*--tracking-*--spacing-*--radius-*--shadow-*--breakpoint-*--container-*--ease-*

SCSS

@use "../../brand/tokens/dist/tokens" as cx;
color: cx.$cx-color-fg;
background: map-get(cx.$cx-colors, "navy-900");

SCSS 只有亮色字面量;暗色语义值在 $cx-colors-dark map 里,主题切换请用 CSS 变量而不是 SCSS。

Figma(Tokens Studio)

Tokens Studio 插件 → Tools → Load from file / JSON → 选 dist/tokens.figma.json。 三个 set:global(原始色、字体、间距等)、lightdark(语义色与阴影,值为对 global 的引用); $themes 已定义 Light / Dark 两个主题(global 为 source,light/dark 分别 enabled)。 导出 Figma Variables 时会得到 color/bg/DEFAULTcolor/bg/raised 这样的路径。 字号 px、行高 %、字距 %、间距 px、阴影 dropShadow

iOS / macOS

dist/Tokens.swift 加进 target:

Text("Croprix").foregroundStyle(CXColor.fg).font(CXFont.sans(CXFont.sizeMd, weight: CXFont.weightSemibold))
    .padding(CXSpace.s4).background(CXColor.bgRaised, in: RoundedRectangle(cornerRadius: CXRadius.md))

语义色用文件末尾的 Color(light:dark:) 扩展,跟随系统外观(UIKit 走 UIColor(dynamicProvider:), AppKit 走 NSColor(name:dynamicProvider:))。字体名 CXFont.familySans = "Montserrat" 要求 App 已打包该字体。

Android

dist/tokens.xmlres/values/tokens.xmldist/tokens-night.xmlres/values-night/tokens.xml (values-night 里文件名随意,同名覆盖即可)。语义色是 @color/ 引用,夜间自动切换。 间距 dp、字号 sp、行高 / 字距为 float dimen、字重 / z / 时长为 integer、字体栈与缓动为 string。

对比度核验

dist/contrast-report.md 由 build 自动生成。门槛:正文角色 ≥ 4.5:1,大字 / 图形 / 装饰角色 ≥ 3:1。 核验矩阵:fgfg.mutedbrandlinksuccesswarningdangerinfo 各对 bg / bg.raised / bg.sunken (正文 4.5);fg.subtle 同三底(装饰 3.0);accent.fgaccent(4.5);whiteaccent(大字 3.0,仅亮色); fg.inversebg.inverse(4.5);chart.1–6bg(图形 3.0);亮暗两套。 另有几组"参考组合"只记录不拦截(accentbgaccent.fgaccent.hoverborder.strongbg)。

语义映射(fg.subtle=sand.600、success=leaf.800、warning=harvest.700、danger=crimson.700、chart.2/3/4/6 各深一阶)是按上述门槛核验后定稿的值,decisions.md §3.3 表与本仓库 tokens.json 一致;改任一方都要重跑 build 并看 contrast-report.md

官网 src/styles/tokens.css → 新 token 对应表

官网现有变量(ACTIVE SLOTS 部分)与本系统的对应关系。本次不改官网;迁移时按此表替换。 "≈" 表示明度接近但不是同一色(官网原值是 oklch 手调,新系统是色阶)。

官网变量 新 token(CSS) 说明
--paper / --bg / --surface --cx-color-bg 页面底(sand.50 / navy.950)
--paper-2 / --surface-sunk --cx-color-bg-sunken
--paper-3 --cx-color-sand-200(暗 --cx-color-navy-800 无语义角色,用原始阶
--surface-raised --cx-color-bg-raised
--surface-night / --surface-night-2 --cx-color-navy-950 / --cx-color-navy-900 亮色页面上的夜色面板,固定原始色
--ink / --fg-1 / --on-paper --cx-color-fg
--ink-2 / --fg-2 --cx-color-sand-900 官网 L 0.32;新系统没有"fg 第二级",用 sand.900
--ink-3 / --fg-3 --cx-color-fg-muted
--ink-4 / --fg-4 --cx-color-fg-subtle
--hairline --cx-color-border 官网是半透明墨,新系统是实色 sand.200
--hairline-strong --cx-color-border-strong
--leaf / --moss / --accent --cx-color-accent
--leaf-deep / --moss-deep --cx-color-accent-hover
--leaf-soft / --moss-soft --cx-color-accent-soft
--navy --cx-color-brand
--navy-deep --cx-color-brand-strong
--navy-soft --cx-color-navy-100(暗 --cx-color-navy-800
--harvest / --warning --cx-color-warning(文字)/ --cx-color-chart-3(填充)
--harvest-soft --cx-color-harvest-100(暗 --cx-color-harvest-900
--soil --cx-color-soil-800(暗 --cx-color-soil-400
--soil-soft --cx-color-soil-200(暗 --cx-color-soil-900
--sky --cx-color-sky-400
--sky-deep / --info --cx-color-info
--signal / --live --cx-color-leaf-400 "在线 / 活体"指示点;图形角色,对 navy.950 7.4:1
--crimson / --danger --cx-color-danger
--positive --cx-color-success
--on-leaf --cx-color-accent-fg
--on-navy / --on-ink --cx-color-fg-inverse
--on-navy-2 / --on-navy-3 --cx-color-sand-300 / --cx-color-sand-500 反色区块上的次级 / 三级文字
--logo-ink --cx-color-navy-900,暗 --cx-color-white 暗色请直接换 croprix-logo-reverse.svg 资产
--font-display / --font-sans --cx-font-family-sans 中文由 :lang(zh) 规则切到 --cx-font-family-cjk,不再混在一个栈里
--font-mono --cx-font-family-mono
--fs-12 / --fs-13 --cx-font-size-xs(12.8px)
--fs-14 / --fs-15 --cx-font-size-sm(14px)
--fs-16 / --fs-17 / --fs-18 --cx-font-size-md(16px)
--fs-20 --cx-font-size-lg(20px)
--fs-24 / --fs-28 --cx-font-size-xl(25px)
--fs-32 --cx-font-size-2xl(31px)
--fs-40 --cx-font-size-3xl(39px)
--fs-56 --cx-font-size-4xl(49px)
--fs-72 / --fs-96 --cx-font-size-5xl(61px) 新阶封顶 61px
--lh-tight / --lh-snug --cx-line-height-5xl(1.05)/ --cx-line-height-2xl(1.2) 行高随字号阶走,不再独立命名
--lh-body --cx-line-height-md(1.6)
--lh-loose --cx-line-height-cjk-md(1.75)/ --cx-line-height-vi-md(1.7)
--space-2 / --space-6 4px 基准里没有 2 / 6,就近取 --cx-space-1 / --cx-space-2
--space-4--space-128 --cx-space-1--cx-space-32(同像素值,rem 单位) 官网按像素命名,新系统按 4px 步数命名
--radius-xs/sm/md/lg --cx-radius-xs/sm/md/lg
--radius-xl(20px) --cx-radius-xl(16px)或 --cx-radius-2xl(24px)
--radius-pill --cx-radius-full
--shadow-sm/md/lg --cx-shadow-sm/md/lg 官网暖墨色阴影 → navy 色相阴影
--shadow-inset inset 0 0 0 var(--cx-border-width-hairline) var(--cx-color-border)
--ease --cx-motion-ease-standard
--dur-fast / --dur-med / --dur-slow --cx-motion-duration-fast / -base / -enter 240→200ms,480→400ms
--max-content(1320px) --cx-container-lg(1200px)或 --cx-container-xl(1440px)
--max-prose(640px) 组件级值,保留在官网
--gutter(80px) --cx-container-margin-lg(48px)+ --cx-space-20(80px) 页边距按断点取 margin.sm/md/lg
--theme 改读 html[data-theme]