关于 create-canvas
create-canvas 是用于构建自由布局工作区的技能,可将项目内容呈现为可命名、可移动的预览。它指导在现有仓库中实现画布,并关注安全隔离、可访问的手势,以及仅保存布局而不保存预览内容。
主要功能
- 01通过注册表管理画布项目
- 02移动、平移和缩放预览
- 03使用无障碍控件复制项目名称
- 04保存视角、主题和位置
- 05使用合成数据隔离预览
适用场景
- 01探索多个 UI 组件版本
- 02在工作区排列带名称的组件预览
- 03重新加载后保留画布布局
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ ibelick/ ui-skills --skill create-canvas安装后在 Claude Code 中输入/create-canvas确认已加载。
详细介绍
创建画布
通过对话构建一个自由布局的工作区,用于探索和迭代。模型会修改源文件中的内容。画布会让这些内容成为实时内容,并且有名称、可移动且易于引用。
从项目开始
- 阅读仓库规则、路由、组件 API、主题、设计令牌和测试。
- 创建新画布前,先查找是否已有画布。
- 使用项目的框架、组件、字体排版、设计令牌、主题和访问控制。
- 遵守有关编辑、命令和浏览器访问的限制。
- 更改范围、添加依赖项、修改共享代码或公开画布前,先征求同意。
- 如果无法确定如何安全隔离,请先询问再继续。切勿挂载不安全的预览。
- 其他决策采用合理的默认值。不要要求用户重复明确的请求。
- 将画布代码放在一起。将摄像机和放置逻辑与预览、测试数据及其注册表分开。不要构建框架。
- 从一个安全的实时预览、一个易读的标签和一个独立的移动手柄开始。确保它能够挂载。
- 接下来添加注册表和所需内容。然后添加复制、摄像机控制、现有主题和已保存布局。
在源代码中保留内容
注册表是画布项的类型化列表。每个条目都定义稳定的 ID、唯一且易读的名称、组件、安全的测试数据、初始位置和尺寸。
- 让注册表易于查找。添加项目不得要求修改摄像机或手势代码。
- 通过源代码编辑来添加、复制、重命名和移除项目。不要添加运行时编辑器控件或删除快捷键。
- 在源代码中保留成员项、名称、尺寸和实现。浏览器存储不得创建或隐藏项目。
- 绝不要在运行时将存储的字符串或模型响应作为代码执行。
- 对于后续请求,更新现有工作区。保留名称、ID、位置和无关的实验内容。
- 如果指代不明确,请询问用户指的是哪个项目。
- 对于“再试一个版本”,保留原始版本。为每个变体分配新的 ID、唯一且易读的名称,并使用独立状态。
- 对于“修改这个版本”,在原位置更新该项目。只有用户要求时才重命名。
- 对于移除请求,只移除指定的注册表条目。保留共享组件和无关工作。
- 比较单项功能时,其他数据、内容、尺寸和全局主题保持不变。
- 对于范围更广的备选方案,说明布局差异。除非用户要求,否则不要创建完整的变体矩阵。
- 根据测量出的边界,将新增项目放在附近的空白区域。通过摄像机显示新增项目,不要重新排列现有项目或重置视图。
- 内容扩展、尺寸调整和重新加载后,保留位置。允许有意重叠。即使项目重叠,也要确保移动手柄可用。
保持工作区简洁
- 使用纯色背景、细微的预览边界和尽可能少的固定控件填满视口。
- 使用每个预览预期的尺寸。不要将内容拉伸到过大的框架中。
- 不要添加装饰性卡片、横幅或背景图案。
- 在预览上方显示每个项目的名称,例如
Pricing card · compact。不要使用含糊的名称或不透明 ID 作为标签。 - 让名称可通过按钮操作,但不要应用按钮样式,也不要单独设置复制按钮。
- 点击、按 Enter、Space 或触摸时复制准确的名称。不要复制 ID、代码或 URL。
- 在悬停和键盘聚焦时说明复制操作。仅悬停时不得复制。触摸操作不得要求先悬停。
- 如可用,使用剪贴板 API。仅在复制成功后显示简短的“已复制”反馈。反馈期间保持名称可见。
- 如果剪贴板访问失败或不可用,提供可选中的文本。不要崩溃,也不要声称复制成功。
- 在标签旁放置可见的移动手柄。标签负责复制,不负责拖动。手柄移动项目,而不是项目主体。
- 根据当前缩放级别,将指针移动转换为画布坐标。
- 支持在聚焦的手柄上使用键盘移动。提供可见的焦点样式和无障碍操作说明。
- 在画布导航界面和手柄上使用
cursor: default,包括手势进行期间。 - 在预览内部保留原生的文本、链接、输入和调整大小光标。不要将光标规则应用于所有后代元素。
- 包含平移、缩放、适配全部内容、重置视图、一个全局主题选择器和已保存的布局。
- 使用现有主题 API 支持浅色、深色和命名主题。画布控件、预览、菜单和对话框使用相同主题。
- 不要臆造主题,也不要添加每个预览单独的主题。如果不支持主题,请省略选择器并说明原因。
- 如果通过公共 API 无法设置门户主题,请说明限制。
- 除非用户要求,否则省略调整大小、宽度预设、对比布局、绘图、连接器、目录、属性编辑器、多选、吸附和撤销/重做。
- 对于用户要求的移动端或桌面端预览,请在注册表中定义其尺寸。
保留实时内容
- 通过公共 API 复用生产组件。不要为支持画布而更改其源代码、导出项、钩子或样式。
- 让生产组件独立于画布代码。
- 仅在画布中进行实验。只有在用户要求时,才将实验内容移入生产环境。
- 挂载之前,使用合成数据、模拟服务、安全提供程序和现有回调,避免发起真实请求或写入数据。
- 绝不使用个人数据或生产凭据。
- 如果无法安全隔离,请省略该预览并说明原因。单独使用 iframe 或文档并不能实现隔离。
- 保留点击、输入、文本选择、快捷键、焦点、嵌套滚动和触摸输入。
- 保留禁用和只读示例的真实行为。
- 移动项目、复制名称、更改主题或更改视图时,不要重新挂载预览或清除输入。
- 预览草稿无需在重新加载后保留。
- 将门户保留在其原生根节点中,并维持屏幕空间尺寸。由库管理定位和模态焦点。
- 仅在必要时使用公共容器 API。确保门户在不同缩放级别下都能正确对齐且可点击。
- 如果变换会破坏门户,请说明限制或提出使用单独预览文档的方案。
- 不要修补库、浏览器 API、预览 DOM 或门户根节点。
- 在画布宿主中定义导航,包括门户中的链接。不要更改组件链接或路由器内部逻辑。
- 画布项目中的链接应显示其目标,而不是滚动页面。
- 其他导航不得执行真实的项目操作,也不得在无提示的情况下丢失工作区。
将手势与预览输入分开
- 支持从空白区域拖动鼠标平移。
- 支持在空白区域和预览上使用 Ctrl/Meta + 滚轮和触控板捏合进行缩放。
- 滚轮或捏合缩放时,保持指针下方的画布点不动。
- 提供放大和缩小按钮及键盘控制。以视口中心为缩放中心。
- 双向平滑缩放,不出现跳变或漂移。保留项目位置和预览状态。
- 在浏览器允许的情况下,支持触控平移和捏合。
- 画布外壳获得焦点时,支持使用键盘移动视图。
- 为所有画布控件提供清晰可见的键盘焦点。
- 将无障碍的全景适配和重置视图控件固定在可触达的位置,即使项目位于屏幕外也能使用。
- 布局稳定后执行全景适配。适配实际边界,包括每个标题、手柄和边界。不要重新排列项目。
- 仅重置视图。保留成员关系、位置、主题和草稿。
- 支持在画布任意位置(包括预览上)使用 Space + 主按钮拖动和中键拖动进行平移。
- 明确的平移手势优先于项目移动和名称复制。
- 平移后,不要激活控件、复制标签、跟随链接或触发中键自动滚动。
- 如果交互控件或可编辑区域处于焦点状态,不要启用 Space 平移。
- 保留按钮和标签的 Space 激活功能。保留预览方向键、Escape 和撤销功能。
- 将模态框 Portal 放在画布手势处理范围之外。保留其焦点、背景行为和原生控件。
- 支持在空白区域和预览上使用双指触控板平移。
- 如果嵌套滚动区域可以沿手势方向滚动,就让它滚动;否则平移画布。
- 修改键滚轮和捏合缩放优先于滚动路由。其他 Portal 滚动保持原生行为。
- 仅在应用接管的手势中取消事件和限制触控。不要禁用预览内容上的原生输入。
- 使用单指通过手柄移动项目。保留普通的单指预览交互。
- 支持双指画布平移和捏合缩放,且不破坏预览的原生手势。报告浏览器限制,而不是禁用预览触控。
- 跟踪每次交互由哪个手势接管。取消时、窗口失去焦点时以及标签页隐藏时,清除按住的按键状态。
- 处理指针数量变化、指针取消和指针捕获丢失。
- 卸载时释放捕获,并清理监听器、观察器、计时器和动画帧。
- 路由处于活动状态期间,对文档视口和画布滚动边界应用
overscroll-behavior-x: none。 - 阻止 Chrome 水平历史记录滑动。仅使用内部包装器无法保证阻止该行为。
- 卸载时恢复之前的文档样式。保留嵌套水平滚动、前进/后退控件和导航快捷键。
- 不要通过
pushState困住历史记录、修补浏览器 API 或留下永久的全局处理器。 - 防止原生页面滚动移动画布。通过移动视图来显示屏幕外的键盘焦点。
- 要求视图坐标、项目位置和缩放值均为有限值且有界。
- 将指针和滚轮更新合并,每个动画帧最多写入一次变换。
- 将活动手势值保存在组件级 React 状态之外。视图移动不得导致预览重新渲染。
- 仅更新画布自有的包装器。手势期间不要更改预览 DOM 或影响布局的位置。
- 缓存测量得到的边界。内容、尺寸或布局变化时,一并刷新边界。
- 测量内容边界时忽略临时渲染占位符。
- 不要每帧测量所有预览,也不要交替执行布局读取和写入。
- 在手势结束后保存,或使用有界防抖。不要在每次指针事件时写入存储。
- 卸载时,在可能的情况下安全地刷新待保存内容。
- 避免高开销效果、永久的逐预览合成提示,以及因单个项目移动而触发的全画布处理。
- 只有在有性能分析证据时才添加虚拟化或记忆化。卸载屏幕外内容可能导致输入丢失,并破坏焦点或 Portal。
保存布局,而非内容
- 仅保存摄像机、受支持的主题偏好,以及以稳定注册表 ID 为键的位置。
- 使用较小的版本化文档,并将其存储在特定于项目和画布的键下。
- 遵循现有的应用偏好和无关的主题配置。不要创建与之冲突的主题偏好。
- 对已保存的布局应用相同的数值限制。按照项目惯例验证 ID、受支持的主题、文档大小和位置数量。
- 渲染所有当前注册表条目。应用有效的已保存位置,并忽略过时的 ID。
- 始终显示新条目。立即使用当前来源名称和尺寸。
- 处理格式错误的数据、不可用的存储和配额错误,确保画布正常运行。
- 对已知的旧格式,仅保留对当前 ID 有效的摄像机值、主题和位置。
- 丢弃已保存的成员关系、名称、尺寸、重复项,以及隐藏或已移除的状态。对于未知版本,使用安全默认值。
- 切勿存储或反序列化可执行组件、机密、令牌、账户数据或表单内容。
- 除非明确要求,否则不要保存预览草稿或交互历史记录。
测试并如实报告
运行仓库要求的检查。确保路由已挂载、导入均可解析,且控制台没有错误。检查差异,确认没有意外的生产环境改动。
对于新画布或控制器变更,测试上述每项行为。对于仅涉及内容的变更,在不重建控制器的情况下测试受影响的行为。使用多种缩放级别和视口尺寸进行测试,并在已有保存布局的情况下测试重新加载。
使用受支持的设备进行触控测试。使用实际触控板输入,以及真实的历史记录条目进行 Chrome 历史记录滑动测试。
在空白区域和预览上分别测试两个方向的缩放。确保缩放锚点固定不动,没有跳变或漂移。测试按钮和键盘缩放时视口中心周围的缩放效果。测试在预览内容和嵌套滚动区域上使用触控板平移,包括滚动区域到达滚动边界时的情况。
只有实际运行过测试,才能报告测试通过。编译和源代码审查无法证明浏览器中的行为。报告无法进行的设备测试和浏览器限制。
在声称性能流畅之前,应对有代表性的、内容丰富的画布进行性能分析,而非只测试一个空白示例。记录预览数量、浏览器、设备,以及平移、缩放和移动时的测量数据。调查长任务、重复布局、同步存储写入和预览重复渲染问题。报告观察到的卡顿和未测试的情况。若只修改预览,则无需重建或分析未变更的控制器。
最后用简短报告说明以下详情:
- 变更:涉及的路径、目的、本地实验、共享组件变更,以及新增预览的确切名称。
- 已运行的检查:运行过的测试及其结果。
- 未正常工作或未测试:限制、遗漏及原因。
- 所做决策:未经询问而自行选择的默认值。