@szc-ft/mcp-szcd-client 0.34.2 → 0.38.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/agents/build.js +59 -1
- package/agents/platforms.json +7 -0
- package/agents/szcd-component-expert.qoder.md +2 -0
- package/opencode-extension/opencode.json +9 -0
- package/opencode-extension/skills/local-browser-test/SKILL.md +91 -0
- package/opencode-extension/skills/local-browser-test/config.example.yaml +51 -0
- package/opencode-extension/skills/local-browser-test/lib/api-call-executor.js +251 -0
- package/opencode-extension/skills/local-browser-test/lib/browser-engine.js +95 -21
- package/opencode-extension/skills/local-browser-test/lib/config-loader.js +104 -0
- package/opencode-extension/skills/local-browser-test/lib/console-archiver.js +100 -0
- package/opencode-extension/skills/local-browser-test/lib/global-setup.js +72 -0
- package/opencode-extension/skills/local-browser-test/lib/har-collector.js +124 -0
- package/opencode-extension/skills/local-browser-test/lib/html-reporter.js +248 -0
- package/opencode-extension/skills/local-browser-test/lib/projects.js +46 -0
- package/opencode-extension/skills/local-browser-test/lib/raw-script-helpers.js +93 -0
- package/opencode-extension/skills/local-browser-test/lib/redact.js +94 -0
- package/opencode-extension/skills/local-browser-test/lib/report-retain.js +84 -0
- package/opencode-extension/skills/local-browser-test/lib/retry-policy.js +160 -0
- package/opencode-extension/skills/local-browser-test/lib/storage-state.js +111 -0
- package/opencode-extension/skills/local-browser-test/lib/tag-runner.js +103 -0
- package/opencode-extension/skills/local-browser-test/lib/test-plan.js +2 -0
- package/opencode-extension/skills/local-browser-test/lib/trace-collector.js +94 -0
- package/opencode-extension/skills/local-browser-test/lib/trend-aggregator.js +97 -0
- package/opencode-extension/skills/local-browser-test/lib/workspace-init.js +178 -0
- package/opencode-extension/skills/local-browser-test/local-browser-executor.js +226 -2
- package/opencode-extension/skills/local-browser-test/tests/integration/pr-01.test.js +254 -0
- package/opencode-extension/skills/local-browser-test/tests/integration/pr-02.test.js +263 -0
- package/opencode-extension/skills/local-browser-test/tests/integration/pr-03.test.js +308 -0
- package/opencode-extension/skills/local-browser-test/tests/integration/pr-04.test.js +168 -0
- package/opencode-extension/skills/local-browser-test/tests/integration/pr-05.test.js +183 -0
- package/opencode-extension/skills/local-browser-test/tests/integration/pr-06.test.js +252 -0
- package/opencode-extension/skills/local-browser-test/tests/integration/pr-07.test.js +168 -0
- package/opencode-extension/skills/local-browser-test/tests/integration/pr-08.test.js +293 -0
- package/opencode-extension/skills/shadcn-design-to-code/SKILL.md +352 -0
- package/opencode-extension/skills/shadcn-design-to-code/examples/1.1-overview-page.tsx +382 -0
- package/opencode-extension/skills/shadcn-design-to-code/references/install-pitfalls.md +526 -0
- package/opencode-extension/skills/shadcn-design-to-code/references/layouts.md +551 -0
- package/opencode-extension/skills/shadcn-design-to-code/references/sketch-mapping.md +247 -0
- package/opencode-extension/skills/shadcn-design-to-code/references/tokens.md +534 -0
- package/opencode-extension/skills/szcd-upload-zip/SKILL.md +45 -0
- package/package.json +70 -70
- package/qwen-extension/qwen-extension.json +10 -1
- package/qwen-extension/skills/local-browser-test/SKILL.md +91 -0
- package/qwen-extension/skills/local-browser-test/config.example.yaml +51 -0
- package/qwen-extension/skills/local-browser-test/lib/api-call-executor.js +251 -0
- package/qwen-extension/skills/local-browser-test/lib/browser-engine.js +95 -21
- package/qwen-extension/skills/local-browser-test/lib/config-loader.js +104 -0
- package/qwen-extension/skills/local-browser-test/lib/console-archiver.js +100 -0
- package/qwen-extension/skills/local-browser-test/lib/global-setup.js +72 -0
- package/qwen-extension/skills/local-browser-test/lib/har-collector.js +124 -0
- package/qwen-extension/skills/local-browser-test/lib/html-reporter.js +248 -0
- package/qwen-extension/skills/local-browser-test/lib/projects.js +46 -0
- package/qwen-extension/skills/local-browser-test/lib/raw-script-helpers.js +93 -0
- package/qwen-extension/skills/local-browser-test/lib/redact.js +94 -0
- package/qwen-extension/skills/local-browser-test/lib/report-retain.js +84 -0
- package/qwen-extension/skills/local-browser-test/lib/retry-policy.js +160 -0
- package/qwen-extension/skills/local-browser-test/lib/storage-state.js +111 -0
- package/qwen-extension/skills/local-browser-test/lib/tag-runner.js +103 -0
- package/qwen-extension/skills/local-browser-test/lib/test-plan.js +2 -0
- package/qwen-extension/skills/local-browser-test/lib/trace-collector.js +94 -0
- package/qwen-extension/skills/local-browser-test/lib/trend-aggregator.js +97 -0
- package/qwen-extension/skills/local-browser-test/lib/workspace-init.js +178 -0
- package/qwen-extension/skills/local-browser-test/local-browser-executor.js +226 -2
- package/qwen-extension/skills/local-browser-test/tests/integration/pr-01.test.js +254 -0
- package/qwen-extension/skills/local-browser-test/tests/integration/pr-02.test.js +263 -0
- package/qwen-extension/skills/local-browser-test/tests/integration/pr-03.test.js +308 -0
- package/qwen-extension/skills/local-browser-test/tests/integration/pr-04.test.js +168 -0
- package/qwen-extension/skills/local-browser-test/tests/integration/pr-05.test.js +183 -0
- package/qwen-extension/skills/local-browser-test/tests/integration/pr-06.test.js +252 -0
- package/qwen-extension/skills/local-browser-test/tests/integration/pr-07.test.js +168 -0
- package/qwen-extension/skills/local-browser-test/tests/integration/pr-08.test.js +293 -0
- package/qwen-extension/skills/shadcn-design-to-code/SKILL.md +352 -0
- package/qwen-extension/skills/shadcn-design-to-code/examples/1.1-overview-page.tsx +382 -0
- package/qwen-extension/skills/shadcn-design-to-code/references/install-pitfalls.md +526 -0
- package/qwen-extension/skills/shadcn-design-to-code/references/layouts.md +551 -0
- package/qwen-extension/skills/shadcn-design-to-code/references/sketch-mapping.md +247 -0
- package/qwen-extension/skills/shadcn-design-to-code/references/tokens.md +534 -0
- package/qwen-extension/skills/szcd-upload-zip/SKILL.md +45 -0
- package/scripts/lib/common.js +8 -1
- package/standard-skill/local-browser-test/SKILL.md +91 -0
- package/standard-skill/local-browser-test/config.example.yaml +51 -0
- package/standard-skill/local-browser-test/lib/api-call-executor.js +251 -0
- package/standard-skill/local-browser-test/lib/browser-engine.js +95 -21
- package/standard-skill/local-browser-test/lib/config-loader.js +104 -0
- package/standard-skill/local-browser-test/lib/console-archiver.js +100 -0
- package/standard-skill/local-browser-test/lib/global-setup.js +72 -0
- package/standard-skill/local-browser-test/lib/har-collector.js +124 -0
- package/standard-skill/local-browser-test/lib/html-reporter.js +248 -0
- package/standard-skill/local-browser-test/lib/projects.js +46 -0
- package/standard-skill/local-browser-test/lib/raw-script-helpers.js +93 -0
- package/standard-skill/local-browser-test/lib/redact.js +94 -0
- package/standard-skill/local-browser-test/lib/report-retain.js +84 -0
- package/standard-skill/local-browser-test/lib/retry-policy.js +160 -0
- package/standard-skill/local-browser-test/lib/storage-state.js +111 -0
- package/standard-skill/local-browser-test/lib/tag-runner.js +103 -0
- package/standard-skill/local-browser-test/lib/test-plan.js +2 -0
- package/standard-skill/local-browser-test/lib/trace-collector.js +94 -0
- package/standard-skill/local-browser-test/lib/trend-aggregator.js +97 -0
- package/standard-skill/local-browser-test/lib/workspace-init.js +178 -0
- package/standard-skill/local-browser-test/local-browser-executor.js +226 -2
- package/standard-skill/local-browser-test/tests/integration/pr-01.test.js +254 -0
- package/standard-skill/local-browser-test/tests/integration/pr-02.test.js +263 -0
- package/standard-skill/local-browser-test/tests/integration/pr-03.test.js +308 -0
- package/standard-skill/local-browser-test/tests/integration/pr-04.test.js +168 -0
- package/standard-skill/local-browser-test/tests/integration/pr-05.test.js +183 -0
- package/standard-skill/local-browser-test/tests/integration/pr-06.test.js +252 -0
- package/standard-skill/local-browser-test/tests/integration/pr-07.test.js +168 -0
- package/standard-skill/local-browser-test/tests/integration/pr-08.test.js +293 -0
- package/standard-skill/shadcn-design-to-code/SKILL.md +352 -0
- package/standard-skill/shadcn-design-to-code/examples/1.1-overview-page.tsx +382 -0
- package/standard-skill/shadcn-design-to-code/references/install-pitfalls.md +526 -0
- package/standard-skill/shadcn-design-to-code/references/layouts.md +551 -0
- package/standard-skill/shadcn-design-to-code/references/sketch-mapping.md +247 -0
- package/standard-skill/shadcn-design-to-code/references/tokens.md +534 -0
- package/standard-skill/szcd-upload-zip/SKILL.md +45 -0
- package/opencode-extension/skills/local-browser-test/local-browser-executor.cjs +0 -742
- package/qwen-extension/skills/local-browser-test/local-browser-executor.cjs +0 -742
|
@@ -0,0 +1,526 @@
|
|
|
1
|
+
# shadcn MCP 实测坑 + 审计清单
|
|
2
|
+
|
|
3
|
+
> 2026-06-29 实测 shadcn 官方 MCP(`npx shadcn@latest mcp`)v1.0.0 在 Qwen Code stdio 模式下发现的问题
|
|
4
|
+
> 必读:违反 = 报错或拿到错误数据
|
|
5
|
+
|
|
6
|
+
## 坑 1:list/search 不传 `registries` 必报错
|
|
7
|
+
|
|
8
|
+
**症状**:
|
|
9
|
+
```json
|
|
10
|
+
{
|
|
11
|
+
"result": {
|
|
12
|
+
"content": [{
|
|
13
|
+
"type": "text",
|
|
14
|
+
"text": "No registries are configured. Add registries to components.json (use get_project_registries to inspect) or pass them explicitly."
|
|
15
|
+
}]
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
**根因**:
|
|
21
|
+
`get_project_registries` 能从 `components.json` 隐式识别 `@shadcn` 默认 registry,但 `list_items_in_registries` / `search_items_in_registries` 不行——必须显式传 `registries: ["@shadcn"]`。
|
|
22
|
+
|
|
23
|
+
**复现步骤**:
|
|
24
|
+
```bash
|
|
25
|
+
# ❌ 报错
|
|
26
|
+
mcp__shadcn__list_items_in_registries(limit=10)
|
|
27
|
+
# → "No registries are configured..."
|
|
28
|
+
|
|
29
|
+
# ✅ 工作
|
|
30
|
+
mcp__shadcn__list_items_in_registries(registries=["@shadcn"], limit=10)
|
|
31
|
+
# → Found 363 items in registries @shadcn
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
**SKILL.md 工作流必须强制要求**:
|
|
35
|
+
|
|
36
|
+
```python
|
|
37
|
+
# 错误的工具调用
|
|
38
|
+
mcp__shadcn__list_items_in_registries(limit=10) # ❌
|
|
39
|
+
|
|
40
|
+
# 正确的工具调用
|
|
41
|
+
mcp__shadcn__list_items_in_registries(registries=["@shadcn"], limit=10) # ✅
|
|
42
|
+
|
|
43
|
+
# 搜索也一样
|
|
44
|
+
mcp__shadcn__search_items_in_registries(query="dialog") # ❌
|
|
45
|
+
mcp__shadcn__search_items_in_registries(registries=["@shadcn"], query="dialog") # ✅
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
**自动修复**(在 SKILL.md 步骤 4 头部加规则):
|
|
49
|
+
|
|
50
|
+
```
|
|
51
|
+
对所有 mcp__shadcn__list_items_in_registries / search_items_in_registries 调用:
|
|
52
|
+
- 必须显式传 registries: ["@shadcn"](除非用户配置了其他 namespace)
|
|
53
|
+
- 例外:get_project_registries 不需要
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## 坑 2:view_items 只返回元信息,不返回源码
|
|
57
|
+
|
|
58
|
+
**症状**:
|
|
59
|
+
```json
|
|
60
|
+
{
|
|
61
|
+
"result": {
|
|
62
|
+
"content": [{
|
|
63
|
+
"type": "text",
|
|
64
|
+
"text": "## dialog\n\n**Type:** registry:ui\n**Files:** 1 file(s)\n**Dependencies:** @radix-ui/react-dialog\n"
|
|
65
|
+
}]
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
只有 3 行元信息:Type / Files / Dependencies。**没有组件源码、没有 Props、没有 variants、没有示例代码。**
|
|
71
|
+
|
|
72
|
+
**根因**:
|
|
73
|
+
shadcn 设计的预期是"view 拿元信息 → add 拿源码"两步走。view 是元数据查询工具,不是源码查询工具。
|
|
74
|
+
|
|
75
|
+
**复现步骤**:
|
|
76
|
+
```bash
|
|
77
|
+
# ❌ 拿不到源码
|
|
78
|
+
mcp__shadcn__view_items_in_registries(items=["@shadcn/dialog"])
|
|
79
|
+
# → 只有 3 行元信息
|
|
80
|
+
|
|
81
|
+
# ✅ 拿源码
|
|
82
|
+
mcp__shadcn__get_add_command_for_items(items=["@shadcn/dialog"])
|
|
83
|
+
# → "npx shadcn@latest add @shadcn/dialog"
|
|
84
|
+
$ npx shadcn@latest add @shadcn/dialog
|
|
85
|
+
# → 下载到 components/ui/dialog.tsx
|
|
86
|
+
$ cat components/ui/dialog.tsx
|
|
87
|
+
# → 完整源码
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
**正确的工作流**(4 步):
|
|
91
|
+
|
|
92
|
+
```
|
|
93
|
+
1. mcp__shadcn__view_items_in_registries(items=["@shadcn/<name>"])
|
|
94
|
+
→ 看 Type 判断是否合适(registry:ui 是组件,registry:example 是示例,registry:block 是完整 block)
|
|
95
|
+
→ 看 Dependencies 知道要装什么
|
|
96
|
+
|
|
97
|
+
2. mcp__shadcn__get_item_examples_from_registries(query="<name>-demo")
|
|
98
|
+
→ 拿 demo 用法(参考,不直接复制到生产代码)
|
|
99
|
+
|
|
100
|
+
3. mcp__shadcn__get_add_command_for_items(items=["@shadcn/<name>", ...])
|
|
101
|
+
→ 拿 npx add 命令
|
|
102
|
+
|
|
103
|
+
4. 本地执行 npx shadcn@latest add @shadcn/<name> ...
|
|
104
|
+
→ 真实源码下载到 components/ui/<name>.tsx
|
|
105
|
+
|
|
106
|
+
5. read_file 读 components/ui/<name>.tsx
|
|
107
|
+
→ 拿真实 Props / variants / API
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
**反模式(浪费 token)**:
|
|
111
|
+
|
|
112
|
+
```
|
|
113
|
+
❌ 调 view_items 5 次想拿 5 个组件的源码
|
|
114
|
+
→ 只拿到 5 份 3 行元信息,没有源码
|
|
115
|
+
|
|
116
|
+
❌ 用 view_items 的输出当组件文档写代码
|
|
117
|
+
→ 没有 Props 怎么写 <Button variant="?">?
|
|
118
|
+
|
|
119
|
+
✅ 调 view_items 1 次拿元信息 → add → read_file → 真实 Props
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## 坑 3:view_items 找不到某些组件(如 data-table)
|
|
123
|
+
|
|
124
|
+
**症状**:
|
|
125
|
+
```json
|
|
126
|
+
{
|
|
127
|
+
"result": {
|
|
128
|
+
"content": [{
|
|
129
|
+
"type": "text",
|
|
130
|
+
"text": "Error (NOT_FOUND): The item at https://ui.shadcn.com/r/styles/new-york/data-table.json was not found.\n\n💡 Check if the item name is correct and the registry URL is accessible.\n\nContext: {\n \"url\": \"https://ui.shadcn.com/r/styles/new-york/data-table.json\"\n}"
|
|
131
|
+
}]
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
**根因**:
|
|
137
|
+
- 一些组件(如 `data-table` / `chart`)在 `https://ui.shadcn.com/docs/components/<name>` 有文档
|
|
138
|
+
- 但**不在** `https://ui.shadcn.com/r/styles/new-york/<name>.json` 这个 registry URL 中
|
|
139
|
+
- view_items 走 registry URL,找不到就报 NOT_FOUND
|
|
140
|
+
|
|
141
|
+
**修复**:
|
|
142
|
+
- `data-table` 走 shadcn 官方文档 https://ui.shadcn.com/docs/components/data-table 复制代码
|
|
143
|
+
- `chart` 同上 https://ui.shadcn.com/docs/components/chart
|
|
144
|
+
- 一些特殊组件(block 的 dashboard-01)走 `@shadcn/dashboard-01`
|
|
145
|
+
|
|
146
|
+
**已知"view_items 找不到但实际可用"清单**:
|
|
147
|
+
- `data-table` → https://ui.shadcn.com/docs/components/data-table
|
|
148
|
+
- `chart` → https://ui.shadcn.com/docs/components/chart
|
|
149
|
+
- `breadcrumb` 部分版本
|
|
150
|
+
- `sonner` 部分版本(可能要 `@shadcn/sonner` 而非 `@shadcn/toast`)
|
|
151
|
+
|
|
152
|
+
## 坑 4:search_items 返回 `[object Promise]` 字段
|
|
153
|
+
|
|
154
|
+
**症状**:
|
|
155
|
+
```
|
|
156
|
+
- button (registry:ui) [@shadcn]
|
|
157
|
+
Add command: `[object Promise]`
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
**根因**:
|
|
161
|
+
list_items / search_items 返回的列表项中,每项有一个"Add command"字段。但该字段的渲染在某些情况下是异步的,没等待 Promise resolve 就序列化了,显示为 `[object Promise]`。
|
|
162
|
+
|
|
163
|
+
**影响**:
|
|
164
|
+
不影响 list/search 的核心功能(你仍然能拿到组件清单),但**`Add command` 字段不可用**。
|
|
165
|
+
|
|
166
|
+
**修复**:
|
|
167
|
+
要拿 add 命令必须单独调 `get_add_command_for_items`,不能依赖 list/search 返回的字段。
|
|
168
|
+
|
|
169
|
+
```python
|
|
170
|
+
# ❌ 依赖 list 返回的 Add command
|
|
171
|
+
items = list_items_in_registries(registries=["@shadcn"])
|
|
172
|
+
for item in items:
|
|
173
|
+
cmd = item['add_command'] # "[object Promise]" 错的
|
|
174
|
+
run(cmd) # 跑不了
|
|
175
|
+
|
|
176
|
+
# ✅ 单独调 get_add_command_for_items
|
|
177
|
+
add_cmd = get_add_command_for_items(items=["@shadcn/button", "@shadcn/card"])
|
|
178
|
+
# → "npx shadcn@latest add @shadcn/button @shadcn/card"
|
|
179
|
+
run(add_cmd) # 正确
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
## 坑 5:跨 components.json 路径
|
|
183
|
+
|
|
184
|
+
**症状**:
|
|
185
|
+
shadcn MCP 通过 `process.cwd()` 找 `components.json`。如果 IDE 在 `~/projects/foo/` 启动,但 `components.json` 在 `~/projects/foo/app/`,MCP 找不到。
|
|
186
|
+
|
|
187
|
+
**根因**:
|
|
188
|
+
shadcn CLI 早期版本默认 `components.json` 在项目根,但 Next.js 项目可能放在子目录。
|
|
189
|
+
|
|
190
|
+
**修复**:
|
|
191
|
+
- 确保 `components.json` 在 `process.cwd()` 目录下
|
|
192
|
+
- 或者用 `pnpm dlx shadcn@latest mcp init --client qwen` 让它自动初始化
|
|
193
|
+
|
|
194
|
+
## 坑 6:npx 首次启动慢
|
|
195
|
+
|
|
196
|
+
**症状**:
|
|
197
|
+
第一次 `npx -y shadcn@latest mcp` 要 10-30 秒下载。
|
|
198
|
+
|
|
199
|
+
**根因**:
|
|
200
|
+
npx 每次都重新拉最新版本。
|
|
201
|
+
|
|
202
|
+
**修复**:
|
|
203
|
+
```json
|
|
204
|
+
// .mcp.json 用固定版本,避免每次下载
|
|
205
|
+
{
|
|
206
|
+
"mcpServers": {
|
|
207
|
+
"shadcn": {
|
|
208
|
+
"command": "npx",
|
|
209
|
+
"args": ["-y", "shadcn@1.0.0", "mcp"] // 固定版本
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
或全局安装:
|
|
216
|
+
```bash
|
|
217
|
+
npm install -g shadcn
|
|
218
|
+
# .mcp.json
|
|
219
|
+
{
|
|
220
|
+
"mcpServers": {
|
|
221
|
+
"shadcn": {
|
|
222
|
+
"command": "shadcn",
|
|
223
|
+
"args": ["mcp"]
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
---
|
|
230
|
+
|
|
231
|
+
## 审计清单(来自 shadcn MCP `get_audit_checklist`)
|
|
232
|
+
|
|
233
|
+
代码生成后必跑:
|
|
234
|
+
|
|
235
|
+
```json
|
|
236
|
+
{
|
|
237
|
+
"tool": "mcp__shadcn__get_audit_checklist",
|
|
238
|
+
"result": {
|
|
239
|
+
"checklist": [
|
|
240
|
+
"Ensure imports are correct i.e named vs default imports",
|
|
241
|
+
"If using next/image, ensure images.remotePatterns next.config.js is configured correctly.",
|
|
242
|
+
"Ensure all dependencies are installed.",
|
|
243
|
+
"Check for linting errors or warnings",
|
|
244
|
+
"Check for TypeScript errors",
|
|
245
|
+
"Use the Playwright MCP if available."
|
|
246
|
+
]
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
展开解读:
|
|
252
|
+
|
|
253
|
+
### 1. Imports 检查
|
|
254
|
+
|
|
255
|
+
shadcn 组件**都用 named imports**(不导出 default):
|
|
256
|
+
|
|
257
|
+
```tsx
|
|
258
|
+
// ✅ 正确
|
|
259
|
+
import { Button } from "@/components/ui/button"
|
|
260
|
+
import { Card, CardHeader, CardContent, CardFooter } from "@/components/ui/card"
|
|
261
|
+
import { Form, FormField, FormItem, FormLabel, FormControl, FormMessage } from "@/components/ui/form"
|
|
262
|
+
|
|
263
|
+
// ❌ 错误
|
|
264
|
+
import Button from "@/components/ui/button"
|
|
265
|
+
import * as Card from "@/components/ui/card"
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
### 2. next/image 配置
|
|
269
|
+
|
|
270
|
+
如果用 shadcn 的 Avatar 等组件引用了 next/image 优化,需要在 `next.config.js` 配置:
|
|
271
|
+
|
|
272
|
+
```js
|
|
273
|
+
// next.config.js
|
|
274
|
+
module.exports = {
|
|
275
|
+
images: {
|
|
276
|
+
remotePatterns: [
|
|
277
|
+
{ protocol: "https", hostname: "images.unsplash.com" },
|
|
278
|
+
{ protocol: "https", hostname: "avatars.githubusercontent.com" },
|
|
279
|
+
],
|
|
280
|
+
},
|
|
281
|
+
}
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
### 3. 依赖安装
|
|
285
|
+
|
|
286
|
+
shadcn 装组件时**自动安装依赖**(从 `package.json` 读 deps)。但如果手动复制源码,需要:
|
|
287
|
+
|
|
288
|
+
```bash
|
|
289
|
+
# shadcn 装组件后会自动装这些(如果缺)
|
|
290
|
+
npm install class-variance-authority clsx tailwind-merge
|
|
291
|
+
npm install @radix-ui/react-slot @radix-ui/react-dialog @radix-ui/react-dropdown-menu ...
|
|
292
|
+
npm install lucide-react
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
### 4. Lint 错误
|
|
296
|
+
|
|
297
|
+
常见 lint 错误:
|
|
298
|
+
|
|
299
|
+
```tsx
|
|
300
|
+
// ❌ 错误:未使用的 import
|
|
301
|
+
import { Card, CardTitle, CardDescription } from "@/components/ui/card"
|
|
302
|
+
// 只用了 Card,其他未用
|
|
303
|
+
|
|
304
|
+
// ❌ 错误:inline-style 写错
|
|
305
|
+
<div style={{ color: red }}> // 缺引号
|
|
306
|
+
<div style={{ color: "red" }}> // ✅
|
|
307
|
+
|
|
308
|
+
// ❌ 错误:className 拼错
|
|
309
|
+
<div className="bg-prmary"> // bg-primary
|
|
310
|
+
<div className="bg-primary"> // ✅
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
### 5. TypeScript 错误
|
|
314
|
+
|
|
315
|
+
常见 TS 错误:
|
|
316
|
+
|
|
317
|
+
```tsx
|
|
318
|
+
// ❌ 错误:Props 类型不匹配
|
|
319
|
+
<Input type="email" value={123} onChange={() => {}} />
|
|
320
|
+
// Input 期望 value: string
|
|
321
|
+
|
|
322
|
+
// ❌ 错误:缺少必填 prop
|
|
323
|
+
<FormField name="email" /> // 必须有 control prop
|
|
324
|
+
|
|
325
|
+
// ❌ 错误:as 转换
|
|
326
|
+
<Button asChild> // 需要 Button 内部支持 asChild(cva variants)
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
### 6. Playwright MCP 验证(可选)
|
|
330
|
+
|
|
331
|
+
如有 Playwright MCP server,跑 e2e 验证:
|
|
332
|
+
- 点击所有按钮能触发 onClick
|
|
333
|
+
- 切换 Tab 内容变化
|
|
334
|
+
- 提交表单触发 onSubmit
|
|
335
|
+
- Dialog 打开/关闭正常
|
|
336
|
+
|
|
337
|
+
---
|
|
338
|
+
|
|
339
|
+
## 实测有用的 3 个工具组合
|
|
340
|
+
|
|
341
|
+
### 组合 1:浏览 + 安装
|
|
342
|
+
|
|
343
|
+
```python
|
|
344
|
+
# 列 50 个 UI 组件
|
|
345
|
+
mcp__shadcn__list_items_in_registries(registries=["@shadcn"], types=["ui"], limit=50)
|
|
346
|
+
# → 选 5 个要用的
|
|
347
|
+
|
|
348
|
+
# 安装
|
|
349
|
+
mcp__shadcn__get_add_command_for_items(items=[
|
|
350
|
+
"@shadcn/button", "@shadcn/card", "@shadcn/dialog", "@shadcn/form", "@shadcn/input"
|
|
351
|
+
])
|
|
352
|
+
# → "npx shadcn@latest add @shadcn/button @shadcn/card ..."
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
### 组合 2:搜索 + 拿 demo
|
|
356
|
+
|
|
357
|
+
```python
|
|
358
|
+
# 搜对话框
|
|
359
|
+
mcp__shadcn__search_items_in_registries(registries=["@shadcn"], query="dialog")
|
|
360
|
+
# → dialog, alert-dialog, dialog-demo, command-dialog, drawer-dialog
|
|
361
|
+
|
|
362
|
+
# 拿 dialog 的 demo
|
|
363
|
+
mcp__shadcn__get_item_examples_from_registries(registries=["@shadcn"], query="dialog-demo")
|
|
364
|
+
# → 完整 demo 代码
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
### 组合 3:审计 + 修复
|
|
368
|
+
|
|
369
|
+
```python
|
|
370
|
+
# 跑审计
|
|
371
|
+
mcp__shadcn__get_audit_checklist()
|
|
372
|
+
# → 6 项清单
|
|
373
|
+
|
|
374
|
+
# 检查 import 正确性(手动)
|
|
375
|
+
# 跑 tsc / eslint
|
|
376
|
+
# 跑 dev server 看是否启动
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
---
|
|
380
|
+
|
|
381
|
+
## 经验沉淀(持续更新)
|
|
382
|
+
|
|
383
|
+
### 经验 1:先装 block 再装组件
|
|
384
|
+
|
|
385
|
+
如果 Sketch 是常见场景(Dashboard / 登录 / 定价),**优先装对应 block**:
|
|
386
|
+
|
|
387
|
+
```bash
|
|
388
|
+
# Dashboard
|
|
389
|
+
npx shadcn@latest add @shadcn/dashboard-01
|
|
390
|
+
# → 包含 sidebar + 4 stat + 2 chart + 1 table 全套
|
|
391
|
+
|
|
392
|
+
# 登录
|
|
393
|
+
npx shadcn@latest add @shadcn/login-01
|
|
394
|
+
# → 居中表单 + 背景
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
block 装完后,按需修改其内部组件样式(直接改源码)。
|
|
398
|
+
|
|
399
|
+
### 经验 2:types 过滤节省 token
|
|
400
|
+
|
|
401
|
+
```python
|
|
402
|
+
# 全量列(363 个,含 style / example / block / hook)
|
|
403
|
+
list_items_in_registries(registries=["@shadcn"], limit=10)
|
|
404
|
+
# → "index (registry:style) [@shadcn]" 等
|
|
405
|
+
|
|
406
|
+
# 只列 UI 组件(~50 个,节省 90% token)
|
|
407
|
+
list_items_in_registries(registries=["@shadcn"], types=["ui"], limit=50)
|
|
408
|
+
# → 只列 button, card, dialog ...
|
|
409
|
+
|
|
410
|
+
# 只列 example(找 demo 用)
|
|
411
|
+
list_items_in_registries(registries=["@shadcn"], types=["example"], limit=20)
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
**types 枚举**:
|
|
415
|
+
- `lib` - 工具库
|
|
416
|
+
- `block` - 完整页面 block
|
|
417
|
+
- `component` - 业务组件
|
|
418
|
+
- `ui` - UI 基础组件
|
|
419
|
+
- `hook` - React hooks
|
|
420
|
+
- `page` - 完整页面
|
|
421
|
+
- `file` - 单文件
|
|
422
|
+
- `theme` - 主题
|
|
423
|
+
- `style` - 样式文件
|
|
424
|
+
- `item` - 通用
|
|
425
|
+
- `base` - 基础
|
|
426
|
+
- `font` - 字体
|
|
427
|
+
|
|
428
|
+
### 经验 3:用 limit + offset 翻页
|
|
429
|
+
|
|
430
|
+
363 个 item 一次拿不完:
|
|
431
|
+
|
|
432
|
+
```python
|
|
433
|
+
# 第 1 页
|
|
434
|
+
list_items_in_registries(registries=["@shadcn"], limit=100)
|
|
435
|
+
# → "More items available. Use offset: 100 to see the next page."
|
|
436
|
+
|
|
437
|
+
# 第 2 页
|
|
438
|
+
list_items_in_registries(registries=["@shadcn"], limit=100, offset=100)
|
|
439
|
+
|
|
440
|
+
# 第 3 页
|
|
441
|
+
list_items_in_registries(registries=["@shadcn"], limit=100, offset=200)
|
|
442
|
+
# → 第 201-263 个(剩 63 个)
|
|
443
|
+
|
|
444
|
+
# 第 4 页
|
|
445
|
+
list_items_in_registries(registries=["@shadcn"], limit=100, offset=300)
|
|
446
|
+
# → 第 301-363 个
|
|
447
|
+
```
|
|
448
|
+
|
|
449
|
+
实战中**不需要全量列**——按需 search 就够了:
|
|
450
|
+
```python
|
|
451
|
+
# 知道名字就直接 view
|
|
452
|
+
view_items_in_registries(items=["@shadcn/button", "@shadcn/card"])
|
|
453
|
+
|
|
454
|
+
# 不知道名字用 search
|
|
455
|
+
search_items_in_registries(registries=["@shadcn"], query="chart")
|
|
456
|
+
```
|
|
457
|
+
|
|
458
|
+
### 经验 4:dark mode 配色落地
|
|
459
|
+
|
|
460
|
+
shadcn 默认支持 dark mode。**注意:dark mode 不是组件特性,是 CSS 变量切换**。
|
|
461
|
+
|
|
462
|
+
```tsx
|
|
463
|
+
// 组件代码完全不变
|
|
464
|
+
<Card>
|
|
465
|
+
<CardHeader>
|
|
466
|
+
<CardTitle>标题</CardTitle>
|
|
467
|
+
</CardHeader>
|
|
468
|
+
</Card>
|
|
469
|
+
|
|
470
|
+
// 切换 dark mode 只需要在 html 加 class="dark"
|
|
471
|
+
<html className="dark">
|
|
472
|
+
```
|
|
473
|
+
|
|
474
|
+
落地时 **globals.css 必须写完整 dark 段**:
|
|
475
|
+
|
|
476
|
+
```css
|
|
477
|
+
:root {
|
|
478
|
+
--background: 0 0% 100%;
|
|
479
|
+
--foreground: 222.2 47.4% 11.2%;
|
|
480
|
+
/* ... */
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
.dark {
|
|
484
|
+
--background: 222.2 47.4% 11.2%;
|
|
485
|
+
--foreground: 210 40% 98%;
|
|
486
|
+
/* ... 暗色版 */
|
|
487
|
+
}
|
|
488
|
+
```
|
|
489
|
+
|
|
490
|
+
如果从 Sketch 提取了 light 模式 token,**自动推导 dark 模式**:
|
|
491
|
+
- 背景色:取反(白→深色)
|
|
492
|
+
- 文字色:取反(深→浅色)
|
|
493
|
+
- 边框色:取反
|
|
494
|
+
- 品牌色:保持或微调
|
|
495
|
+
|
|
496
|
+
### 经验 5:响应式断点策略
|
|
497
|
+
|
|
498
|
+
shadcn 默认 Tailwind 断点:
|
|
499
|
+
- `sm`: 640px
|
|
500
|
+
- `md`: 768px
|
|
501
|
+
- `lg`: 1024px
|
|
502
|
+
- `xl`: 1280px
|
|
503
|
+
- `2xl`: 1536px
|
|
504
|
+
|
|
505
|
+
**Sketch 默认是桌面 1440px 宽**。从桌面推导响应式:
|
|
506
|
+
|
|
507
|
+
```
|
|
508
|
+
桌面 4 列 → mobile 1 列
|
|
509
|
+
grid-cols-1 md:grid-cols-2 lg:grid-cols-4
|
|
510
|
+
|
|
511
|
+
桌面 3 列 → mobile 1 列
|
|
512
|
+
grid-cols-1 md:grid-cols-2 lg:grid-cols-3
|
|
513
|
+
|
|
514
|
+
桌面 2 列 → mobile 1 列
|
|
515
|
+
grid-cols-1 lg:grid-cols-2
|
|
516
|
+
|
|
517
|
+
桌面 1 列 → 永远 1 列
|
|
518
|
+
grid-cols-1
|
|
519
|
+
```
|
|
520
|
+
|
|
521
|
+
**移动端优先**写法(推荐):
|
|
522
|
+
```tsx
|
|
523
|
+
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
|
|
524
|
+
{/* 移动端 1 列,平板 2 列,桌面 3 列 */}
|
|
525
|
+
</div>
|
|
526
|
+
```
|