开发
组件开发流程
开发 QtShadcn 组件的工作流:先研究 shadcn/ui 官方规范再实现(M2 教训)。
QtShadcn 组件开发流程
When to Use
- 开发 qtshadcn 组件库(
~/dev/qt/qtshadcn)新组件(对应 GitHub issues,每批一个,实现完关 issue) - 需要实现 shadcn/ui 风格(Design Token 驱动)的 QML 组件
铁律:先研究再实现
开发任何组件前必须研究 shadcn/ui 参考实现,禁止凭印象直接写。 M2 教训:凭印象写的 Button 尺寸整体小一档、漏 link variant、圆角 8px(应为 6px)等,全靠事后对照返工。
1. 抓官方文档(含 variants/sizes 列表)
# 网速慢用代理 7897或7890
curl -sL -x http://127.0.0.1:7897 "https://ui.shadcn.com/docs/components/<name>" -o /tmp/shadcn-<name>.html
python3 -c "
import re, html
text = open('/tmp/shadcn-<name>.html').read()
m = re.search(r'<main[^>]*>(.*?)</main>', text, re.S)
body = m.group(1) if m else text
body = re.sub(r'<script.*?</script>', '', body, flags=re.S)
body = re.sub(r'<[^>]+>', ' ', body)
print(html.unescape(re.sub(r'\s+', ' ', body)))
"
2. 抓源码(gh api 认证,免限流)
shadcn-ui/ui 仓库 2026 年已重构:
- v2/v3 稳定路径(广为人知的 cva 定义):
apps/www/registry/default/ui/<name>.tsx - v4 新路径:
apps/v4/registry/__components__/base-luma.tsx(主题变体文件,内部import("@/styles/base-luma/ui/<name>")),styles 路径apps/v4/styles/base-luma/ui/<name>.tsx
# 先列目录找路径(路径常变)
gh api "repos/shadcn-ui/ui/contents/apps/v4/registry/__components__" --jq '.[].name'
# 再拿文件内容
gh api "repos/shadcn-ui/ui/contents/apps/v4/registry/__components__/base-luma.tsx" --jq '.content' | base64 -d
注意:GitHub Contents API 未认证会限流(尤其走代理 IP);raw.githubusercontent 路径随重构 404,用 gh api 列目录确认。
3. 梳理规范清单(输出对照表再写码)
| 维度 | 必须确认 |
|---|---|
| variants | 完整列表(Button: default/secondary/destructive/outline/ghost/link) |
| sizes | 全部尺寸 + 像素值(Button: xs=32 / sm=36 / default=40 / lg=44 / icon=40) |
| 交互状态 | hover / pressed / disabled(opacity-50) / loading / focus(ring) |
| 样式细节 | 圆角(rounded-md=6px)、字重(font-medium=500)、padding、hover 语义 |
| API | 属性 / 事件 / 变体枚举命名 |
| 无障碍/键盘 | 继承 QQC 基类行为(键盘导航/Focus/Accessible 白拿) |
4. 对照实现(QtShadcn 项目规范)
- 组件命名
Shadcn*前缀,文件src/qml/Components/ShadcnXxx.qml,加进src/CMakeLists.txt的QML_FILES - 基于 QQC 基类(
import QtQuick.Controls.Basic,style-specific import 是 token 自绘前提),只替换 background/contentItem - variant → token 映射集中在
src/qml/Theme/VariantTokens.qml:新增 variant = 枚举 + 映射表各加一项(顺序对齐);用 QtObject 属性定义(var 对象字面量在 qmlcache 下不可靠) - 颜色经
theme.tokens[token名]查询(保持 mode 切换绑定;存颜色值会变静态) - 文字居中:QQC 会把 contentItem 拉伸到内容区全宽 → Item 包装 + RowLayout
anchors.centerIn(水平垂直都稳);Row 子项 AlignTop 会偏上 - 动画用 Shape + Animator(禁 Canvas 动画);文案 qsTr();import 无版本号;Layout 子项用
Layout.*不用裸 width
5. showcase 验证
examples/showcase/Main.qml展示全部 variant × size × 状态(含 disabled/loading/拉伸宽度)make build构建;python 后台启动 + poll 存活 + stderr 干净 +screencapture截图给用户确认- 确认后 commit + 关对应 GitHub issue
M2 Button 实测偏差教训(防再犯)
- 尺寸:Medium=40 / Large=44 / Small=36 / XS=32 / Icon=40(shadcn h-10/h-11/h-9/h-8/size-10)
- 漏 link variant:text-primary + hover 下划线,无背景无 hover 块
- 圆角:button 用 rounded-md = 6px(theme.radius 8 用于卡片/容器)
- 字重 font-medium = 500
- disabled / loading:opacity 50%
- hover 语义:default/secondary/destructive 变暗(90% 透明度等效黑 8% overlay);outline/ghost 用 accent 背景 + accentForeground 文字;link 仅下划线
- 按钮组:无 border 的 variant(如 Primary)中间需 1px 分隔线(前景色 15% 透明度);spacing: -1 合并边框;圆角只留两端
项目速查
- 技术方案:设计 → 技术方案(11 节 = 组件开发流程)
- 组件计划:GitHub issues #1-10(每批一个,实现完关对应 issue)
- 构建:Qt 6.5+ / CMake 3.24+;token 自绘须
QQuickStyle::setStyle("Basic")(macOS 默认 native style 拒绝自定义 contentItem) - 规范技能:qt-qml(Qt 官方 agent-skills,QML 最佳实践)