UX Spec Generator
Generate structured user interaction specifications that bridge UI design with frontend implementation.
Output Structure
specs/ux/
├── README.md # 总览文档 (Overview)
├── global/ # 全局交互
│ └── shared-components.yaml
├── components/ # 可复用组件交互 (grouped by category)
│ ├── navigation/ # 导航类组件
│ │ ├── header.yaml
│ │ ├── sidebar.yaml
│ │ └── breadcrumb.yaml
│ ├── content/ # 内容类组件
│ │ ├── post-card.yaml
│ │ ├── proposal-card.yaml
│ │ └── comment-item.yaml
│ ├── form/ # 表单类组件
│ │ ├── text-input.yaml
│ │ ├── tag-input.yaml
│ │ └── markdown-editor.yaml
│ ├── feedback/ # 反馈类组件
│ │ ├── toast.yaml
│ │ ├── modal.yaml
│ │ └── loading.yaml
│ └── action/ # 操作类组件
│ ├── like-button.yaml
│ ├── follow-button.yaml
│ └── share-button.yaml
├── pages/ # 页面交互 (one file per page)
│ ├── home.yaml
│ ├── post-detail.yaml
│ └── ...
├── flows/ # 用户流程 (grouped by category)
│ ├── content/ # 内容类流程
│ │ ├── create-post.yaml
│ │ └── like-content.yaml
│ ├── team/ # 团队类流程
│ │ └── join-team.yaml
│ ├── auth/ # 认证类流程
│ └── social/ # 社交类流程
├── forms/ # 表单交互
│ └── post-create-form.yaml
└── state/ # 状态管理
└── state-management.yaml
Workflow
1. Gather Source Materials
Read in parallel:
specs/design/pages.yaml— Component structure, actions, data sourcesspecs/design/*.pen— Detailed design via Pencil MCP toolsspecs/testcases/*.md— User journeys and expected behaviors
2. Determine Scope
Default: Generate specs for ALL pages in pages.yaml
Selective: If user specifies pages, generate only for those:
"生成 home 和 post-detail 页面的 UX spec"
→ Generate only for pages: [home, post-detail]
3. Generate UX Spec Files
Create the directory structure and write files:
- README.md — Overview document with index and summary
- global/ — Shared component interactions
- components/ — Reusable component specs grouped by category
- pages/ — One YAML file per page
- flows/ — User journeys grouped by category
- forms/ — Form interaction specs
- state/ — State management and error handling
4. Report Completion
List generated files and any placeholders due to missing information.
File Schemas
README.md (Overview)
# UX Interaction Specifications
Generated: {timestamp}
Version: 1.0
## Summary
| Category | Count | Status |
|----------|-------|--------|
| Components | 12 | ✅ Complete |
| Pages | 5 | ✅ Complete |
| Flows | 3 | ⚠️ 1 placeholder |
| Forms | 2 | ✅ Complete |
## Components
| Category | Components | Files |
|----------|------------|-------|
| Navigation | header, sidebar, breadcrumb | [components/navigation/](components/navigation/) |
| Content | post-card, proposal-card, comment-item | [components/content/](components/content/) |
| Form | text-input, tag-input, markdown-editor | [components/form/](components/form/) |
| Feedback | toast, modal, loading | [components/feedback/](components/feedback/) |
| Action | like-button, follow-button, share-button | [components/action/](components/action/) |
## Pages
| Page | Route | File |
|------|-------|------|
| Home | `/` | [pages/home.yaml](pages/home.yaml) |
| Post Detail | `/posts/{id}` | [pages/post-detail.yaml](pages/post-detail.yaml) |
## User Flows
### Content Flows
- [Create Post](flows/content/create-post.yaml) — 发布新帖子
- [Like Content](flows/content/like-content.yaml) — 点赞内容
### Team Flows
- [Join Team](flows/team/join-team.yaml) — 加入团队
## Placeholders (TODO)
- [ ] `pages/login.yaml` — Not designed
- [ ] `flows/auth/login.yaml` — Missing test cases
components/{category}/{component-name}.yaml
Component categories:
navigation/— 导航类:header, sidebar, breadcrumb, tabs, paginationcontent/— 内容类:post-card, proposal-card, comment-item, user-avatarform/— 表单类:text-input, tag-input, markdown-editor, file-uploadfeedback/— 反馈类:toast, modal, loading, skeleton, empty-stateaction/— 操作类:like-button, follow-button, share-button, bookmark-button
# Component: Like Button
name: like-button
category: action
description: 点赞按钮,支持乐观更新
props:
target_type:
type: string
enum: [post, comment, resource]
required: true
target_id:
type: string
required: true
initial_count:
type: number
default: 0
initial_liked:
type: boolean
default: false
states:
default:
icon: heart-outline
color: text-secondary
liked:
icon: heart-filled
color: accent-primary
loading:
icon: spinner
disabled: true
interactions:
- trigger: click
condition: "!is_loading"
action: toggle_like
api_call:
method: POST
endpoint: "/api/interactions"
body:
type: like
target_type: "{target_type}"
target_id: "{target_id}"
optimistic_update:
- field: liked
operation: toggle
- field: count
operation: "{liked ? decrement : increment}"
error_rollback: true
on_unauthenticated:
action: show_modal
target: login-prompt
- trigger: hover
action: show_tooltip
content: "{liked ? '取消点赞' : '点赞'}"
accessibility:
role: button
aria-label: "{liked ? '取消点赞' : '点赞'}, 当前 {count} 人点赞"
aria-pressed: "{liked}"
global/shared-components.yaml
# Global shared component interactions
version: "1.0"
shared_components:
global-header:
components:
site-logo:
interactions:
- trigger: click
action: navigate
target: "/"
search-bar:
interactions:
- trigger: focus
action: expand
target: self
- trigger: submit
action: navigate
target: "/search?q={query}"
publish-btn:
interactions:
- trigger: click
action: toggle_panel
target: multi-function-panel.publish-center
sidebar-nav:
components:
nav-explore:
interactions:
- trigger: click
action: navigate
target: "/"
active_indicator: true
multi-function-panel:
panels:
publish-center:
show_trigger: header-right.publish-btn
components:
find-teammate-card:
interactions:
- trigger: click
action: navigate
target: "/posts?tag=find-teammate"
pages/{page-name}.yaml
# Page: Home
route: "/"
description: 首页,展示热门提案和内容流
sections:
main-tabs:
components:
tab-bar:
interactions:
- trigger: click
action: filter_content
params:
tab: "{selected_tab}"
api_call:
method: GET
endpoint: "/api/posts"
query: "{tab.filter}"
loading_state: main-content
hot-proposals:
components:
proposal-card:
interactions:
- trigger: click
action: navigate
target: "/posts/{id}"
- trigger: click
target_element: like-btn
action: toggle_like
api_call:
method: POST
endpoint: "/api/interactions"
body:
type: like
target_type: post
target_id: "{id}"
optimistic_update:
field: like_count
operation: increment
error_rollback: true
flows/{category}/{flow-name}.yaml
Flow categories:
content/— 内容操作:create-post, edit-post, delete-post, like-contentteam/— 团队操作:join-team, create-team, invite-memberauth/— 认证操作:login, logout, registersocial/— 社交操作:follow-user, comment, share
# Flow: Create Post
name: 发布新帖子
category: content
description: 用户从首页发布新帖子的完整流程
trigger: click header-right.publish-btn
preconditions:
- user.is_authenticated
steps:
- step: 1
page: home
component: header-right.publish-btn
trigger: click
result:
action: show_panel
target: publish-center
- step: 2
page: home
panel: publish-center
component: find-teammate-card | find-idea-card | publish-proposal-card
trigger: click
result:
action: navigate
target: "/posts/create?type={selected_type}"
- step: 3
page: post-create
component: post-form
trigger: fill_form
fields:
- title (required)
- body (required, markdown)
- tags (optional)
- cover_image (optional)
validation:
title: min_length: 1, max_length: 200
body: min_length: 1
- step: 4
page: post-create
component: submit-btn
trigger: click
api_call:
method: POST
endpoint: "/api/posts"
body: "{form_data}"
loading_state: submit-btn
- step: 5a
condition: success
result:
action: navigate
target: "/posts/{new_post.id}"
toast: "发布成功"
- step: 5b
condition: error
result:
action: show_error
target: form
message: "{error.message}"
forms/{form-name}.yaml
# Form: Post Create
route: "/posts/create"
description: 创建新帖子表单
fields:
title:
type: text
required: true
validation:
min_length: 1
max_length: 200
interactions:
- trigger: input
action: validate_field
- trigger: blur
action: show_error_if_invalid
body:
type: markdown-editor
required: true
interactions:
- trigger: input
action: auto_save_draft
debounce: 3000
- trigger: paste_image
action: upload_image
api_call:
method: POST
endpoint: "/api/resources"
body: FormData
on_success:
action: insert_image_markdown
tags:
type: tag-input
interactions:
- trigger: input
action: search_suggestions
api_call:
method: GET
endpoint: "/api/tags?q={query}"
- trigger: select
action: add_tag
submit:
trigger: click submit-btn
validation: validate_all_fields
on_valid:
api_call:
method: POST
endpoint: "/api/posts"
loading_state: submit-btn
on_invalid:
action: scroll_to_first_error
state/state-management.yaml
# State Management
version: "1.0"
loading_indicators:
- component: "*-btn"
type: spinner
disable_while_loading: true
- component: "*-list"
type: skeleton
- component: page
type: progress-bar
error_handling:
network_error:
action: show_toast
type: error
message: "网络连接失败,请重试"
retry_button: true
auth_required:
action: show_modal
target: login-prompt
permission_denied:
action: show_toast
type: error
message: "您没有权限执行此操作"
not_found:
action: navigate
target: "/404"
placeholders:
- page: login
status: not_designed
required_interactions:
- email input validation
- password input
- submit form
- OAuth buttons
Interaction Types Reference
Trigger Types
| Trigger | Description | Example |
|---|---|---|
click |
单击元素 | 按钮、链接、卡片 |
double-click |
双击元素 | 编辑模式切换 |
focus |
获取焦点 | 输入框展开 |
blur |
失去焦点 | 验证输入 |
input |
输入内容 | 实时搜索、表单验证 |
submit |
提交表单 | 表单提交 |
select |
选择选项 | 下拉菜单、标签选择 |
file_selected |
选择文件 | 图片/文件上传 |
paste_image |
粘贴图片 | Markdown编辑器 |
Action Types
| Action | Description | Params |
|---|---|---|
navigate |
页面跳转 | target: URL |
show_panel |
显示面板 | target: panel_id |
toggle_panel |
切换面板 | target: panel_id |
show_modal |
显示弹窗 | target: modal_id |
show_dropdown |
显示下拉菜单 | options: [] |
show_confirm |
显示确认对话框 | confirm_action: {} |
filter_content |
筛选内容 | params: {} |
toggle_like |
切换点赞 | api_call: {} |
submit_form |
提交表单 | api_call: {} |
validate_field |
验证字段 | - |
show_toast |
显示提示 | message, type |
update_field |
更新字段 | field, operation |
clear_input |
清空输入 | - |
upload_file |
上传文件 | api_call: {} |
Conditions
condition: user.is_authenticated # 用户已登录
condition: is_author # 当前用户是作者
condition: is_admin # 当前用户是管理员
condition: "!already_liked" # 未点赞
condition: visibility=public # 公开可见
condition: status=published # 已发布状态
API Call Structure
api_call:
method: POST | GET | PUT | DELETE
endpoint: "/api/posts/{id}"
body: # POST/PUT body
type: like
target_id: "{id}"
query: # GET query params
page: 1
limit: 20
Success/Error Handling
on_success:
- action: navigate
target: "/posts/{id}"
- action: show_toast
message: "操作成功"
- action: update_field
field: like_count
operation: increment
on_error:
- action: show_toast
type: error
message: "{error.message}"
- action: show_form_errors
on_unauthenticated:
action: show_modal
target: login-prompt
Reading .pen Files
Use Pencil MCP tools to extract component details:
mcp__pencil__batch_get(
filePath: "specs/design/basic.pen",
patterns: [{ reusable: true }],
readDepth: 2
)
Extract from .pen files:
- Component hierarchy and nesting
- Interactive elements (buttons, inputs, links)
- Style states (hover, active, disabled)
- Layout relationships
Validation Checklist
Before completing, verify:
- README.md complete — Overview lists all components, pages, flows, forms with links
- Components categorized — Reusable components grouped by type in
components/{category}/ - All pages covered — Every page in pages.yaml has a corresponding file in
pages/ - Flows categorized — User flows grouped by type in appropriate subdirectories
- API endpoints defined — Every data mutation has an api_call
- Error states handled — Loading, success, and error states in
state/ - Placeholders listed — Missing items noted in README.md TODO section
Converted and distributed by TomeVault — claim your Tome and manage your conversions.