开发

M3 组件规范对照表

M3(Card/Input/Badge/Switch/Tabs/Dialog)shadcn/ui v4 官方规范 vs QtShadcn 实现差距对照。铁律产物:先输出对照表,确认后再写码。

M3 组件规范对照表

来源:shadcn/ui 官方文档 + 源码(apps/v4/registry/bases/base/ui/*.tsx + apps/v4/registry/styles/style-luma.css),抓取于 2026-08-18。 依据:组件开发流程铁律(先研究 → 输出对照表 → 确认 → 实现)。

0. 公共决策(跨组件)

0.1 新增 Design Tokens(ThemeManager)

shadcn 语义中 M3 组件需要但当前 tokens 缺失的项:

新 Tokenlightdark对应 shadcn 默认值用途
card#ffffff#09090bbg-cardCard 底色(= background)
cardForeground#09090b#fafafatext-card-foregroundCard 正文色(= foreground)
input#e4e4e7#27272abg-inputInput 底色(= 本主题 border 值)
popover#ffffff#09090bbg-popoverDialog/浮层底色(= background)
popoverForeground#09090b#fafafatext-popover-foreground浮层正文色(= foreground)
  • QtShadcnTheme.qml 同步暴露只读属性:card cardForeground input popover popoverForeground
  • light/dark 两套 tokens 各加 5 项(值如上,与背景/边框体系自洽)

0.2 圆角体系决策(v4 激进大圆角 vs 项目既有体系)

v4 luma 风格大量使用 rounded-3xl(24px) / rounded-4xl(32px),与本项目 M2 已定体系 (控件 6px / 容器 8px)冲突。决策:遵循项目既有体系,不跟 v4 大圆角

组件v4 官方QtShadcn 采用理由
Card 容器rounded-4xl (32px)theme.radius (8px)项目既定「radius 8 用于卡片/容器」
Inputrounded-3xl (24px)6px(控件级)与 ShadcnButton 一致
Badgerounded-3xl (24px)胶囊 radius: 999badge 惯例为胶囊(v4 24px 亦近胶囊)
Switchrounded-fullrounded-full开关天然胶囊,无冲突
TabsListrounded-fulltheme.radius (8px)容器级;胶囊与按钮族不协调
Dialogrounded-4xl (32px)theme.radius (8px)容器级

若后续想对齐 v4 大圆角,仅需改各组件圆角属性,不影响 token 体系。


1. ShadcnCard(纯组合组件,无 QQC 基类)

结构(对齐 shadcn 组合方式)

Card(容器)
├── CardHeader  (padding、间距,可含 title/description/action)
│   ├── CardTitle        (font-medium, text-base=16px)
│   ├── CardDescription  (text-sm=14px, mutedForeground)
│   └── CardAction       (右上角动作区,可选)
├── CardContent (内容区)
└── CardFooter  (flex 横向,底部按钮区)

shadcn 规范值

v4 官方值换算/决策
容器底色bg-card text-card-foreground新 token card / cardForeground
容器描边ring-1 ring-foreground/5(light)/10(dark)1px,前景色 5%/10% 透明
阴影shadow-md轻阴影
圆角rounded-4xl (32px)8px(theme.radius)
内边距--card-spacing: spacing(6) = 24px;size="sm" 时 spacing(4) = 16px支持 size: default/sm
文本text-sm(14px);Title text-base(16px) font-medium;Description text-sm mutedForeground
Header/Content/Footer 横向 paddingpx-(--card-spacing)24px(sm 16px)
Footerflex items-center子项水平排列、垂直居中

QML 实现要点

  • 纯组合:ShadcnCard 容器 + ShadcnCardHeader + ShadcnCardTitle + ShadcnCardDescription + ShadcnCardContent + ShadcnCardFooter 六个 QML 类型
  • 容器:Rectangle + radius: theme.radius + color: theme.card + border.width: 1 + border.color: Qt.rgba(theme.foreground, 0.05) + 阴影(layer 或简单矩形叠层)
  • 子组件用 Item 派生、default property 接子项、leftPadding/rightPadding/topPadding/bottomPadding 由外部 padding 属性控制(对齐 shadcn:Header/Content/Footer 各自带 padding,Card 管 gap)
  • 内容流:Header/Content/Footer 垂直堆叠(Column),间距 gap-1.5(6px) 等对齐
  • 提供 size: "default" | "sm" 属性(sm 内边距 16px)

2. ShadcnInput(基于 QQC.TextField)

shadcn 规范值

v4 官方值换算/决策
高度h-936px
圆角rounded-3xl (24px)6px(控件级)
底色bg-input/50theme.input 50% 透明
边框border-transparent(常态)1px 透明,聚焦切 ring
聚焦态focus-visible:border-ring focus-visible:ring-3 ring-ring/30border=ring + 3px 外环 30% 透明
内边距px-3 py-1左右 12px / 上下 4px
字号text-base(16) / md:text-sm(14)用 14px(桌面)
placeholdertext-muted-foregroundmutedForeground
disabledopacity-5050% 透明(与 Button 一致)
file 按钮file:text-foreground不支持(桌面无需)

QML 实现要点

  • import QtQuick.Controls.Basic,基于 TextField,重写 background + placeholderTextColor
  • 背景 Rectangleradius: 6,常态 color: Qt.rgba(theme.input, 0.5) + 1px 透明边框;activeFocusborder.color: theme.ring + 外扩 ring 环(3px、30% 透明,同 Button 焦点环做法)
  • placeholderTextColor: theme.mutedForeground
  • 禁用态 opacity: 0.5!enabled
  • implicitWidth: 200(shadcn 无默认宽,w-full 由外部决定)

3. ShadcnBadge

shadcn 规范值

v4 官方值换算/决策
高度h-520px
圆角rounded-3xl (24px)胶囊(radius: 20)
内边距px-2 py-0.5左右 8px / 上下 2px
字号/字重text-xs(12px) font-medium12px / Font.Medium
描边border border-transparent1px 透明(outline variant 换 border token)

variants(v4 官方,6 种)

variant底色文字hover(包裹 <a> 时)
defaultprimaryprimaryForegroundbg-primary/80
secondarysecondarysecondaryForegroundbg-secondary/80
destructivebg-destructive/10透明底红字destructivebg-destructive/20
outline透明foregroundbg-muted + mutedForeground
ghost透明foregroundbg-muted
link透明primary下划线(underline-offset-4)

注意 v4 变化:destructive 是「透明底 + 红字」(旧版是实心红底白字),按 v4 实现。

QML 实现要点

  • 无 QQC 基类:Item/Rectangle 容器 + 内部 Text(对齐 Button 的居中做法)
  • variant → token 查表:新增 VariantTokens.badge(bg/fg 字符串,沿用现有机制);destructive 需特殊处理(底色 = destructive 10% 透明,非实心)
  • 支持 text 属性;implicitWidth: text + 16implicitHeight: 20
  • 复用 theme.tokens[] 查询保持 mode 切换绑定

4. ShadcnSwitch(基于 QQC.Switch)

shadcn 规范值(size: default / sm)

defaultsm
轨道44×20px(w-11 h-5)28×16px(w-7 h-4)
滑块24×16px(w-6 h-4)16×12px(w-4 h-3)
checked 滑块位移translate-x-[calc(100%-8px)] = 16px8px
轨道圆角rounded-fullrounded-full
轨道 checkedbg-primary border-primary同左
轨道 uncheckedbg-input/90 border-transparent同左
滑块色bg-background shadow-sm同左(dark checked 用 primaryForeground)

QML 实现要点

  • 基于 QQC.Switch(Basic style),重写 background + indicator(或 contentItem
  • 轨道:Rectangle 宽高随 size(44×20 / 28×16),radius: height/2checkedtheme.primary + 1px primary 边框;!checkedQt.rgba(theme.input, 0.9) + 透明边框
  • 滑块:Rectangle(24×16 / 16×12),radius: height/2color: theme.backgroundx 绑定:checked ? width - thumb.width - 2*border : 2(用 Behavior on xNumberAnimation 150ms 过渡)
  • 聚焦环:activeFocus 时 3px ring 外环(同 Input)
  • disabled:opacity: 0.5

5. ShadcnTabs(基于 QQC.TabBar / TabButton / StackLayout)

结构

ShadcnTabs(容器)
├── ShadcnTabsList(TabBar 视觉:胶囊底 or line)
│   ├── ShadcnTabsTrigger(TabButton,选中态 + 指示器)
│   └── ...
└── ShadcnTabsContent(StackLayout 页区)

shadcn 规范值

v4 官方值(default variant)决策
TabsList 底色bg-muted rounded-full p-1 h-9bg-muted + theme.radius(8) + p-4 + 高 36
TabsList line variantgap-1 bg-transparent下划线式(v4 新增)
Triggerrounded-full px-3 py-1 text-sm font-medium6px 圆角、12px padding、14px/Medium
Trigger 常态text-foreground/60(dark: mutedForeground)foreground 60% 透明
Trigger hovertext-foreground全不透明
Trigger 选中(default)bg-background text-foreground白底 + 前景色
Trigger 选中(line)下划线 after:h-0.5 after:bg-foreground(bottom -5px)2px 下划线指示器
TabsContenttext-sm flex-114px

QML 实现要点

  • ShadcnTabs:暴露 currentIndex/currentItem/currentTitle,管 Trigger 与 Content 的联动
  • ShadcnTabsListTabBar(Basic),重写 backgroundposition 对齐 shadcn(列表在上)
  • ShadcnTabsTriggerTabButton,重写 background(选中 bg-background / 常态透明)+ 内容 Text(60%→100% 透明切换)+ line variant 下划线指示器(Rectangle 2px,x 动画可选)
  • ShadcnTabsContentStackLayout(或 TabBar + 关联 StackLayout),currentIndex 绑定
  • 提供 variant: default/lineorientation(横向为主,vertical 后期)

6. ShadcnDialog(基于 QQC.Dialog)

结构

ShadcnDialog(Popup 封装)
├── ShadcnDialogOverlay  (bg-black/30 + backdrop-blur)
├── ShadcnDialogContent  (popover 底 + 圆角 + 阴影 + 居中)
│   ├── ShadcnDialogHeader(Title + Description)
│   │   ├── ShadcnDialogTitle
│   │   └── ShadcnDialogDescription
│   ├── (业务内容)
│   └── ShadcnDialogFooter(按钮区,右对齐)
└── ShadcnDialogClose  (右上角 X,ghost 图标按钮)

shadcn 规范值

v4 官方值换算/决策
遮罩bg-black/30 backdrop-blur-sm黑 30% + 背景模糊
容器底色bg-popover text-popover-foreground新 token popover/popoverForeground
容器宽max-w-md = 448pxmax-w-[calc(100%-2rem)]448px,小屏留 32px 边距
容器圆角rounded-4xl (32px)8px(theme.radius)
容器内边距p-6(24px),gap-6(24px)24px
阴影shadow-xl ring-1 ring-foreground/5重阴影 + 1px 前景 5% 环
标题text-base font-medium leading-none16px / Medium
描述text-sm text-muted-foreground14px / mutedForeground
Footerflex justify-end gap-2右对齐
关闭按钮右上角 ghost 图标按钮(X),absolute top-4 right-4ShadcnButton.Ghost + Icon(M4 前用文本 ✕)
动画fade-in + zoom-in-95,duration 100msopacity + scale 动画

QML 实现要点

  • 基于 QQC.Dialog(Basic),modal: true;重写 overlay(黑 30% + blur)
  • 内容:ShadcnDialogContent 容器(popover 底 + 8px 圆角 + 1px 环 + 阴影 + 448px 宽),居中于 overlay
  • standardButtons: Dialog.NoButton,关闭由右上角 X / Esc(QQC 自带)触发
  • Header/Footer 组合组件对齐 Card 风格;closeButtonVisible 属性控制 X 显示(shadcn showCloseButton
  • 动画:进入时 opacity 0→1 + scale 0.95→1(100ms),退出反向

7. 各组件 API 草案(与 shadcn 对齐)

// Card
ShadcnCard { size: "default" }  // default | sm
    ShadcnCardHeader {
        ShadcnCardTitle { text: "标题" }
        ShadcnCardDescription { text: "描述" }
    }
    ShadcnCardContent { /* 业务内容 */ }
    ShadcnCardFooter {
        ShadcnButton { text: "确定" }
    }

// Input
ShadcnInput {
    placeholderText: "请输入"
    onAccepted: ...
}

// Badge
ShadcnBadge { text: "New"; variant: ShadcnBadge.Variant.Default }
// Default / Secondary / Destructive / Outline / Ghost / Link

// Switch
ShadcnSwitch { checked: true; size: ShadcnSwitch.Size.Default }  // Default | Small

// Tabs
ShadcnTabs {
    currentIndex: 0
    ShadcnTabsList {   // variant: "default" | "line"
        ShadcnTabsTrigger { text: "账户" }
        ShadcnTabsTrigger { text: "密码" }
    }
    ShadcnTabsContent { /* 页 1 */ }
    ShadcnTabsContent { /* 页 2 */ }
}

// Dialog
ShadcnDialog {
    id: dialog
    title: "确认删除"
    ShadcnDialogContent {
        ShadcnDialogHeader {
            ShadcnDialogTitle { text: dialog.title }
            ShadcnDialogDescription { text: "此操作不可撤销。" }
        }
        ShadcnDialogFooter {
            ShadcnButton { text: "取消"; onClicked: dialog.close() }
            ShadcnButton { text: "删除"; variant: ShadcnButton.Variant.Destructive; onClicked: dialog.close() }
        }
    }
}

8. 实现顺序与验证

  1. ThemeManager 加 5 个新 token + QtShadcnTheme 暴露属性(先行,供后续组件使用)
  2. Card → Input → Badge → Switch → Tabs → Dialog(每个:实现 → QML_FILES 注册 → showcase 新页 → 全状态展示)
  3. showcase「组合示例」:新建项目对话框(Dialog + Card + Input + Button + Tabs 组合),验证 M3 集成
  4. make build + 运行截图确认 + commit + 关闭 GitHub issues
Copyright © 2026