mcpField
G
generative-ui

generative-ui

github.com/himself65设计与 UI3.5k3.4k 次安装3 天前更新
代码仓库

关于 generative-ui

用于借助 Claude 内置 show_widget 工具创建交互式 HTML 和 SVG 小组件的设计 Skill,面向 Claude 用户及其他宿主环境工作流,提供视觉类型选择、样式规范和模板;不支持该工具时也说明独立 HTML 输出方式。

主要功能

  1. 01视觉类型选择指引
  2. 02HTML 与 SVG 小组件模式
  3. 03适配浅色和深色模式的设计规范
  4. 04Chart.js 配置指引
  5. 05按宿主环境区分渲染方法

适用场景

  1. 01制作内嵌交互式说明
  2. 02将选项对比呈现为视觉网格
  3. 03在对话中呈现图表或示意图
  4. 04show_widget 不可用时保存独立小组件

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/himself65/finance-skills --skill generative-ui

安装后在 Claude Code 中输入/generative-ui确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

README.md
references/
chart_js.md
design_system.md
svg_and_diagrams.md

详细介绍

生成式 UI 技能

此技能包含 Claude 内置 show_widget 工具的完整设计系统——这项生成式 UI 功能可在 claude.ai 对话中内联呈现交互式 HTML/SVG 小组件。以下指南是从 Anthropic 的「Imagine — Visual Creation Suite」设计规则中提取的实际规则,因此无需调用 read_me 进行初始化,也能直接制作高质量小组件。

工作原理:在 claude.ai 上,Claude 可以使用 show_widget 工具,在对话中内联呈现原始 HTML/SVG 片段。此技能提供了设计系统、模板和使用模式,帮助你更好地使用该工具。

Codex 和其他宿主环境:先检查可用工具。若宿主环境提供了文档说明的可视化接口,请使用该接口;否则,将完整的 HTML 文档保存到工作区,并返回可点击的文件链接。对于独立输出,以下仅允许片段的规则不适用:请包含文档包装结构和视口元数据,定义模板使用的 CSS 变量和 SVG 类(包括暗色模式颜色),并显式加载图表依赖。以下宿主环境专用 CDN 允许列表和注入样式描述的是 Claude 的渲染器,并非 Codex 的能力。如果宿主环境不支持聊天后续操作按钮和 sendPrompt 处理程序,请移除它们;本地滑块和计算功能则应保持可用。条件允许时,请在浏览器中验证已保存的输出。


第 1 步:选择合适的可视化类型

根据动词来选择,而不是名词。同一主题会根据用户的需求采用不同的可视化形式:

用户的说法类型格式
「X 是如何工作的」说明性示意图SVG
「X 架构」结构图SVG
「有哪些步骤」流程图SVG
「解释复利」交互式说明HTML
「比较这些选项」对比网格HTML
「显示收入图表」Chart.js 图表HTML
「创建联系卡片」数据记录HTML
「画一幅日落」艺术作品/插画SVG

第 2 步:构建小组件

结构(严格顺序)
<style>  →  HTML content  →  <script>

内容会逐个令牌地流式输出。样式必须先于其目标元素定义,脚本必须在 DOM 就绪后运行。

设计理念
  • 无缝:用户不应察觉宿主 UI 与小组件的边界
  • 扁平:不要使用渐变、网格背景、噪声纹理或装饰效果。采用简洁的纯色表面
  • 紧凑:在线展示核心内容,其余内容用文字说明
  • 避免默认的「AI 设计」风格:不要使用奶油色或米白色面板、标题中的斜体强调词、编号式「01 / 02 / 03」章节标签、代码之外的等宽字体标签,以及胶囊形按钮——这些风格显得千篇一律,也与宿主 UI 不协调
  • 文字放在回复中,可视化内容放在工具中——说明文字、描述和摘要应作为工具调用之外的普通回复文本;小组件中只保留可视化元素
核心规则
  • 不要使用 `` 或 /* 注释 */(浪费令牌,会破坏流式传输)
  • 字号不得低于 11px
  • 不要使用表情符号——请使用 CSS 图形或 SVG 路径
  • 不要使用渐变、投影、模糊、发光或霓虹效果
  • 外层容器不得使用深色/彩色背景(仅限透明背景——宿主会提供背景)
  • 排版:仅使用两种字重:400 常规、500 中等。绝不使用 600 或 700。标题:h1=22px、h2=18px、h3=16px——字重均为 500。正文=16px、字重 400、行高 1.7
  • 始终使用句首字母大写格式。不要使用标题式大小写,也不要全部大写
  • 不要在句中加粗——实体名称使用 代码样式,不要用 粗体
  • 不要使用 <!DOCTYPE>、<html>、<head> 或 <body>——只使用内容片段
  • 不要使用 position: fixed——请使用常规文档流布局
  • 流式传输期间不要使用选项卡、轮播或 display: none 区块
  • 不要嵌套滚动——高度应自动适配
  • 圆角:卡片使用 border-radius: var(--border-radius-lg),元素使用 var(--border-radius-md)
  • 单侧边框(border-left、border-top)不要添加圆角
  • 所有显示的数字都要取整——使用 Math.round()、.toFixed(n) 或 Intl.NumberFormat
CDN 允许列表(由 CSP 强制执行)

外部资源仅允许从以下来源加载:

  • cdnjs.cloudflare.com
  • cdn.jsdelivr.net
  • unpkg.com
  • esm.sh

所有其他来源都会被拦截——请求会静默失败。

CSS 变量

背景:--color-background-primary(白色)、-secondary(表面)、-tertiary(页面背景)、-info、-danger、-success、-warning 文本:--color-text-primary(黑色)、-secondary(柔和)、-tertiary(提示)、-info、-danger、-success、-warning 边框:--color-border-tertiary(0.15α,默认)、-secondary(0.3α,悬停)、-primary(0.4α)、语义色 -info/-danger/-success/-warning 排版:--font-sans、--font-serif、--font-mono 布局:--border-radius-md(8px)、--border-radius-lg(12px)、--border-radius-xl(16px)

所有变量都会自动适配浅色/深色模式。

深色模式为必选项——所有颜色在两种模式下都必须适用:

  • 在 HTML 中:文本始终使用 CSS 变量。不要硬编码颜色,例如 color: #333
  • 在 SVG 中:使用预设颜色类(c-blue、c-teal 等)——它们会自动适配浅色/深色模式
  • 自检:如果背景接近黑色,每个文本元素是否仍然清晰可读?
sendPrompt(text)

一个全局函数,可将消息发送到聊天中,就像用户亲自输入一样。当用户的下一步操作适合让 Claude 思考时,请使用它。过滤、排序、切换和计算则应在 JS 中处理。


第 3 步:使用可用宿主渲染

当宿主提供 show_widget 时,请按以下示例直接传入 widget 代码。在 Codex 中,如果没有该工具,请使用上述独立 HTML 方案;不要自行编造 show_widget 调用。

{
  "title": "snake_case_widget_name",
  "widget_code": "<style>...</style>\n<div>...</div>\n<script>...</script>"
}
参数类型必填描述
titlestring是用于 widget 的 snake_case 标识符
widget_codestring是HTML 或 SVG 代码。若为 SVG:以 <svg> 开头。若为 HTML:使用内容片段

对于 SVG 输出:让 widget_code 以 <svg 开头——系统会自动检测并进行适当封装。


第 4 步:Chart.js 模板

对于图表,请使用 onload 回调模式处理脚本加载顺序:

<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 12px;">
  <div style="background: var(--color-background-secondary); border-radius: var(--border-radius-md); padding: 1rem;">
    <div style="font-size: 13px; color: var(--color-text-secondary);">Label</div>
    <div style="font-size: 24px; font-weight: 500;" id="stat1">—</div>
  </div>
</div>

<div style="position: relative; width: 100%; height: 300px; margin-top: 1rem;">
  <canvas id="myChart"></canvas>
</div>

<div style="display: flex; align-items: center; gap: 12px; margin-top: 1rem;">
  <label style="font-size: 14px; color: var(--color-text-secondary);">Parameter</label>
  <input type="range" min="0" max="100" value="50" id="param" step="1" style="flex: 1;" />
  <span style="font-size: 14px; font-weight: 500; min-width: 32px;" id="param-out">50</span>
</div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/4.5.1/chart.umd.js" onload="initChart()"></script>
<script>
function initChart() {
  const slider = document.getElementById('param');
  const out = document.getElementById('param-out');
  let chart = null;

  function update() {
    const val = parseFloat(slider.value);
    out.textContent = val;
    document.getElementById('stat1').textContent = val.toFixed(1);

    const labels = [], data = [];
    for (let x = 0; x <= 100; x++) {
      labels.push(x);
      data.push(x * val / 100);
    }

    if (chart) chart.destroy();
    chart = new Chart(document.getElementById('myChart'), {
      type: 'line',
      data: { labels, datasets: [{ data, borderColor: '#7F77DD', borderWidth: 2, pointRadius: 0, fill: false }] },
      options: {
        responsive: true,
        maintainAspectRatio: false,
        plugins: { legend: { display: false } },
        scales: { x: { grid: { display: false } } }
      }
    });
  }

  slider.addEventListener('input', update);
  update();
}
if (window.Chart) initChart();
</script>

Chart.js 规则:

  • Canvas 无法解析 CSS 变量——请使用硬编码的十六进制颜色值
  • 仅在包装器 div 上设置高度,绝不要在 canvas 本身设置
  • 始终设置 responsive: true, maintainAspectRatio: false
  • 始终禁用默认图例,并自行构建 HTML 图例
  • 数字格式:-$5M,而非 $-5M(负号放在货币符号前)
  • 在 CDN 脚本标签上使用 onload="initChart()",并添加 if (window.Chart) initChart(); 作为备用方案

第 5 步:SVG 图表模板

对于流程图和图表,请使用带有预置类的 SVG:

<svg width="100%" viewBox="0 0 680 H">
  <defs>
    <marker id="arrow" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="6" markerHeight="6" orient="auto-start-reverse">
      <path d="M2 1L8 5L2 9" fill="none" stroke="context-stroke" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
    </marker>
  </defs>

  
  <g class="node c-blue" onclick="sendPrompt('Tell me more about this')">
    <rect x="250" y="40" width="180" height="44" rx="8" stroke-width="0.5"/>
    <text class="th" x="340" y="62" text-anchor="middle" dominant-baseline="central">Step one</text>
  </g>

  
  <line x1="340" y1="84" x2="340" y2="120" class="arr" marker-end="url(#arrow)"/>

  
  <g class="node c-teal" onclick="sendPrompt('Explain this step')">
    <rect x="230" y="120" width="220" height="56" rx="8" stroke-width="0.5"/>
    <text class="th" x="340" y="140" text-anchor="middle" dominant-baseline="central">Step two</text>
    <text class="ts" x="340" y="158" text-anchor="middle" dominant-baseline="central">Processes the input</text>
  </g>
</svg>

SVG 规则:

  • ViewBox 始终为 680px 宽(viewBox="0 0 680 H")。将 H 设置为适配内容并留出 40px 内边距
  • 安全区域:x=40 至 x=640,y=40 至 y=(H-40)
  • 预置类:t(14px)、ts(12px 次要文本)、th(14px 中等字重 500)、box、node、arr、c-{color}
  • 每个 <text> 元素都必须带有类(t、ts 或 th)
  • 在框内垂直居中文字时,使用 dominant-baseline="central"
  • 连接线路径需要设置 fill="none"(SVG 默认值为 fill: black)
  • 描边宽度:边框和边缘为 0.5px
  • 让所有节点都可点击:onclick="sendPrompt('...')"

第 6 步:交互式讲解模板

对于交互式讲解(滑块、实时计算、内嵌 SVG):

<div style="display: flex; align-items: center; gap: 12px; margin: 0 0 1.5rem;">
  <label style="font-size: 14px; color: var(--color-text-secondary);">Years</label>
  <input type="range" min="1" max="40" value="20" id="years" style="flex: 1;" />
  <span style="font-size: 14px; font-weight: 500; min-width: 24px;" id="years-out">20</span>
</div>

<div style="display: flex; align-items: baseline; gap: 8px; margin: 0 0 1.5rem;">
  <span style="font-size: 14px; color: var(--color-text-secondary);">$1,000 →</span>
  <span style="font-size: 24px; font-weight: 500;" id="result">$3,870</span>
</div>

<div style="margin: 2rem 0; position: relative; height: 240px;">
  <canvas id="chart"></canvas>
</div>

<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/4.5.1/chart.umd.js" onload="initChart()"></script>
<script>
function initChart() {
  // slider logic, chart rendering, sendPrompt() for follow-ups
}
if (window.Chart) initChart();
</script>

使用 sendPrompt() 让用户提出后续问题:sendPrompt('What if I increase the rate to 10%?')


第 7 步:回复用户

渲染小组件后,简要说明:

  1. 小组件展示了什么
  2. 如何与之交互(各控件的作用)
  3. 数据中的一个关键发现

保持简洁——小组件本身已能说明问题。


参考文件

  • references/design_system.md — 完整的色彩调色板(9 组 × 7 个色阶)、CSS 变量、UI 组件模式、指标卡片、布局规则
  • references/svg_and_diagrams.md — SVG viewBox 设置、字体校准、预置类,以及带示例的流程图/结构图/说明性图表模式
  • references/chart_js.md — Chart.js 配置、脚本加载顺序、画布尺寸、图例模式、仪表板布局

需要特定设计令牌、SVG 坐标计算或 Chart.js 配置详情时,请阅读相关参考文件。

评论

支持 Markdown