- 人工智能
- AI 应用
- 桌面应用
【免费下载链接】open-codesign
Open-source Claude Design alternative. One-click import your Claude Code / Codex API key. Prompt → prototype / slides / PDF. Multi-model (Claude, GPT, Gemini, Kimi, GLM, Ollama). BYOK, local-first, MIT.
本指南以 Open CoDesign 内置方法技能(method skill)empty-states.md 为绝对核心,讲解「首次使用 / 无结果 / 错误」三种空状态的分类规则、文案与代码模式,并结合仓库源码(技能加载器、SkillFrontmatter 校验、内置脚手架)揭示其在实际 AI 生成流程中的落地机制。读完本文,你将掌握一套可直接复用的空状态设计规范,以及 Open CoDesign 中技能文件的编写、加载与调用原理,能自己编写或改造同类的设计技能。
Open CoDesign 是一款本地优先(local-first)、支持多模型(Claude、GPT、Gemini、Kimi、GLM、Ollama)的开源设计生成工具,核心工作流是"Prompt → 原型 / 幻灯片 / PDF"。为了让 AI 生成的设计稿在细节上达到专业水准,项目内置了一批"方法技能"(method skill)——以 Markdown 编写的规则说明书,由 agent 在写代码前加载。empty-states就是其中专门约束"空状态"(empty state)设计的技能。
一、empty-states 技能是什么:定位与触发条件
empty-states是 Open CoDesign 内置技能之一,其任务定位记录在技能文件的 YAML frontmatter 中(见 empty-states.md):
name: empty-states:技能 ID,同时是skill(name)工具调用的入参;description:明确说明它为三类关键空状态设计界面——首次使用(还没有任何记录)、无结果(筛选/搜索无匹配)、错误(网络/服务失败),并用于替换一切笼统的 "No data" 占位符;trigger.providers: ['*']:对所有模型提供方(Claude、GPT、Gemini 等)通用,不区分具体厂商;trigger.scope: system:触发作用域为系统级,即任何生成任务都可能在合适时机调用;user_invocable: true:用户也可以主动要求加载该技能。
什么时候应该触发它
技能正文第一段定义了触发时机——任何可能渲染出零条数据的 UI 表面:
- 列表、表格、看板(kanban)、收件箱视图;
- 搜索与筛选结果面板;
- 依赖数据的仪表盘与统计组件;
- 通知、动态流、评论线程;
- 任何可能发生网络或查询失败的界面。
也就是说,空状态不是"最后补一个占位图"的收尾工作,而是一类必须被提前设计的状态,任何数据驱动的界面都要覆盖。
技能文件在仓库中的组织方式
empty-states技能文件位于应用模板树中:
apps/desktop/resources/templates/skills/empty-states.md根据 templates/README.md 的说明,skills/*.md是可编辑的 Markdown 方法技能,通过skill(name)加载,它们描述"如何工作"(布局、可访问性、图表、表单、响应式行为、工艺检查等)。整个resources/templates目录会在首次启动时被复制到用户的应用数据目录中,形成一棵用户可编辑的模板树,用户可以在<userData>/templates/skills/下看到并修改这些技能文件。
仓库中的技能全家桶(见 skills 目录)还包括form-layout、loading-skeleton、surface-elevation、cjk-typography、accessibility-states、responsive-layout、craft-polish等同级技能,empty-states是其中的 P0 级设计技能之一(见 apps/desktop/CHANGELOG.md 中 "5 new P0 design skills" 的发布记录)。
二、三条铁律:恰好三种空状态,绝不合并、绝不裸奔
技能的 Rules 部分确立了整个规范的核心——世界上恰好有三种空状态,每种有各自的文案模式,不能折叠成一个通用组件:
- 首次使用(First-use)——用户还没有创建第一条记录。
- 一句话解释这个功能是做什么的;
- 一个主 CTA——创建第一条记录的那个动作;
- 一张与产物相关的示意插图(发票、图表、聊天气泡),不要用通用的剪贴板或放大镜图标。
- 无结果(No-results)——用户筛选或搜索后没有任何匹配。
- 复述用户的查询:
No tickets matched "urgnet",必须原样引用实际查询词; - 从以下四种补救动作中提供两个:清除筛选(clear-filter)、扩大搜索范围(broaden-search)、拼写建议(suggest-spelling)、最近结果(recent-results);
- 绝不能复用首次使用的插图——否则用户会以为自己的数据丢失了。
- 复述用户的查询:
- 错误(Error)——请求失败。
- 用通俗语言说明原因:
Network unreachable、Server returned 500; - 主 CTA:重试(Retry);
- 次级链接:反馈问题(或打开调试详情面板);
- 绝不能让整屏只显示一条堆栈跟踪。
- 用通俗语言说明原因:
另外还有两条补充规则:
- 统计占位:统计卡片没有数据时渲染一个长破折号
—,而不是0。0是一个真实值(今天的销售额是零),—才表示"没有数据"。代码模式是{value ?? '—'}。 - 绝不允许上线一个只写着 "No data" 或 "Nothing here yet" 的界面——每一个空状态都必须回答"我接下来该做什么?"。
Do / Don't 速查
Do(应当)
- 在无结果消息中原样引用用户的查询词;
- 每个分类使用不同的插图,让用户能直观区分"第一次来"和"没有匹配";
- 错误状态提供 Retry 按钮,并在重试时使用乐观 UI(optimistic UI);
- 空状态文案与其他字符串一起进入本地化(i18n)目录。
Don't(禁止)
- 不要把首次使用插图复用到无结果状态;
- 不要在从未收到过数据的统计卡片上显示
0; - 不要单独展示技术错误码(如
Error 500),必须搭配人类可读的原因; - 不要让空状态被一个永远不结束的 spinner 遮住。
三、Code patterns:四段可直接落地的 TSX 模板
技能文件提供了四段可复制的 React/TSX 代码模式,全部基于 Tailwind 类名实现。
3.1 首次使用(First-use)
<div className="grid place-items-center gap-4 py-16 text-center"> <InvoiceIllustration className="w-32 h-32 opacity-80" /> <p className="max-w-sm text-sm text-muted-foreground"> Invoices you create will appear here. Send your first one to get paid. </p> <button className="h-11 px-4 rounded-md bg-blue-600 text-white"> Create invoice </button> </div>关键点:一句功能说明 + 一个主 CTA + 与产物强相关的插图(发票示例)。插图用opacity-80弱化视觉重量,避免喧宾夺主。
3.2 无结果(No-results)
<div className="grid place-items-center gap-3 py-12 text-center"> <SearchIllustration className="w-24 h-24 opacity-70" /> <p className="text-sm">No tickets matched <strong>"{query}"</strong>.</p> <div className="flex gap-2"> <button onClick={clearFilters} className="h-9 px-3 text-sm rounded border">Clear filters</button> <button onClick={broaden} className="h-9 px-3 text-sm rounded border">Search all projects</button> </div> </div>关键点:查询词用<strong>原样强调;提供两个补救动作(清除筛选 + 扩大搜索范围);插图换成了放大镜类(注意:它和首次使用的产物插图不同——首次使用禁止用放大镜,这里是"搜索"语义的合法场景,且不能复用首次使用插图)。
3.3 错误(Error)
<div className="grid place-items-center gap-3 py-12 text-center"> <AlertIllustration className="w-24 h-24 text-red-500" /> <p className="text-sm">Network unreachable. Check your connection and try again.</p> <button onClick={retry} className="h-10 px-4 rounded bg-blue-600 text-white">Retry</button> <a href="/support" className="text-xs underline text-muted-foreground">Report this problem</a> </div>关键点:人类可读的原因说明(Network unreachable)+ Retry 主按钮 + "Report this problem" 次级链接。错误插图用text-red-500传达警示语义。
3.4 统计占位(Stats placeholder)
<dd className="text-2xl font-semibold">{value ?? '—'}</dd>关键点:用空值合并运算符??——只有value为null/undefined时才显示—,真实的0值照常渲染。
四、从规范到实现:技能在 Open CoDesign 中如何被加载与调用
empty-states不只是一份给人看的规范,它是会被 agent 实际加载执行的"可运行规则"。理解其背后的加载机制,能让你真正掌握这类技能文件的编写方法。
4.1 Frontmatter 的 Schema 定义
技能 frontmatter 由 Zod schema SkillFrontmatterV1 严格校验,字段包括:
| 字段 | 类型/默认值 | 说明 |
|---|---|---|
schemaVersion | 字面量1 | 版本标识 |
name | 字符串(必填) | 技能名,对应文件名 slug |
description | 字符串(必填,≤1536 字符) | 给 agent 的能力描述 |
aliases | 字符串数组,默认[] | 别名,可用别名调用 |
dependencies | 字符串数组,默认[] | 依赖的其他技能 |
validationHints | 字符串数组,默认[] | 校验提示 |
trigger | {providers: ['*'], scope: 'system' \| 'prefix'} | 触发条件:适用模型、作用域 |
disable_model_invocation | 布尔,默认false | 是否禁止模型主动调用 |
user_invocable | 布尔,默认true | 是否允许用户主动调用 |
allowed_tools | 字符串数组,可选 | 技能可用的工具白名单 |
empty-states.md的 frontmatter 完全符合该 schema:providers: ['*']表示所有模型提供方通用,scope: system为系统级,disable_model_invocation: false+user_invocable: true意味着模型可以自动触发、用户也可以手动点名。
4.2 加载器与优先级
技能加载器位于 packages/core/src/skills/loader.ts,包含一套手写的轻量 YAML frontmatter 解析器(支持折叠标量>、字面量标量|、行内序列[a, b]、块序列- item等),然后通过SkillFrontmatterV1.safeParse校验,失败会抛出ERROR_CODES.SKILL_LOAD_FAILED。
加载分为三个层级,优先级为project > user > builtin(见loadAllSkills):
builtinDir:应用内置技能目录(即resources/templates/skills);userDir:~/.config/open-codesign/skills之类的用户目录;projectDir:<project>/.codesign/skills项目目录。
当多个层级存在同名技能时,高优先级覆盖低优先级——用户或项目可以改写内置技能的行为,这是技能体系可定制性的关键。
4.3 skill 工具:agent 如何"读规则"
packages/core/src/tools/skill.ts 中的makeSkillTool把技能暴露为 agent 的skill工具:
- 入参
name即技能 ID(如empty-states),描述中明确列举了empty-states等内置技能名; invokeSkill先列出技能清单(listSkillManifest),按名字或别名匹配,再从模板树中读取 Markdown 正文返回给模型;- 每个会话对每个技能只加载一次,重复调用会返回简短的 "already loaded" 提示,避免重复注入整篇文本浪费上下文(
dedup机制); - 读取路径经过
resolveSafeManifestPath安全检查:拒绝符号链接穿越模板根目录("registered path escapes template root" / "registered path traverses symbolic link"),防止路径逃逸。
也就是说,当生成任务涉及列表、仪表盘、搜索等界面时,agent 会调用skill("empty-states")把这份规范注入上下文,再据此写代码。测试用例 packages/core/src/tools/skill.test.ts 和 packages/core/src/skills/loader.test.ts 均覆盖了empty-states的加载与依赖解析。
4.4 配套脚手架:empty-states.jsx
除方法技能外,仓库还提供了配套的可复制源码片段 empty-states.jsx,在 scaffolds/manifest.json 中登记为ui-primitive类别。它内置了五种空状态变体:搜索无结果(🔍)、收件箱清零(✉️)、图表无数据(📊)、看板为空(🗂)、出错重试(⚠️),每种都包含图标、标题、说明与 CTA 按钮,可作为scaffold(kind, destPath)复制的起点素材。注意区分:skills/*.md是"方法规则"(如何做),scaffolds/ui-primitives/*.jsx是"起点素材"(直接复制的代码),二者通过 manifest 分开管理。
五、把规范落进你自己的界面:一份 5 步检查清单
把empty-states技能提炼成可执行的设计流程:
- 盘点所有零数据场景:列表、搜索、仪表盘、通知、评论线程,逐个标注属于"首次使用 / 无结果 / 错误"中的哪一类——绝不合并,也绝不遗漏错误态。
- 按分类写文案:首次使用写"功能是什么 + 下一步动作";无结果原样引用查询词并给两个补救动作;错误用通俗语言说明原因并给 Retry 与反馈入口。
- 分配插图语义:首次使用用产物相关图(发票、图表、气泡),无结果用搜索语义图,两者必须不同;错误用警示语义图。统计卡片无数据一律
—,不用0。 - 给每个空状态一个"下一步":主 CTA 指向能改变现状的动作(创建、清筛、重试、换关键词)。
- 本地化与重试体验:文案进 i18n 字符串目录;错误重试配合乐观 UI,避免用户卡在永不停歇的 spinner 前。
对照 Do / Don't 清单 逐项自检:是否复用了插图?是否显示了裸错误码?是否出现了裸 "No data"?
六、结语:空状态是一等公民,而不是事后补丁
empty-states技能的价值在于把"空状态设计"从可有可无的收尾工作提升为有明确分类、有固定文案模式、有代码模板、有落地机制的一等设计规则。在 Open CoDesign 中,它通过 frontmatter(SkillFrontmatterV1)+ Markdown 正文 + 加载器(loader.ts)+skill工具(skill.ts)这条完整链路进入每个生成会话,让任何模型在产出列表、仪表盘、搜索界面时都能遵守同一套高标准。
如果你正在 Open CoDesign 中编写自己的技能,或希望在自己的产品中推行空状态规范,可以直接把 empty-states.md 作为模板:写好 frontmatter(名称、描述、触发条件)、写清 Rules 与 Do/Don't、附上可复制的代码模式,然后放入skills目录即可被加载。记住它的核心判断:三种空状态,缺一不可;每个空状态都必须回答"下一步做什么"。
- 人工智能
- AI 应用
- 桌面应用
【免费下载链接】open-codesign
Open-source Claude Design alternative. One-click import your Claude Code / Codex API key. Prompt → prototype / slides / PDF. Multi-model (Claude, GPT, Gemini, Kimi, GLM, Ollama). BYOK, local-first, MIT.
相关推荐
Phoenix 前端空状态(Empty States)设计规范:从 "No tags" 到 "No results" 的语义化实现指南
Phoenix 前端空状态(Empty States)设计规范:从 "No tags" 到 "No results" 的语义化实现指南 Phoenix 前端(位
可观测性AI 评测LLMOpsAI 应用人工智能Open CoDesign DESIGN.md设计系统实战:把品牌规范变成可复用的AI设计记忆
Open CoDesign DESIGN.md设计系统实战:把品牌规范变成可复用的AI设计记忆 Open CoDesign 是一款开源的桌面端 AI 设计工具(
人工智能AI 应用桌面应用typescript-sdk 服务端 Tools 开发指南:registerTool 注册、参数校验与结构化输出
typescript sdk 服务端 Tools 开发指南:registerTool 注册、参数校验与结构化输出 本篇指南基于 @modelcontextpro
人工智能AI 应用桌面应用
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考