generative-ui
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseGenerative UI Skill
生成式UI技能
This skill contains the complete design system for Claude's built-in tool — the generative UI feature that renders interactive HTML/SVG widgets inline in claude.ai conversations. The guidelines below are the actual Anthropic "Imagine — Visual Creation Suite" design rules, extracted so you can produce high-quality widgets directly without needing the setup call.
show_widgetread_meHow it works: On claude.ai, Claude has access to the tool which renders raw HTML/SVG fragments inline in the conversation. This skill provides the design system, templates, and patterns to use it well.
show_widget本技能包含Claude内置工具的完整设计系统——该生成式UI功能可在claude.ai对话中内联渲染交互式HTML/SVG组件。以下指南是Anthropic官方的「Imagine — 视觉创作套件」设计规则,提取后可让你直接生成高质量组件,无需先调用进行设置。
show_widgetread_me工作原理:在claude.ai平台上,Claude可访问工具,该工具能在对话中内联渲染原始HTML/SVG片段。本技能提供了使用该工具的设计系统、模板和模式。
show_widgetStep 1: Pick the Right Visual Type
步骤1:选择合适的视觉类型
Route on the verb, not the noun. Same subject, different visual depending on what was asked:
| User says | Type | Format |
|---|---|---|
| "how does X work" | Illustrative diagram | SVG |
| "X architecture" | Structural diagram | SVG |
| "what are the steps" | Flowchart | SVG |
| "explain compound interest" | Interactive explainer | HTML |
| "compare these options" | Comparison grid | HTML |
| "show revenue chart" | Chart.js chart | HTML |
| "create a contact card" | Data record | HTML |
| "draw a sunset" | Art/illustration | SVG |
根据动词而非名词来选择。同一主题,根据用户的提问方式选择不同的视觉类型:
| 用户提问 | 类型 | 格式 |
|---|---|---|
| "X的工作原理是什么" | 说明性图表 | SVG |
| "X的架构" | 结构图表 | SVG |
| "步骤有哪些" | 流程图 | SVG |
| "解释复利" | 交互式讲解器 | HTML |
| "对比这些选项" | 对比表格 | HTML |
| "展示收入图表" | Chart.js图表 | HTML |
| "创建联系卡片" | 数据记录 | HTML |
| "画日落" | 艺术插画 | SVG |
Step 2: Build the Widget
步骤2:构建组件
Structure (strict order)
结构(严格顺序)
<style> → HTML content → <script>Output streams token-by-token. Styles must exist before the elements they target, and scripts must run after the DOM is ready.
<style> → HTML内容 → <script>输出是逐token流式传输的。样式必须在其目标元素之前定义,脚本必须在DOM准备完成后运行。
Philosophy
设计理念
- Seamless: Users shouldn't notice where the host UI ends and your widget begins
- Flat: No gradients, mesh backgrounds, noise textures, or decorative effects. Clean flat surfaces
- Compact: Show the essential inline. Explain the rest in text
- Text goes in your response, visuals go in the tool — all explanatory text, descriptions, and summaries must be written as normal response text OUTSIDE the tool call. The tool output should contain ONLY the visual element
- 无缝衔接:用户不应注意到宿主UI和组件的边界
- 扁平化:无渐变、网格背景、噪点纹理或装饰效果,采用简洁的平面设计
- 紧凑性:仅展示核心内容,其余说明用文本补充
- 文本在响应中,视觉在工具中——所有解释性文本、描述和摘要必须作为普通响应文本写在工具调用之外。工具输出应仅包含视觉元素
Core Rules
核心规则
- No or
<!-- comments -->(waste tokens, break streaming)/* comments */ - No font-size below 11px
- No emoji — use CSS shapes or SVG paths
- No gradients, drop shadows, blur, glow, or neon effects
- No dark/colored backgrounds on outer containers (transparent only — host provides the bg)
- Typography: two weights only: 400 regular, 500 medium. Never use 600 or 700. Headings: h1=22px, h2=18px, h3=16px — all font-weight 500. Body text=16px, weight 400, line-height 1.7
- Sentence case always. Never Title Case, never ALL CAPS
- No mid-sentence bolding — entity names go in not bold
code style - No ,
<!DOCTYPE>,<html>, or<head>— just content fragments<body> - No — use normal-flow layouts
position: fixed - No tabs, carousels, or sections during streaming
display: none - No nested scrolling — auto-fit height
- Corners: for cards,
border-radius: var(--border-radius-lg)for elementsvar(--border-radius-md) - No rounded corners on single-sided borders (border-left, border-top)
- Round every displayed number — use ,
Math.round(), or.toFixed(n)Intl.NumberFormat
- 禁止使用或
<!-- comments -->(浪费token,破坏流式传输)/* comments */ - 字体大小不得小于11px
- 禁止使用emoji——改用CSS形状或SVG路径
- 禁止使用渐变、阴影、模糊、发光或霓虹效果
- 外部容器不得使用深色/彩色背景(仅透明——由宿主提供背景)
- 排版:仅使用两种字重:400常规、500中等。绝不要使用600或700。标题:h1=22px,h2=18px,h3=16px——全部为font-weight 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 Allowlist (CSP-enforced)
CDN白名单(受CSP限制)
External resources may ONLY load from:
cdnjs.cloudflare.comcdn.jsdelivr.netunpkg.comesm.sh
All other origins are blocked — the request silently fails.
外部资源仅可从以下地址加载:
cdnjs.cloudflare.comcdn.jsdelivr.netunpkg.comesm.sh
所有其他源均被阻止——请求会静默失败。
CSS Variables
CSS变量
Backgrounds: (white), (surfaces), (page bg), , , ,
Text: (black), (muted), (hints), , , ,
Borders: (0.15α, default), (0.3α, hover), (0.4α), semantic
Typography: , ,
Layout: (8px), (12px), (16px)
--color-background-primary-secondary-tertiary-info-danger-success-warning--color-text-primary-secondary-tertiary-info-danger-success-warning--color-border-tertiary-secondary-primary-info/-danger/-success/-warning--font-sans--font-serif--font-mono--border-radius-md--border-radius-lg--border-radius-xlAll auto-adapt to light/dark mode.
Dark mode is mandatory — every color must work in both modes:
- In HTML: always use CSS variables for text. Never hardcode colors like
color: #333 - In SVG: use pre-built color classes (,
c-blue, etc.) — they handle light/dark automaticallyc-teal - Mental test: if the background were near-black, would every text element still be readable?
背景色:(白色)、(表面色)、(页面背景)、、、、
文本色:(黑色)、(弱化色)、(提示色)、、、、
边框色:(透明度0.15,默认)、(透明度0.3, hover状态)、(透明度0.4)、语义化的
字体:、、
布局:(8px)、(12px)、(16px)
--color-background-primary-secondary-tertiary-info-danger-success-warning--color-text-primary-secondary-tertiary-info-danger-success-warning--color-border-tertiary-secondary-primary-info/-danger/-success/-warning--font-sans--font-serif--font-mono--border-radius-md--border-radius-lg--border-radius-xl所有变量会自动适配亮色/暗色模式。
暗色模式是强制要求——每种颜色必须在两种模式下都可用:
- 在HTML中:始终使用CSS变量设置文本颜色。绝不要硬编码颜色如
color: #333 - 在SVG中:使用预定义的颜色类(、
c-blue等)——它们会自动适配亮色/暗色模式c-teal - 测试方法:如果背景接近黑色,所有文本元素是否仍清晰可读?
sendPrompt(text)
sendPrompt(text)sendPrompt(text)
sendPrompt(text)A global function that sends a message to chat as if the user typed it. Use it when the user's next step benefits from Claude thinking. Handle filtering, sorting, toggling, and calculations in JS instead.
一个全局函数,可模拟用户输入向聊天发送消息。当用户的下一步操作需要Claude进一步思考时使用。过滤、排序、切换和计算逻辑应在JS中处理。
Step 3: Render with show_widget
show_widget步骤3:使用show_widget
渲染
show_widgetThe tool is built into claude.ai — no activation needed. Pass your widget code directly:
show_widgetjson
{
"title": "snake_case_widget_name",
"widget_code": "<style>...</style>\n<div>...</div>\n<script>...</script>"
}| Parameter | Type | Required | Description |
|---|---|---|---|
| string | Yes | Snake_case identifier for the widget |
| string | Yes | HTML or SVG code. For SVG: start with |
For SVG output: start with — it will be auto-detected and wrapped appropriately.
widget_code<svgshow_widgetjson
{
"title": "snake_case_widget_name",
"widget_code": "<style>...</style>\n<div>...</div>\n<script>...</script>"
}| 参数 | 类型 | 是否必填 | 描述 |
|---|---|---|---|
| 字符串 | 是 | 组件的蛇形命名标识符 |
| 字符串 | 是 | HTML或SVG代码。SVG需以 |
对于SVG输出:需以开头——会被自动检测并适当包裹。
widget_code<svgStep 4: Chart.js Template
步骤4:Chart.js模板
For charts, use callback pattern to handle script load ordering:
onloadhtml
<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.4.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 rules:
- Canvas cannot resolve CSS variables — use hardcoded hex
- Set height ONLY on the wrapper div, never on canvas itself
- Always
responsive: true, maintainAspectRatio: false - Always disable default legend, build custom HTML legends
- Number formatting: not
-$5M(negative sign before currency symbol)$-5M - Use on CDN script tag +
onload="initChart()"as fallbackif (window.Chart) initChart();
对于图表,使用回调模式处理脚本加载顺序:
onloadhtml
<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.4.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();
Step 5: SVG Diagram Template
步骤5:SVG图表模板
For flowcharts and diagrams, use SVG with pre-built classes:
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>
<!-- Single-line node (44px tall) -->
<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>
<!-- Connector arrow -->
<line x1="340" y1="84" x2="340" y2="120" class="arr" marker-end="url(#arrow)"/>
<!-- Two-line node (56px tall) -->
<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 rules:
- ViewBox always 680px wide (). Set H to fit content + 40px padding
viewBox="0 0 680 H" - Safe area: x=40 to x=640, y=40 to y=(H-40)
- Pre-built classes: (14px),
t(12px secondary),ts(14px medium 500),th,box,node,arrc-{color} - Every element must carry a class (
<text>,t, orts)th - Use for vertical text centering in boxes
dominant-baseline="central" - Connector paths need (SVG defaults to
fill="none")fill: black - Stroke width: 0.5px for borders and edges
- Make all nodes clickable:
onclick="sendPrompt('...')"
对于流程图和图表,使用带有预定义类的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>
<!-- 单行节点(高44px) -->
<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)"/>
<!-- 双行节点(高56px) -->
<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()。设置H以适配内容并添加40px内边距
viewBox="0 0 680 H" - 安全区域:x=40至x=640,y=40至y=(H-40)
- 预定义类:(14px)、
t(12px次要文本)、ts(14px中等字重500)、th、box、node、arrc-{color} - 每个元素必须携带类(
<text>、t或ts)th - 盒子内垂直居中文本使用
dominant-baseline="central" - 连接线需设置(SVG默认
fill="none")fill: black - 边框和线条的描边宽度:0.5px
- 所有节点需可点击:
onclick="sendPrompt('...')"
Step 6: Interactive Explainer Template
步骤6:交互式讲解器模板
For interactive explainers (sliders, live calculations, inline SVG):
html
<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.4.1/chart.umd.js" onload="initChart()"></script>
<script>
function initChart() {
// slider logic, chart rendering, sendPrompt() for follow-ups
}
if (window.Chart) initChart();
</script>Use to let users ask follow-ups:
sendPrompt()sendPrompt('What if I increase the rate to 10%?')对于交互式讲解器(滑块、实时计算、内联SVG):
html
<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.4.1/chart.umd.js" onload="initChart()"></script>
<script>
function initChart() {
// 滑块逻辑、图表渲染、使用sendPrompt()处理后续问题
}
if (window.Chart) initChart();
</script>使用让用户发起后续提问:
sendPrompt()sendPrompt('What if I increase the rate to 10%?')Step 7: Respond to the User
步骤7:响应用户
After rendering the widget, briefly explain:
- What the widget shows
- How to interact with it (which controls do what)
- One key insight from the data
Keep it concise — the widget speaks for itself.
渲染组件后,简要说明:
- 组件展示的内容
- 如何与组件交互(各个控件的功能)
- 数据中的一个关键洞察
保持简洁——组件本身已说明大部分内容。
Reference Files
参考文件
- — Complete color palette (9 ramps × 7 stops), CSS variables, UI component patterns, metric cards, layout rules
references/design_system.md - — SVG viewBox setup, font calibration, pre-built classes, flowchart/structural/illustrative diagram patterns with examples
references/svg_and_diagrams.md - — Chart.js configuration, script load ordering, canvas sizing, legend patterns, dashboard layout
references/chart_js.md
Read the relevant reference file when you need specific design tokens, SVG coordinate math, or Chart.js configuration details.
- — 完整调色板(9个色系×7个色阶)、CSS变量、UI组件模式、指标卡片、布局规则
references/design_system.md - — SVG ViewBox设置、字体校准、预定义类、流程图/结构图/说明图的模式及示例
references/svg_and_diagrams.md - — Chart.js配置、脚本加载顺序、Canvas尺寸、图例模式、仪表板布局
references/chart_js.md
当你需要特定的设计标记、SVG坐标计算或Chart.js配置细节时,阅读相关参考文件。