14 KiB
14 KiB
Pika 布局组件规划
基于 Pika 设计规范的布局组件设计 设计原则:以 Apple HIG 为准,AI-First,三级别尺寸体系
一、核心理念
1.1 设计价值观(与根规范一致)
Pika 布局组件基于 Apple Human Interface Guidelines 的三大核心原则构建:
| 原则 | 说明 |
|---|---|
| 层级 | 建立清晰的视觉层级,区分内容和控件 |
| 和谐 | 与硬件和软件设计保持一致 |
| 一致性 | 采用平台约定,跨组件保持统一 |
1.2 AI-First 设计原则
所有布局组件遵循 Pika 的 AI-First 设计原则:
| 原则 | 说明 |
|---|---|
| 零歧义 | Props 名称自解释,无简称、无隐式行为 |
| 零默认假设 | 所有视觉行为显式声明 |
| 一致性 | 相同概念用相同 prop 名 |
| 扁平化 | 最多一层嵌套 |
| 确定性 | 相同输入始终产生相同输出 |
二、统一尺寸体系(三级别)
所有布局组件使用统一的三级别尺寸体系:
| 级别 | 间距 | 圆角 | 字体大小 |
|---|---|---|---|
| small | 8px | 4px | 12px |
| middle | 16px | 8px | 14px |
| large | 24px | 12px | 16px |
2.1 Design Token(与根规范一致)
--nv-spacing-small: 8px;
--nv-spacing-middle: 16px;
--nv-spacing-large: 24px;
--nv-radius-small: 4px;
--nv-radius-middle: 8px;
--nv-radius-large: 12px;
--nv-radius-full: 9999px;
--nv-font-size-small: 12px;
--nv-font-size-middle: 14px;
--nv-font-size-large: 16px;
三、组件体系
3.1 组件清单
| 组件 | 说明 | 优先级 |
|---|---|---|
| Layout | 页面布局容器 | P0 |
| Header | 顶部导航栏 | P0 |
| Footer | 底部区域 | P0 |
| Content | 内容区域 | P0 |
| Sider | 侧边栏 | P0 |
| Row | 栅格行 | P1 |
| Col | 栅格列 | P1 |
| Space | 间距组件 | P2 |
| HStack | 水平排列 | P2 |
| VStack | 垂直排列 | P2 |
| Divider | 分隔线 | P2 |
四、组件详细设计
4.1 Layout 布局容器
Props 定义(AI-First)
export interface LayoutProps {
/** 是否有侧边栏(用于 SSR 避免样式闪烁) */
hasSider?: boolean
/** 子元素 */
children?: React.ReactNode
className?: string
style?: React.CSSProperties
}
export interface HeaderProps {
/** 高度 */
height?: number | string
/** 是否固定在顶部 */
fixed?: boolean
/** 子元素 */
children?: React.ReactNode
className?: string
style?: React.CSSProperties
}
export interface FooterProps {
/** 内边距 */
padding?: number | string
/** 子元素 */
children?: React.ReactNode
className?: string
style?: React.CSSProperties
}
export interface ContentProps {
/** 内边距 */
padding?: number | string
/** 子元素 */
children?: React.ReactNode
className?: string
style?: React.CSSProperties
}
export interface SiderProps {
/** 宽度 */
width?: number | string
/** 折叠后的宽度 */
collapsedWidth?: number
/** 是否可折叠 */
collapsible?: boolean
/** 当前折叠状态 */
collapsed?: boolean
/** 默认折叠状态 */
defaultCollapsed?: boolean
/** 折叠状态变化回调 */
onCollapse?: (collapsed: boolean) => void
/** 响应式断点 */
breakpoint?: 'small' | 'middle' | 'large'
/** 断点变化回调 */
onBreakpoint?: (broken: boolean) => void
/** 是否反转箭头方向 */
reverseArrow?: boolean
/** 自定义触发器 */
trigger?: React.ReactNode
/** 子元素 */
children?: React.ReactNode
className?: string
style?: React.CSSProperties
}
使用示例
// 基础布局
<Layout>
<Layout.Header>Header</Layout.Header>
<Layout.Content>Content</Layout.Content>
<Layout.Footer>Footer</Layout.Footer>
</Layout>
// 经典后台布局
<Layout>
<Layout.Sider
width={200}
collapsedWidth={80}
collapsible
breakpoint="middle"
>
<Menu />
</Layout.Sider>
<Layout>
<Layout.Header fixed>Header</Layout.Header>
<Layout.Content padding={24}>Content</Layout.Content>
</Layout>
</Layout>
Design Token
--nv-layout-header-height: 64px;
--nv-layout-footer-padding: var(--nv-spacing-middle);
--nv-layout-sider-width: 200px;
--nv-layout-sider-collapsed-width: 80px;
--nv-layout-trigger-height: 48px;
--nv-layout-content-padding: var(--nv-spacing-middle);
4.2 Grid 栅格系统
Props 定义(AI-First)
export interface RowProps {
/** 栅格间隔 */
gutter?: number | [number, number]
/** 主轴对齐方式 */
justify?: 'start' | 'end' | 'center' | 'space-around' | 'space-between'
/** 交叉轴对齐方式 */
align?: 'start' | 'end' | 'center' | 'baseline' | 'stretch'
/** 子元素 */
children?: React.ReactNode
className?: string
style?: React.CSSProperties
}
export interface ColProps {
/** 栅格格数 (0-24) */
span?: number
/** 左侧偏移格数 */
offset?: number
/** 栅格顺序 */
order?: number
/** 响应式栅格 */
small?: number | { span?: number; offset?: number; order?: number }
middle?: number | { span?: number; offset?: number; order?: number }
large?: number | { span?: number; offset?: number; order?: number }
/** 子元素 */
children?: React.ReactNode
className?: string
style?: React.CSSProperties
}
使用示例
// 基础栅格
<Row gutter={16}>
<Col span={12}><Card /></Col>
<Col span={12}><Card /></Col>
</Row>
// 响应式布局
<Row gutter={[16, 16]}>
<Col
small={24}
middle={12}
large={6}
>
响应式列
</Col>
</Row>
// 间距和对齐
<Row
gutter={[16, 16]}
justify="space-between"
align="center"
>
<Col span={8} offset={2}></Col>
<Col span={12}></Col>
</Row>
Design Token
--nv-grid-gutter: var(--nv-spacing-middle);
--nv-grid-columns: 24;
4.3 Space 间距组件
Props 定义(AI-First)
export interface SpaceProps {
/** 间距方向 */
direction?: 'horizontal' | 'vertical'
/** 间距大小 */
size?: 'small' | 'middle' | 'large'
/** 对齐方式 */
align?: 'start' | 'end' | 'center' | 'baseline'
/** 是否换行(仅水平方向有效) */
wrap?: boolean
/** 分隔符 */
split?: React.ReactNode
/** 子元素 */
children?: React.ReactNode
className?: string
style?: React.CSSProperties
}
使用示例
// 基础使用
<Space size="middle">
<Button>按钮</Button>
<Button>按钮</Button>
</Space>
// 垂直排列
<Space direction="vertical" size="small">
<Input />
<Input />
</Space>
// 带分隔符
<Space split={<Divider type="vertical" />}>
<Text>Link 1</Text>
<Text>Link 2</Text>
</Space>
// 自动换行
<Space wrap size="middle">
{tags.map(tag => <Tag key={tag}>{tag}</Tag>)}
</Space>
Design Token
--nv-space-gap-small: var(--nv-spacing-small);
--nv-space-gap-middle: var(--nv-spacing-middle);
--nv-space-gap-large: var(--nv-spacing-large);
4.4 Stack 弹性盒布局
Props 定义(AI-First)
export interface StackProps {
/** 排列方向 */
direction?: 'horizontal' | 'vertical'
/** 间距 */
gap?: 'small' | 'middle' | 'large' | number | string
/** 主轴对齐方式 */
justify?: 'start' | 'end' | 'center' | 'space-around' | 'space-between' | 'space-evenly'
/** 交叉轴对齐方式 */
align?: 'start' | 'end' | 'center' | 'baseline' | 'stretch'
/** 是否换行 */
wrap?: boolean
/** 子元素 */
children?: React.ReactNode
className?: string
style?: React.CSSProperties
}
// 便捷组件
export interface HStackProps extends Omit<StackProps, 'direction'> {}
export interface VStackProps extends Omit<StackProps, 'direction'> {}
使用示例
// 使用 Stack
<Stack direction="horizontal" gap="middle" justify="space-between">
<Logo />
<Nav />
</Stack>
// 使用 HStack
<HStack gap="middle" justify="space-between">
<Logo />
<Nav />
</HStack>
// 使用 VStack
<VStack gap="small" align="center">
<Avatar />
<Name />
<Desc />
</VStack>
4.5 Divider 分隔线
Props 定义(AI-First)
export interface DividerProps {
/** 方向 */
type?: 'horizontal' | 'vertical'
/** 是否虚线 */
dashed?: boolean
/** 子元素(居中文字) */
children?: React.ReactNode
className?: string
style?: React.CSSProperties
}
使用示例
// 水平分隔
<Divider />
// 带文字
<Divider>内容</Divider>
// 垂直分隔
<Space split={<Divider type="vertical" />}>
<Text>Link 1</Text>
<Text>Link 2</Text>
</Space>
// 虚线
<Divider dashed />
Design Token
--nv-divider-color: var(--nv-color-border);
--nv-divider-padding: var(--nv-spacing-middle);
五、AI-First 设计规范
5.1 Props 命名规范
| 规则 | 说明 |
|---|---|
| 布尔属性 | 动词/形容词 + 肯定形式:disabled, collapsible, fixed, wrap, dashed |
| 事件回调 | on + 动词 + 名词:onCollapse, onBreakpoint |
| 尺寸 | 统一使用 small, middle, large |
| 响应式断点 | 统一使用 small, middle, large |
5.2 样式绑定规范
使用 data-* 属性进行样式绑定:
<div
data-direction="horizontal"
data-size="middle"
data-wrap="true"
/>
5.3 组件导入规范
每个组件独立导入,路径即名字:
import { Layout } from '@Pika/ui/layout'
import { Header, Footer, Sider, Content } from '@Pika/ui/layout'
import { Row, Col } from '@Pika/ui/grid'
import { Space } from '@Pika/ui/space'
import { Stack, HStack, VStack } from '@Pika/ui/stack'
import { Divider } from '@Pika/ui/divider'
六、完整使用示例
6.1 经典后台布局
import { Layout, Row, Col, Space, HStack, VStack, Divider } from '@Pika/ui'
const App = () => {
const [collapsed, setCollapsed] = useState(false)
return (
<Layout>
<Layout.Sider
width={200}
collapsedWidth={80}
collapsible
collapsed={collapsed}
onCollapse={setCollapsed}
breakpoint="middle"
>
<Menu />
</Layout.Sider>
<Layout>
<Layout.Header fixed>
<HStack justify="space-between">
<Logo />
<UserMenu />
</HStack>
</Layout.Header>
<Layout.Content padding={24}>
<VStack gap="middle">
<PageTitle />
<Row gutter={[16, 16]}>
<Col
small={24}
middle={12}
large={6}
>
<Card />
</Col>
<Col
small={24}
middle={12}
large={6}
>
<Card />
</Col>
<Col
small={24}
middle={12}
large={6}
>
<Card />
</Col>
<Col
small={24}
middle={12}
large={6}
>
<Card />
</Col>
</Row>
<Divider />
<Space size="middle">
<Button>保存</Button>
<Button variant="outline">取消</Button>
</Space>
</VStack>
</Layout.Content>
<Layout.Footer>
© 2024 Pika UI
</Layout.Footer>
</Layout>
</Layout>
)
}
七、文件结构
src/components/
├── layout/
│ ├── index.ts
│ ├── Layout.tsx
│ ├── Header.tsx
│ ├── Footer.tsx
│ ├── Sider.tsx
│ ├── Content.tsx
│ ├── Layout.module.css
│ └── Layout.test.tsx
├── grid/
│ ├── index.ts
│ ├── Row.tsx
│ ├── Col.tsx
│ ├── Grid.module.css
│ └── Grid.test.tsx
├── space/
│ ├── index.ts
│ ├── Space.tsx
│ ├── Space.module.css
│ └── Space.test.tsx
├── stack/
│ ├── index.ts
│ ├── Stack.tsx
│ ├── HStack.tsx
│ ├── VStack.tsx
│ ├── Stack.module.css
│ └── Stack.test.tsx
└── divider/
├── index.ts
├── Divider.tsx
├── Divider.module.css
└── Divider.test.tsx
八、优先级规划
Phase 1: 核心布局 (P0)
| 组件 | 说明 | 预估工时 |
|---|---|---|
| Layout | 布局容器 | 1h |
| Header | 顶部导航栏 | 0.5h |
| Footer | 底部区域 | 0.5h |
| Content | 内容区域 | 0.5h |
| Sider | 侧边栏 | 2h |
Phase 2: 栅格系统 (P1)
| 组件 | 说明 | 预估工时 |
|---|---|---|
| Row | 行容器 | 1h |
| Col | 列组件 | 1.5h |
Phase 3: 间距和弹性盒 (P2)
| 组件 | 说明 | 预估工时 |
|---|---|---|
| Space | 间距组件 | 1h |
| Stack | 弹性盒容器 | 1h |
| HStack | 水平排列 | 0.25h |
| VStack | 垂直排列 | 0.25h |
| Divider | 分隔线 | 0.5h |
九、与根设计规范的对照
| 根规范 | 实现方式 |
|---|---|
| 三级别尺寸 | small, middle, large 统一应用于所有组件 |
| AI-First | 所有 Props 使用联合类型字面量,无魔法字符串 |
| Apple HIG | 圆角、间距、动效遵循 Apple 规范 |
| data- 样式绑定* | 使用 data-* 属性而非 className 拼接 |
| 自包含组件 | 每个组件独立导入,路径即名字 |
| 统一事件命名 | on + 动词 + 名词 规则 |
十、设计总结
Pika 布局组件的特点
- 简洁统一 - 三级别尺寸体系,无过度设计
- AI 友好 - Props 自解释,类型安全,确定导入路径
- Apple HIG 优先 - 遵循 Apple 人机交互指南
- 语义化 - Space, HStack, VStack 提供清晰的布局语义
- 可扩展 - 支持响应式、折叠等高级功能
AI 提示工程
1. 导入路径 = @Pika/ui/组件名 (layout/grid/space/stack/divider)
2. 尺寸 prop 始终叫 size,值从 small/middle/large 选
3. 响应式断点统一:small/middle/large
4. 布尔 prop 用动词开头 (collapsible, fixed, wrap, dashed)
5. 回调命名 = on + 动词 + 名词 (onCollapse, onBreakpoint)
6. 所有 prop 类型用联合类型字面量定义
7. 使用 Space 代替手动计算间距
8. 使用 HStack/VStack 进行弹性盒布局
Pika 布局组件:简洁、统一、AI-First