OpenPencil 设计变量完全指南:集合、模式与填充绑定实战
前端桌面应用AI 应用MCP 服务【免费下载链接】open-pencilAI-native design editor. Open-source Figma alternative.项目地址https://gitcode.com/gh_mirrors/op/open-pencil点击查看免费下载设计变量Design Variables是 OpenPencil 中复用设计令牌的核心机制——颜色、间距等属性以变量的形式存储并可绑定到图层节点。修改一个变量的值所有使用它的节点都会同步更新。本文以官方用户指南 packages/docs/user-guide/variables.md 为骨架结合场景图scene-graph数据结构与 DOM-CSS 导出引擎的源码实现系统讲解变量的组织方式、多模式主题切换原理、样式表生成规则以及在画布上绑定与解绑填充变量的完整工作流。读完本文你将能熟练管理变量集合与模式、理解导出的 CSS 结构与条件规则、并掌握从设计到代码的变量交付链路。打开变量对话框在 OpenPencil 中变量通过一个专门的对话框进行管理打开方式有三种通过菜单View → Variables…在命令面板中搜索 Variables在未选中任何节点时点击 Design 面板中 Variables 区块的入口。对话框右上角的Expand按钮可以让它占据窗口的大部分空间方便在大型设计系统中编辑。对话框的布局分三块实现见 src/components/variables/TokensPanel.vue 与其容器 VariablesDialog.vue左侧列出当前激活集合active collection的变量右侧编辑当前选中的变量或集合下方实时展示这些变量生成的样式表stylesheet。在窄窗口或手机上对话框一次只显示一个模式变量列表、集合设置、样式表会以覆盖层的形式在列表上方展开并带有返回按钮。打开/关闭状态由编辑器状态中的variablesOpen字段控制见 src/app/editor/tokens/dialog.ts对话框内部直接复用了画布上的文档快捷键CmdZ撤销、CmdShiftZ/CmdY重做因此对话框中进行的每次更改都构成一个可撤销的历史步骤。集合Collections变量按集合组织。宽对话框中集合显示在侧边栏并标注各自包含的变量数量窗口变窄时变成标签页手机上则收进下拉菜单。操作说明切换集合点击侧边栏中的集合或它的标签创建集合点击 Collections 旁边的或工具栏中的文件夹按钮重命名或删除在未选中变量时右侧编辑面板会变为集合编辑可改名或从名称旁的⋯菜单中删除切换属性设置手动切换模式的属性名attribute默认集合名为 Theme 时是data-theme可改成其他名称如data-color-scheme以匹配已有代码库从数据结构看集合对应场景图中的VariableCollection接口见 packages/scene-graph/src/types.ts#L736-L749export interface VariableCollection { id: string name: string /** 默认模式排在第一位与 Figma 一致。 */ modes: VariableCollectionMode[] defaultModeId: string variableIds: string[] /** * 用于切换无自身条件模式如 [data-themedark]的属性名 *>export interface VariableCollectionMode { modeId: string name: string /** * 模式在 CSS 中的生效位置选择器[data-themedark]、.compact * 或 at-rule 前导media (max-width: 640px)。缺省时使用该轴的默认值。 */ condition?: string }默认模式与 Applies when集合的默认模式为Always on始终开启在导出的样式表中写入:root。其他每个模式都有Applies when何时生效设置并实时显示其写入的 CSS。下表完整列出可用的条件类型与对应 CSS源自官方文档条件解析实现见 packages/dom-css/src/tokens/conditions.tsApplies whenCSS手动切换Switched manually集合的切换属性被设为该模式例如 Theme 集合的 Dark 模式对应[data-themedark]系统处于深色模式 / 浅色模式media (prefers-color-scheme: dark)/light开启高对比度media (prefers-contrast: more)开启减弱动画media (prefers-reduced-motion: reduce)屏幕窄于 / 宽于某个宽度media (max-width: 640px)/min-width容器窄于 / 宽于某个宽度container (max-width: 640px)/min-width自定义 CSS任意选择器或media、supports、container查询这些“特征条件”会被parseFeatureCondition用 css-tree 解析成结构化的FeatureCondition包含规则类型 media/container、特征名与取值并重新序列化为标准 CSS因此空格、大小写和注释不会影响条件含义packages/dom-css/src/tokens/conditions.ts#L44-L66。画布行为与导出行为的分野在画布上只要把图层设到某个模式该图层就会显示该模式的值——无论条件是什么。但在导出的代码中手动切换的模式通过在元素上添加属性来开启因此设为该模式的图层导出时会带上该属性例如data-themedark其他条件含自定义选择器的模式导出为字面值而非令牌因为决定模式何时生效的是样式表而不是图层本身。该行为由modeAttribute与defaultModeCondition共同实现packages/dom-css/src/tokens/stylesheet.ts#L74-L92手动模式缺省条件的默认形态是[data-themedark]这样的属性选择器模式名通过modeSlug转成合法的标识符例如 Figma 风格的模式 id1:2会被 slug 化重名模式按顺序编号dark-2。管理变量变量按名称中的文件夹路径分组Brand/Primary会以Primary显示在Brand组下每一行展示变量的 CSS 名称与每个模式下的一个值。分组实现对应 src/app/editor/tokens/model.ts 中的splitName与tokenGroups变量名最后一个/之前的部分作为组路径组在侧边栏形成带深度的树groupTree组内数量统计包含嵌套组。常用管理操作创建变量— 点击Create variable或并选择类型新变量创建后立即进入编辑状态选择— 点击行或用方向键移动后按 EnterShift-click 选择连续范围Cmd-clickWindows/Linux 为 Ctrl-click单独增删过滤— 在搜索栏输入关键字可按名称、CSS 名称、描述或值过滤例如--color-brand、一个十六进制颜色或别名指向的变量模糊匹配与命令面板一致实现为 src/app/editor/tokens/model.ts 中的searchTokenIds基于fuzzyFilter搜索键覆盖 name、css、description、values 四项点击侧边栏中的组可只看该组及其内部组过滤按钮可只显示部分类型原地重命名或编辑— 在列表中双击名称或双击数字/文本值右键菜单— 重命名、复制、移动到组或新组、删除选中的变量Delete 或 Backspace 同样删除重排— 拖动行调整顺序顺序保存在文件中reorderedVariableIds保证过滤状态下列表拖拽不会打乱隐藏行的位置多选操作— 右侧面板可批量移入组、复制或删除撤销与重做— 对话框内与画布一致CmdZ、CmdShiftZ/CmdYWindows/Linux 为 Ctrl每次更改一步Enter 提交字段并返回列表字段中有未提交文本时CmdZ仅撤销键入。编辑变量选中变量后右侧面板提供以下编辑项名称与 CSS 名称— CSS 名称留空时按名称和作用域自动推导例如--color-brand-primary。输入时不用带--前缀CSS 不允许的名称会被标记且不保存单位Unit— 仅数字变量px、rem、%、ms、s、deg或无数值按该单位输入值Value / Values— 每个模式一个值。颜色值会打开取色器。值旁的变量按钮可让该值指向另一个同类型变量即别名跟随目标变量变化Detach variable则恢复为当前显示的字面值CSS 表达式CSS expression— 仅数字变量写入如clamp(1rem, 4vw, 1.5rem)这样的表达式替代 CSS 中的数字而画布仍按存储的数字绘制作用域Scopes— 该变量可被提供给哪些属性描述Description隐藏于发布Hide from publishing— 以此为库使用的文件将看不到该变量。底层数据结构VariableVariable接口完整定义了上述编辑项packages/scene-graph/src/types.ts#L695-L719export interface Variable { id: string name: string type: VariableType // COLOR | FLOAT | STRING | BOOLEAN collectionId: string valuesByMode: Recordstring, VariableValue description: string hiddenFromPublishing: boolean scopes?: VariableScope[] // 缺省表示所有作用域 /** 各平台代码片段WEB 片段为 --x 或 var(--x) 时命名该令牌的自定义属性否则按名称推导。 */ codeSyntax?: PartialRecordCodeSyntaxPlatform, string /** 仅 FLOAT。缺省时在写入 CSS 时按作用域推断。 */ unit?: TokenUnit /** 按模式 id 记录的原始 CSS用于数字无法表达的表达式clamp()、calc()。 */ expressions?: Recordstring, TokenExpression pluginData?: PluginDataEntry[] key?: string // 发布库的 key用于 colorVar 的 assetRef 解析 version?: string // 发布库的版本 }单位与数字的推导规则数字变量的单位并非只能手动指定——缺省时由类型与作用域推断packages/dom-css/src/tokens/values.ts 中的variableUnit显式设置的unit优先OPACITY、FONT_STYLE、FONT_VARIATIONS作用域的数字无单位其余数字默认为像素长度即画布绘制所用的单位。写入 CSS 时tokenNumberToCSS负责换算例如内部存储 24 的rem变量会输出1.5remms变量输出150ms数字保留 6 位小数以保证rem对每个像素步长精确0.5px即0.03125rem。作用域清单作用域按变量类型划分并同时决定令牌的 Tailwind 命名空间见 src/app/editor/tokens/scopes.tsCOLORALL_FILLS、FRAME_FILL、SHAPE_FILL、TEXT_FILL、STROKE、EFFECT_COLORFLOATCORNER_RADIUS、WIDTH_HEIGHT、GAP、STROKE_FLOAT、OPACITY、EFFECT_FLOAT、FONT_STYLE、FONT_SIZE、LINE_HEIGHT、LETTER_SPACING、PARAGRAPH_SPACING、PARAGRAPH_INDENTSTRINGTEXT_CONTENT、FONT_FAMILY、FONT_STYLEBOOLEAN无。别名Alias与解析值指向另一变量时形成别名链。aliasCandidatessrc/app/editor/tokens/model.ts#L226-L269确保候选对象类型相同、不是自身、也不是会反向指向当前变量的对象否则两者互相解析为空。画布实际取色时通过resolveVariable递归解析packages/scene-graph/src/variables.ts#L241-L270优先取当前激活模式的值其次回退到集合默认模式再次取任意一个存在的值遇到别名则沿aliasId继续递归带 visited 集合防环。节点级别的解析resolveColorVariableForNode/resolveVariableForNode还会先计算节点所在集合的激活模式packages/scene-graph/src/variables.ts#L283-L321。CSS 名称的推导CSS 名称由variableCSSNames统一分配packages/dom-css/src/tokens/names.ts#L118-L142先让声明了codeSyntax.WEB片段如var(--brand)的变量保留其名称再为其余变量按deriveCSSName推导推导时先确定 Tailwind 命名空间variableNamespace颜色 →color单一作用域映射到对应命名空间再按名称首段推断如Color/primary不会变成--color-color-primary名称段 slug 化并合并重复段Gap/gap-1→gap-1最后保证全文档唯一——冲突的名称按顺序追加数字后缀。样式表Stylesheet对话框底部实时显示激活集合对应的 CSS 自定义属性。复制按钮可将整个文档的变量复制为CSS或Tailwind v4 主题格式与告警文案定义见 src/app/editor/tokens/copy.ts 的createTokenCopy因此跨集合的别名也能解析——复制会遍历所有集合而不只是当前激活集合。样式表由buildTokenStylesheet生成packages/dom-css/src/tokens/stylesheet.ts#L159-L280核心规则每个集合的默认模式构成基础集写入:rootTailwind 格式下有命名空间的令牌额外写入theme其他每个模式只声明与其默认值不同的变量并包裹在其条件mode.condition ?? defaultModeCondition之下别名在导出中保持var(--x)引用且在目标变量改变的每个模式中重新声明——因为自定义属性按计算值继承若不在--blue变化处重声明--primary: var(--blue):root处解析的结果会一直是旧值布尔变量没有 CSS 值无法写出时会收集到issues复制时通过 toast 提示被遗漏的令牌名称Tailwind 格式额外为每个非默认模式生成custom-variant如dark (:where([data-themedark], [data-themedark] *))模式名相同如两个集合都有 Dark时以集合名做前缀避免冲突。样式合法性在浏览器中使用浏览器自身的 CSS 解析器CSSStyleSheet校验无浏览器的环境CLI、MCP则加载 CSSOM 包进行无头校验loadTokenValidatorpackages/dom-css/src/tokens/stylesheet.ts#L287-L291非法的声明或条件会以TokenStylesheetIssue形式反馈。将变量绑定到填充在属性面板的 Fill 区块中使用变量选择器可将颜色变量绑定到节点的填充绑定Bind— 从选择器中选中一个颜色变量。填充上会出现一个带变量名称的紫色徽章badge解绑Detach— 点击徽章上的解绑按钮。填充恢复为解析后的颜色值。当变量的值改变或切换模式时所有绑定的填充都会自动更新。绑定在底层写入节点的boundVariables由编辑器统一管理见 packages/core/src/editor/variable-bindings.tsbindVariable(nodeId, path, variableId)设置绑定unbindVariable移除恢复历史快照时会清理指向已不存在变量的陈旧绑定。实用建议用集合分组相关令牌例如 Primitives 存原始颜色、Semantic 存基于角色的别名、Spacing 存布局数值模式适合主题切换——在同一集合中定义 Light 与 Dark 两个模式的值变量支持别名——Semantic 集合可以引用 Primitives 集合的值关于填充与取色器的工作方式可参阅 Drawing Shapes 指南。围绕本文主题可继续在仓库中深入阅读 packages/scene-graph/src/variables.ts模式激活与解析、packages/dom-css/src/tokens/stylesheet.ts样式表与条件生成以及 packages/scene-graph/src/types.ts数据结构定义理解变量从画布编辑到代码交付的完整链路。赞分享前端桌面应用AI 应用MCP 服务【免费下载链接】open-pencilAI-native design editor. Open-source Figma alternative.项目地址https://gitcode.com/gh_mirrors/op/open-pencil点击查看免费下载相关推荐useColorVariableBinding在 OpenPencil 中为填充与描边颜色编辑器接入设计变量绑定useColorVariableBinding在 OpenPencil 中为填充与描边颜色编辑器接入设计变量绑定 useColorVariableBindin前端桌面应用AI 应用MCP 服务OpenPencil 设计变量Variables完全指南集合、模式与 CSS 令牌导出OpenPencil 设计变量Variables完全指南集合、模式与 CSS 令牌导出 OpenPencil 的变量系统是构建可复用设计系统的基础设施把前端桌面应用AI 应用MCP 服务Open-Pencil SDK使用 useColorVariableBinding 将填充与描边颜色绑定到设计变量Open Pencil SDK使用 useColorVariableBinding 将填充与描边颜色绑定到设计变量 useColorVariableBindi前端桌面应用AI 应用MCP 服务上一篇你的Android手机能运行Windows应用吗揭秘突破性的移动计算方案下一篇终极指南四步让旧Mac免费升级最新macOS系统创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考