yuanlang12/openpipal/interactive-prototype
Claude Code and agent skill by yuanlang12/openpipal
- community
Checking that the SKILL.md file is still in the repository.
可交互原型 + 手机设备外框的说明书——DCLogic 状态驱动的交互清单,以及 ios-frame / android-frame 两件外框共 13 个预制件的全部 props 与默认值、明暗方案在两个平台上完全不同的下发方式、内容区自带的内边距与层序、"看着成了其实没生效"的一批静默失败(裸属性、驼峰属性名、IOSList 的下传规则)。判据:taskType=原型,或用户要"能点的 / 手机 App 原型 / phone mockup / 多屏流程"时必读;写第一行之前先读 dc-authoring(DC 格式、模板语法、x-import 协议、逻辑块都归它),再读这份。
Install
npx vskill@latest install yuanlang12/openpipal/interactive-prototypeSKILL.md
可交互原型(Interactive prototype)
这份技能管两件事:怎么让一份 DC 摸起来像真的在运行的 app, 以及怎么把它装进两件设备外框预制件(./ios-frame.jsx 7 个件、./android-frame.jsx 6 个件,共 13 个)。
DC 文件格式本身(骨架、{{ }} 空穴、sc-for/sc-if、伪态样式、x-import 协议、 DCLogic、data-props、画板模式、告警表)全在 dc-authoring,这里只引用不重复。
1. 骨架(可直接抄,每一行都跑得通)
两屏 iOS 原型:列表 → 详情,滑动切换,浮一枚毛玻璃迷你播放条。
逻辑块的三条硬条件(dc-authoring §4 的约定,这里只重申,写错就整块失效): 标签必须是 <script type="text/x-dc" data-dc-script>(不写 type 浏览器会先执行一遍并抛 ReferenceError); 类名必须恰好叫 `Component`;必须 extends DCLogic,且必须有 renderVals()。
2. 两件设备外框
绝不自己手绘手机壳。状态栏、灵动岛/挖孔、导航区、Home Indicator / 手势条、圆角、描边、 落地阴影、内容裁切全部自带,自己画既是像素级精细活又白烧 token。
| iOS | Android | ||
|---|---|---|---|
| 文件 | ./ios-frame.jsx | ./android-frame.jsx | |
| 外框组件 | IOSDevice | AndroidDevice | |
默认尺寸 / hint-size | 402px,874px | 412px,892px | |
| 机身边框 | 无(整块就是屏) | 10px 实体边框,box-sizing:border-box | |
| 屏幕可用区 | 402 × 874 | 392 × 872(各边被边框吃掉 10px) | |
| 顶部系统区 | 状态栏 54px,浮在内容之上 | 状态栏 36px,占位在流内 | |
| 底部系统区 | Home Indicator 浮层(内容区自带 28px 余量) | 手势导航条 26px,占位在流内 | |
| 系统区能否关掉 | 导航区能(不传 title),状态栏与 Indicator 不能 | 都不能,状态栏与手势条恒在 |
2.1 怎么挂
13 个件全部挂在 `window` 上,都能用 x-import 的 component-from-global-scope 直接挂进模板, 属性与 children 原样透传,可以嵌套(外框里套列表,列表里套行)。 不要为了用它们去写 React.createElement——那条路做 UI 布局宿主的就地编辑摸不到。
- 顶层那个 `x-import` 必须写 `hint-size`(= 外框尺寸),否则流式期只有一个撑不出版面的小占位。
- 套在外框里的子件不用写 `hint-size`:它们和外框同一个文件,外框就绪的那一刻它们已经在
window上,
永远不会进占位态。
- 所有
x-import都写成成对标签(<x-import …></x-import>)。HTML 解析器不认自闭合的未知元素,
写 /> 会把后面的兄弟节点全吞进去。
2.2 title 的三态语义(两件同款判定:title !== undefined)
| 你写的 | 结果 | |
|---|---|---|
| 不传 `title` | 没有导航栏 / 应用栏。做全屏 app、自定义头部、通栏封面的唯一正确写法 | |
title="" | 出一条空标题的导航栏(合法用法:只要那条横杆占位) | |
title="Library" | 正常标题 |
自带导航栏上的按钮全是装饰——IOSNavBar 的返回尖角与三点、AndroidAppBar 的两枚图标位 都没有事件接口,点不动。所以:原型需要真的能点的返回键 / 操作按钮 = 不要传 `title`,自己画头部。 iOS 侧不传 title 时内容区自动让出 54px 顶部内边距,你的自定义头部从那里往下画就压不到时间。
2.3 iOS 全表(./ios-frame.jsx)
| 组件 | props(= 后是默认值) | |
|---|---|---|
IOSDevice | children、width=402、height=874、dark=false、title(不传=无导航区)、keyboard=false | |
IOSStatusBar | dark=false、time='9:41' | |
IOSNavBar | title='Title'、dark=false、trailingIcon=true | |
IOSGlassPill | children、dark=false、style={} | |
IOSList | header、children、dark=false | |
IOSListRow | title、detail、icon、chevron=true、isLast=false、dark=false | |
IOSKeyboard | dark=false |
IOSListRow的 `icon` 传的是一个颜色值(画左侧 30×30 的圆角色块),不是图标名。IOSList自带 18px 上外边距与左右各 16px 内缩,别再包一层带 padding 的容器。IOSGlassPill的style是唯一暴露出来的毛玻璃配方(半透明底 +backdrop-filter+
高光/暗边/描边三层 inset):浮动按钮、Toast、迷你播放条、分段控件都拿它当底座,别自己配一套。 它的 children 装在一个内层 inline-flex 里,要横向铺开就给自己的那层写死宽度。
IOSStatusBar/IOSNavBar/IOSKeyboard/IOSGlassPill也能脱离外框单独挂
(做尺寸放大图、系统件对照页),此时 dark 得自己传。
2.4 Android 全表(./android-frame.jsx)
| 组件 | props(= 后是默认值) | |
|---|---|---|
AndroidDevice | children、width=412、height=892、dark=false、title(不传=无应用栏)、large=false、keyboard=false | |
AndroidStatusBar | dark=false、time='9:30' | |
AndroidAppBar | title='Title'、large=false | |
AndroidListItem | headline、supporting、leading | |
AndroidNavBar | dark=false | |
AndroidKeyboard | 无 props |
large="{{ true }}"的应用栏把标题下沉成独立一行(30px 字号),首行只剩两枚图标位;
高度约 132px,不传 large 时 64px。
AndroidListItem的leading是放进圆形头像位的字符(primary 底 + 反色字),不传就没有头像位;
supporting 不传则是单行项(56px 高),传了变双行(72px 高)。
2.5 明暗方案:两件的下发方式不同,这是最大的用法分野
Android —— `AndroidDevice` 在根节点上下发 15 个 M3 角色变量,屏幕内容可以直接写 var(--m3-…),跟着 dark 一起翻,而且这是静态内联样式(不走空穴,流式期就有观感):
变量名大小写敏感,照抄这 15 个(角色名保持驼峰):
变量只在 AndroidDevice 子树里有定义(AndroidStatusBar / AndroidNavBar 自己也带一份); AndroidAppBar / AndroidListItem / AndroidKeyboard 没有 `dark` 形参,靠继承这些变量, 单独拿出去用会落回浅色兜底。想换主色,在设备内的任意一层写 style="--m3-primary:#7c4dff" 覆盖即可,下面的系统件跟着变。
iOS —— 没有这套。色板全部内联在组件内部,屏幕内容拿不到任何变量,配色只能自己定并手动同步。 外框内部用的就是下面这两套,照抄它,你的内容才和系统件同一套:
| 角色 | light(dark=false) | dark(dark=true) | |
|---|---|---|---|
| 屏幕底 | #f2f2f7 | #000000 | |
| 卡片 / 分组底 | #ffffff | #1c1c1e | |
| 主文本 | #101014 | #f5f5f7 | |
| 次要文本 | rgba(60,60,67,0.60) | rgba(235,235,245,0.62) | |
| 弱化文本 / 尖角 | rgba(60,60,67,0.34) | rgba(235,235,245,0.32) | |
| 分隔线 | rgba(60,60,67,0.22) | rgba(235,235,245,0.18) | |
| 强调色 | #007aff | #0a84ff |
推论:iOS 侧挑一套明暗写死,不要做运行时明暗切换。 要切换就得把每处配色都走空穴, 而空穴在流式全程是空的(逻辑块未上场),整份原型在生成期间会没有样式。要明暗开关就用 Android。
2.6 几何预算(够不够放得下,先按这张表算)
| 内容区高度 | 备注 | ||
|---|---|---|---|
iOS 传 title | ≈ 697px | 导航区约 149px(含让出的 54px 状态栏)+ 底部 28px 余量 | |
iOS 不传 title | ≈ 792px | 顶部自动 54px 内边距 + 底部 28px 余量 | |
iOS keyboard="{{ true }}" | 再减 ≈ 270px | 同时底部 28px 余量归零 | |
Android 不传 title | 810 × 392 | 892 − 20 边框 − 36 状态栏 − 26 手势条 | |
Android 传 title(小应用栏) | 746 × 392 | 再减 64px 应用栏 | |
Android 传 title + large="{{ true }}" | 678 × 392 | 再减 132px 应用栏 | |
Android keyboard="{{ true }}" | 再减 ≈ 250px |
改尺寸就得同步改 `hint-size`,否则流式期占位框和终态尺寸对不上,用户会看到跳版。 且 width / height 直接进 CSS,必须写成整值空穴:width="{{ 390 }}"(写 width="390" 是没单位的 CSS 值,会被丢掉,外框塌成内容高)。
2.7 多屏叙事
- 一台设备内部切屏:骨架里那套——一条轨道 +
transform:translateX+transition,
由 state.screen 驱动。全屏页(Now Playing 这类)从底部升起就换成 translateY。
- 多台设备并排看流程:画板模式(dc-authoring §6)。每台设备各自装进一个绝对定位的
根直接子元素,打上 data-screen-label,宿主的逐屏截图与文本摘要按它分组。
- 状态栏时间只在单独挂 `IOSStatusBar` / `AndroidStatusBar` 时能改(
time,默认9:41/9:30):
设备外框内部是写死 dark 一个参数挂上去的,time 传给 IOSDevice 不会转下去。 想让多屏叙事的时间推进,就得不用设备外框、自己拼一台。多数情况下不值得——保持默认时间即可。
3. 什么才算"可交互"
逐项自检,缺一项就还是静态 mockup:
- 状态驱动:列表增删、选中、展开折叠、步骤指示全部走
state+setState,不摆一次性 DOM。 - hover / active 态:可点元素给
style-hover/style-active(伪态样式,dc-authoring §2.3)。
这两个不必进 state——纯 CSS 就够,进 state 反而多一次重渲染。
- 表单校验:
<input>/<textarea>是普通 DOM 元素,照常用。必填与格式错误即时提示,
非法时提交按钮 disabled + 灰化。
- 过渡动画:面板切换、元素出入场写
transition/transform,不做硬切。 - 多步导航流:向导 / tab / 路由式切换要有前进后退,且状态在步骤间保留。
- 真键盘体验自己做:两件的
IOSKeyboard/AndroidKeyboard都是静态外观件,
不可交互、没有任何回调,按不下去。要"打字"就在内容区用真 <input> + state, 外框的 keyboard 只负责把那块视觉占位铺出来。
4. 运行时已经替你做了什么(别写这些)
- 整台设备的外观:圆角、描边、落地阴影、内容裁切、灵动岛 / 挖孔、状态栏(含信号 Wi-Fi 电池)、
Home Indicator、手势导航条——全部自带。
- 内容区已经是滚动容器(
flex:1+overflow:auto):不要自己写外层滚动壳,
不要给屏幕内容写 height:874px。
- iOS 已经替系统区让好了位:不传
title时顶部 54px 内边距,不开keyboard时底部 28px 余量。 - 两套明暗色板已经算好:不要写
@media (prefers-color-scheme),明暗由darkprop 一处切换。 - 毛玻璃配方已经封在
IOSGlassPill与IOSKeyboard里:不要自己调backdrop-filter。 - 导出降级已经想过:
backdrop-filter在 headless 截图 / PDF 里可能不合成,底色本身撑得住可读性——
不用为导出另写一套替代样式。
- 平台字体栈铺在外框根节点上:屏幕内容不写
font-family就继承(iOS 一套、Android 一套)。
字体口径照 dc-authoring §7,不拉网络字体。
- 全部图标是内联 SVG 自绘,零外部资源:离线、导出、大陆网络下都在。
- 外框文件由宿主内联(
from="./ios-frame.jsx"就够),不走网络、不用自己 fetch。 - 自检卡按内容挑外框:产物里出现 ios-frame /
IOSDevice时,宿主的自检预览卡自动用
402×874 的手机比例展示——你不用为它做任何事。
5. 约束与静默失败(不知道就会踩,踩了不报错)
This is the start of the file. Read the full SKILL.md on GitHub.
Security
- Security scanPassed, 96 of 100Pattern checks on the skill's files.
- Model reviewNot runA model review is scheduled for the next rescan.
Quality evaluation
- Task evaluationNot runNo evaluation yet. Run one in Skill Studio.
Source
- SKILL.md in the repositoryCheckingresources/skills/interactive-prototype/SKILL.md
Popularity
- 7-day trend score
- 0
Not refreshed yet.
Works with
Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.
- Claude Code
- Cursor
- GitHub Copilot
- Windsurf
- Codex
- Gemini CLI
- Cline
- Amp
- Roo Code
- Goose
- Continue
- Kilo Code
- Junie
- Trae
- OpenHands
- Qwen Code
- AI Agent
- Tabnine Chat
- Sourcegraph Cody
- Amazon Q
- Firebase Genkit
- Sweep
- Devin
- Phind
- Mentat
- Claude Desktop
- Aider
- GPT Pilot
- Plandex
- bolt.new
- v0
- Replit Agent
- Anse
- TypingMind
- BetterChatGPT
- LibreChat
- Warp AI
- Pieces
- Fig AI
Embed badge
[](https://verified-skill.com/skills/yuanlang12/openpipal/interactive-prototype)