Files
RustUI/_plans/layout-components-plan.md
T
2026-05-31 09:36:23 +08:00

14 KiB
Raw Blame History

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 布局组件的特点

  1. 简洁统一 - 三级别尺寸体系,无过度设计
  2. AI 友好 - Props 自解释,类型安全,确定导入路径
  3. Apple HIG 优先 - 遵循 Apple 人机交互指南
  4. 语义化 - Space, HStack, VStack 提供清晰的布局语义
  5. 可扩展 - 支持响应式、折叠等高级功能

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