关于 qt-figma-token-extraction
从 Figma 提取设计令牌并映射到 QML 类型,以 Theme 单例为核心生成 QML 设计系统。支持通过 Figma MCP 或本地 curl 工作流提取令牌。
主要功能
- 01提取 Figma 变量和样式
- 02将令牌映射到 QML 类型
- 03生成 Theme 单例设计系统
- 04处理变量模式和别名
- 05为生成的 QML 配置 Qt 项目文件
适用场景
- 01根据 Figma 令牌创建 QML 主题
- 02将颜色和字体样式迁入 Qt 项目
- 03从多个 Figma 来源生成设计系统文件
MCP 相关
该技能可使用 Figma MCP 工具读取变量并提取设计令牌,也提供本地 curl 提取流程作为替代方案。
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ theqtcompanyrnd/ agent-skills --skill qt-figma-token-extraction安装后在 Claude Code 中输入/qt-figma-token-extraction确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
examples/FontInterface.qmlPrimitives.qmlSpacing.qmlTheme.qmlTypography.qmlreferences/token-mapping.md详细介绍
Figma 令牌提取技能
此技能可从 Figma 文件中提取设计令牌,将其映射到 QML 类型,并生成可直接使用的 QML 设计系统,其中包含统一的 Theme 单例。
技能结构
支持文件会与此 SKILL.md 一同加载:
qt-figma-token-extraction/
├── SKILL.md # this file — entry point
├── references/
│ └── token-mapping.md # Figma variable type → QML type mapping rules
└── examples/
├── Primitives.qml # primitive color palette template
├── Theme.qml # semantic token template (references Primitives)
├── FontInterface.qml # font loaders + icon index template
├── Spacing.qml # spacing and radii template
└── Typography.qml # typography scale template
到达步骤 4(类型映射)时,请先阅读 references/token-mapping.md,再生成任何 QML。
在步骤 6 生成 QML 文件时,请将 examples/ 中的文件用作结构模板——它们体现了 Qt Design Studio 实际使用的命名和组织模式。
步骤 0 — 检查 Qt 项目设置
始终调用 AskUserQuestion 工具——即使看起来已经打开了项目,也不要假设当前打开的项目就是目标项目。
调用前,请阅读上下文,使问题更贴合用户的情况:
- 如果已有项目打开(可以看到文件,且存在
CMakeLists.txt),请在第一个选项中写明项目名称,方便用户确认或更换目标。 - 如果用户请求的是更新(“更新我的颜色”“重新提取令牌”“同步设计系统”),请省略“创建新项目”选项——更新始终针对现有项目。
对于更新请求——提供两个选项,不提供“创建新项目”选项:
tool: AskUserQuestion
question: "Which project should I update the design tokens in?"
options:
- "This project — <detected project name or path> (currently open)"
- "A different existing project — I'll give you the path"
对于初始设置请求——提供全部三个选项:
tool: AskUserQuestion
question: "Which Qt project should I set up the design system in?"
options:
- "This project — <detected project name or path> (currently open)"
- "A different existing project — I'll give you the path"
- "Create a new project"
如果当前没有打开任何项目,请将第一个选项替换为仅含 "一个现有项目 — 我会提供路径"。
**如果项目已存在(已确认或已提供路径):**记录项目路径。继续步骤 1——暂时不要询问 Figma 文件。
**如果需要新建项目:**立即搭建文件夹结构并创建 main.cpp 和 main.qml,然后继续步骤 1:
my-project/
├── CMakeLists.txt ← set up in Step 7
├── main.cpp ← create now (template below)
├── main.qml ← create now (template below)
└── design-system/ ← generated files go here
请使用以下确切内容创建 main.cpp——使用 QGuiApplication,而非 QApplication(Qt Quick 不需要 Widgets):
#include <QGuiApplication>
#include <QQmlApplicationEngine>
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QQmlApplicationEngine engine;
engine.loadFromModule("<ProjectName>", "Main");
if (engine.rootObjects().isEmpty())
return -1;
return app.exec();
}
将 <ProjectName> 替换为 qt_add_qml_module() 中使用的 URI——两者必须完全一致。
**不要使用旧的
QUrl url(u"qrc:/..."_qs)模式。**在 Qt 6 中,qt_add_qml_module会将文件放在qrc:/qt/qml/<URI>/下,而不是像 Qt 5 那样放在qrc:/<URI>/下。使用旧路径会导致加载失败且不显示错误。loadFromModule()可完全避免此问题,是 Qt 6.5+ 的正确方式。
请创建 Main.qml 作为占位文件——M 必须大写,不能小写。loadFromModule() 区分大小写,并会查找名为 Main 的类型,该类型对应 Main.qml:
import QtQuick
Window {
width: 640
height: 480
visible: true
title: "My Qt App"
}
**CMake 设置:**完整的 CMakeLists.txt(包括单例注册)将在步骤 7 中、所有 QML 文件都已确定后编写。现在不要编写。如果用户遇到任何构建配置问题,请建议用户查看 Qt 的 CMake 文档:https://doc.qt.io/qt-6/cmake-get-started.html,而不要在此处直接排查。
步骤 1 — 路由问题
请针对以下每个问题逐一调用 AskUserQuestion 工具。如果当前界面不支持 AskUserQuestion 工具,请以纯文本提出相同问题,并等待用户回答后再继续。暂时不要询问任何 Figma 链接。
调用 1 — 模式:
tool: AskUserQuestion
question: "Does your Figma design system use multiple variable modes?"
options:
- "Yes — for example Light and Dark themes"
- "No — single mode only"
- "I'm not sure"
等待用户回答,然后询问:
调用 2 — 终端:
tool: AskUserQuestion
question: "Are you comfortable running a short command in a terminal on your own computer?"
options:
- "Yes, I can use a terminal"
- "No, I prefer not to use a terminal"
| 答案组合 | 使用的方法(内部) |
|---|---|
| 单个模式 / 不确定 + 任意终端回答 | MCP 方法——提取期间检查是否存在多个模式,并按需调整 |
| 多个模式 + 熟悉终端 | curl 方法——通过一条命令获取所有模式 |
| 多个模式 + 不熟悉终端 | 使用手动切换模式的 MCP 方法 |
如果用户对模式的回答是“我不确定”,请使用 MCP 方法,并在提取期间检查是否存在多个模式。检查后再说明发现的情况,不要提前解释。
**不要询问文件使用的是 Variables 还是 Styles。**在步骤 2 收到 Figma 文件 URL 后自动检测——调用
get_variable_defs或检查文件,并报告发现的情况。如果存在 Variables,则提取 Variables;如果只有 Styles,则提取 Styles;如果两者都存在,则两者都提取。
第 2 步 — 收集所有 Figma 文件链接
了解提取方法后,在开始提取之前,一次性询问所有 Figma 文件 URL。这样可以避免之后中断工作流。
询问用户:
“请分享包含设计令牌的所有 Figma 文件 URL。如果令牌分散在多个文件或页面中(例如,颜色在一个文件中,字体排版在另一个文件中),请现在分享所有链接,并告诉我每个文件包含什么内容。”
等待用户提供所有 URL 后再继续。从每个 URL 中提取文件 key——即 /design/ 与下一个 / 之间的字母数字字符串。记录每个文件或页面包含哪些令牌类型。
社区文件说明: 如果任何 URL 指向用户尚未复制到其账户的 Figma 社区文件,请立即提醒用户:提取工具无法直接访问社区文件。请用户先将文件复制到 Figma 草稿中(打开文件 → 复制到你的草稿),然后分享新的 URL。
MCP 方法 — 通过 Figma MCP 提取
(适用于:单模式系统,或用户不熟悉终端的情况)
要求: 已连接 Figma MCP。无需个人访问令牌或本地设置。
注意: 此方法只读取 Figma 中当前激活的变量模式。如果设计系统包含多个模式(例如,浅色/深色),用户需要在每次读取之间切换 Figma 中的模式——可以操作,但步骤更多。不要一开始就提及此限制;只有在提取过程中发现多个模式时,才进行说明。
第 1a 步 — 确认已连接 Figma MCP
开始操作前,先确认 Figma MCP 工具可用。查找名称暗示变量提取、设计上下文读取或文件元数据的工具——不同的 Figma MCP 服务可能使用不同的确切名称(例如 get_variable_defs、getVariableDefinitions、figma_get_variables)。将本技能中的工具名称视为示例,而非固定约定;应按用途匹配,而非按确切字符串匹配。
如果完全没有可用的 Figma 工具,请告诉用户:
“Figma MCP 连接器尚未连接。请在 Claude 界面中连接它(设置 → 连接器或 MCP 配置),然后再回来开始操作。”
确认连接之前不要继续。
第 1b 步 — 检查模式
使用文件节点 ID 调用 get_variable_defs,查看有哪些集合和模式:
Tool: get_variable_defs
Input: { "nodeId": "<root node id or specific variable group node id>" }
如果响应显示有多个模式,且用户需要全部模式,请说明需要用户在每次读取之间切换 Figma 中的模式,然后继续操作。
第 1c 步 — 提取变量
对相关节点调用 get_variable_defs。每次处理一个集合,逐个提取令牌类别——颜色、字体排版、间距、圆角、阴影。对于每个集合,读取当前激活模式的值。
如果需要记录多个模式:
- 提取并记录当前模式的所有值
- 请用户切换 Figma 中当前激活的模式(视图菜单 → 变量模式,或画布上的模式切换器)
- 再次调用
get_variable_defs,并记录新模式的值 - 对每个模式重复此操作
- 合并为一个包含模式键的令牌文件(参见第 5 步中的输出格式)
第 1d 步 — 解析别名
如果任何变量值引用了另一个变量(即别名),请将其解析为最终值。不要将尚未解析的别名引用写入输出文件——标记所有无法解析的引用并询问用户。
curl 方法 — 从用户的本地计算机提取
(适用情况:存在多种变量模式,且用户熟悉终端)
需要: 终端访问权限(curl 已内置于 macOS 和 Linux;Windows 10 及更高版本也可使用),以及 Figma Personal Access Token(查看者权限范围即可)。
重要: 运行任何 curl 命令前,请先完成本节中的所有步骤,尤其是 PAT 设置和验证。使用无效令牌运行 curl 会生成损坏的输出文件。
不支持社区文件。 curl 命令仅适用于用户自己账号中的 Figma 文件(用户拥有或受邀访问的文件)。用户正在查看但尚未复制的社区文件会返回 403 错误。如果用户使用的是社区文件,请先让其复制到自己的账号:在 Figma 中打开社区文件 → 点击 复制到你的草稿 → 使用复制后的文件 URL。
第 1a 步 — 设置 Figma Personal Access Token
请先完成此步骤。询问用户:
“运行提取命令前,你需要一个 Figma Personal Access Token。你已经有了吗?”
如果有:继续进行验证(第 1b 步)。
如果没有,请引导用户创建:
- 在浏览器或桌面应用中打开 Figma
- 点击头像(左上角)→ 设置
- 转到 安全 选项卡
- 向下滚动到 Personal access tokens → 点击 Generate new token
- 为令牌取任意名称(例如“Claude token export”),并将权限范围设为 Viewer
- 立即复制令牌 — Figma 只会显示一次
第 1b 步 — 继续之前验证 PAT 是否有效
如果 PAT 最近已验证过(90 天内),用户可以跳过此步骤。否则,请让用户在终端中运行以下验证命令:
curl -H "X-Figma-Token: YOUR_TOKEN" "https://api.figma.com/v1/me"
预期结果:一条包含其 Figma 账号电子邮件地址的 JSON 响应(例如 "email": "[email protected]")。
如果响应包含 "status": 403 或 "Invalid token":说明令牌错误或已过期。请让用户生成新令牌并重试。验证成功前,请勿继续提取。
第 1c 步 — 提取变量
请用户在终端中运行:
curl -H "X-Figma-Token: YOUR_TOKEN" "https://api.figma.com/v1/files/FILE_KEY/variables/local" -o design-tokens-raw.json
这会将完整的原始变量导出内容 — 包含所有集合、所有模式和所有值 — 保存到 design-tokens-raw.json。
第 1d 步 — 分享结果
命令运行完成后,请用户选择以下任一方式:
- 将
design-tokens-raw.json上传到对话中,或 - 将其内容粘贴到对话中
然后继续下面的第 2 步(文本样式)。
提取样式
注意: Figma 样式(文本、颜色、效果)与变量分开存放,需要单独提取。如果用户的设计系统主要使用样式作为令牌来源(而非变量),则此步骤将成为主要提取步骤,而非辅助步骤。如果设计系统同时使用变量和样式,请先完成第 1 步,再执行此步骤。
逐页处理: Figma 文件通常会将不同类型的令牌分散在多个页面中(例如,一个页面放颜色,另一个页面放排版)。不要尝试一次提取所有内容。询问用户每种令牌类型位于哪个页面,然后每次提取一个页面。每处理完一页,先确认找到了哪些内容,再继续下一页。
MCP 方法 — 文本样式
对使用设计系统文本样式的文本框或组件使用 get_design_context。请用户在 Figma 中选择一个包含代表性文本元素的框架 — 标题、正文、标签 — 并读取它:
Tool: get_design_context
Input: { "fileKey": "<key>", "nodeId": "<selected text frame node id>" }
从响应中提取每种文本样式的名称、字体系列、字号、字重、行高和字间距。遍历所有文本角色(H1–H6、正文、标签、说明文字、代码)。如果一个框架中未显示全部样式,请用户选择其他框架。
curl 方法 — 文本样式
文本样式需要调用两次 curl:第一次获取包含节点 ID 的样式列表,第二次获取这些节点的实际属性值。第 1a 步中的 PAT 已通过验证,可直接继续:
curl -H "X-Figma-Token: YOUR_TOKEN" "https://api.figma.com/v1/files/FILE_KEY/styles" -o text-styles-list.json
然后从 text-styles-list.json 中提取 node_id 值,用逗号连接后运行:
curl -H "X-Figma-Token: YOUR_TOKEN" "https://api.figma.com/v1/files/FILE_KEY/nodes?ids=NODE_IDS" -o text-styles-nodes.json
从 text-styles-nodes.json 中提取每种文本样式的字体系列、字号、字重、行高、字间距,以及应用的任何文本装饰或文本转换。
命令完成后,请用户将这两个文件上传或粘贴到对话中。
将文本样式合并到令牌文件中
文本样式会合并到 design-tokens.json 的 typography 部分。将它们标记为 "source": "textStyle",以便与基于变量的排版令牌区分:
"typography": {
"fontFamilyHeading": { "value": "Titillium Web", "figmaName": "Font/Heading", "type": "STRING", "source": "variable" },
"h1Size": { "value": 36, "unit": "px", "figmaName": "H1/Size", "type": "FLOAT", "source": "variable" },
"h1": {
"figmaName": "Heading/H1",
"source": "textStyle",
"fontFamily": "Titillium Web",
"fontSize": 36,
"fontWeight": 600,
"lineHeight": 54,
"letterSpacing": 0
},
"bodyDefault": {
"figmaName": "Body/Default",
"source": "textStyle",
"fontFamily": "Inter",
"fontSize": 14,
"fontWeight": 400,
"lineHeight": 22,
"letterSpacing": 0
}
}
如果设计系统完全通过文本样式定义排版(且没有排版变量),则不会有 source: "variable" 条目——这没有问题,仅使用文本样式就足够了。
第 3 步 — 检查原始输出
无论使用哪种方法,在应用命名约定之前,都要与用户一起检查原始令牌数据:
- 已提取所有文件: 确认用户提到的每个文件都已提取。若有任何文件缺失,请勿继续。
- 集合已包含: 集合名称是否与用户预期的各文件内容相符?
- 已捕获模式: 如果有多种模式,请确认所有模式都已显示,且值正确。
- 颜色值: 抽查一些十六进制值,并与 Figma 文件核对。
- 别名解析: 引用原始令牌的语义令牌应已解析出值。如果某个别名无法解析,几乎可以肯定是因为它引用的原始令牌位于尚未提取的文件中——请返回并先提取该文件,再继续。
- 缺少集合: 如果缺少预期内容,请询问用户它位于哪个 Figma 文件中,并将该文件添加到清单中。
第 4 步 — 映射令牌类型并应用命名约定
生成任何 QML 之前,请先阅读 references/token-mapping.md,以确定每种 Figma 变量类型对应的正确 QML 类型(COLOR → color、FLOAT → int 或 real、STRING → string 等)。在所有生成的文件中一致地应用此映射。
询问用户是否已有命名约定。如果没有,请使用以下 Qt Design Studio 约定并确认:
| 令牌类型 | 约定 | 示例 |
|---|---|---|
| 原始颜色 | {family}_{scale} | neutral_900、neon_500 |
| 原始分组 | 每个系列使用嵌套的 QtObject | Primitives.neutrals.neutral_900 |
| 语义颜色 | {role}_{variant} | background_default、text_muted |
| 语义分组 | 在 Theme 单例上使用扁平结构 | Theme.background_default |
| 语义变体 | _default / _muted / _subtle | stroke_strong、stroke_muted、stroke_subtle |
| 通知令牌 | notification_{type}_{variant} | notification_alert_default、notification_danger_muted |
| 间距步长 | x{multiplier} | x4(= 8 px)、x8(= 16 px) |
| 圆角半径 | radius_{size} | radius_s、radius_m、radius_full |
| 字体加载器 | 描述性组件名称 | interFont、titilliumSemiBold、inconsolata |
| 图标名称 | {icon_name}_{size} | close_16、settings_fill_16 |
所有名称均使用 snake_case。原始 Figma 名称始终保存在 design-tokens.json 的 figmaName 字段中。
JSON 与 QML 的命名: 这些约定适用于生成的 QML 输出。出于 JSON 兼容性考虑,
design-tokens.json使用 camelCase 存储令牌键(例如backgroundPrimary、cornerRadiusM)——生成 QML 时会在第 6 步将其转换为 snake_case。
步骤 5 — 编写 design-tokens.json
编写一个合并后的 design-tokens.json,包含所有提取的文件。来自不同 Figma 文件的原始令牌和语义令牌分别放在不同的区块中,以保留双层结构,并明确每个令牌所属的层级。单模式令牌使用扁平的 value 字段;多模式令牌则将值嵌套在 modes 下:
{
"meta": {
"extractedAt": "<ISO 8601 timestamp>",
"namingConvention": "camelCase (JSON) / snake_case (QML)",
"extractionMethod": "MCP | curl",
"sources": [
{ "figmaFileName": "Global Tokens", "url": "<Figma URL>", "tier": "primitive" },
{ "figmaFileName": "Design Tokens", "url": "<Figma URL>", "tier": "semantic" }
]
},
"_comment_primitives": "Raw values from the Global Tokens file — the building blocks",
"colors": {
"neutral000": { "value": "#ffffff", "figmaName": "Neutral/000", "type": "COLOR" },
"neon600": { "value": "#1f9b5d", "figmaName": "Neon/600", "type": "COLOR" }
},
"_comment_semantic": "Semantic values from the Design Tokens file — reference primitives via resolvedFrom",
"semanticColors": {
"backgroundPrimary": {
"figmaName": "Background/Primary", "type": "COLOR",
"resolvedFrom": "neutral000",
"modes": {
"Light": { "value": "#ffffff" },
"Dark": { "value": "#181818" }
}
}
},
"typography": {
"fontFamilyHeading": { "value": "Titillium Web", "figmaName": "Font/Heading", "type": "STRING" },
"h1Size": { "value": 36, "unit": "px", "figmaName": "H1/Size", "type": "FLOAT" },
"h1Weight": { "value": 600, "figmaName": "H1/Weight", "type": "FLOAT" },
"h1LineHeight": { "value": 54, "unit": "px", "figmaName": "H1/LineHeight", "type": "FLOAT" }
},
"spacing": {
"x4": { "value": 8, "unit": "px", "figmaName": "Spacing/X4", "type": "FLOAT" },
"x8": { "value": 16, "unit": "px", "figmaName": "Spacing/X8", "type": "FLOAT" }
},
"radii": {
"cornerRadiusS": { "value": 4, "unit": "px", "figmaName": "Radius/Small", "type": "FLOAT" },
"cornerRadiusFull": { "value": 9999, "unit": "px", "figmaName": "Radius/Full", "type": "FLOAT" }
},
"shadows": {
"shadowLow": {
"offsetX": 0, "offsetY": 1, "blur": 3, "spread": 0,
"color": "rgba(0,0,0,0.12)", "figmaName": "Shadow/Low"
}
}
}
保存到设计系统项目文件夹的根目录。向用户确认路径。
步骤 6 — 生成 QML 文件
以完整的 design-tokens.json 为唯一可信来源,生成 QML 单例文件。将所有文件放在 Qt 项目根目录下的 design-system/ 文件夹中。
首先读取资源模板
编写任何 QML 之前,先读取与每个输出文件对应的资源文件。这些是权威模板——定义了应遵循的确切结构、命名、分组和区块顺序:
| 输出文件 | 要读取的示例 | 内容说明 |
|---|---|---|
Primitives.qml | examples/Primitives.qml | 每个颜色系列对应一个嵌套的 QtObject,采用 {family}_{scale} 命名 |
Theme.qml | examples/Theme.qml | 扁平的语义令牌,引用 Primitives,并按角色分组 |
Spacing.qml | examples/Spacing.qml | x{n} 间距步长、radius_{size} 圆角半径 |
FontInterface.qml | examples/FontInterface.qml | 内联 component 字体加载器、带有 Unicode 映射的 Icons QtObject |
Typography.qml | examples/Typography.qml | 字体粗细常量,以及字号/粗细成对的字体比例 |
每次生成文件之前,立即读取该资源文件——不要依赖先前读取时的记忆。
文件夹结构
design-system/
├── Primitives.qml ← raw color palette (nested by family: neutrals, accents)
├── Theme.qml ← semantic color tokens (references Primitives)
├── Spacing.qml ← spacing steps and corner radii
└── FontInterface.qml ← font loaders + icon unicode index
按以下顺序生成:先生成 Primitives(没有依赖项),然后生成 Spacing 和 FontInterface(相互独立),最后生成 Theme(引用 Primitives)。
不要手动编写 qmldir。 模块注册由 CMakeLists.txt 中的
qt_add_qml_module()处理。单例注册使用set_source_files_properties——在步骤 7 中更新。
生成规则
- 所有值均来自
design-tokens.json——绝不硬编码令牌文件中没有的值 - 全程使用
snake_case——background_default、neutral_900、x4、radius_m Primitives.qml仅存放原始值——不包含语义含义。Theme.qml仅存放语义令牌——始终引用Primitives,绝不使用原始十六进制值- 根据
references/token-mapping.md应用类型映射——颜色使用readonly property color,尺寸使用readonly property int,字体名称使用readonly property string - 在每个文件顶部添加源注释和 CMake 说明
- 使用区块注释对相关属性进行分组(
// ── Section name ─────) - 如果 JSON 中缺少某个令牌,请添加
// TODO: <figmaName>占位符,不要猜测值 - 导入: 使用
import QtQuick——在 Qt 6 中,import QtQuick.Window是多余的(Window 已包含在内),但添加后不会报错 - 特效和渐变: 使用来自
import QtQuick.Effects的MultiEffect(从 Qt 6.5 开始提供)。绝不要使用Qt5Compat.GraphicalEffects——它需要额外的兼容模块,且并非所有 Qt 6 配置都提供该模块 - QML 编码技能: 如果有
qt-development-skills:qt-qml技能,在生成 QML 文件时使用它,以确保采用正确的 Qt 6 模式
第 7 步 — 审核、修复 QML 并更新 CMakeLists.txt
生成所有 QML 文件后,运行验证流程——请勿跳过以下任何检查:
QML 验证:
- 检查是否存在
// TODO:占位符——将其标记出来,并询问用户如何解决 - 验证每个属性类型是否符合
references/token-mapping.md中的规则 - 确认每个文件中都包含
pragma Singleton和import QtQuick - 检查是否有本应从令牌文件读取的值被硬编码
CMakeLists.txt — 必须更新:
请务必在此步骤中更新 CMakeLists.txt——不要留给用户处理。打开该文件,找到 qt_add_qml_module() 块,并确保所有生成的设计系统文件都列在 QML_FILES 下,且已通过 set_source_files_properties 注册。单例无法在 QML 中访问,最常见的原因就是这里配置不当。
命名规则:
main.cpp中的目标名称、URI 和loadFromModule()调用必须使用相同的项目名称字符串。使用project()CMake 调用中的实际项目名称——不要直接使用MyProject作为名称。
cmake_minimum_required(VERSION 3.16)
project(<ProjectName> VERSION 0.1 LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
# Version pin must match qt_standard_project_setup REQUIRES below
find_package(Qt6 6.5 REQUIRED COMPONENTS Quick)
qt_standard_project_setup(REQUIRES 6.5)
# MACOSX_BUNDLE is required on macOS — without it, qt_add_qml_module creates
# a directory named <ProjectName>/ which collides with the linker output file
# (EISDIR error). MACOSX_BUNDLE makes the output MyQtApp.app, no collision.
qt_add_executable(<ProjectName> MACOSX_BUNDLE
main.cpp
)
set_source_files_properties(
design-system/Primitives.qml
design-system/Theme.qml
design-system/Spacing.qml
design-system/FontInterface.qml
PROPERTIES QT_QML_SINGLETON_TYPE TRUE
)
qt_add_qml_module(<ProjectName>
URI <ProjectName>
VERSION 1.0
QML_FILES
Main.qml # capital M — must match loadFromModule("<ProjectName>", "Main")
design-system/Primitives.qml
design-system/Theme.qml
design-system/Spacing.qml
design-system/FontInterface.qml
# NOTE: do NOT add main.cpp here — it belongs only in qt_add_executable()
)
target_link_libraries(<ProjectName> PRIVATE Qt6::Quick)
将每个 <ProjectName> 替换为相同的字符串——例如 MyQtApp——使其与 project() 调用中的名称以及 main.cpp 中的 loadFromModule("<ProjectName>", "Main") 调用相匹配。
更新 CMakeLists.txt 后,向用户确认文件已保存,并向其演示如何在 Main.qml 中使用这些单例:
import QtQuick // Window is part of QtQuick in Qt 6 — do NOT add import QtQuick.Window
import <ProjectName> // imports all singletons from the module
Window {
visible: true
width: 640
height: 480
color: Theme.background_default
}
CMake 问题: 如果用户更新
CMakeLists.txt后遇到构建错误,建议用户查阅 Qt 的 CMake 文档:https://doc.qt.io/qt-6/cmake-get-started.html,而不是在此处直接排查。
第 8 步 — 总结
简要总结,并请用户检查输出:
- 各类别提取的令牌总数(颜色、间距、排版、圆角)
- 已捕获的模式和主题
- 任何尚未解决的别名或需要处理的
// TODO:占位符 - 生成的文件:
design-tokens.json、Primitives.qml、Theme.qml、Spacing.qml、FontInterface.qml - 提醒用户:必须在
CMakeLists.txt中为每个单例文件设置set_source_files_properties(... QT_QML_SINGLETON_TYPE TRUE) - 使用本文末尾的令牌类别检查清单确认没有遗漏任何内容
- 确认设计系统基础已准备就绪——现在可以开始组件生成技能
令牌类别检查清单
- 基础颜色调色板(所有颜色系列和色阶)
- 包含所有模式的语义颜色令牌(如有)
- 字体系列(标题、正文、等宽)
- 字重(数值:400/500/600/700)
- 来自变量的字体尺寸阶梯(如果定义为变量,则包含每种角色对应的大小、字重和行高)
- 文本样式(H1–H6、正文、标签、说明文字、代码——字体系列、大小、字重、行高、字母间距)
- 间距阶梯(基础单位和所有命名步长)
- 圆角(S、M、L、Full)
- 阴影/海拔层级(如有)
- 图标尺寸令牌(如有)
- 动画/持续时间令牌(如有)