ccbot-cli 2.0.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/bin/adapters/claude.js +150 -0
- package/bin/adapters/codex.js +439 -0
- package/bin/install.js +509 -349
- package/bin/lib/ccline.js +82 -0
- package/bin/lib/utils.js +87 -34
- package/bin/uninstall.js +48 -0
- package/config/AGENTS.md +630 -0
- package/config/CLAUDE.md +229 -20
- package/config/ccline/config.toml +161 -0
- package/config/codex-config.example.toml +22 -0
- package/config/settings.example.json +32 -0
- package/output-styles/abyss-cultivator.md +399 -0
- package/package.json +14 -5
- package/skills/SKILL.md +159 -0
- package/skills/domains/ai/SKILL.md +34 -0
- package/skills/domains/ai/agent-dev.md +242 -0
- package/skills/domains/ai/llm-security.md +288 -0
- package/skills/domains/ai/prompt-and-eval.md +279 -0
- package/skills/domains/ai/rag-system.md +542 -0
- package/skills/domains/architecture/SKILL.md +42 -0
- package/skills/domains/architecture/api-design.md +225 -0
- package/skills/domains/architecture/caching.md +299 -0
- package/skills/domains/architecture/cloud-native.md +285 -0
- package/skills/domains/architecture/message-queue.md +329 -0
- package/skills/domains/architecture/security-arch.md +297 -0
- package/skills/domains/data-engineering/SKILL.md +207 -0
- package/skills/domains/development/SKILL.md +46 -0
- package/skills/domains/development/cpp.md +246 -0
- package/skills/domains/development/go.md +323 -0
- package/skills/domains/development/java.md +277 -0
- package/skills/domains/development/python.md +288 -0
- package/skills/domains/development/rust.md +313 -0
- package/skills/domains/development/shell.md +313 -0
- package/skills/domains/development/typescript.md +277 -0
- package/skills/domains/devops/SKILL.md +39 -0
- package/skills/domains/devops/cost-optimization.md +272 -0
- package/skills/domains/devops/database.md +217 -0
- package/skills/domains/devops/devsecops.md +198 -0
- package/skills/domains/devops/git-workflow.md +181 -0
- package/skills/domains/devops/observability.md +280 -0
- package/skills/domains/devops/performance.md +336 -0
- package/skills/domains/devops/testing.md +283 -0
- package/skills/domains/frontend-design/SKILL.md +38 -0
- package/skills/domains/frontend-design/claymorphism/SKILL.md +119 -0
- package/skills/domains/frontend-design/claymorphism/references/tokens.css +52 -0
- package/skills/domains/frontend-design/component-patterns.md +202 -0
- package/skills/domains/frontend-design/engineering.md +287 -0
- package/skills/domains/frontend-design/glassmorphism/SKILL.md +140 -0
- package/skills/domains/frontend-design/glassmorphism/references/tokens.css +32 -0
- package/skills/domains/frontend-design/liquid-glass/SKILL.md +137 -0
- package/skills/domains/frontend-design/liquid-glass/references/tokens.css +81 -0
- package/skills/domains/frontend-design/neubrutalism/SKILL.md +143 -0
- package/skills/domains/frontend-design/neubrutalism/references/tokens.css +44 -0
- package/skills/domains/frontend-design/state-management.md +680 -0
- package/skills/domains/frontend-design/ui-aesthetics.md +110 -0
- package/skills/domains/frontend-design/ux-principles.md +156 -0
- package/skills/domains/infrastructure/SKILL.md +200 -0
- package/skills/domains/mobile/SKILL.md +224 -0
- package/skills/domains/orchestration/SKILL.md +29 -0
- package/skills/domains/orchestration/multi-agent.md +263 -0
- package/skills/domains/security/SKILL.md +54 -0
- package/skills/domains/security/blue-team.md +436 -0
- package/skills/domains/security/code-audit.md +265 -0
- package/skills/domains/security/pentest.md +226 -0
- package/skills/domains/security/red-team.md +375 -0
- package/skills/domains/security/threat-intel.md +372 -0
- package/skills/domains/security/vuln-research.md +369 -0
- package/skills/orchestration/multi-agent/SKILL.md +493 -0
- package/skills/run_skill.js +129 -0
- package/skills/tools/gen-docs/SKILL.md +116 -0
- package/skills/tools/gen-docs/scripts/doc_generator.js +435 -0
- package/skills/tools/lib/shared.js +98 -0
- package/skills/tools/verify-change/SKILL.md +140 -0
- package/skills/tools/verify-change/scripts/change_analyzer.js +289 -0
- package/skills/tools/verify-module/SKILL.md +127 -0
- package/skills/tools/verify-module/scripts/module_scanner.js +171 -0
- package/skills/tools/verify-quality/SKILL.md +160 -0
- package/skills/tools/verify-quality/scripts/quality_checker.js +337 -0
- package/skills/tools/verify-security/SKILL.md +143 -0
- package/skills/tools/verify-security/scripts/security_scanner.js +283 -0
- package/bin/lib/registry.js +0 -61
- package/config/.claudeignore +0 -11
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: testing
|
|
3
|
+
description: 软件测试。单元测试、集成测试、TDD、测试框架。当用户提到测试、单元测试、pytest、Jest、mock、TDD时使用。
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# 🔧 炼器秘典 · 软件测试
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
## 测试金字塔
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
/\
|
|
13
|
+
/ \ E2E 测试 (少)
|
|
14
|
+
/----\
|
|
15
|
+
/ \ 集成测试 (中)
|
|
16
|
+
/--------\
|
|
17
|
+
/ \ 单元测试 (多)
|
|
18
|
+
--------------
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Python (pytest)
|
|
22
|
+
|
|
23
|
+
```python
|
|
24
|
+
import pytest
|
|
25
|
+
from myapp import calculate, UserService
|
|
26
|
+
|
|
27
|
+
# 基础测试
|
|
28
|
+
def test_add():
|
|
29
|
+
assert calculate.add(1, 2) == 3
|
|
30
|
+
|
|
31
|
+
# 参数化
|
|
32
|
+
@pytest.mark.parametrize("a,b,expected", [
|
|
33
|
+
(1, 2, 3),
|
|
34
|
+
(0, 0, 0),
|
|
35
|
+
(-1, 1, 0),
|
|
36
|
+
])
|
|
37
|
+
def test_add_params(a, b, expected):
|
|
38
|
+
assert calculate.add(a, b) == expected
|
|
39
|
+
|
|
40
|
+
# Fixture
|
|
41
|
+
@pytest.fixture
|
|
42
|
+
def user_service():
|
|
43
|
+
service = UserService()
|
|
44
|
+
yield service
|
|
45
|
+
service.cleanup()
|
|
46
|
+
|
|
47
|
+
def test_create_user(user_service):
|
|
48
|
+
user = user_service.create("test")
|
|
49
|
+
assert user.name == "test"
|
|
50
|
+
|
|
51
|
+
# Mock
|
|
52
|
+
from unittest.mock import Mock, patch
|
|
53
|
+
|
|
54
|
+
@patch('myapp.requests.get')
|
|
55
|
+
def test_fetch(mock_get):
|
|
56
|
+
mock_get.return_value.json.return_value = {"id": 1}
|
|
57
|
+
result = fetch_user(1)
|
|
58
|
+
assert result["id"] == 1
|
|
59
|
+
|
|
60
|
+
# 异步测试
|
|
61
|
+
@pytest.mark.asyncio
|
|
62
|
+
async def test_async_fetch():
|
|
63
|
+
result = await async_fetch()
|
|
64
|
+
assert result is not None
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### 运行命令
|
|
68
|
+
```bash
|
|
69
|
+
pytest # 运行所有
|
|
70
|
+
pytest test_file.py # 指定文件
|
|
71
|
+
pytest -k "test_add" # 匹配名称
|
|
72
|
+
pytest -v # 详细输出
|
|
73
|
+
pytest --cov=myapp # 覆盖率
|
|
74
|
+
pytest -x # 失败即停
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## JavaScript (Jest/Vitest)
|
|
78
|
+
|
|
79
|
+
```javascript
|
|
80
|
+
import { describe, it, expect, vi } from 'vitest';
|
|
81
|
+
|
|
82
|
+
// 基础测试
|
|
83
|
+
describe('add', () => {
|
|
84
|
+
it('should add two numbers', () => {
|
|
85
|
+
expect(add(1, 2)).toBe(3);
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it.each([
|
|
89
|
+
[1, 2, 3],
|
|
90
|
+
[0, 0, 0],
|
|
91
|
+
[-1, 1, 0],
|
|
92
|
+
])('add(%i, %i) = %i', (a, b, expected) => {
|
|
93
|
+
expect(add(a, b)).toBe(expected);
|
|
94
|
+
});
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
// Mock
|
|
98
|
+
vi.mock('./api', () => ({
|
|
99
|
+
getUser: vi.fn().mockResolvedValue({ id: 1, name: 'test' })
|
|
100
|
+
}));
|
|
101
|
+
|
|
102
|
+
it('should fetch user', async () => {
|
|
103
|
+
const user = await fetchUser(1);
|
|
104
|
+
expect(user.name).toBe('test');
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
// Spy
|
|
108
|
+
const spy = vi.spyOn(console, 'log');
|
|
109
|
+
doSomething();
|
|
110
|
+
expect(spy).toHaveBeenCalledWith('message');
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## Go (testing)
|
|
114
|
+
|
|
115
|
+
```go
|
|
116
|
+
package main
|
|
117
|
+
|
|
118
|
+
import (
|
|
119
|
+
"testing"
|
|
120
|
+
"github.com/stretchr/testify/assert"
|
|
121
|
+
)
|
|
122
|
+
|
|
123
|
+
func TestAdd(t *testing.T) {
|
|
124
|
+
result := Add(1, 2)
|
|
125
|
+
assert.Equal(t, 3, result)
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// 表驱动测试
|
|
129
|
+
func TestAddTable(t *testing.T) {
|
|
130
|
+
tests := []struct {
|
|
131
|
+
name string
|
|
132
|
+
a, b int
|
|
133
|
+
expected int
|
|
134
|
+
}{
|
|
135
|
+
{"positive", 1, 2, 3},
|
|
136
|
+
{"zero", 0, 0, 0},
|
|
137
|
+
{"negative", -1, 1, 0},
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
for _, tt := range tests {
|
|
141
|
+
t.Run(tt.name, func(t *testing.T) {
|
|
142
|
+
assert.Equal(t, tt.expected, Add(tt.a, tt.b))
|
|
143
|
+
})
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// Benchmark
|
|
148
|
+
func BenchmarkAdd(b *testing.B) {
|
|
149
|
+
for i := 0; i < b.N; i++ {
|
|
150
|
+
Add(1, 2)
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
## 测试原则
|
|
156
|
+
|
|
157
|
+
```yaml
|
|
158
|
+
FIRST:
|
|
159
|
+
- Fast: 快速执行
|
|
160
|
+
- Independent: 相互独立
|
|
161
|
+
- Repeatable: 可重复
|
|
162
|
+
- Self-validating: 自验证
|
|
163
|
+
- Timely: 及时编写
|
|
164
|
+
|
|
165
|
+
AAA:
|
|
166
|
+
- Arrange: 准备数据
|
|
167
|
+
- Act: 执行操作
|
|
168
|
+
- Assert: 验证结果
|
|
169
|
+
|
|
170
|
+
原则:
|
|
171
|
+
- 每个测试只验证一件事
|
|
172
|
+
- 测试边界条件
|
|
173
|
+
- 测试异常情况
|
|
174
|
+
- 避免测试实现细节
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
## TDD 流程
|
|
178
|
+
|
|
179
|
+
```
|
|
180
|
+
红 → 绿 → 重构
|
|
181
|
+
|
|
182
|
+
1. 红: 写一个失败的测试
|
|
183
|
+
2. 绿: 写最少代码让测试通过
|
|
184
|
+
3. 重构: 优化代码,保持测试通过
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
---
|
|
188
|
+
|
|
189
|
+
## 测试策略(源自 testing-strategy)
|
|
190
|
+
|
|
191
|
+
### 测试金字塔比例
|
|
192
|
+
|
|
193
|
+
| 层级 | 占比 | 执行时间 | 成本 |
|
|
194
|
+
|------|------|----------|------|
|
|
195
|
+
| 单元测试 | 70% | <1s | 低 |
|
|
196
|
+
| 集成测试 | 20% | 1-10s | 中 |
|
|
197
|
+
| E2E测试 | 10% | 10s-5m | 高 |
|
|
198
|
+
|
|
199
|
+
### 测试左移 Checklist
|
|
200
|
+
|
|
201
|
+
```yaml
|
|
202
|
+
需求阶段: 可测试性评审、验收标准定义、测试用例设计
|
|
203
|
+
开发阶段: TDD、单元测试同步编写、代码审查包含测试
|
|
204
|
+
提交阶段: Pre-commit Hook、本地测试必过、静态分析
|
|
205
|
+
CI阶段: 自动化测试、覆盖率门禁、性能基准测试
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
### 契约测试要点
|
|
209
|
+
|
|
210
|
+
- 消费者驱动契约 (CDC):Consumer 定义期望 → Provider 验证契约
|
|
211
|
+
- 工具:Pact(多语言)、Spring Cloud Contract(Java)
|
|
212
|
+
- 核心:Provider API <-> Contract <-> Consumer,双方独立验证
|
|
213
|
+
|
|
214
|
+
### 覆盖率策略
|
|
215
|
+
|
|
216
|
+
```yaml
|
|
217
|
+
类型: 行覆盖率、分支覆盖率、函数覆盖率、语句覆盖率
|
|
218
|
+
门禁: 全局 ≥80%,核心模块 ≥90%
|
|
219
|
+
排除: tests/、migrations/、__init__.py、config 文件
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
### 变异测试
|
|
223
|
+
|
|
224
|
+
- 修改源码(变异体)验证测试是否能捕获
|
|
225
|
+
- 工具:Stryker (JS)、Pitest (Java)
|
|
226
|
+
- 阈值:high 80% / low 60% / break 50%
|
|
227
|
+
|
|
228
|
+
### 测试最佳实践
|
|
229
|
+
|
|
230
|
+
- AAA 模式:Arrange → Act → Assert
|
|
231
|
+
- 命名:`should [预期行为] when [条件]`
|
|
232
|
+
- 单一职责:每个测试只验证一件事
|
|
233
|
+
- 数据隔离:Fixture/Factory 模式,每测试独立实例
|
|
234
|
+
- 并行执行:Jest `maxWorkers: '50%'`、pytest `-n auto`
|
|
235
|
+
|
|
236
|
+
---
|
|
237
|
+
|
|
238
|
+
## E2E 测试(源自 e2e-testing)
|
|
239
|
+
|
|
240
|
+
### Playwright vs Cypress
|
|
241
|
+
|
|
242
|
+
| 特性 | Playwright | Cypress |
|
|
243
|
+
|------|-----------|---------|
|
|
244
|
+
| 多浏览器 | Chromium/Firefox/WebKit | Chromium/Firefox/Edge |
|
|
245
|
+
| 多标签页/iframe | 原生支持 | 有限 |
|
|
246
|
+
| 并行执行 | 原生支持 | 需付费 |
|
|
247
|
+
| 调试体验 | 一般 | 优秀 |
|
|
248
|
+
|
|
249
|
+
### 选择器优先级
|
|
250
|
+
|
|
251
|
+
```
|
|
252
|
+
1. data-testid (推荐)
|
|
253
|
+
2. role + accessible name
|
|
254
|
+
3. 稳定的 class/id
|
|
255
|
+
4. 文本内容 (谨慎)
|
|
256
|
+
5. CSS/XPath (避免)
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
### E2E Checklist
|
|
260
|
+
|
|
261
|
+
```yaml
|
|
262
|
+
架构:
|
|
263
|
+
- 页面对象模式 (POM) 封装页面操作
|
|
264
|
+
- 测试独立性:通过 API 准备数据,不依赖其他测试
|
|
265
|
+
- 智能等待:waitForSelector/waitForResponse,禁止 waitForTimeout
|
|
266
|
+
|
|
267
|
+
网络:
|
|
268
|
+
- Mock API:page.route() / cy.intercept() 隔离后端
|
|
269
|
+
- 等待响应:waitForResponse 确认数据加载
|
|
270
|
+
|
|
271
|
+
可视化回归:
|
|
272
|
+
- Playwright: toHaveScreenshot() + mask 动态内容
|
|
273
|
+
- Percy/Chromatic: 云端截图对比
|
|
274
|
+
|
|
275
|
+
认证:
|
|
276
|
+
- Playwright: storageState 复用登录态
|
|
277
|
+
- Cypress: cy.session() 缓存会话
|
|
278
|
+
|
|
279
|
+
CI集成:
|
|
280
|
+
- retries: CI 环境 2 次重试
|
|
281
|
+
- artifacts: 失败时保存截图/视频/trace
|
|
282
|
+
```
|
|
283
|
+
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: frontend-design
|
|
3
|
+
description: 前端设计美学秘典。UI美学、组件模式、UX原则。当魔尊需要前端设计、UI/UX指导、组件设计时使用。
|
|
4
|
+
license: MIT
|
|
5
|
+
user-invocable: true
|
|
6
|
+
disable-model-invocation: false
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# 🎨 前端设计美学秘典
|
|
10
|
+
|
|
11
|
+
## 知识主题
|
|
12
|
+
|
|
13
|
+
| 主题 | 文档 | 涵盖 |
|
|
14
|
+
|------|------|------|
|
|
15
|
+
| UI美学 | [ui-aesthetics.md](ui-aesthetics.md) | 色彩理论、排版系统、间距系统、视觉层次、设计令牌、暗色模式、阴影层级 |
|
|
16
|
+
| 组件模式 | [component-patterns.md](component-patterns.md) | 布局模板、响应式设计、交互模式、动画、表单设计、卡片组件、导航模式 |
|
|
17
|
+
| UX原则 | [ux-principles.md](ux-principles.md) | 可用性、无障碍、信息架构、用户流程、加载体验、反馈设计、移动端优先、性能感知 |
|
|
18
|
+
| 状态管理 | [state-management.md](state-management.md) | Redux、Zustand、Jotai、Recoil、Context API、性能优化 |
|
|
19
|
+
| 前端工程化 | [engineering.md](engineering.md) | 性能优化、Web Vitals、测试(Vitest/Playwright)、构建工具(Vite/Webpack) |
|
|
20
|
+
|
|
21
|
+
## 设计风格系统
|
|
22
|
+
|
|
23
|
+
| 风格 | 文档 | 涵盖 |
|
|
24
|
+
|------|------|------|
|
|
25
|
+
| Claymorphism | [claymorphism/SKILL.md](claymorphism/SKILL.md) | 软陶风格、大圆角、双内阴影、偏移外阴影、暗色模式 |
|
|
26
|
+
| Glassmorphism | [glassmorphism/SKILL.md](glassmorphism/SKILL.md) | 毛玻璃风格、backdrop-filter、透明度、模糊层级 |
|
|
27
|
+
| Neubrutalism | [neubrutalism/SKILL.md](neubrutalism/SKILL.md) | 新粗野主义、粗边框、实色偏移阴影、高饱和色彩 |
|
|
28
|
+
| Liquid Glass | [liquid-glass/SKILL.md](liquid-glass/SKILL.md) | Apple 液态玻璃、半透明深度感知、弹簧动画、环境响应 |
|
|
29
|
+
|
|
30
|
+
## 使用场景
|
|
31
|
+
|
|
32
|
+
- 设计系统建立
|
|
33
|
+
- 组件库开发
|
|
34
|
+
- UI/UX审查
|
|
35
|
+
- 无障碍改进
|
|
36
|
+
- 响应式布局
|
|
37
|
+
- 交互动画设计
|
|
38
|
+
- 设计风格选型(Claymorphism / Glassmorphism / Neubrutalism / Liquid Glass)
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: claymorphism
|
|
3
|
+
description: Claymorphism design system skill. Use when building soft, puffy, clay-like UI components with large radii, dual inner shadows, and offset outer shadows.
|
|
4
|
+
license: MIT
|
|
5
|
+
user-invocable: false
|
|
6
|
+
disable-model-invocation: false
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Claymorphism Design Spec
|
|
10
|
+
|
|
11
|
+
## 3 Core Elements
|
|
12
|
+
|
|
13
|
+
1. **Large Radius** — Generous `border-radius` (20–50px) for a puffy, inflated look
|
|
14
|
+
2. **Dual Inner Shadows** — Light inset from top-left + dark inset from bottom-right to simulate 3D clay surface
|
|
15
|
+
3. **Offset Outer Shadow** — Directional `box-shadow` offset (not centered) to ground the element
|
|
16
|
+
|
|
17
|
+
## CSS Tokens
|
|
18
|
+
|
|
19
|
+
Reference: [references/tokens.css](references/tokens.css)
|
|
20
|
+
|
|
21
|
+
```css
|
|
22
|
+
@import 'references/tokens.css';
|
|
23
|
+
|
|
24
|
+
.clay-card {
|
|
25
|
+
background: var(--clay-bg-card);
|
|
26
|
+
border-radius: var(--clay-radius-lg);
|
|
27
|
+
box-shadow: var(--clay-shadow);
|
|
28
|
+
color: var(--clay-text);
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Component Examples
|
|
33
|
+
|
|
34
|
+
### Card
|
|
35
|
+
```css
|
|
36
|
+
.clay-card {
|
|
37
|
+
background: var(--clay-bg-card);
|
|
38
|
+
border-radius: var(--clay-radius-lg);
|
|
39
|
+
box-shadow: var(--clay-shadow);
|
|
40
|
+
padding: 1.5rem;
|
|
41
|
+
color: var(--clay-text);
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### Button
|
|
46
|
+
```css
|
|
47
|
+
.clay-btn {
|
|
48
|
+
background: var(--clay-bg-button);
|
|
49
|
+
border: none;
|
|
50
|
+
border-radius: var(--clay-radius-pill);
|
|
51
|
+
box-shadow: var(--clay-shadow);
|
|
52
|
+
padding: 0.75rem 1.5rem;
|
|
53
|
+
color: var(--clay-text);
|
|
54
|
+
cursor: pointer;
|
|
55
|
+
transition: box-shadow 0.2s;
|
|
56
|
+
}
|
|
57
|
+
.clay-btn:hover {
|
|
58
|
+
box-shadow: var(--clay-shadow-elevated);
|
|
59
|
+
}
|
|
60
|
+
.clay-btn:active {
|
|
61
|
+
box-shadow: var(--clay-shadow-pressed);
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### Input
|
|
66
|
+
```css
|
|
67
|
+
.clay-input {
|
|
68
|
+
background: var(--clay-bg);
|
|
69
|
+
border: none;
|
|
70
|
+
border-radius: var(--clay-radius);
|
|
71
|
+
box-shadow: var(--clay-shadow-pressed);
|
|
72
|
+
padding: 0.75rem 1rem;
|
|
73
|
+
color: var(--clay-text);
|
|
74
|
+
}
|
|
75
|
+
.clay-input:focus {
|
|
76
|
+
outline: 2px solid var(--clay-accent);
|
|
77
|
+
outline-offset: 2px;
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### Toggle
|
|
82
|
+
```css
|
|
83
|
+
.clay-toggle {
|
|
84
|
+
width: 56px;
|
|
85
|
+
height: 30px;
|
|
86
|
+
background: var(--clay-bg-card);
|
|
87
|
+
border-radius: var(--clay-radius-pill);
|
|
88
|
+
box-shadow: var(--clay-shadow-pressed);
|
|
89
|
+
}
|
|
90
|
+
.clay-toggle-knob {
|
|
91
|
+
width: 24px;
|
|
92
|
+
height: 24px;
|
|
93
|
+
background: var(--clay-bg);
|
|
94
|
+
border-radius: 50%;
|
|
95
|
+
box-shadow: var(--clay-shadow);
|
|
96
|
+
transition: transform 0.2s;
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## Dark Mode Notes
|
|
101
|
+
|
|
102
|
+
- Dark mode reduces inner highlight intensity (`rgba(255,255,255,0.05)` vs `0.6`) to avoid glowing artifacts
|
|
103
|
+
- Outer shadow opacity increases to maintain depth on dark backgrounds
|
|
104
|
+
- Background colors shift to warm dark tones — avoid pure black to preserve the clay feel
|
|
105
|
+
- All dark tokens are defined in `[data-theme="dark"]` in `tokens.css`
|
|
106
|
+
|
|
107
|
+
## Accessibility Notes
|
|
108
|
+
|
|
109
|
+
- Ensure **contrast ratio ≥ 4.5:1** for text — clay backgrounds are muted, verify against `--clay-text`
|
|
110
|
+
- Provide visible `:focus` outlines since clay shadows alone don't indicate focus
|
|
111
|
+
- Use `prefers-contrast: more` to flatten shadows and increase text contrast
|
|
112
|
+
|
|
113
|
+
```css
|
|
114
|
+
@media (prefers-contrast: more) {
|
|
115
|
+
.clay-card {
|
|
116
|
+
box-shadow: 0 0 0 2px var(--clay-text);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
```
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
:root {
|
|
2
|
+
/* Backgrounds — soft, muted pastels */
|
|
3
|
+
--clay-bg: #f0e6db;
|
|
4
|
+
--clay-bg-card: #e8ddd4;
|
|
5
|
+
--clay-bg-button: #d4c4b0;
|
|
6
|
+
--clay-accent: #c4a882;
|
|
7
|
+
|
|
8
|
+
/* Radius — large, rounded, puffy */
|
|
9
|
+
--clay-radius: 20px;
|
|
10
|
+
--clay-radius-lg: 32px;
|
|
11
|
+
--clay-radius-pill: 50px;
|
|
12
|
+
|
|
13
|
+
/* Shadows — dual inner + offset outer */
|
|
14
|
+
--clay-shadow:
|
|
15
|
+
8px 8px 16px rgba(0, 0, 0, 0.12),
|
|
16
|
+
inset -4px -4px 8px rgba(0, 0, 0, 0.08),
|
|
17
|
+
inset 4px 4px 8px rgba(255, 255, 255, 0.6);
|
|
18
|
+
--clay-shadow-elevated:
|
|
19
|
+
12px 12px 24px rgba(0, 0, 0, 0.15),
|
|
20
|
+
inset -6px -6px 12px rgba(0, 0, 0, 0.1),
|
|
21
|
+
inset 6px 6px 12px rgba(255, 255, 255, 0.7);
|
|
22
|
+
--clay-shadow-pressed:
|
|
23
|
+
2px 2px 6px rgba(0, 0, 0, 0.1),
|
|
24
|
+
inset -6px -6px 12px rgba(0, 0, 0, 0.12),
|
|
25
|
+
inset 6px 6px 12px rgba(255, 255, 255, 0.5);
|
|
26
|
+
|
|
27
|
+
/* Text */
|
|
28
|
+
--clay-text: #4a3f35;
|
|
29
|
+
--clay-text-muted: #8a7e72;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/* Dark mode */
|
|
33
|
+
[data-theme="dark"] {
|
|
34
|
+
--clay-bg: #2a2520;
|
|
35
|
+
--clay-bg-card: #352f28;
|
|
36
|
+
--clay-bg-button: #443c33;
|
|
37
|
+
--clay-accent: #6b5d4f;
|
|
38
|
+
--clay-shadow:
|
|
39
|
+
8px 8px 16px rgba(0, 0, 0, 0.35),
|
|
40
|
+
inset -4px -4px 8px rgba(0, 0, 0, 0.25),
|
|
41
|
+
inset 4px 4px 8px rgba(255, 255, 255, 0.05);
|
|
42
|
+
--clay-shadow-elevated:
|
|
43
|
+
12px 12px 24px rgba(0, 0, 0, 0.4),
|
|
44
|
+
inset -6px -6px 12px rgba(0, 0, 0, 0.3),
|
|
45
|
+
inset 6px 6px 12px rgba(255, 255, 255, 0.06);
|
|
46
|
+
--clay-shadow-pressed:
|
|
47
|
+
2px 2px 6px rgba(0, 0, 0, 0.3),
|
|
48
|
+
inset -6px -6px 12px rgba(0, 0, 0, 0.35),
|
|
49
|
+
inset 6px 6px 12px rgba(255, 255, 255, 0.04);
|
|
50
|
+
--clay-text: #d4c8bc;
|
|
51
|
+
--clay-text-muted: #8a7e72;
|
|
52
|
+
}
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
# 组件模式
|
|
2
|
+
|
|
3
|
+
## 布局模板
|
|
4
|
+
|
|
5
|
+
### 经典布局模式
|
|
6
|
+
圣杯布局(header/nav/main/aside/footer)、卡片网格、侧边栏、仪表盘。优先使用Grid,Flexbox做一维布局。
|
|
7
|
+
|
|
8
|
+
```css
|
|
9
|
+
.layout {
|
|
10
|
+
display: grid;
|
|
11
|
+
grid-template:
|
|
12
|
+
"header header" auto
|
|
13
|
+
"nav main" 1fr
|
|
14
|
+
"nav aside" auto
|
|
15
|
+
"footer footer" auto
|
|
16
|
+
/ 200px 1fr;
|
|
17
|
+
gap: 1rem;
|
|
18
|
+
min-height: 100vh;
|
|
19
|
+
}
|
|
20
|
+
@media (max-width: 768px) {
|
|
21
|
+
.layout {
|
|
22
|
+
grid-template: "header" "nav" "main" "aside" "footer" / 1fr;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
### Flexbox卡片网格
|
|
28
|
+
```css
|
|
29
|
+
.card-grid {
|
|
30
|
+
display: flex;
|
|
31
|
+
flex-wrap: wrap;
|
|
32
|
+
gap: 1.5rem;
|
|
33
|
+
}
|
|
34
|
+
.card {
|
|
35
|
+
flex: 1 1 300px;
|
|
36
|
+
max-width: 400px;
|
|
37
|
+
padding: 1.5rem;
|
|
38
|
+
border-radius: 8px;
|
|
39
|
+
box-shadow: var(--shadow-2);
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## 响应式设计
|
|
44
|
+
|
|
45
|
+
### 响应式断点策略
|
|
46
|
+
移动优先:320px基准→640px(sm)→768px(md)→1024px(lg)→1280px(xl)。使用em单位断点(除以16)。优先容器查询。
|
|
47
|
+
|
|
48
|
+
```css
|
|
49
|
+
.card-container {
|
|
50
|
+
container-type: inline-size;
|
|
51
|
+
}
|
|
52
|
+
.card {
|
|
53
|
+
padding: 1rem;
|
|
54
|
+
}
|
|
55
|
+
@container (min-width: 400px) {
|
|
56
|
+
.card {
|
|
57
|
+
display: grid;
|
|
58
|
+
grid-template-columns: 150px 1fr;
|
|
59
|
+
gap: 1rem;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## 交互模式
|
|
65
|
+
|
|
66
|
+
### 微交互设计原则
|
|
67
|
+
反馈即时(<100ms)、过渡流畅(200-300ms)、状态清晰(hover/active/focus)、减少认知负担。
|
|
68
|
+
|
|
69
|
+
```css
|
|
70
|
+
.btn {
|
|
71
|
+
transition: all 0.2s ease;
|
|
72
|
+
}
|
|
73
|
+
.btn:hover {
|
|
74
|
+
transform: translateY(-2px);
|
|
75
|
+
box-shadow: var(--shadow-3);
|
|
76
|
+
}
|
|
77
|
+
.btn:active {
|
|
78
|
+
transform: translateY(0);
|
|
79
|
+
}
|
|
80
|
+
.btn:focus-visible {
|
|
81
|
+
outline: 2px solid var(--primary);
|
|
82
|
+
outline-offset: 2px;
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## 动画
|
|
87
|
+
|
|
88
|
+
### CSS关键帧动画
|
|
89
|
+
```css
|
|
90
|
+
@keyframes fadeInUp {
|
|
91
|
+
from {
|
|
92
|
+
opacity: 0;
|
|
93
|
+
transform: translateY(20px);
|
|
94
|
+
}
|
|
95
|
+
to {
|
|
96
|
+
opacity: 1;
|
|
97
|
+
transform: translateY(0);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
.animate-in {
|
|
101
|
+
animation: fadeInUp 0.4s ease-out;
|
|
102
|
+
}
|
|
103
|
+
@media (prefers-reduced-motion: reduce) {
|
|
104
|
+
.animate-in {
|
|
105
|
+
animation: none;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### Framer Motion模板
|
|
111
|
+
```javascript
|
|
112
|
+
const fadeInUp = {
|
|
113
|
+
initial: { opacity: 0, y: 20 },
|
|
114
|
+
animate: { opacity: 1, y: 0 },
|
|
115
|
+
transition: { duration: 0.4, ease: "easeOut" }
|
|
116
|
+
};
|
|
117
|
+
const stagger = {
|
|
118
|
+
animate: { transition: { staggerChildren: 0.1 } }
|
|
119
|
+
};
|
|
120
|
+
<motion.div variants={stagger}>
|
|
121
|
+
<motion.div variants={fadeInUp} />
|
|
122
|
+
</motion.div>
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## 表单设计
|
|
126
|
+
|
|
127
|
+
### 表单UX模式
|
|
128
|
+
标签上置、内联验证、清晰错误提示、禁用状态明显、必填标记、合理分组、自动聚焦首字段。
|
|
129
|
+
|
|
130
|
+
```css
|
|
131
|
+
.form-field {
|
|
132
|
+
display: flex;
|
|
133
|
+
flex-direction: column;
|
|
134
|
+
gap: 0.5rem;
|
|
135
|
+
}
|
|
136
|
+
.input {
|
|
137
|
+
padding: 0.75rem;
|
|
138
|
+
border: 1px solid #d1d5db;
|
|
139
|
+
border-radius: 6px;
|
|
140
|
+
font-size: 1rem;
|
|
141
|
+
transition: border-color 0.2s;
|
|
142
|
+
}
|
|
143
|
+
.input:focus {
|
|
144
|
+
outline: none;
|
|
145
|
+
border-color: var(--primary);
|
|
146
|
+
box-shadow: 0 0 0 3px rgba(59,130,246,0.1);
|
|
147
|
+
}
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
## 卡片组件
|
|
151
|
+
|
|
152
|
+
### 玻璃拟态卡片
|
|
153
|
+
```css
|
|
154
|
+
.glass-card {
|
|
155
|
+
background: rgba(255, 255, 255, 0.1);
|
|
156
|
+
backdrop-filter: blur(10px);
|
|
157
|
+
border: 1px solid rgba(255, 255, 255, 0.2);
|
|
158
|
+
border-radius: 12px;
|
|
159
|
+
padding: 1.5rem;
|
|
160
|
+
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);
|
|
161
|
+
}
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
## 导航模式
|
|
165
|
+
|
|
166
|
+
### 响应式导航栏
|
|
167
|
+
```css
|
|
168
|
+
.nav {
|
|
169
|
+
display: flex;
|
|
170
|
+
justify-content: space-between;
|
|
171
|
+
align-items: center;
|
|
172
|
+
padding: 1rem;
|
|
173
|
+
}
|
|
174
|
+
.nav-links {
|
|
175
|
+
display: flex;
|
|
176
|
+
gap: 2rem;
|
|
177
|
+
}
|
|
178
|
+
@media (max-width: 768px) {
|
|
179
|
+
.nav-links {
|
|
180
|
+
display: none;
|
|
181
|
+
}
|
|
182
|
+
.nav-links.open {
|
|
183
|
+
display: flex;
|
|
184
|
+
flex-direction: column;
|
|
185
|
+
position: absolute;
|
|
186
|
+
top: 100%;
|
|
187
|
+
left: 0;
|
|
188
|
+
right: 0;
|
|
189
|
+
background: white;
|
|
190
|
+
padding: 1rem;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
## 审查清单
|
|
196
|
+
|
|
197
|
+
- [ ] 响应式适配
|
|
198
|
+
- [ ] 交互状态完整
|
|
199
|
+
- [ ] 无障碍支持
|
|
200
|
+
- [ ] 性能优化
|
|
201
|
+
- [ ] 浏览器兼容
|
|
202
|
+
- [ ] 动画流畅
|