Files
RustUI/DESIGN_SPEC.md
2026-05-31 09:36:23 +08:00

786 lines
19 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Pika 设计规范
> AI-Native 组件库:专为大模型代码生成优化的 AntV 类可视化 + UI 组件库。
> 核心目标:**让 AI 第一次生成的代码就能跑、就能看、就能用。**
> 设计原则:以 Apple Human Interface Guidelines 为准,融合 Ant Design 成熟实践。
---
## 一、核心理念
### 1.1 设计价值观
Pika 基于 Apple Human Interface Guidelines 的三大核心原则构建,同时融合 Ant Design 的成熟实践经验:
#### 层级 (Hierarchy)
**建立清晰的视觉层级**,使控件和界面元素突出内容、区分层次。
**核心要点:**
- 内容和控件应该明确区分
- 重要的信息应该占据主要位置
- 使用视觉层次帮助用户快速理解界面
#### 和谐 (Harmony)
**与硬件和软件的同心设计保持一致**,在界面元素、系统体验和设备之间创造和谐。
**核心要点:**
- 界面元素与硬件设计协调
- 保持跨平台的一致性
- 尊重平台特有的交互方式
#### 一致性 (Consistency)
**采用平台约定**,保持一致的设计,在不同窗口大小和显示器间持续适应。
**核心要点:**
- 遵循各平台的交互惯例
- 用户在切换设备时感到熟悉
- 保持操作的一致性预期
#### 意义感 (Meaningful)
每个设计决策都应该服务于用户目标和业务价值。设计不仅仅是美观,更是解决问题的工具。
**核心要点:**
- 设计服务于功能,而非装饰
- 关注用户任务和目标
- 创造有价值的用户体验
#### 生长性 (Growing)
设计系统应该具有自我进化和适应能力,随着用户需求和技术发展不断迭代完善。
**核心要点:**
- 支持组件的扩展和定制
- 适应不同场景和需求
- 持续迭代和优化
### 1.2 AI 优先 (AI-First)
Pika 面向 AI 代码生成进行优化,同时遵循 Apple HIG 的设计原则:
| 原则 | 说明 | 反例 | 正例 |
|------|------|------|------|
| **零歧义** | 每个 prop 名称自解释,无简称、无隐式行为 | `allowClear` | `showClear` |
| **零默认假设** | 所有视觉行为显式声明,不靠"常识" | `status` 默认 `undefined` | `status: 'default' \| 'error' \| 'warning' \| 'success'` |
| **一致性** | 相同概念用相同 prop 名,跨组件统一 | `dataSource` / `options` / `treeData` | 统一 `data` |
| **扁平化** | 最多一层嵌套,禁止深层 renderProps | `columns[].render()` | `column.renderCell` |
| **确定性** | 相同输入始终产生相同输出,无随机行为 | 默认不带 `key` 警告 | 强制 `key` 或无状态 |
### 1.3 可视化 + UI 一体化
Pika 融合 AntV 的数据可视化能力与 Apple HIG / Ant Design 的 UI 能力,共享同一套设计 Token、交互模式、主题系统。
---
## 二、设计原则(以 Apple HIG 为准)
### 2.1 色彩系统
**设计原则(以 Apple 为准):**
1. **避免使用相同颜色表示不同含义**
- 在整个界面中一致地使用颜色
- 如果用品牌色表示交互式按钮可点击,不要用相同颜色来样式化非交互文本
2. **确保应用的所有颜色在浅色、深色和高对比度环境下都正常工作**
- 系统颜色会根据外观设置细微调整
- 开启"增强对比度"设置时,颜色差异会更加明显
3. **在各种光照条件下测试应用的配色方案**
4. **考虑作品和半透明性如何影响附近颜色**
**语义化颜色(以 Apple 为准):**
```css
/* Apple 语义化颜色 */
--apple-label: rgba(0, 0, 0, 0.88);
--apple-secondary-label: rgba(0, 0, 0, 0.6);
--apple-tertiary-label: rgba(0, 0, 0, 0.3);
--apple-separator: rgba(0, 0, 0, 0.12);
/* Pika 品牌色(融合) */
--nv-color-primary: #6C5CE7;
--nv-color-primary-hover: #A29BFE;
--nv-color-primary-active: #4A3DBF;
```
**功能色:**
```css
/* 成功色 */
--nv-color-success: #00B894;
--nv-color-success-hover: #33c9a5;
--nv-color-success-active: #009975;
/* 警告色 */
--nv-color-warning: #FDCB6E;
--nv-color-warning-hover: #fdd97d;
--nv-color-warning-active: #e6b800;
/* 错误色 */
--nv-color-error: #FF7675;
--nv-color-error-hover: #ff9493;
--nv-color-error-active: #e0504f;
/* 信息色 */
--nv-color-info: #74B9FF;
--nv-color-info-hover: #96ccff;
--nv-color-info-active: #4da3ff;
```
**无障碍色彩:**
| 原则 | 说明 |
|-----|------|
| 避免仅依靠颜色区分对象 | 使用文本标签或符号形状标识对象或状态 |
| 确保足够对比度 | 最小 4.5:1,推荐 7:1 |
| 考虑文化差异 | 颜色含义因文化而异 |
### 2.2 字体系统
**字体规范:**
```css
/* 字体族 */
--nv-font-family: "SF Pro", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
--nv-font-family-mono: "SF Mono", "JetBrains Mono", monospace;
/* 字体大小(三个级别) */
--nv-font-size-small: 12px;
--nv-font-size-middle: 14px;
--nv-font-size-large: 16px;
/* 字重 */
--nv-font-weight-regular: 400;
--nv-font-weight-medium: 500;
--nv-font-weight-semibold: 600;
--nv-font-weight-bold: 700;
```
**字号层级:**
| 级别 | 字号 | 字重 | 用途 |
|-----|------|------|------|
| 标题 | 20px | 600 | 页面标题 |
| 正文大 | 16px | 500 | 卡片标题 |
| 正文 | 14px | 400 | 正文内容 |
| 辅助 | 12px | 400 | 辅助说明 |
**最小触摸目标:**
- **最小触摸目标:44 × 44 px**
### 2.3 间距系统
**基础间距(三个级别):**
```css
--nv-spacing-small: 8px;
--nv-spacing-middle: 16px;
--nv-spacing-large: 24px;
```
**安全区域:**
| 平台 | 安全区域处理 |
|-----|------------|
| iOS | 尊重 Dynamic Island 和传感器外壳 |
| iPadOS | 尊重摄像头外壳 |
| macOS | 避免在窗口底部放置控件 |
### 2.4 圆角系统
**圆角(三个级别):**
```css
--nv-radius-small: 4px;
--nv-radius-middle: 8px;
--nv-radius-large: 12px;
--nv-radius-full: 9999px;
```
| 元素类型 | 圆角值 |
|---------|-------|
| 按钮 | 8px |
| 卡片 | 8px |
| 输入框 | 8px |
| 标签 | 4px |
| 头像 | 50% (圆形) |
### 2.5 阴影系统
**阴影(三个级别):**
```css
--nv-shadow-small: 0 1px 2px rgba(0, 0, 0, 0.05);
--nv-shadow-middle: 0 4px 8px rgba(0, 0, 0, 0.08);
--nv-shadow-large: 0 8px 16px rgba(0, 0, 0, 0.12);
--nv-shadow-focus: 0 0 0 3px rgba(108, 92, 231, 0.2);
```
### 2.6 动效系统
**动效原则:**
1. **有目的地添加动效** - 支持体验而非喧宾夺主
2. **让动效成为可选的** - 使用替代方案如触觉和音频
3. **追求与用户手势一致的逼真反馈**
4. **让用户可以取消动效**
**动效时长(三个级别):**
| 类型 | 时长 |
|-----|------|
| 快速 | 0.15s |
| 正常 | 0.25s |
| 缓慢 | 0.4s |
**动效曲线:**
```css
--nv-ease-default: cubic-bezier(0.4, 0, 0.2, 1);
--nv-ease-in: cubic-bezier(0.4, 0, 1, 1);
--nv-ease-out: cubic-bezier(0, 0, 0.2, 1);
--nv-ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);
```
---
## 三、深色模式
### 3.1 核心原则
1. **避免提供应用特定的外观设置** - 让用户使用系统设置
2. **确保应用在两种外观下都看起来良好**
3. **使用语义化颜色自动适应**
### 3.2 颜色适配
**背景颜色:**
| 类型 | 浅色模式 | 深色模式 |
|-----|---------|---------|
| 背景 | #FFFFFF | #1C1C1E |
| 浮层 | #F5F5F5 | #2C2C2E |
**文本颜色:**
| 类型 | 浅色模式 | 深色模式 |
|-----|---------|---------|
| 主要 | #1a1a2e | #FFFFFF |
| 次要 | #666666 | rgba(255,255,255,0.65) |
| 禁用 | #999999 | rgba(255,255,255,0.35) |
### 3.3 对比度要求
- **最小对比度:4.5:1**
- **推荐对比度:7:1**
---
## 四、AI 友好的组件设计
### 4.1 核心理念
Pika 是专为 AI 代码生成优化的组件库。设计时始终考虑 AI 的理解能力和生成习惯。
### 4.2 统一数据模型
所有列表/表格/图表组件使用统一的数据 prop 名称:
```tsx
// ✅ Pika 方式 — AI 容易理解和记忆
<Table data={items} />
<List data={items} />
<Chart data={items} />
<Timeline data={items} />
// ❌ 不统一 — AI 容易混淆
<Table dataSource={items} /> // 为什么不是 data
<Select options={items} /> // 为什么叫 options
<Tree treeData={items} /> // 为什么叫 treeData
```
### 4.3 统一尺寸体系
所有组件使用统一的 size prop,值从三个级别中选择:
```tsx
// ✅ 所有组件共用 size,无例外
size: 'small' | 'middle' | 'large'
<Button size="small" />
<Input size="middle" />
<Select size="large" />
```
**尺寸定义**
| 级别 | 字体大小 | 组件高度 | 间距 |
|-----|---------|---------|------|
| small | 12px | 32px | 8px |
| middle | 14px | 40px | 16px |
| large | 16px | 48px | 24px |
### 4.4 统一事件命名
```tsx
// ✅ on + 动词 + 名词 — AI 容易理解意图
onClick // 点击事件
onChange // 值变化事件
onSelect // 选择事件
onClose // 关闭事件
// ❌ on + 名词 + 动词 — 增加 AI 推理负担
onMenuClick // ❌ → onClick 即可
onPanelChange // ❌ → onChange
```
### 4.5 统一布尔 prop 命名
```tsx
// ✅ 动词/形容词 + 肯定形式 — 语义清晰
disabled: boolean // 禁用
loading: boolean // 加载中
readOnly: boolean // 只读
showSearch: boolean // 显示搜索
showClear: boolean // 显示清除
// ❌ 不一致 — AI 容易混淆
// allowClear / showSearch / bordered / dropdownMatchSelectWidth
```
### 4.6 自包含组件 + 确定导入路径
```tsx
// ✅ 每个组件独立导入,路径即名字 — AI 不会选错路径
import { Button } from '@Pika/ui/button'
import { Modal } from '@Pika/ui/modal'
import { LineChart } from '@Pika/ui/line-chart'
// ❌ 统一入口 — AI 可能 tree-shake 失败
import { Button } from '@Pika/ui'
```
### 4.7 类型优先原则
所有 prop 使用联合类型字面量,AI 能看到所有可选值:
```tsx
// ✅ 明确枚举 — AI 不会遗漏任何可能性
type ButtonVariant = 'solid' | 'outline' | 'ghost' | 'text' | 'link'
type ButtonSize = 'small' | 'middle' | 'large'
type Status = 'default' | 'success' | 'warning' | 'error' | 'info'
// ❌ boolean 类型 — 隐藏了其他可能性
<Button ghost /> // 为什么不是 outline
<Button primary /> // primary 和 type="primary" 是什么关系?
```
### 4.8 远离魔法字符串
```tsx
// ✅ 枚举/常量 — AI 不会拼错值
<Table scrollBar={{ placement: 'overlay' }} />
Toast.show({ type: 'success' })
// ❌ 魔法字符串 — AI 可能拼错
Toast.show({ type: 'sueecss' }) // 拼写错误难以发现
```
### 4.9 组件原子化
一个组件只做一件事,避免"大而全"的上帝组件:
```tsx
// ✅ 拆分 — AI 容易选择和组合
<Table /> // 纯表格
<TableFilter /> // 表格筛选
<TableSort /> // 表格排序
// ❌ 不拆分 — 30+ propsAI 难以理解
<Table filter sort pagination editable onRowClick ... />
```
### 4.10 使用 data-* 属性进行样式绑定
```tsx
// ✅ data-* 属性 — AI 删除/修改时不易出错
<button
data-variant="solid"
data-size="middle"
data-status="success"
data-loading={isLoading}
/>
// ❌ classnames 拼接 — AI 难以追踪所有组合
<button className={cn('btn', `btn-${variant}`, `btn-${size}`, { 'btn-loading': loading })} />
```
### 4.11 Props 声明规范
```tsx
// ✅ 正确做法 — 完整类型定义
interface ButtonProps {
/** 按钮风格变体 */
variant?: 'solid' | 'outline' | 'ghost' | 'text' | 'link'
/** 按钮尺寸 */
size?: 'small' | 'middle' | 'large'
/** 按钮状态 */
status?: 'default' | 'success' | 'warning' | 'error' | 'info'
/** 是否禁用 */
disabled?: boolean
}
// ❌ 禁止做法 — 类型不明确
interface BadProps {
type?: string // ❌ string 类型,AI 不知道可选值
mode?: any // ❌ any 类型,无类型提示
[key: string]: any // ❌ 透传,AI 无法推理
}
```
### 4.12 状态映射规范
使用对象映射替代 switch-case
```tsx
// ✅ 对象映射 — AI 容易理解和修改
const STATUS_STYLES = {
default: { bg: '#f5f5f5', color: '#333' },
success: { bg: '#e8fdf5', color: '#00B894' },
warning: { bg: '#fffbeb', color: '#e6b800' },
error: { bg: '#fff5f5', color: '#FF7675' },
} as const
// ❌ switch-case — 层层嵌套,AI 难以维护
switch (status) {
case 'success': return { bg: '#e8fdf5', color: '#00B894' }
case 'warning': return { bg: '#fffbeb', color: '#e6b800' }
// ... 更多 case
}
```
---
## 五、组件规范
### 5.1 按钮 (Button)
**按钮变体:**
```tsx
<Button variant="solid"></Button>
<Button variant="outline"></Button>
<Button variant="ghost"></Button>
<Button variant="text"></Button>
<Button variant="link"></Button>
```
**按钮尺寸:**
```tsx
<Button size="small"></Button>
<Button size="middle"></Button>
<Button size="large"></Button>
```
**按钮形状(以 Apple 为准):**
```tsx
<Button shape="default"></Button>
<Button shape="round"></Button>
<Button shape="circle"></Button>
<Button shape="pill"></Button> // Apple 风格
```
**按钮状态:**
```tsx
<Button status="default"></Button>
<Button status="success"></Button>
<Button status="warning"></Button>
<Button status="error"></Button>
```
**按钮属性:**
```tsx
export type ButtonVariant = 'solid' | 'outline' | 'ghost' | 'text' | 'link'
export type ButtonSize = 'large' | 'middle' | 'small'
export type ButtonShape = 'default' | 'circle' | 'round' | 'pill'
export type ButtonStatus = 'default' | 'success' | 'warning' | 'error' | 'info'
export interface ButtonProps {
variant?: ButtonVariant
size?: ButtonSize
shape?: ButtonShape
status?: ButtonStatus
disabled?: boolean
loading?: boolean
fullWidth?: boolean
icon?: ReactNode
iconPosition?: 'left' | 'right'
onClick?: React.MouseEventHandler<HTMLButtonElement>
}
```
### 5.2 输入框 (Input)
**输入框尺寸:**
- 单行文本字段:40 px
- 多行文本字段:最小 80 px
```tsx
<Input size="small" />
<Input size="middle" />
<Input size="large" />
```
**输入框状态:**
```tsx
<Input status="default" />
<Input status="success" />
<Input status="warning" />
<Input status="error" />
```
### 5.3 导航组件
**导航栏(以 Apple 为准):**
| 平台 | 高度 |
|-----|------|
| iOS 普通 | 44 pt |
| iOS 大标题 | 64 pt |
| iPadOS | 44 pt |
**标签栏(以 Apple 为准):**
| 平台 | 高度 |
|-----|------|
| iOS | 49 pt |
| iOS (含 Home Indicator) | 83 pt |
| 最多标签数 | 5 个 |
**侧边栏(以 Apple 为准):**
| 平台 | 宽度 |
|-----|------|
| iPadOS | 280 pt |
| macOS | 320 pt |
### 5.4 列表与表格
**列表行高度:**
| 类型 | 高度 |
|-----|------|
| 紧凑 | 32px |
| 标准 | 40px |
| 大 | 56px |
### 5.5 模态与弹窗(以 Apple 为准)
**操作表 (Action Sheets)**
- 从底部滑出的卡片
- 圆角:14 pt
**提醒 (Alerts)**
- 中央弹出
- 圆角:14 pt
- 避免过度使用
**浮层 (Popovers)**
- 箭头指向锚点
- 圆角:10 pt
---
## 六、平台特定规范
### 6.1 触摸目标
- **最小触摸目标:44 × 44 px**
### 6.2 响应式布局
- 支持不同屏幕尺寸
- 支持横屏和竖屏
- 支持暗色模式
### 6.3 手势支持
- 支持点击、滑动、拖拽
- 避免与系统手势冲突
---
## 七、结合 AntV 的可视化组件规范
### 7.1 图表组件统一接口
```tsx
interface ChartBaseProps<T> {
data: T[]
xField: keyof T
yField: keyof T
seriesField?: keyof T
color?: string | string[] | ((d: T) => string)
tooltip?: boolean | TooltipConfig
legend?: boolean | LegendConfig
animation?: boolean | AnimationConfig
}
```
### 7.2 支持的图表类型
```tsx
<LineChart data={data} xField="date" yField="value" />
<BarChart data={data} xField="category" yField="count" />
<PieChart data={data} angleField="value" colorField="name" />
<AreaChart data={data} xField="date" yField="value" />
<ScatterChart data={data} xField="age" yField="income" />
<DualAxesChart data={data} left={{ yField: 'revenue' }} right={{ yField: 'rate' }} />
```
---
## 八、可落地的 Token 体系
```ts
export const tokens = {
color: {
primary: '#6C5CE7',
primaryHover: '#A29BFE',
primaryActive: '#4A3DBF',
success: '#00B894',
warning: '#FDCB6E',
error: '#FF7675',
info: '#74B9FF',
},
radius: {
small: '4px',
middle: '8px',
large: '12px',
full: '9999px',
},
space: {
small: '8px',
middle: '16px',
large: '24px',
},
font: {
family: '"SF Pro", -apple-system, BlinkMacSystemFont, sans-serif',
familyMono: '"SF Mono", "JetBrains Mono", monospace',
size: { small: 12, middle: 14, large: 16 },
weight: { regular: 400, medium: 500, semibold: 600, bold: 700 },
},
shadow: {
small: '0 1px 2px rgba(0,0,0,0.05)',
middle: '0 4px 8px rgba(0,0,0,0.08)',
large: '0 8px 16px rgba(0,0,0,0.12)',
focus: '0 0 0 3px rgba(108, 92, 231, 0.2)',
},
motion: {
fast: '0.15s',
normal: '0.25s',
slow: '0.4s',
easeDefault: 'cubic-bezier(0.4, 0, 0.2, 1)',
easeSpring: 'cubic-bezier(0.34, 1.56, 0.64, 1)',
},
} as const
```
---
## 九、无障碍设计
### 9.1 视觉无障碍
1. **支持文字缩放** - 允许用户调整文本大小
2. **支持屏幕阅读器** - 所有元素可访问
3. **足够的颜色对比度** - 最小 4.5:1
### 9.2 运动无障碍
1. **尊重"减少运动"设置**
2. **可选的运动效果**
---
## 十、AI 友好的代码约束
### 10.1 Props 声明规范
```tsx
interface ButtonProps {
variant?: 'solid' | 'outline' | 'ghost' | 'text' | 'link'
size?: 'large' | 'middle' | 'small'
status?: 'default' | 'success' | 'warning' | 'error' | 'info'
}
```
### 10.2 状态映射
```tsx
const STATUS_STYLES = {
default: { bg: '#f5f5f5', color: '#333' },
success: { bg: '#e8fdf5', color: '#00B894' },
warning: { bg: '#fffbeb', color: '#e6b800' },
error: { bg: '#fff5f5', color: '#FF7675' },
} as const
```
### 10.3 样式绑定
```tsx
// data-* 属性 + CSS 属性选择器
<button data-variant="solid" data-size="md" data-status="success" />
```
---
## 十一、项目结构
```
Pikaui/
├── packages/
│ ├── core/
│ │ ├── Button/
│ │ ├── Input/
│ │ ├── Typography/
│ │ └── ...
│ ├── charts/
│ ├── icons/
│ ├── theme/
│ └── utils/
├── apps/
│ └── docs/
```
---
## 十二、总结:Pika 给 AI 的"提示工程"
```
1. 导入路径 = @Pika/ui/组件名
2. 数据 prop 始终叫 data
3. 尺寸 prop 始终叫 size,值从 large/middle/small 选
4. 布尔 prop 用动词开头
5. 所有 prop 类型用联合类型字面量定义
6. 状态样式用 data-* 属性
7. 回调命名 = on + 动词 + 名词
8. 每个组件独立文件
9. 可视化组件统一 xField / yField / data
10. 状态类型统一:default | success | warning | error | info
```
> **Pika 的核心竞争力:简洁统一的设计规范,专为 AI 代码生成优化。**