Skip to content

Commit c9a559c

Browse files
committed
docs(llm): update developer guide
1 parent a592a27 commit c9a559c

File tree

1 file changed

+82
-24
lines changed

1 file changed

+82
-24
lines changed

llm/developer_guide.md

Lines changed: 82 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,67 @@
22

33
本指南专为 AI 模型设计,旨在提供标准化的代码模板和明确的步骤,以生成符合 SoybeanUI 架构规范的高质量组件代码。
44

5-
## 核心架构原则
5+
## 1. 项目架构概览
66

7-
1. **Headless (逻辑层)**: 位于 `headless/`。负责状态、交互、A11y。**严禁包含 CSS/样式**
8-
2. **UI (表现层)**: 位于 `src/`。负责视觉样式、主题变体。使用 `tailwind-variants`
9-
3. **单向依赖**: UI 层依赖 Headless 层,Headless 层****依赖 UI 层。
7+
SoybeanUI 采用 **Headless UI (逻辑层)****Styled UI (表现层)** 分离的架构模式。
8+
9+
### 1.1 核心分层
10+
11+
- **Headless 层 (`headless/`)**:
12+
- **职责**: 负责组件的状态管理、交互逻辑、无障碍访问 (A11y) 和 DOM 结构。
13+
- **原则**: **严禁包含任何 CSS 样式**。只关注功能,不关注长相。
14+
- **技术**: Vue 3 (Composition API), TypeScript.
15+
- **UI 层 (`src/`)**:
16+
- **职责**: 负责组件的视觉样式、主题变体、动画效果。
17+
- **原则**: 依赖 Headless 层提供的逻辑组件,通过 `tailwind-variants` 注入样式。
18+
- **技术**: Vue 3, Tailwind CSS (UnoCSS), Tailwind Variants.
19+
20+
### 1.2 依赖关系
21+
22+
`UI 层` -> `Headless 层` (单向依赖)
23+
24+
---
25+
26+
## 2. 目录结构详解
27+
28+
```
29+
soybean-ui/
30+
├── headless/ # [逻辑层] Headless 组件库 workspace
31+
│ └── src/
32+
│ ├── components/ # Headless 组件源码
33+
│ │ └── {component}/ # 单个组件目录
34+
│ │ ├── {component}-root.vue # 根组件
35+
│ │ ├── {component}-item.vue # 子组件
36+
│ │ ├── context.ts # 依赖注入上下文
37+
│ │ ├── types.ts # 类型定义
38+
│ │ └── index.ts # 导出文件
39+
│ ├── composables/ # 共享组合式函数 (useContext, useId 等)
40+
│ └── primitive/ # 基础图元组件
41+
├── src/ # [表现层] UI 组件库 workspace
42+
│ ├── components/ # UI 组件源码
43+
│ │ └── {component}/ # 单个组件目录
44+
│ │ ├── {component}.vue # UI 组件实现
45+
│ │ ├── types.ts # UI 组件类型定义
46+
│ │ ├── context.ts # (可选) UI 层上下文
47+
│ │ └── index.ts # 导出文件
48+
│ ├── variants/ # [关键] 样式变体定义
49+
│ │ └── {component}.ts # 使用 tailwind-variants 定义样式
50+
│ └── theme/ # 主题配置与工具函数
51+
├── package.json # 项目根配置
52+
└── uno.config.ts # UnoCSS 配置
53+
```
54+
55+
---
56+
57+
## 3. 开发流程与代码规范
58+
59+
开发一个新组件通常分为两个阶段:首先实现 Headless 逻辑,然后实现 UI 样式。
1060

1161
---
1262

13-
## 第一阶段:Headless 层开发 (`headless/src/components/{component}/`)
63+
### 第一阶段:Headless 层开发 (`headless/src/components/{component}/`)
1464

15-
### 1. 定义类型 (`types.ts`)
65+
#### 1. 定义类型 (`types.ts`)
1666

1767
**目标**: 定义组件的 Props, Emits, Context 参数以及样式槽 (Theme Slots)。
1868

@@ -66,7 +116,7 @@ export interface {ComponentName}ThemeContextParams {
66116
}
67117
```
68118

69-
### 2. 定义上下文 (`context.ts`)
119+
#### 2. 定义上下文 (`context.ts`)
70120

71121
**目标**: 创建类型安全的 Provide/Inject 对。
72122

@@ -94,7 +144,7 @@ export const [provide{ComponentName}ThemeContext, use{ComponentName}ThemeContext
94144
);
95145
```
96146

97-
### 3. 实现 Root 组件 (`{component}-root.vue`)
147+
#### 3: 实现组件 (`{component}-root.vue`, `{component}-item.vue`)
98148

99149
**目标**: 初始化状态,提供 Context,渲染根元素。
100150

@@ -105,6 +155,8 @@ export const [provide{ComponentName}ThemeContext, use{ComponentName}ThemeContext
105155
- 使用 `use{ComponentName}ThemeContext` 获取样式并应用 `ui.root`
106156
- 使用 `transformPropsToContext` 传递 Props。
107157

158+
**Root 组件示例**:
159+
108160
```vue
109161
<script setup lang="ts">
110162
import { computed, shallowRef } from 'vue';
@@ -143,7 +195,7 @@ provide{ComponentName}RootContext({
143195
</template>
144196
```
145197

146-
### 4. 实现子组件 (如 `{component}-item.vue`)
198+
**Item 组件示例**:
147199

148200
**目标**: 消费 Context,渲染子元素。
149201

@@ -170,7 +222,7 @@ const cls = computed(() => themeContext?.ui?.value?.item);
170222
</template>
171223
```
172224

173-
### 5. 导出 Headless 组件 (`index.ts`)
225+
#### 5. 导出 Headless 组件 (`index.ts`)
174226

175227
```typescript
176228
export { default as {ComponentName}Root } from './{component}-root.vue';
@@ -186,9 +238,9 @@ export * from './types';
186238

187239
---
188240

189-
## 第二阶段:UI 层开发 (`src/components/{component}/`)
241+
### 第二阶段:UI 层开发 (`src/components/{component}/`)
190242

191-
### 1. 定义样式变体 (`src/variants/{component}.ts`)
243+
#### 1. 定义样式变体 (`src/variants/{component}.ts`)
192244

193245
**目标**: 使用 Tailwind CSS 定义组件样式。
194246

@@ -217,7 +269,7 @@ export const {componentName}Variants = tv({
217269
});
218270
```
219271

220-
### 2. 定义 UI 类型 (`src/components/{component}/types.ts`)
272+
#### 2. 定义 UI 类型 (`src/components/{component}/types.ts`)
221273

222274
**目标**: 扩展 Headless Props,添加 UI 属性。
223275

@@ -241,7 +293,7 @@ export type {ComponentName}Props = {ComponentName}RootProps & {
241293
export type {ComponentName}Emits = {ComponentName}RootEmits;
242294
```
243295

244-
### 3. 实现 UI 组件 (`src/components/{component}/{component}.vue`)
296+
#### 3. 实现 UI 组件 (`src/components/{component}/{component}.vue`)
245297

246298
**目标**: 组合 Headless 组件,注入样式 Context。
247299

@@ -298,7 +350,7 @@ provide{ComponentName}ThemeContext({ ui });
298350
</template>
299351
```
300352

301-
### 4. 导出 UI 组件 (`index.ts`)
353+
#### 4. 导出 UI 组件 (`index.ts`)
302354

303355
```typescript
304356
export { default as S{ComponentName} } from './{component}.vue';
@@ -314,18 +366,24 @@ export * from './types';
314366
| 函数名 | 用途 |
315367
| :--------------------- | :---------------------------------------- |
316368
| `useContext` | 创建 Provide/Inject 对。 |
317-
| `useId` | 生成唯一 ID。 |
318369
| `useForwardElement` | 在组件间传递 DOM 元素引用。 |
319370
| `useForwardListeners` | 转发事件监听器。 |
320371
| `useOmitProps` | 剔除 Props 中的特定属性,返回响应式对象。 |
321372
| `useSelection` | 处理 v-model 选择逻辑 (单选/多选)。 |
322373
| `useControllableState` | 处理受控/非受控状态。 |
323374

324-
## 检查清单
325-
326-
1. [ ] **Headless**: `types.ts` 定义了 `ThemeSlot``Ui` 类型?
327-
2. [ ] **Headless**: `context.ts` 导出了 `ThemeContext`
328-
3. [ ] **Headless**: 组件内部使用了 `use{ComponentName}ThemeContext` 获取样式?
329-
4. [ ] **UI**: `variants` 定义了所有 `ThemeSlot`
330-
5. [ ] **UI**: 组件使用了 `useOmitProps` 过滤 UI 属性?
331-
6. [ ] **UI**: 组件提供了 `ThemeContext`
375+
## 关键注意事项
376+
377+
1. **Headless**: `types.ts` 定义了 `ThemeSlot``Ui` 类型?
378+
2. **Headless**: `context.ts` 导出了 `ThemeContext`
379+
3. **Props 透传**: 使用 `useOmitProps` 确保 UI 特有的 Props (如 `size`, `variant`) 不会被透传到 DOM 节点上导致 HTML 属性污染。
380+
4. **事件转发**: 使用 `useForwardListeners` 确保组件上的事件监听器能正确绑定到 Headless 组件内部的元素上。
381+
5. **Slot 一致性**: `headless/**/types.ts` 中的 `ThemeSlot` 定义必须与 `src/variants/**.ts` 中的 `slots` 键名完全一致。
382+
6. **Headless**: 组件内部使用了 `use{ComponentName}ThemeContext` 获取样式?
383+
7. **UI**: `variants` 定义了所有 `ThemeSlot`
384+
8. **UI**: 组件使用了 `useOmitProps` 过滤 UI 属性?
385+
9. **UI**: 组件提供了 `ThemeContext`
386+
10. **命名规范**:
387+
- Headless 组件: `{ComponentName}Root`, `{ComponentName}Item`
388+
- UI 组件: `S{ComponentName}` (S 前缀)
389+
- Context: `provide{ComponentName}Context`, `use{ComponentName}Context`

0 commit comments

Comments
 (0)