Impeccable colorize 配色指南:在既有品牌世界里引入有策略的颜色
【免费下载链接】impeccableThe design language that makes your AI harness better at design.项目地址: https://gitcode.com/GitHub_Trending/im/impeccable
背景上下文:执行 colorize 前,需要先获取并确认现有品牌颜色作为额外上下文(existing brand colors)。
Impeccable 的colorize命令(技能定义见 SKILL.md)用于为过于单调、灰暗、缺乏视觉兴趣的界面引入有策略的颜色:把颜色当作**层级(hierarchy)、意义(meaning)与氛围(atmosphere)**来使用,而不是在"上色"的幌子下替换整个视觉世界。读完本篇,你将掌握 colorize 的完整工作流——从 visitor mode 判定、选色前审计、策略命名,到 OKLCH 色阶推导、WCAG 对比验证、系统尺度应用,以及 Live 模式下的color-amount签名参数契约;同时你会看到这些规则如何在仓库的 Rust 实现(crates/foundation/src/color.rs、crates/context/src/palette.rs)与工程质量地板(craft-floor.md)中得到落地。
一、colorize 的定位与核心原则
在 Impeccable 的命令体系中,colorize属于Enhance(增强)类命令。其在 command-metadata.json 中的定义为:
Add strategic color to features that are too monochromatic or lack visual interest, making interfaces more engaging and expressive. Use when the user mentions the design looking gray, dull, lacking warmth, needing more color, or wanting a more vibrant or expressive palette.
即:当用户提到设计"看起来灰、沉闷、缺少温度、需要更多颜色、想要更鲜明更有表现力的调色板"时触发。触发场景明确、目标单一——为既有界面加入有策略的颜色。
colorize 的第一条铁律写在文档开头:
引入颜色作为层级、意义与氛围。保留已确认的品牌与语义惯例;不要借"上色"之名替换一个视觉世界。
这句话定义了命令的边界:
- 保留品牌承诺:已确认的 brand colors 是约束,不是素材;
- 保留语义惯例:成功/警告/错误/信息的既有语义色不能因"好看"而被改写;
- 不是身份替换:如果任务真正要求的是一个全新身份(new identity),colorize 不负责这件事,应转入 new-work.md。
从源码结构看,这套"保留 vs 替换"的分界与 SKILL.md 中"Refinement preserves; redesign replaces"的原则一脉相承:colorize 属于 refinement,默认保留既有身份,只有用户显式要求重建时才进入 departure 模式。
二、先定 visitor mode:颜色在这块表面上承载什么
动手选色之前,必须先回答一个问题:这块表面的访客成功长什么样?Impeccable 将其划分为四类 mode(见 SKILL.md),colorize 文档将其归并为两种颜色策略:
| 模式组合 | 颜色的职责 |
|---|---|
| Persuade + Experience(营销、活动、作品集、画廊) | 颜色可以承载"声音"(voice),当所选视觉世界需要时,可以占有大面积区域;设计即产品,颜色是说服与体验的一部分 |
| Operate + Read(应用 UI、仪表盘、文档、帮助) | 颜色主要用于编码动作、选中、状态、寻路与阅读层级;此时稀缺性赋予强调色力量——颜色用得越少,单一强调色越有力 |
同一块表面必须二选一,且 mode 只在对应的 surface brief 中持久化。这也是后续一切颜色决策的前提:在 Operate 界面上把大面积区域染成氛围色,与在 Persuade 页面上使用克制点缀一样,都是策略错位。
三、选色前先审计:读什么、找什么
"先审计,再选色"是 colorize 的固定步骤。在执行任何颜色编辑之前,需要读取以下输入:
- DESIGN.md(视觉系统字段,若缺失则从 CSS 变量、计算样式与兄弟组件提取身份);
- tokens(原始色值与语义 token,若项目有 token 系统);
- assets(真实资源,避免在占位色上做决策);
- 当前主题(light/dark 各一套);
- 代表性状态(hover、disabled、loading、error、empty 等)。
在此基础上逐项识别(对应文档原文六条清单):
- 哪些颜色是已确认的品牌承诺;
- 当前的表面、文本、动作与语义角色分别是什么;
- 哪些位置灰度掩盖了层级或状态;
- 存在哪些对比失败与纯颜色传达(color-only communication)问题;
- 是否存在亮/暗主题或数据可视化要求;
- 任务要的是更多颜色,还是一个全新身份。
审计结论决定后续分支:若需要全新身份,使用 new-work.md;只有当无法从现有材料推断出有约束力的品牌决策时,才向用户提问。换言之,推断优先、提问兜底。
四、选择策略:先命名意图,再动笔
colorize 要求在任何编辑之前,先命名四个设计意图:
- 情绪温度(emotional temperature):这片颜色是冷、暖、中性还是混合;
- 主导关系(dominant relationship):主色与表面、强调色之间是什么关系;
- 对比范围(contrast range):从最亮到最暗的跨度;
- 颜色剂量(color dosage):颜色覆盖多少面积、出现多少次。
策略可以是克制的(restrained),也可以是沉浸式的(immersive),但必须服从 brief 与所选视觉世界,而不是套用一个固定百分比规则("不超过 X% 的彩色"这类教条被明确否决)。
构建角色,而非一袋色卡
这是 colorize 的核心方法论:调色板不是一堆好看的色值,而是一组职责明确的角色(roles)。文档列出八类角色:
- canvas 与抬升表面(elevated surfaces);
- 主文本与次级文本;
- 动作、焦点与选中(action / focus / selection);
- 边框与分隔线;
- 成功、警告、错误与信息(语义色);
- 需要时的数据类别或刻度。
每一类角色都应能在界面上找到自己的"职位描述";没有角色的颜色就是装饰,而"与层级、状态、内容或视觉世界无关的装饰,不是颜色策略"(文档原话)。
色彩空间:优先 OKLCH
- 使用项目现有的色彩空间——不要为了"现代"而强行改写既有体系;
- 对于全新的 web 调色板,优先 OKLCH,因为它的lightness(明度)与 chroma(彩度)可以可预测地独立调整;
- 色相(hue)从产品含义与视觉方向中选择,绝不从默认的类别联想中选(比如"金融=蓝、健康=绿"这种默认映射是被明确否定的)。
仓库对此提供了直接的工具支撑:impeccable palette命令(crates/context/src/palette.rs)内置了由 palette_data.rs 生成的 100+ 个种子(seed),每个种子都以oklch(L C H)三元组为核心,并附带一句 mood(氛围)与一句 strategy(策略提示)。例如:
Seed { id: "seed-201", l: 0.647, c: 0.262, h: 0.3, mood: "sealing-wax crimson — one confident stamp of red on pristine white paper", strategy: "Pure white surface lets a high-chroma crimson primary do all the brand work, paired with a hue-shifted warm coral accent for hierarchy without competing saturation" }种子通过--id <seed>直接选取,或用--from <key>对 key 做 SHA-256 哈希后加权挑选(hash_unit与weighted_pick实现于 palette.rs),也可通过环境变量IMPECCABLE_PALETTE_SEED指定。输出会给出oklch(L C H)原值、色相的自然语言描述(hue_word,如 "pure red"、"teal"、"cobalt / indigo")以及一条示例策略。这正呼应了"色相从产品含义出发"的原则——种子提供的是方向与参考,最终 hue 仍由产品含义裁定。
五、在系统尺度上应用颜色
colorize 不追求"这里加一点、那里加一点",而是强调**系统尺度(system scale)**上的应用。文档给出七条操作性规则:
- 让最强的颜色拥有一个刻意的区域或角色,而不是散落成小碎点(scattering tiny accents);
- 保持主操作易被发现——不要把它专属的颜色花在装饰上;
- 中性色染色要克制:只有当品牌色调真正创造凝聚力时才给中性色染色;当灰符合该视觉世界时,中性灰是完全有效的选择;
- 彩色表面上的次级文本,从前景色或表面色派生,而不是用洗过的泛灰(washed-out generic gray);
- 保持语义含义一致,但尊重平台与领域惯例,不要假定固定的语义色相(平台惯例优先于个人偏好);
- 数据可视化中,颜色不能是唯一编码——同时使用明度、彩度、形状、标签或图案,保证色弱用户也能区分;
- 暗色模式要显式设计表面高度与对比,不要机械地反转亮色主题。
当项目存在 token 系统时,还应先定义原始值(primitives)与语义 token(semantic tokens),主题切换通常只重映射语义角色——即亮暗主题共享同一组原始色值,通过语义 token 指向不同的原始值,而不是为暗色主题另起一套颜色。
六、对比与感知:用计算验证,而非肉眼
颜色策略是否成立,最终要落到计算过的前景/背景对比上。colorize 文档给出的 WCAG AA 最低门槛如下:
| 内容 | WCAG AA 最低对比 |
|---|---|
| 正文文本(body text) | 4.5:1 |
| 大号文本(large text) | 3:1 |
| 控件、图标、焦点指示(controls, icons, focus indicators) | 3:1 |
并且强调:不要只依赖肉眼判断。需要检查的状态包括:交互状态(hover/active/focus)、叠加层(overlays)、图片上的文字、禁用内容(disabled content)、以及亮暗两套主题;还应模拟常见视觉缺陷(色盲/色弱)。凡是用颜色传达的信息,必须同时有文本、形状、图标或位置作为冗余通道。
源码中的对比与中性判断
这些规则在仓库中有直接的 Rust 实现(crates/foundation/src/color.rs),它们支撑着 Impeccable 的检测器在编辑后自动核查颜色质量:
relative_luminance与contrast_ratio:按 WCAG 相对亮度公式计算对比度——正是上面表格三条门槛的度量函数;is_neutral_color:用正则解析rgb/rgba、oklch/lch/oklab/lab、hsl/hwb等多种写法,通过 max-min 差(RGB 阈值 30)或彩度阈值(OKLCH 阈值 0.02、HSL 饱和度阈值 10 等)判定某颜色是否"中性"——用于识别"该有颜色却灰掉"的区域;has_chroma(c, threshold = 30):判断颜色是否带彩度;get_hue:从 RGB 计算色相角,支撑色相族划分;composite_color_over与parse_color_mix:处理半透明叠加与color-mix()——对应文档中"优先显式颜色而非半透明叠加链"的规则。
工程地板 craft-floor.md 对颜色提出了与 colorize 一致的硬性检查:"Contrast: body and placeholder text ≥4.5:1, large text ≥3:1. On colored surfaces tint secondary text from that hue or the foreground; never gray."(正文与占位文本 ≥4.5:1,大号文本 ≥3:1;彩色表面上的次级文本从该色调或前景色派生,绝不用灰。)当项目的设计钩子(hook)开启时,这些机械检查会在编辑时自动执行,colorize 需要与检测结果协同。
OKLCH 色阶推导的要点
文档对 OKLCH ramp 的推导给出两条明确约束:
- 变化 lightness,并在接近纯白与纯黑时降低 chroma;
- 不要为了数学上的均匀,在极端明度处维持高 chroma(高彩度在极亮/极暗处是感知错误,不是精确)。
另一个关键建议:优先显式颜色,而不是一串半透明叠加层——因为 alpha 会让最终对比变得依赖上下文(叠在什么上面就是什么),无法稳定通过对比验证。这正是composite_color_over这类函数存在的意义:把叠加结果算出来,再验证算出来的实色。
七、验证清单与交接
颜色全部落地后,按以下五项逐条验证(对应文档原文):
- 每个颜色都有一个稳定的角色,或一个属于该视觉世界的氛围用途;
- 注意力落在预期的动作、内容或状态上;
- 调色板在安静、密集、交互、错误与空状态下都成立;
- 亮暗主题各自被独立构图,而非机械反转;
- 对比与非颜色线索在所有相关状态下通过;
- 最终结果可被认出是这款产品,而不是通用的"彩色化"处理。
当调色板证明了自己的位置后,交接给/impeccable polish做最终质量收尾。
八、Live 模式下的 colorize:color-amount 签名参数
当 colorize 从live 模式被调用时,存在一个强制契约:每个 variant 都必须声明一个color-amount参数。CSS 必须基于var(--p-color-amount, 0.5)编写,这样用户可以在中性与该 variant 的完整颜色策略之间连续滑动,而无需重新生成。
参数定义(文档原文 JSON):
{"id":"color-amount","kind":"range","min":0,"max":1,"step":0.05,"default":0.5,"label":"Color amount"}这是一个range类型的滑块:min0、max1、step0.05、默认值 0.5。滑块在浏览器中以零成本驱动 CSS 变量--p-color-amount,你的作用域 CSS 里写作var(--p-color-amount, 0.5)。
除color-amount外,最多再添加两个 variant-specific 参数,例如 palette(调色板选择)、temperature(冷暖)或 tint behavior(染色行为)。所有参数都必须遵循 live.md 的参数契约。
live 模式下 colorize 的完整行为
结合 live.md 可以还原 colorize 在 live 会话中的完整语义:
- 每次 colorize 调用,三个 variant 必须是不同的色相家族,并且变化彩度与对比策略("different hue family each; vary chroma and contrast strategy")——这与上文"每个 variant 从不同主轴上做文章"的原则一致;
- 参数是设计的一部分:在规划三个 variant 时就要为每个 variant 命名 2–3 个参数旋钮,而不是事后补装;
- 参数预算按元素的视觉体量缩放:叶级/微型元素(按钮、图标、裸标题)0 参数;小型组合(简单卡片、带标签输入框,≤5 个视觉子元素)0–1 个;中型组合(区块、导航簇,6–15 个)目标 2 个;大型组合(hero、整个区域,16+ 个)目标 2–3 个,硬上限 4 个。
color-amount是 colorize 的 MUST 参数,在预算内强制占位且不可重复; - 参数声明写在 wrapper 属性
data-impeccable-params上(组件预览路径则写在componentDir/params.json,按 variant 编号键控,schema 相同); - 接受(accept)时,浏览器回传当前参数值,
impeccable live-accept将其写成兄弟注释<!-- impeccable-param-values SESSION_ID: {"color-amount":0.7} -->;随后的 carbonize 清理会把滑块值烘焙进源码——range参数替换为字面量或更新变量的默认值。
因此,live 模式下的 colorize 工作流是:规划三个不同色相家族与彩度/对比策略的 variant → 每个 variant 声明color-amount(+ 至多两个辅助参数)→ 用var(--p-color-amount, 0.5)编写 CSS → 交付后由用户实时滑动参数预览 → 接受后将参数值烘焙为永久形式。
结语
colorize 的全部规则可以浓缩为一句话:颜色在 Impeccable 里是系统的角色分配,不是装饰的剂量游戏。从 visitor mode 判定、选色前审计、策略命名,到 OKLCH 色阶、WCAG 计算验证、语义 token 重映射,再到 live 模式下必须携带的color-amount签名参数——每一步都在回答同一个问题:"这个颜色在这个界面上负责什么?" 而 crates/foundation/src/color.rs 的对比/中性/色相判定函数、crates/context/src/palette.rs 的 OKLCH 种子库与 craft-floor.md 的地板检查,共同把这份设计判断落成了可计算、可验证、可复用的工程能力。
【免费下载链接】impeccableThe design language that makes your AI harness better at design.项目地址: https://gitcode.com/GitHub_Trending/im/impeccable
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考