关于 pencilplaybook
pencilplaybook 是用于 Pencil 界面设计的技能,通过配置流程和可复用布局脚手架指导屏幕制作,适合设计应用及营销页面的设计人员。它还包含画布尺寸检查、设计指南和品牌变量工作流。
主要功能
- 01配置与入门说明
- 02九种可复用布局脚手架
- 03画布尺寸验证
- 04设计指南与令牌工作流
适用场景
- 01搭建应用仪表盘或数据表格
- 02按 390×844px 设计移动屏幕
- 03设计营销页面并在 390px 宽度检查
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ stevembarclay/ pencilplaybook --skill pencilplaybook安装后在 Claude Code 中输入/pencilplaybook确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
.gitignoreCHANGELOG.mdLICENSEonboarding.mdREADME.mdsetup.md.claude/skills/best-in-world-strategy/references/question-bank.md.claude/skills/skill-creator/LICENSE.txt.claude/skills/skill-creator/scripts/init_skill.pyquick_validate.pypackage_skill.pypresets/grove.jsonember.jsonmaterial.jsonmidnight.jsonbloom.jsonvolt.jsonminimal.jsonreferences/tool-reference.md详细介绍
Pencil Pro
主要解析规则
首次使用前必须配置此技能。
如果用户说“运行 PencilPlaybook 设置向导”或要求设置或配置 PencilPlaybook:
→ 阅读 .claude/skills/pencilplaybook/setup.md 并严格按照其中的说明操作。
如果用户说“使用 PencilPlaybook 构建我的第一个屏幕”或要求开始设计:
→ 阅读 .claude/skills/pencilplaybook/onboarding.md 并严格按照其中的说明操作。
已配置的分辨率:(运行设置以配置)
如果现有 .pen 文件中的屏幕根节点与已配置的分辨率不匹配,请在编辑前指出。若画布尺寸有误,切勿直接在其上构建而不说明偏差。
常见例外 — 营销页面: 无论应用分辨率如何,均按 1440px 设计。营销页面会在各种浏览器宽度下展示——按 1440px 设计,并在 390px 下验证。
会话启动(每次 Pencil 会话)
1. get_editor_state() — check active document and selection
2. open_document("path/to/your-file.pen") — open target file
3. get_guidelines(topic="web-app") — load design guidelines
4. set_variables(<token map below>) — inject brand tokens
5. get_variables() — confirm tokens stored
6. snapshot_layout() — verify canvas dimensions
你的 token 映射 — 在每次会话开始时,使用此对象运行 set_variables。变量可能不会在不同的 Claude Code 会话之间保留。
{
"color-primary": "YOUR_HEX",
"color-primary-dark": "YOUR_HEX",
"color-accent": "YOUR_HEX",
"color-background": "YOUR_HEX",
"color-surface": "YOUR_HEX",
"color-border": "YOUR_HEX",
"color-text": "YOUR_HEX",
"color-text-muted": "YOUR_HEX",
"color-success": "YOUR_HEX",
"color-warning": "YOUR_HEX",
"color-error": "YOUR_HEX",
"font-sans": "YOUR_FONT",
"font-mono": "YOUR_FONT",
"font-serif": "YOUR_FONT",
"spacing-card": "24",
"spacing-gap-sm": "8",
"spacing-gap-md": "16",
"spacing-gap-lg": "24",
"spacing-gap-xl": "32",
"content-max-width": "YOUR_VALUE",
"sidebar-width": "YOUR_VALUE"
}
运行 set_variables 后,调用 get_variables() 确认所有 token 均已存储。
脚手架脚本
九个脚手架脚本,涵盖最常见的布局类型。使用前先运行设置向导,填入下方的尺寸和颜色值。
脚手架 A — 应用仪表盘
指标、KPI、活动动态、监控
sidebar=I("root", {name:"Sidebar", width:SCAFFOLD_SIDEBAR_WIDTH, height:SCAFFOLD_CANVAS_HEIGHT, bg:"SIDEBAR_BG", display:"flex", flexDirection:"column"})
pageArea=I("root", {name:"PageArea", width:SCAFFOLD_PAGE_AREA_WIDTH, height:SCAFFOLD_CANVAS_HEIGHT, x:SCAFFOLD_SIDEBAR_WIDTH, bg:"PAGE_BG"})
pageHeader=I("pageArea", {name:"PageHeader", width:SCAFFOLD_PAGE_AREA_WIDTH, height:64, bg:"SURFACE_COLOR", borderBottom:"1px solid BORDER_COLOR", display:"flex", alignItems:"center", px:32})
statsBar=I("pageArea", {name:"StatsBar", y:64, width:SCAFFOLD_PAGE_AREA_WIDTH, height:80, bg:"STATS_BG", display:"flex", alignItems:"center", gap:24, px:32})
contentWrap=I("pageArea", {name:"ContentWrap", y:144, width:SCAFFOLD_PAGE_AREA_WIDTH, height:SCAFFOLD_CONTENT_HEIGHT_A, display:"flex", justifyContent:"center", p:32})
contentInner=I("contentWrap", {name:"ContentInner", width:SCAFFOLD_CONTENT_MAX, display:"flex", flexDirection:"column", gap:24})
脚手架完成后:运行 snapshot_layout(),确认 pageArea.width 和 contentInner.width 正确。
脚手架 B — 应用列表 / 队列
表格、资源库、队列、用户管理
sidebar=I("root", {name:"Sidebar", width:SCAFFOLD_SIDEBAR_WIDTH, height:SCAFFOLD_CANVAS_HEIGHT, bg:"SIDEBAR_BG"})
pageArea=I("root", {name:"PageArea", width:SCAFFOLD_PAGE_AREA_WIDTH, height:SCAFFOLD_CANVAS_HEIGHT, x:SCAFFOLD_SIDEBAR_WIDTH, bg:"PAGE_BG"})
pageHeader=I("pageArea", {name:"PageHeader", width:SCAFFOLD_PAGE_AREA_WIDTH, height:64, bg:"SURFACE_COLOR", borderBottom:"1px solid BORDER_COLOR", display:"flex", alignItems:"center", px:32})
commandStrip=I("pageArea", {name:"CommandStrip", y:64, width:SCAFFOLD_PAGE_AREA_WIDTH, height:52, bg:"SURFACE_COLOR", borderBottom:"1px solid BORDER_COLOR", display:"flex", alignItems:"center", gap:16, px:32})
tableWrap=I("pageArea", {name:"TableWrap", y:116, width:SCAFFOLD_PAGE_AREA_WIDTH, height:SCAFFOLD_CONTENT_HEIGHT_B, display:"flex", justifyContent:"center", px:32, pt:24})
tableInner=I("tableWrap", {name:"TableInner", width:SCAFFOLD_CONTENT_MAX, display:"flex", flexDirection:"column", gap:0})
tableHeader=I("tableInner", {name:"TableHeader", width:SCAFFOLD_CONTENT_MAX, height:40, bg:"TABLE_HEADER_BG", borderBottom:"1px solid BORDER_COLOR", display:"flex", alignItems:"center"})
脚手架 C — 应用详情 / 审核
双面板详情视图、审核流程、并排布局
sidebar=I("root", {name:"Sidebar", width:SCAFFOLD_SIDEBAR_WIDTH, height:SCAFFOLD_CANVAS_HEIGHT, bg:"SIDEBAR_BG"})
pageArea=I("root", {name:"PageArea", width:SCAFFOLD_PAGE_AREA_WIDTH, height:SCAFFOLD_CANVAS_HEIGHT, x:SCAFFOLD_SIDEBAR_WIDTH, bg:"PAGE_BG"})
pageHeader=I("pageArea", {name:"PageHeader", width:SCAFFOLD_PAGE_AREA_WIDTH, height:64, bg:"SURFACE_COLOR", borderBottom:"1px solid BORDER_COLOR"})
actionBar=I("pageArea", {name:"ActionBar", y:64, width:SCAFFOLD_PAGE_AREA_WIDTH, height:56, bg:"SURFACE_COLOR", borderBottom:"1px solid BORDER_COLOR"})
contentWrap=I("pageArea", {name:"ContentWrap", y:120, width:SCAFFOLD_PAGE_AREA_WIDTH, height:SCAFFOLD_CONTENT_HEIGHT_C, display:"flex", justifyContent:"center"})
contentInner=I("contentWrap", {name:"ContentInner", width:SCAFFOLD_CONTENT_MAX, height:SCAFFOLD_CONTENT_HEIGHT_C, display:"flex", gap:0})
leftPanel=I("contentInner", {name:"LeftPanel", width:SCAFFOLD_LEFT_PANEL, height:SCAFFOLD_CONTENT_HEIGHT_C, bg:"SURFACE_COLOR", borderRight:"1px solid BORDER_COLOR"})
rightPanel=I("contentInner", {name:"RightPanel", width:SCAFFOLD_RIGHT_PANEL, height:SCAFFOLD_CONTENT_HEIGHT_C, bg:"PAGE_BG", p:24, display:"flex", flexDirection:"column", gap:20})
注意:左右分栏默认约为 40/60。根据功能调整——常见比例:40/60、38/62、50/50。
脚手架 D — 营销页面
落地页、产品页——无论应用画布尺寸如何,始终为 1440px 宽
navbar=I("root", {name:"Navbar", width:1440, height:72, bg:"SURFACE_COLOR", borderBottom:"1px solid BORDER_COLOR", display:"flex", alignItems:"center", px:80})
heroSection=I("root", {name:"HeroSection", y:72, width:1440, height:600, bg:"HERO_BG", display:"flex", flexDirection:"column", alignItems:"center", justifyContent:"center"})
heroContent=I("heroSection", {name:"HeroContent", width:SCAFFOLD_MARKETING_CONTENT_MAX, display:"flex", flexDirection:"column", alignItems:"center", gap:24})
section1=I("root", {name:"Section1", y:672, width:1440, height:480, bg:"SURFACE_COLOR", display:"flex", flexDirection:"column", alignItems:"center", py:80})
section1Content=I("section1", {name:"Section1Content", width:SCAFFOLD_MARKETING_CONTENT_MAX})
营销页面采用移动优先设计。按 1440px 设计,并在交付前验证 390px 宽度下的布局。
脚手架 E — 模态框 / 对话框
确认操作、破坏性操作、快速编辑表单、侧边预览面板
先运行脚手架 A、B 或 C。然后在 pageArea 上叠加此模态框——不要将其插入根节点。
backdrop=I("pageArea", {name:"ModalBackdrop", width:SCAFFOLD_PAGE_AREA_WIDTH, height:SCAFFOLD_CANVAS_HEIGHT, bg:"rgba(0,0,0,0.48)", display:"flex", alignItems:"center", justifyContent:"center"})
modal=I("backdrop", {name:"Modal", width:480, bg:"SURFACE_COLOR", borderRadius:8, border:"1px solid BORDER_COLOR", display:"flex", flexDirection:"column", overflow:"hidden"})
modalHeader=I("modal", {name:"ModalHeader", height:56, px:24, display:"flex", alignItems:"center", justifyContent:"space-between", borderBottom:"1px solid BORDER_COLOR"})
modalBody=I("modal", {name:"ModalBody", px:24, py:20, display:"flex", flexDirection:"column", gap:16})
modalFooter=I("modal", {name:"ModalFooter", height:60, px:24, display:"flex", alignItems:"center", justifyContent:"flex-end", gap:12, borderTop:"1px solid BORDER_COLOR"})
脚手架完成后:运行 snapshot_layout(),确认模态框可见且居中。根据使用场景调整模态框宽度:380px(紧凑型确认框)、480px(标准表单)、600px(宽表单)、720px(详情 / 预览)。
脚手架 F — 向导 / 步骤条
多步骤表单、引导流程、设置步骤、结账
sidebar=I("root", {name:"Sidebar", width:SCAFFOLD_SIDEBAR_WIDTH, height:SCAFFOLD_CANVAS_HEIGHT, bg:"SIDEBAR_BG"})
pageArea=I("root", {name:"PageArea", width:SCAFFOLD_PAGE_AREA_WIDTH, height:SCAFFOLD_CANVAS_HEIGHT, x:SCAFFOLD_SIDEBAR_WIDTH, bg:"PAGE_BG"})
pageHeader=I("pageArea", {name:"PageHeader", width:SCAFFOLD_PAGE_AREA_WIDTH, height:64, bg:"SURFACE_COLOR", borderBottom:"1px solid BORDER_COLOR", display:"flex", alignItems:"center", px:32})
stepperBar=I("pageArea", {name:"StepperBar", y:64, width:SCAFFOLD_PAGE_AREA_WIDTH, height:60, bg:"SURFACE_COLOR", borderBottom:"1px solid BORDER_COLOR", display:"flex", alignItems:"center", justifyContent:"center"})
contentWrap=I("pageArea", {name:"ContentWrap", y:124, width:SCAFFOLD_PAGE_AREA_WIDTH, height:SCAFFOLD_CONTENT_HEIGHT_F, display:"flex", justifyContent:"center", px:32, pt:32})
contentInner=I("contentWrap", {name:"ContentInner", width:640, display:"flex", flexDirection:"column", gap:24})
actionFooter=I("pageArea", {name:"ActionFooter", y:SCAFFOLD_WIZARD_FOOTER_Y, width:SCAFFOLD_PAGE_AREA_WIDTH, height:72, bg:"SURFACE_COLOR", borderTop:"1px solid BORDER_COLOR", display:"flex", alignItems:"center", justifyContent:"space-between", px:32})
注意:ContentInner 默认宽 640px,适用于专注的单列表单。在 ActionFooter 中将返回按钮放在左侧、下一步 / 提交按钮放在右侧(justifyContent:"space-between")。
脚手架 G — 移动屏幕
390×844px(iPhone 14 标准尺寸)。所有移动屏幕均使用此脚手架——尺寸为硬编码,无需设置值。
statusBar=I("root", {name:"StatusBar", width:390, height:44, bg:"PAGE_BG"})
navBar=I("root", {name:"NavBar", y:44, width:390, height:56, bg:"SURFACE_COLOR", borderBottom:"1px solid BORDER_COLOR", display:"flex", alignItems:"center", px:16})
scrollContent=I("root", {name:"ScrollContent", y:100, width:390, height:688, bg:"PAGE_BG", display:"flex", flexDirection:"column", overflow:"hidden"})
contentPad=I("scrollContent", {name:"ContentPad", width:390, display:"flex", flexDirection:"column", gap:16, px:16, pt:16})
bottomNav=I("root", {name:"BottomNav", y:788, width:390, height:56, bg:"SURFACE_COLOR", borderTop:"1px solid BORDER_COLOR", display:"flex", alignItems:"center", justifyContent:"space-around"})
注意:如果不显示系统界面,请移除 statusBar 并将 navBar.y 设为 0。对于没有标签导航的应用,请移除 bottomNav。此脚手架中的触控目标必须至少为 44×44px。
脚手架 H — 表单 / 数据录入
设置页、个人资料编辑、大量数据录入——单列居中表单
sidebar=I("root", {name:"Sidebar", width:SCAFFOLD_SIDEBAR_WIDTH, height:SCAFFOLD_CANVAS_HEIGHT, bg:"SIDEBAR_BG"})
pageArea=I("root", {name:"PageArea", width:SCAFFOLD_PAGE_AREA_WIDTH, height:SCAFFOLD_CANVAS_HEIGHT, x:SCAFFOLD_SIDEBAR_WIDTH, bg:"PAGE_BG"})
pageHeader=I("pageArea", {name:"PageHeader", width:SCAFFOLD_PAGE_AREA_WIDTH, height:64, bg:"SURFACE_COLOR", borderBottom:"1px solid BORDER_COLOR", display:"flex", alignItems:"center", justifyContent:"space-between", px:32})
formWrap=I("pageArea", {name:"FormWrap", y:64, width:SCAFFOLD_PAGE_AREA_WIDTH, height:SCAFFOLD_CONTENT_HEIGHT_H, display:"flex", justifyContent:"center", px:32, pt:32})
formInner=I("formWrap", {name:"FormInner", width:600, display:"flex", flexDirection:"column", gap:28})
formSection=I("formInner", {name:"FormSection1", display:"flex", flexDirection:"column", gap:16})
formActions=I("formInner", {name:"FormActions", display:"flex", gap:12, justifyContent:"flex-end"})
注意:FormInner 默认宽 600px。简单流程使用 480px,宽版双列布局使用 800px。在 formInner 内添加更多 FormSection 节点,以对相关字段分组。
脚手架 I — 空状态 / 引导步骤
无数据视图、首次使用提示、功能发现、空白占位屏幕
sidebar=I("root", {name:"Sidebar", width:SCAFFOLD_SIDEBAR_WIDTH, height:SCAFFOLD_CANVAS_HEIGHT, bg:"SIDEBAR_BG"})
pageArea=I("root", {name:"PageArea", width:SCAFFOLD_PAGE_AREA_WIDTH, height:SCAFFOLD_CANVAS_HEIGHT, x:SCAFFOLD_SIDEBAR_WIDTH, bg:"PAGE_BG"})
pageHeader=I("pageArea", {name:"PageHeader", width:SCAFFOLD_PAGE_AREA_WIDTH, height:64, bg:"SURFACE_COLOR", borderBottom:"1px solid BORDER_COLOR"})
emptyCenter=I("pageArea", {name:"EmptyCenter", y:64, width:SCAFFOLD_PAGE_AREA_WIDTH, height:SCAFFOLD_CONTENT_HEIGHT_H, display:"flex", alignItems:"center", justifyContent:"center"})
emptyContent=I("emptyCenter", {name:"EmptyContent", width:400, display:"flex", flexDirection:"column", alignItems:"center", gap:20})
illustrationArea=I("emptyContent", {name:"IllustrationArea", width:200, height:160, borderRadius:12, bg:"SURFACE_COLOR", border:"1px solid BORDER_COLOR", display:"flex", alignItems:"center", justifyContent:"center"})
textStack=I("emptyContent", {name:"TextStack", width:400, display:"flex", flexDirection:"column", alignItems:"center", gap:8})
emptyActions=I("emptyContent", {name:"EmptyActions", display:"flex", gap:12})
注意:将 IllustrationArea 替换为 G("illustrationArea", "ai", "your prompt") 以生成插图。空状态文案应简短:一个标题(16–18px)、一行辅助说明(14px,弱化显示)、一个主要 CTA。
核心工作流
工作流 1:画布考古
适用场景:“这个 .pen 文件里有什么?”或准备编辑一个你最近没处理过的文件时。
1. open_document("path/to/file.pen")
2. get_editor_state() — get root node IDs
3. batch_get(patterns=["*"]) — read full node tree
4. snapshot_layout() — see computed dimensions
阅读 batch_get 的输出,梳理:有哪些屏幕、各自的尺寸、正在使用哪些令牌,以及哪些元素的命名清晰、哪些不清晰。先在脑中建立模型,再进行任何更改。
**检查画布尺寸:**任何与已配置分辨率不符的屏幕,都是旧版画布,或是为其他目标而构建的。请记录下来。如果要重新设计,请使用上方的脚手架,在目标分辨率下重建。
工作流 2:设计令牌传播
适用场景:品牌颜色或字体发生变化,需要在现有 .pen 文件中同步更新时。
步骤 1 — 检查当前值:
search_all_unique_properties(parentIds=["root"])
查找所有旧令牌值的实例。
步骤 2 — 替换:
replace_all_matching_properties(
parentIds=["root"],
matchProperty="bg",
matchValue="#OLD_VALUE",
newValue="#NEW_VALUE"
)
对使用已更改令牌的每种属性类型(bg、color、borderColor 等)分别运行一次。
步骤 3 — 截图验证:
get_screenshot(nodeId="[root or key screen id]")
常见的令牌传播场景:
- 颜色更改:分别替换
bg、color、borderColor、fill - 字体更改:替换所有文本节点中的
fontFamily - 间距更改:替换特定的
gap、p、px、py值——请谨慎操作;许多元素可能出于不同的结构原因而共用相同的数值
工作流 3:画布空间管理
适用场景:向现有 .pen 文件添加新屏幕时。
find_empty_space_on_canvas(
direction="right",
desiredWidth=SCAFFOLD_CANVAS_WIDTH,
desiredHeight=SCAFFOLD_CANVAS_HEIGHT
)
将返回的 x/y 坐标用作新屏幕根框架的位置。
多屏幕 .pen 文件的约定:
- 屏幕从左到右排列,每列放置一个屏幕
- 屏幕之间的水平间距约为 120px
- 同一屏幕的相关状态纵向堆叠,间距约为 80px
- 屏幕命名格式:
"Screen N — [Name] ([state])"——例如"Screen 2 — User Profile (edit mode)"
工作流 4:获取风格指南(新页面类型)
适用场景:构建应用尚未设计过的页面类型时。
1. get_style_guide_tags()
2. get_style_guide(tags=["enterprise", "dashboard", "minimal", "professional"])
风格指南提供灵感——如果与设计系统存在风格冲突,以设计系统为准。保留:构图规范、留白模式、数据密度处理方式。舍弃:任何与既定视觉语言冲突的内容。
工作流 5:批量检查属性
适用场景:检查 .pen 文件的一致性,或准备替换令牌时。
search_all_unique_properties(
parentIds=["root"],
propertyNames=["bg", "color", "fontFamily", "fontSize", "gap"]
)
用于查找本应使用令牌的硬编码十六进制值、异常字体大小,或破坏网格的间距值。
工作流 6:版本快照(保护你的工作)
适用场景:进行重大重新设计、重构或切换文件之前。
提示词模板:
Using PencilPlaybook, create a version snapshot comment at the top of the
current canvas. Include: current date/time, list of all screens, active
design tokens summary, and a short note of what is about to change.
这相当于一个轻量级撤销检查点,有助于在多个 .pen 文件之间保持一致性。请在以下操作前运行:
- 在大型文件中传播令牌
- 进行结构重构(更改布局、拆分面板)
- 移交给其他会话或协作者
工具参考
快速查阅——完整参数文档见 references/tool-reference.md。
| 工具 | 适用场景 |
|---|---|
get_editor_state | 每次会话开始时 |
open_document | 打开 .pen 文件;输入 "new" 可新建空白画布 |
get_guidelines | 加载设计规则(应用屏幕使用 topic="web-app") |
get_style_guide_tags | 查看可用的灵感标签 |
get_style_guide | 获取新页面类型的灵感 |
batch_get | 读取节点树——用于画布考古 |
batch_design | 创建、更新、复制、移动、删除节点 |
snapshot_layout | 每次搭建脚手架后验证计算所得的尺寸 |
get_screenshot | 每个主要构建步骤后进行视觉检查 |
get_variables | 检查当前令牌状态 |
set_variables | 注入品牌令牌 |
find_empty_space_on_canvas | 放置新屏幕,避免重叠 |
search_all_unique_properties | 替换令牌前检查所有值 |
replace_all_matching_properties | 批量替换令牌 |
export_nodes | 开发人员接手前导出为 PNG/PDF |
屏幕命名与版本控制
文件内命名:
"Screen N — [Feature] ([state])""Screen 1 — Dashboard (empty)"/"Screen 1 — Dashboard (populated)"- 迭代:添加后缀
[v2 post-feedback]— 不要创建新文件
迭代时切勿创建新的 .pen 文件。 将带版本号的屏幕添加到同一文件中。
文件命名:
mockups/<feature>-v1.pen — initial design
mockups/<feature>-redesign.pen — full redesign (significant divergence)
与利益相关方分享后,避免重命名 .pen 文件——这会导致交接文档中的引用失效。
感知设计默认值
用于在 Pencil 中构建组件的速查表。这些默认值有科学依据——除非你的设计系统另有规定,否则请使用这些默认值。
字体排印
| 属性 | 尺寸范围 | 默认值 | 原因 |
|---|---|---|---|
| 字间距 | 56px+(展示文字) | −0.03em | 大字号下字腔看起来更开阔 |
| 字间距 | 32–48px(标题) | −0.015em | 适度收紧 |
| 字间距 | 14–18px(正文) | 0(正常) | 字体通常针对这一范围进行了优化 |
| 字间距 | 10–12px(说明文字) | +0.015em | 小字号下字腔会变窄 |
| 行高 | 正文 | 至少为 1.5× | WCAG SC 1.4.12 |
| 行高 | 标题 | 1.1–1.2× | 更紧凑,提升视觉密度 |
| 行长 | 正文 | 45–75 个字符(65ch 为最佳) | Baymard Institute |
| 最小字号 | 任意文字 | 10px | 小于 10px 时,屏幕上的文字难以辨认 |
颜色
| 属性 | 默认值 | 原因 |
|---|---|---|
| 禁用状态不透明度 | 40% | 50% 会产生有竞争感的虚影;40% 则能充分弱化。(MD3,Workday) |
| 悬停亮度变化 | 至少 8% | 在大多数显示器上,低于 8% 时难以察觉。(NNGroup) |
| 深色表面正文颜色 | #E2E8F0 或 #F1F5F9 | 在非常深的背景上使用纯白会产生光晕。标题可使用白色。(APCA) |
| 非文本对比度 | 至少 3:1 | 图标、边框、表单控件与相邻颜色之间的对比度。(WCAG 2.2 SC 1.4.11) |
| 文本对比度 | 至少 4.5:1 | 正文。大号文字(24px+ 或 18.66px+ 粗体):3:1。(WCAG AA) |
动效
| 属性 | 默认值 | 原因 |
|---|---|---|
| 最短时长 | 100ms | 低于此时长,动效难以察觉——应直接切换 |
| 标准时长 | 200–300ms | 适用于大多数 UI 过渡 |
| 最长时长 | 400ms | 仅用于复杂编排。切勿超过 500ms。 |
| 进入缓动 | cubic-bezier(0, 0, 0.2, 1) | 减速——让进入的元素平稳停下 |
| 退出缓动 | cubic-bezier(0.4, 0, 1, 1) | 加速——让离开的元素迅速消失 |
| 标准缓动 | cubic-bezier(0.4, 0, 0.2, 1) | 用于屏幕内重新定位 |
间距
| 属性 | 默认值 | 原因 |
|---|---|---|
| 触控目标(移动设备) | 44×44px | Apple HIG 的工程目标 |
| 触控目标(桌面设备最小值) | 24×24px | WCAG 2.2 SC 2.5.8 的最低要求 |
| 按钮高度(主要按钮) | 40–44px | 提供舒适的点击目标 |
| 按钮高度(紧凑型) | 32px | 适用于密集型 UI 和次要操作 |
| 边框圆角(卡片) | 最大 8px | >8px 会显得偏消费级或随意 |
| 边框圆角(按钮) | 6px | 对应外侧 8px 圆角、内缩 2px 后的卡片内侧圆角 |
| 焦点环偏移 | 2px | 圆环半径 = 组件圆角 + 2px(WCAG 2.2 SC 2.4.13) |
图标
| 属性 | 默认值 | 原因 |
|---|---|---|
| 最小尺寸 | 16×16px | 小于 16px 时,图标在 1x 密度下会失去清晰度 |
| 描边粗细 | 1.5px(标准),2px(强调) | 与文本的粗细层级保持一致 |
| 视觉对齐 | 圆形图标下移 1px | 相较于方形边界,圆形看起来会悬浮 |
| 触控目标内边距 | 使用透明点击区域扩展至 44×44px | 图标视觉尺寸可以是 20px,点击目标为 44px |
常见错误
| 错误 | 修正方法 |
|---|---|
| 未配置的 SKILL.md | 首次使用前运行 run the PencilPlaybook setup wizard |
| 使用了错误的分辨率构建 | 每次搭建脚手架后都检查 snapshot_layout() |
| 使用硬编码的十六进制值,而非令牌 | 每次会话都先运行 set_variables |
| 将所有屏幕放在一个超大画板中 | 为每个屏幕分别创建画板。使用 find_empty_space_on_canvas 进行布局 |
| 凭感觉替换令牌 | 使用 search_all_unique_properties + replace_all_matching_properties |
| 凭记忆描述 .pen 文件内容 | 先运行 batch_get。绝不要臆测文件内容 |
脚手架搭建后跳过 snapshot_layout | 在你基于损坏的结构继续构建前,发现 0px 尺寸问题 |
单次 batch_design 调用超过 25 个操作 | 将大型构建拆分为多次调用 |
边缘情况
Claude 忽略你的令牌时
如果某项设计决策与配置的令牌映射不符(颜色错误、字体大小随意、擅自使用十六进制值):
- 明确指出:“这个颜色不在令牌映射中。请使用会话开始时设置的变量中的
color-primary。” - 运行
get_variables(),确认令牌确实已设置——如果映射为空,说明跳过了set_variables。重新运行会话启动流程。 - 运行
search_all_unique_properties(parentIds=["root"], propertyNames=["bg","color"]),找出混入的硬编码值,然后批量替换。
如果 Claude 仍在擅自编造值:暂停,在提示词中大声重读 SKILL.md——“使用 PencilPlaybook,[指令]”——重新锚定技能上下文。
从损坏的脚手架中恢复
症状:snapshot_layout() 显示某个节点的 width: 0 或 height: 0。
原因:几乎总是以下情况之一:
- 弹性容器没有明确尺寸,且没有能迫使其扩展的子项
- 父级没有明确宽度,子项却在其中使用了
width:"fill_container" - 绝对定位节点的
x/y坐标冲突或缺失
修复步骤:
1. snapshot_layout() — identify the 0px node
2. batch_get(nodeIds=["[broken-node-id]"]) — inspect its properties
3. U("[broken-node-id]", {width: N, height: N}) — add explicit dimensions
4. snapshot_layout() — confirm fixed before continuing
如果脚手架损坏严重,无法修补:删除根画板(D("frame-id")),使用 get_editor_state() 确认状态干净,然后从头重新搭建脚手架。
多画布项目
在同一会话中处理多个 .pen 文件时:
- 令牌不会在文件之间保留。 每次调用
open_document都需要重新运行set_variables。将令牌映射保存在 SKILL.md 中,并在每次打开文件时粘贴。 - 编辑每个文件前都运行 Canvas Archaeology。 绝不要凭记忆臆测文件结构——始终先运行
batch_get(patterns=["*"])。 - 一次处理一个文件。 不要交错对两个已打开文件调用
batch_design。完成文件 A 的工作后,再打开文件 B。 - 确保跨文件一致性。 如果某个组件出现在多个文件中,请使用完全相同的节点名称。名称不一致会导致令牌传播和审计脚本不可靠。