This Skill corresponds to @opensig/opendesign-token v0.1.1(generated 2026-06), minimum dependency version ≥0.1.1
@opensig/opendesign-token is the design token package of the OpenDesign component library; all tokens use the --o- prefix. If the project uses an earlier version (<0.1.1), some
tokens (such as the seven weight levels, on-demand import, Latin/Chinese split) may not exist—before using the tokens recommended by the Skill, first check the version of this package in the project package.json ; when it is lower than
0.1.1, remind the user to upgrade. To find out in which version a specific token was introduced/changed/removed, check
ReleaseNote。
The component library has six independent themes (openEuler / Ascend / Kunpeng / Mindspore / openGauss / openUBMC), each community project selects one at initialization and does not switch between the six themes at runtime. After a theme is selected, only switching between light/dark mode is needed.
How to use each community theme
Each community project selects a theme at initialization and imports the corresponding theme CSS in the entry file (main.ts). To enable the HarmonyOS font (HarmonyOS Sans SC), import the font CSS after the theme
CSS (@opensig/opendesign-token/fonts/css); see Section 6 "Font Tokens" for details.
openEuler theme (e)
// main.ts 引入(必须在组件样式之前)
import '@opensig/opendesign-token/themes/e.token.css'
Switch light/dark at runtime (set on <html> or <body> ):
document.documentElement.setAttribute('data-o-theme', 'e.light') // 浅色
document.documentElement.setAttribute('data-o-theme', 'e.dark') // 深色
Brand color: Klein Blue (brand blue), use the light shade of the brand color when a control is hovered.
Ascend theme (a)
// main.ts 引入
import '@opensig/opendesign-token/themes/a.token.css'
Switch light/dark at runtime:
document.documentElement.setAttribute('data-o-theme', 'a.light') // 浅色
document.documentElement.setAttribute('data-o-theme', 'a.dark') // 深色
Brand color: Ascend brand color, use a neutral gray tone when a control is hovered.
Kunpeng theme (k)
// main.ts 引入
import '@opensig/opendesign-token/themes/k.token.css'
Switch light/dark at runtime:
document.documentElement.setAttribute('data-o-theme', 'k.light') // 浅色
document.documentElement.setAttribute('data-o-theme', 'k.dark') // 深色
Brand color: Kunpeng brand color, use a neutral gray tone when a control is hovered.
Mindspore theme (m)
// main.ts 引入
import '@opensig/opendesign-token/themes/m.token.css'
Switch light/dark at runtime:
document.documentElement.setAttribute('data-o-theme', 'm.light') // 浅色
document.documentElement.setAttribute('data-o-theme', 'm.dark') // 深色
Brand color: Vivid Blue (vivid blue), use the light shade of the brand blue when a control is hovered.
openGauss theme (g)
// main.ts 引入
import '@opensig/opendesign-token/themes/g.token.css'
Switch light/dark at runtime:
document.documentElement.setAttribute('data-o-theme', 'g.light') // 浅色
document.documentElement.setAttribute('data-o-theme', 'g.dark') // 深色
Brand color: Purple (purple), use the light shade of the brand purple when a control is hovered.
openUBMC theme (u)
// main.ts 引入
import '@opensig/opendesign-token/themes/u.token.css'
Switch light/dark at runtime:
document.documentElement.setAttribute('data-o-theme', 'u.light') // 浅色
document.documentElement.setAttribute('data-o-theme', 'u.dark') // 深色
Brand color: Azure Blue (sky blue), use the light shade of the brand blue when a control is hovered.
Token system architecture
The token names are exactly the sameacross the six themes; only the color values (brand colors, border radii, etc.) differ.
基础 Token(调色板) → 语义 Token(颜色意义) → 组件级 Token
--o-kleinblue-6 → --o-color-primary1 → --btn-color
--o-green-6 → --o-color-success1 → --input-border-color
--o-mixedgray-* → --o-color-info1 → ...
Usage principles:
- Prefer semantic tokens(
--o-color-*、--o-gap-*, etc.), which adapt automatically with light/dark - Do not use palette tokens directly(
--o-kleinblue-*、--o-green-*, etc.), which are internal implementation
Pixso MCP design file → Token mapping guide
When reading design node properties through Pixso MCP, use this section to map Pixso's visual values to the corresponding CSS Tokens, replacing hardcoded values.
Matching process
Pixso 节点属性值(颜色 / 字号 / 间距 / 圆角 / 阴影 / 宽度)
↓
① 识别属性类型 → 查「属性类型速查表」定位到对应章节
↓
② 判断使用响应式 token(--o-r-*)还是静态 token(--o-*)
↓
③ 颜色类:确认是通用功能色(直接反查)还是主题特有色(查 reference)
↓
④ 输出 CSS 变量:var(--o-xxx)
Attribute Type Quick Reference
| Pixso Attribute | Decision Rule | Recommended Token | Reference Section |
|---|---|---|---|
| Fill color | Background color, card/block fill | --o-color-fill* |
Section 1 |
| Fill color | Functional colors (green/orange/red/brand color) | --o-color-success/warning/danger/primary* |
Section 1 |
| Fill color | Brand primary color, Primary — theme-specific | Check the corresponding theme reference | Theme reference |
| Stroke / Border color | Control border | --o-color-control* |
Section 1 |
| Text color | Primary, secondary, and auxiliary text (opacity notation) | --o-color-info1 ~ info4 |
Section 1 |
| Font size | Page title, body text, hint text | --o-r-font_size-*(preferred) |
Section 2 |
| Font size | Fixed font size inside components | --o-font_size-* |
Section 6 |
| Line height | Page-level text | --o-r-line_height-*(preferred) |
Section 2 |
| Padding / Gap | Page blocks, module spacing | --o-r-gap-*(preferred) |
Section 2 |
| Padding / Gap | Fixed spacing inside components | --o-gap-* |
Section 4 |
| Frame width | Multi-column layout, sidebar + main content | --o-r-grid-N(check the pixel comparison table in Section 3 to determine N) |
Section 3 |
| Auto-layout gap | Module horizontal spacing (grid gutter) | --o-r-grid-column-gutter |
Section 3 |
| Corner radius | Card, container corner radius | --o-radius-* |
Section 5 |
| Corner radius | Control corner radius such as buttons and input fields | --o-radius_control-* |
Section 5 |
| Drop shadow | Cards, modals | --o-shadow-* |
Section 7 |
| Reduced opacity (approx. 0.4) | Disabled state | Component disabled prop, not a token |
— |
Color Recognition Priority
Pixso 颜色值
↓
1. 是否为功能色(绿/橙/红)或文字透明度色(rgba 黑/白)?
→ 直接用文末「通用色值反查表」
↓ 否
2. 是否为品牌主色 / Primary / Fill / 圆角?
→ 主题特有,查对应主题 reference 末尾「反查速查表」
↓
3. 替换为 var(--o-xxx)
Artboard Size → Breakpoint Reference
The actual value of a responsive token depends on the breakpoint of the artboard. When reading the Pixso artboard width, use this mapping:
| Pixso Artboard Width | Corresponding Breakpoint | Responsive Token Actual Value Reference Column |
|---|---|---|
| ≤840px | Phone | Phone column in the Section 2 table |
| 841–1200px | Pad | Pad column in the Section 2 table |
| 1201–1680px | Laptop | Laptop column in the Section 2 table |
| >1680px | Desktop | Desktop column in the Section 2 table (= static token value) |
Read font size from Pixso
22pxand the artboard width is 1440px (Laptop breakpoint) → check the Laptop column in Section 2 → choose the closest from the corresponding--o-r-font_size-h3(Laptop: 18px) or--o-r-font_size-display3(Laptop: 32px).
1. Semantic Color Tokens (Recommended)
Primary color palette (Primary)
| Token | Purpose | light example values | dark example values |
|---|---|---|---|
--o-color-primary1 |
Regular primary color | rgb(0, 47, 167) |
rgb(72, 116, 220) |
--o-color-primary2 |
Hover primary color | rgb(81, 119, 202) |
rgb(40, 68, 149) |
--o-color-primary3 |
Active primary color | rgb(0, 39, 147) |
rgb(0, 39, 147) |
--o-color-primary4 |
Disabled primary color | rgb(132, 161, 220) |
rgb(27, 48, 113) |
--o-color-primary1-light |
Primary light color (background) | rgb(190, 206, 237) |
— |
--o-color-primary2-light |
Primary light color (hover background) | rgb(132, 161, 220) |
— |
--o-color-primary3-light |
Primary light color (active background) | rgb(81, 119, 202) |
— |
--o-color-primary4-light |
Primary light color (disabled background) | rgb(227, 234, 246) |
— |
Note: The above color values are examples for the light mode of the openEuler theme. The brand colors of other themes will differ.
Success color (Success)
| Token | Purpose |
|---|---|
--o-color-success1 |
Regular success color (rgb(11, 177, 81) light) |
--o-color-success2 |
Hover success color |
--o-color-success3 |
Active success color |
--o-color-success4 |
Disabled success color |
--o-color-success1-light |
Success light color (background) |
--o-color-success2-light |
Success hover light color |
--o-color-success3-light |
Success active light color |
--o-color-success4-light |
Success disabled light color |
Warning color (Warning)
| Token | Purpose |
|---|---|
--o-color-warning1 |
Regular warning color (rgb(250, 115, 5) light) |
--o-color-warning2 |
Hover warning color |
--o-color-warning3 |
Active warning color |
--o-color-warning4 |
Disabled warning color |
--o-color-warning1-light |
Warning light color (background) |
--o-color-warning2-light ~ --o-color-warning4-light |
Other state light color |
Danger color (Danger)
| Token | Purpose |
|---|---|
--o-color-danger1 |
Regular danger color (rgb(230, 0, 18) light) |
--o-color-danger2 |
Hover danger color |
--o-color-danger3 |
Active danger color |
--o-color-danger4 |
Disabled danger color |
--o-color-danger1-light |
Danger light color (background) |
--o-color-danger2-light ~ --o-color-danger4-light |
Other state light color |
Info color / Text color (Info)
| Token | Purpose | Description |
|---|---|---|
--o-color-info1 |
Primary text | Titles, emphasized text (opaque) |
--o-color-info2 |
Secondary text | Body text (80% opacity) |
--o-color-info3 |
Tertiary text | Auxiliary information (60% opacity) |
--o-color-info4 |
Quaternary text | Disabled/placeholder text (40% opacity) |
--o-color-info1-inverse |
Inverse primary text | White text on dark backgrounds |
--o-color-info2-inverse |
Inverse secondary text | Secondary white text on dark backgrounds |
--o-color-info3-inverse |
Inverse tertiary text | — |
--o-color-info4-inverse |
Inverse quaternary text | — |
Fill color / Background color (Fill)
| Token | Purpose | Description |
|---|---|---|
--o-color-fill1 |
Primary fill | Page background |
--o-color-fill2 |
Secondary fill | Block/card background (most commonly used) |
--o-color-fill3 |
Tertiary fill | Nested card background |
Background color selection rules:
/* 页面背景 */
background-color:
var
(
--o-color-fill1
)
;
/* 卡片/区块背景(最常用) */
background-color:
var
(
--o-color-fill2
)
;
/* 嵌套卡片背景 */
background-color:
var
(
--o-color-fill3
)
;
/* 纯白色(极少使用,特殊场景) */
background-color:
var
(
--o-color-white
)
;
⚠️ Nonexistent token naming—strictly prohibited:
Incorrect usage Correct replacement Description var(--o-color-bg1)var(--o-color-fill2)bg1 does not exist, is not defined in the token CSS, and resolves to transparent var(--o-color-bg2)var(--o-color-fill2)bg2 does not exist, same as above var(--o-color-bg3)var(--o-color-fill3)bg3 does not exist, same as above
bg*Naming is a convention of other design systems (Bootstrap, Element Plus, etc.), opendesign 不推荐使用此命名. Background colors uniformly usefill*。
Control Color (Control)
| Token | Purpose |
|---|---|
--o-color-control1 |
Regular border color (25% opacity) |
--o-color-control2 |
Hover border color (60% opacity) |
--o-color-control3 |
Active border color (80% opacity) |
--o-color-control4 |
Disabled border color (10% opacity) |
--o-color-control1-light |
Regular control background |
--o-color-control2-light |
Hover control background |
--o-color-control3-light |
Active control background |
--o-color-control4-light |
Disabled control background |
--o-color-control-light |
Very light control color (often used for table background) |
Link Color (Link)
| Token | Purpose |
|---|---|
--o-color-link1 |
Regular link color |
--o-color-link2 |
Hover link color |
--o-color-link3 |
Active link color |
--o-color-link4 |
Disabled link color |
Mask Color (Mask)
| Token | Purpose |
|---|---|
--o-color-mask1 |
Global mask (40% transparent) |
--o-color-mask2 |
Local mask (20% transparent) |
Base Color (Base)
| Token | Purpose |
|---|---|
--o-color-white |
Pure white rgb(255, 255, 255)(rarely used directly) |
--o-color-black |
Pure black rgb(0, 0, 0)(rarely used directly) |
2. Responsive Token (Responsive) — Preferred at Page Level
Prefer responsive tokens. For font size, line height, and spacing, responsive variables (
--o-r-*) automatically scale with the viewport and are the first choice for correcting hardcoded values. Static tokens (--o-font_size-*、--o-gap-*) are used only in scenarios that need to remain fixed.
The responsive variable prefix is --o-r-, which takes effect automatically after importing the theme CSS, with no additional import required. There are 4 breakpoints in total:
| Breakpoint | Viewport range | Typical devices |
|---|---|---|
| Phone | ≤840px | Phones, tablets in portrait |
| Pad | 841–1200px | Tablets in landscape |
| Laptop | 1201–1680px | Laptops |
| Desktop | >1680px | Large desktop screens |
Responsive font size + line height
| Semantic | Token name | Phone | Pad | Laptop | Desktop |
|---|---|---|---|---|---|
| Level 1 data display | --o-r-font_size-display1 / line_height |
22/30 | 40/56 | 48/64 | 56/80 |
| Level 2 data display | --o-r-font_size-display2 / line_height |
20/28 | 32/44 | 40/56 | 48/64 |
| Level 3 data display | --o-r-font_size-display3 / line_height |
18/26 | 24/32 | 32/44 | 40/56 |
| Level 1 heading | --o-r-font_size-h1 / line_height |
18/26 | 20/28 | 20/28 | 32/44 |
| Level 2 heading | --o-r-font_size-h2 / line_height |
16/24 | 18/26 | 20/28 | 24/32 |
| Level 3 heading | --o-r-font_size-h3 / line_height |
16/24 | 16/24 | 18/26 | 22/30 |
| Level 4 heading | --o-r-font_size-h4 / line_height |
16/24 | 16/24 | 18/26 | 20/28 |
| Large body text | --o-r-font_size-text2 / line_height |
14/22 | 14/22 | 16/24 | 18/26 |
| Regular body text | --o-r-font_size-text1 / line_height |
14/22 | 14/22 | 14/22 | 16/24 |
| Hint text 1 | --o-r-font_size-tip1 / line_height |
12/18 | 12/18 | 14/22 | 14/22 |
| Hint text 2 | --o-r-font_size-tip2 / line_height |
10/16 | 12/18 | 12/18 | 12/18 |
All units are px. In token names,
font_sizeandline_heightshare suffixes (such as--o-r-font_size-h1with--o-r-line_height-h1)。
Responsive spacing
| Token name | Phone | Pad | Laptop | Desktop |
|---|---|---|---|---|
--o-r-gap-10 |
32px | 40px | 56px | 72px |
--o-r-gap-9 |
24px | 32px | 48px | 64px |
--o-r-gap-8 |
16px | 24px | 40px | 48px |
--o-r-gap-7 |
12px | 16px | 24px | 40px |
--o-r-gap-6 |
12px | 16px | 24px | 32px |
--o-r-gap-5 |
12px | 12px | 16px | 24px |
--o-r-gap-4 |
8px | 8px | 12px | 16px |
--o-r-gap-3 |
8px | 8px | 8px | 12px |
--o-r-gap-2 |
8px | 8px | 8px | 8px |
--o-r-gap-1 |
4px | 4px | 4px | 4px |
Mapping relationship:
--o-r-gap-NDesktop value =--o-gap-N's static value. Responsive variables automatically compress spacing on small screens.
Responsive vs Static Token Selection
| Scenario | Recommended | Reason |
|---|---|---|
| Page titles, body text, section spacing | --o-r-*(responsive) |
Automatically adapts to the viewport, no need to write media queries |
| Fixed sizes inside components (such as 4px spacing next to icons) | --o-gap-*(static) |
The size should not change with the viewport |
| Correction of hardcoded font sizes/spacing in design mockups | --o-r-*(Responsive) |
Preferred, ensuring consistency across multiple platforms |
Referencing font size/line height: ① When font size + line height are output as a pair to the current element, use
font.scssmixin(@include h1;), ensuring pairing and concise invocation; ② When only one item needs to be referenced individually, directly use thevar(--o-r-font_size-*)+var(--o-r-line_height-*)responsive variable. For the mixin's global injection configuration and full usage, see opendesign-application skill → styles-infrastructure Section 4.
3. Grid System Token (Grid) — Page-level module layout
The grid system is used for page-level layout, and is the core configuration form for controlling the width and spacing of each page module in the horizontal direction (X axis). Multi-column layouts, sidebar + main content area, and horizontal divisions between modules should all preferentially use grid variables rather than manually hardcoding width or padding.
24-column responsive grid, 6 breakpoints in total. Takes effect automatically after importing the theme CSS.
| Breakpoint | Viewport range | Columns | Gutter (one side) | Water sink |
|---|---|---|---|---|
| Extra-large screen | >1920px | 24 | 64px | 32px |
| Desktop | 1441–1920px | 24 | 64px | 32px |
| Small desktop | 1201–1440px | 24 | 40px | 24px |
| Tablet landscape | 841–1200px | 12 | 32px | 16px |
| Tablet portrait | 601–840px | 8 | 32px | 16px |
| Mobile | ≤600px | 4 | 24px | 12px |
Key variables:--o-r-grid-1 ~ --o-r-grid-24(N-column width),--o-r-grid-column-gutter(water sink width),--o-r-grid-full(full grid width),
--o-r-grid-padding(grid outer gutter),--o-r-grid-section-width(floor width),--o-r-grid-section-padding(distance from floor edge to viewport edge).
Grid container: directly use the .o-r-grid-container class (
display:flex; max-width:1920px; margin:0 auto; padding:var(--o-r-grid-padding))。
/* 使用栅格列宽变量 */
.column-6 {
width: var(--o-r-grid-6);
}
.column-8 {
width: var(--o-r-grid-8);
}
.column-12 {
width: var(--o-r-grid-12);
}
/* 并排元素间距使用水槽 */
.row {
display: flex;
gap: 0 var(--o-r-grid-column-gutter);
}
Pixso artboard → grid-N pixel reference table
After reading the frame width from Pixso, find the closest value in the row for the corresponding artboard width to determine which
--o-r-grid-N。
Column width formula:col = (画板宽 - 2×留白 - (最大列数-1)×水槽) / 最大列数
grid-N width:grid-N = N × col + (N-1) × 水槽
| Artboard width | Breakpoint | col | Water sink | grid-4 | grid-6 | grid-8 | grid-12 | grid-16 | grid-18 |
|---|---|---|---|---|---|---|---|---|---|
| 1920px | Extra-large screen | 44px | 32px | 272px | 424px | 576px | 880px | 1184px | 1336px |
| 1680px | Desktop | 34px | 32px | 232px | 364px | 496px | 760px | 1024px | 1156px |
| 1440px | Small desktop | ~33.7px | 24px | ~207px | ~322px | ~437px | ~668px | ~899px | ~1014px |
| 1200px | Tablet landscape | 80px | 16px | 368px | 560px | 752px | 1136px | (exceeds 12 columns) | (exceeds 12 columns) |
| 840px | Tablet portrait | 83px | 16px | 380px | 578px | 776px | (exceeds 8 columns) | — | — |
| 375px | Mobile | ~72.75px | 12px | 327px | (exceeds 4 columns) | — | — | — | — |
Note: Tablet landscape supports at most 12 columns, and any excess equals the full width (grid-12 value); tablet portrait supports at most 8 columns; mobile supports at most 4 columns.
Water sink separation principle (core rule)
The spacing between adjacent large blocks in the X-axis direction (Card, floor section, content module, etc.) is fixed at 1 water sink(--o-r-grid-column-gutter), without using gap
token.
Column allocation constraint: The sum of the columns of N side-by-side blocks = the total number of columns at the current breakpoint.
grid-N₁ + gutter + grid-N₂ + gutter + ... + grid-Nₙ = 内容区全宽
即:N₁ + N₂ + ... + Nₙ = 总列数(24 / 12 / 8 / 4,取决于断点)
Equal-width N blocks: columns per block = total columns ÷ N
| Number of side-by-side blocks | Extra-large screen/Desktop/Small desktop (24 columns) | Tablet landscape (12 columns) | Tablet portrait (8 columns) | Mobile (4 columns) |
|---|---|---|---|---|
| 2 equal-width blocks | grid-12 + grid-12 | grid-6 + grid-6 | grid-4 + grid-4 | grid-2 + grid-2 |
| 3 equal-width blocks | grid-8 × 3 | grid-4 × 3 | — (not divisible) | — |
| 4 equal-width blocks | grid-6 × 4 | grid-3 × 4 | grid-2 × 4 | — |
| 6 equal-width blocks | grid-4 × 6 | grid-2 × 6 | — | — |
Floor Grid Adaptation Specification
The width of a floor (overall page block) should be centered, with appropriate blank space on both sides. The following variables are predefined in the token package and do not need to be created manually:
| Variable name | Purpose |
|---|---|
--o-r-grid-section-width |
Floor width |
--o-r-grid-section-padding |
Total distance from the viewport edge to the floor edge |
Width rules for each breakpoint:
| Breakpoint | Floor width | Number of blank grid columns on one side |
|---|---|---|
| >1680px | var(--o-r-grid-20) |
2 columns |
| 1201–1680px | var(--o-r-grid-22) |
1 column |
| ≤1200px | var(--o-r-grid-full) |
0 columns (full width) |
Usage:
.floor {
width: var(--o-r-grid-section-width);
margin: 0 auto;
}
Layout diagram:
|<-- section-padding -->|<--- section-width --->|<-- section-padding -->|
Desktop (>1680px): grid-padding + 2×(col+gutter) | grid-20 | ...
Laptop (1201-1680px): grid-padding + 1×(col+gutter) | grid-22 | ...
Pad及以下 (≤1200px): grid-padding | grid-full | grid-padding
Steps to determine grid-N from the Pixso frame width
① 读取 Pixso 画板宽度 → 确定断点行
② 读取 frame.width
③ 在对照表中找最接近的列值 → 得到 N
(误差在 ±5px 以内可认为是同一列,因设计工具精度或子像素造成)
④ 若 frame 占满内容区(全宽减两侧留白)→ 使用 .o-r-grid-container 包裹即可,无需 grid-N
⑤ 代入:width: var(--o-r-grid-N)
Example: Pixso artboard 1440px, frame width 322px → look up the table "1440px row, grid-6 ≈ 322px" → use width: var(--o-r-grid-6)。
Form component grid rules
In multi-column form layouts, the width of each form item in OForm and input-type components (OInput, OSelect, OTextarea, etc.) should align to grid columns, and row spacing should follow the design specification values.
Multi-column forms: number of items per row and column width allocation
| Breakpoint | Total columns | Items per row | Width Token per item | Label position |
|---|---|---|---|---|
| Desktop >1680px | 24 | 4 items/row | --o-r-grid-6 |
Left-aligned horizontal |
| Laptop 1201–1680px | 24 | 4 items/row | --o-r-grid-6 |
Left-aligned horizontal |
| Pad 841–1200px | 12 | 3 items/row | --o-r-grid-4 |
Left-aligned horizontal |
| Phone ≤840px | 4 | 1 items/row | Full width | Top-aligned stacked |
Verify(Desktop, 4 items × grid-6): 4×grid-6 + 3×gutter = 4×424 + 3×32 = 1696 + 96 = 1792px = 24-column content area ✓ Verify(Tablet landscape, 3 items × grid-4): 3×grid-4 + 2×gutter = 3×368 + 2×16 = 1104 + 32 = 1136px = 12-column content area (1200px artboard) ✓
Row spacing (vertical direction of form item)
| Breakpoint | Spacing between form items per row |
|---|---|
| >840px (horizontal labels) | 32px |
| ≤840px (stacked labels) | 12px |
Label width and internal spacing
| Area | >840px (PC horizontal mode) | ≤840px (mobile stacked mode) |
|---|---|---|
| Label area width | Fixed 96px | Full width (100%) |
| Spacing from label to input box | 4px(spacing from label text to colon) |
8px(from label text to input box) |
| Hint/help text position | Right side of the input box, with 24px | Below the input box, spacing 12px |
Grouping constraints
- In multi-column forms, a single form group (section) is recommended to contain 2–7 form items
- Wide items that span the full row (textareas, file uploads, etc.) occupy a row by themselves (width = full container width)
- The sum of the columns of side-by-side items must equal the total number of columns at the current breakpoint (same as the "gutter separation principle")
Example: Desktop 4-column form layout (>1200px)
/* 每个 form item 宽度 = grid-6 */
.form-item {
width: var(--o-r-grid-6);
}
/* 多列 form 行容器:flex + gutter 间距 */
.form-row {
display: flex;
flex-wrap: wrap;
gap: 32px var(--o-r-grid-column-gutter);
/* ↑ row-gap=32px(PC),column-gap=水槽 */
}
/* 平板横屏(841-1200px):3 列,每项 grid-4 */
@media (max-width: 1200px) {
.form-item { width: var(--o-r-grid-4); }
.form-row { gap: 12px var(--o-r-grid-column-gutter); }
}
/* 手机(≤840px):1 列,全宽 */
@media (max-width: 840px) {
.form-item { width: 100%; }
.form-row { gap: 12px 0; }
}
4. Spacing Token (Gap) — static values
For page-level spacing, it is recommended to use responsive tokens
--o-r-gap-*(see Section 2). The following static tokens apply to fixed spacing scenarios that do not change with the viewport.
Spacing tokens apply to gap、padding、margin and other properties.
| Token | Value | Usage |
|---|---|---|
--o-gap-1 |
4px |
Minimum spacing (inside compact elements) |
--o-gap-2 |
8px |
Small spacing (elements inside a component) |
--o-gap-3 |
12px |
Small to medium spacing (between related elements) |
--o-gap-4 |
16px |
Regular spacing (default, most commonly used) |
--o-gap-5 |
24px |
Medium spacing (between blocks) |
--o-gap-6 |
32px |
Large spacing (page-level layout) |
--o-gap-7 |
40px |
Larger spacing |
--o-gap-8 |
48px |
Very large spacing |
--o-gap-9 |
64px |
Extra-large spacing |
--o-gap-10 |
72px |
Maximum spacing |
5. Radius Token (Radius)
⚠️ Radius values vary by theme: The following
值column contains general reference values; actual values depend on the theme. For example, in the openEuler theme all radii are 4px(close to a square-corner style), while the Mindspore theme is more rounded. When using them, please refer to the radius table in the corresponding theme reference file. There are also no radius variables with the--o-r-radius-1and similarr-prefix; radius tokens have no responsive variants.
Content radius (used for cards, containers, etc.)
| Token | General reference value | Usage |
|---|---|---|
--o-radius-xs |
4px |
Extra-small radius |
--o-radius-s |
8px |
Small radius |
--o-radius-m |
12px |
Medium radius |
--o-radius-l |
16px |
Large radius |
--o-radius-xl |
24px |
Extra-large radius (generally used for cards) |
Control radius (used for components such as buttons and input fields)
| Token | General reference value | Usage |
|---|---|---|
--o-radius_control-xs |
4px |
Extra-small control radius |
--o-radius_control-s |
8px |
Small control radius |
--o-radius_control-m |
12px |
Medium control radius |
--o-radius_control-l |
16px |
Large control radius |
6. Font Token (Font)
For page-level text, it is recommended to use responsive tokens
--o-r-font_size-*/--o-r-line_height-*(see Section 2). The following static tokens apply to fixed font size scenarios that do not change with the viewport.
Font Family — HarmonyOS font
OpenDesign uses HarmonyOS Sans SC(HarmonyOS Sans SC) as the Chinese font family by default, and HarmonyOS Sans as the Latin font family. The font files are released with the
@opensig/opendesign-token package. After they are explicitly imported in the entry file,--o-font_family will actually point to the HarmonyOS font.
⚠️ 0.1.1 Breaking change:
@font-faceThe font family registered by"HarmonyOS"/HarmonyOS-Hanshas been renamed from the old'HarmonyOS Sans SC'to'HarmonyOS Sans'(Chinese) and'HarmonyOS Sans SC', or use the variable directlyvar(--o-font_family)(recommended).- In the old version, after importing the font files,
bodywas automatically applied tovar(--o-font_family); this version no longer applies it automatically, and only registers@font-face. After upgrading, you need to set the font yourself on the root container::root { font-family: var(--o-font_family); }--o-font_weight-boldchanged from600to700(corresponding to theSansSC_Boldfont file); the old600now has an independent--o-font_weight-semiboldvariable corresponding to it. Designers usually use semibold (600) for bold, so please confirm that the bold effect meets expectations.
// main.ts(在主题 CSS 之后引入)
import '@opensig/opendesign-token/themes/e.token.css' // 主题 CSS
import '@opensig/opendesign-token/fonts/css' // 鸿蒙字体(仅注册 @font-face,不自动应用)
If you need only a single weight, you can import on demand to reduce size (
sc-is for Chinese fonts,sans-is for Latin fonts; Chinese has no italic source files, so there are only 7 non-italic directories):// 仅引入中文常规字重(400) import '@opensig/opendesign-token/fonts/sc-regular/font.min.css' // 仅引入拉丁常规字重(400) import '@opensig/opendesign-token/fonts/sans-regular/font.min.css'
| Token | Value | Description |
|---|---|---|
--o-font_family |
'HarmonyOS Sans', 'HarmonyOS Sans SC', Inter, -apple-system, BlinkMacSystemFont, 'PingFang SC', 'Microsoft YaHei', Arial, sans-serif |
Default font family |
--o-font_family-code |
SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', monospace |
Monospace code font family |
Automatic font family fallthrough:
--o-font_familyplaces'HarmonyOS Sans'(Latin family) before'HarmonyOS Sans SC'(Chinese family). The browser matches family by family: Latin characters hit'HarmonyOS Sans'(including an independent italic face,font-style: italiccan directly render true italic); Chinese characters have no corresponding glyph in the'HarmonyOS Sans'font file (that font contains only Latin glyphs), so the browser automatically falls through to the next family'HarmonyOS Sans SC'. Chinese has no source-file italic,font-style: italicwill synthesize a faux italic.
Font Application and Loading
After importing the font CSS, only @font-face registration is completed, it will not be automatically applied to any element. You need to manually apply the font variables on the root container:
/* 全局应用鸿蒙字体(推荐在根容器设置) */
:root {
font-family: var(--o-font_family);
}
code, pre {
font-family: var(--o-font_family-code);
}
⚠️ Setting only
font-family: var(--o-font_family)will not automatically load the font files; you must import them in the entry fileimport '@opensig/opendesign-token/fonts/css'. Chinese fonts (HarmonyOS Sans SC) are split byunicode-range, and only the characters actually used are loaded on demand; Latin fonts (HarmonyOS Sans) are not split, but the file size is small (~28KB/weight), so loading them as a whole on demand has little impact.
Font Weight
HarmonyOS Sans has a total of seven weights, corresponding one-to-one with the seven faces registered by @font-face (the CSS font-weight numeric values match the faces exactly, so no nearest matching is needed).
| Token | Value | Description |
|---|---|---|
--o-font_weight-thin |
250 |
Thin |
--o-font_weight-light |
300 |
Light |
--o-font_weight-regular |
400 |
Regular |
--o-font_weight-medium |
500 |
Medium |
--o-font_weight-semibold |
600 |
SemiBold (headings, emphasis) |
--o-font_weight-bold |
700 |
Bold |
--o-font_weight-black |
900 |
Black |
In actual development: daily use mainly relies on the two weights
--o-font_weight-regular(400) and--o-font_weight-semibold(600); the former is used for body text, and the latter is used for scenarios such as headings and emphasis.
.title {
font-family: var(--o-font_family);
font-weight: var(--o-font_weight-semibold); /* 600,标题加粗 */
}
Font Size
| Token | Value | Purpose |
|---|---|---|
--o-font_size-display1 |
56px |
Level 1 data display |
--o-font_size-display2 |
48px |
Level 2 data display |
--o-font_size-display3 |
40px |
Level 3 data display |
--o-font_size-h1 |
32px |
Level 1 heading |
--o-font_size-h2 |
24px |
Level 2 heading |
--o-font_size-h3 |
22px |
Level 3 heading |
--o-font_size-h4 |
20px |
Level 4 heading |
--o-font_size-text2 |
18px |
Large body text |
--o-font_size-text1 |
16px |
Regular body text (most commonly used) |
--o-font_size-tip1 |
14px |
Hint text (small text) |
--o-font_size-tip2 |
12px |
Auxiliary hint text (smallest) |
Line Height
| Token | Value | Matching font size |
|---|---|---|
--o-line_height-display1 |
80px |
display1 |
--o-line_height-display2 |
64px |
display2 |
--o-line_height-display3 |
56px |
display3 |
--o-line_height-h1 |
44px |
h1 |
--o-line_height-h2 |
32px |
h2 |
--o-line_height-h3 |
30px |
h3 |
--o-line_height-h4 |
28px |
h4 |
--o-line_height-text2 |
26px |
text2 |
--o-line_height-text1 |
24px |
text1 |
--o-line_height-tip1 |
22px |
tip1 |
--o-line_height-tip2 |
18px |
tip2 |
Font and line height should be used together:
/* 响应式(推荐,自动适配多端) */
.title {
font-size: var(--o-r-font_size-h3);
line-height: var(--o-r-line_height-h3);
}
/* 需要字号 + 行高成对输出时,可用 font.scss mixin */
/* 全局注入配置与完整用法见 opendesign-application skill → styles-infrastructure §4 */
.title {
@include h3;
}
/* 静态(仅在需要固定值时使用) */
.fixed-label {
font-size: var(--o-font_size-tip1);
line-height: var(--o-line_height-tip1);
}
7. Shadow Token (Shadow)
| Token | Value | Purpose |
|---|---|---|
--o-shadow-1 |
0 3px 8px rgba(..., 0.08) |
Card, small popup, floor shadow |
--o-shadow-2 |
0 2px 24px rgba(..., 0.15) |
Card hover shadow |
--o-shadow-3 |
0 8px 40px rgba(..., 0.1) |
Large popup, drawer shadow |
8. Animation Token (Animation)
Duration
| Token | Value | Purpose |
|---|---|---|
--o-duration-s |
200ms |
Exit-screen animation |
--o-duration-m1 |
250ms |
standard-in curve enter animation |
--o-duration-m2 |
300ms |
standard curve start/end animation |
--o-duration-m3 |
400ms |
emphasized-in curve enter animation |
--o-duration-l |
500ms |
emphasized curve start/end animation |
--o-duration-xl |
1000ms |
carousel transition animation |
Easing curve (Easing)
| Token | Value | Usage |
|---|---|---|
--o-easing-linear |
cubic-bezier(0, 0, 1, 1) |
Linear |
--o-easing-standard |
cubic-bezier(0.2, 0, 0, 1) |
Standard (component animation,recommended) |
--o-easing-standard-in |
cubic-bezier(0, 0, 0, 1) |
Standard enter |
--o-easing-standard-out |
cubic-bezier(0.3, 0, 1, 1) |
Standard exit |
--o-easing-emphasized |
cubic-bezier(0.2, 0, 0, 1) |
Emphasized (large cards/scene transitions) |
--o-easing-emphasized-in |
cubic-bezier(0.3, 0, 0.8, 0.15) |
Emphasized enter |
--o-easing-emphasized-out |
cubic-bezier(0.05, 0.7, 0.1, 1) |
Emphasized exit |
/* 推荐的动画写法 */
transition: all
var
(
--o-duration-m1
)
var
(
--o-easing-standard
)
;
9. Component Size Token (Control Size)
| Token | Value | Usage |
|---|---|---|
--o-control_size-2xs |
14px |
Extra extra small control |
--o-control_size-xs |
16px |
Extra small control |
--o-control_size-s |
24px |
Small control |
--o-control_size-m |
32px |
Medium control |
--o-control_size-l |
40px |
Large control |
--o-control_size-xl |
48px |
Extra large control |
--o-control_size-2xl |
56px |
Extra extra large control |
10. Icon Size Token (Icon Size)
Standalone icon
| Token | Value |
|---|---|
--o-icon_size-xs |
16px |
--o-icon_size-s |
20px |
--o-icon_size-m |
24px |
--o-icon_size-l |
32px |
--o-icon_size-xl |
40px |
--o-icon_size-2xl |
48px |
--o-icon_size-3xl |
56px |
--o-icon_size-4xl |
64px |
Icon within control (used by components)
| Token | Value |
|---|---|
--o-icon_size_control-xs |
16px |
--o-icon_size_control-s |
20px |
--o-icon_size_control-m |
24px |
--o-icon_size_control-l |
32px |
--o-icon_size_control-xl |
40px |
11. Palette Token (reference, not recommended for direct use)
Palette tokens are raw color values that provide the foundation for semantic tokens, and should not be used directly in business code。
Each color family has 10 shades (1=lightest, 10=darkest); colors are inverted between light/dark modes.
| Color family | Token prefix | Primary color representative | Usage |
|---|---|---|---|
| Brand blue | --o-kleinblue-* |
#002FA7 |
Primary/link color |
| Green | --o-green-* |
#0BB151 |
Success color |
| Orange-red | --o-orange-* |
#FA7305 |
Warning color |
| Red | --o-red-* |
#E60012 |
Danger color |
| Yellow | --o-yellow-* |
#F0BC06 |
Auxiliary color |
| Amber | --o-amber-* |
#E78900 |
Auxiliary color |
| Yellow-green | --o-lime-* |
#A7C900 |
Auxiliary color |
| Light green | --o-light-green-* |
#70B31B |
Auxiliary color |
| Teal | --o-teal-* |
#00B385 |
Auxiliary color |
| Cyan | --o-cyan-* |
#00A7B3 |
Auxiliary color |
| Light blue | --o-light-blue-* |
#009CE5 |
Auxiliary color |
| Blue | --o-blue-* |
#1075E8 |
Auxiliary color |
| Violet | --o-violet-* |
#5E12CB |
Auxiliary color |
| Purple | --o-purple-* |
#8702B3 |
Auxiliary color |
| Pink | --o-pink-* |
#E00070 |
Auxiliary color |
| White | --o-white |
#FFFFFF |
Base |
| Black | --o-black |
#000000 |
Base |
Best practices
OpenDesign component style principles
When using @opensig/opendesign components from the component library, components should be used as a whole, and the internal styles of components should not be modified(unless there is a clear special requirement and it has been confirmed). The visual presentation of components is uniformly controlled by the
Token system:
- Change the component's brand color and corner radius style by switching themes (
data-o-theme) - Control size, color variants, etc. through the props exposed by the component
- Do notoverride the component's internal class styles through CSS (such as
.o-btn__text) - Do notmodify the component's internal structure through
::v-deep/:deep()penetration
Token variables are mainly used to customize business areas' styles (such as page layout, custom cards, business containers, etc.), rather than overriding the component's internals.
✅ Recommended practice
⚠️ Border rules: Only add a border when the design draft DSL has a
strokesproperty; never add a border to cards/containers by default. If the design draft has no stroke, do not write itborder。
.card {
background-color: var(--o-color-fill2); /* 卡片背景 */
/* ⚠️ border 只有在 DSL strokes 非空时才加 */
/* border: 1px solid var(--o-color-control1); */
border-radius: var(--o-radius-m); /* 圆角 */
padding: var(--o-r-gap-4); /* 内边距(响应式) */
box-shadow: var(--o-shadow-1); /* 阴影(有 DSL effects 时才加) */
}
.title {
font-size: var(--o-r-font_size-h3); /* 响应式字号 */
line-height: var(--o-r-line_height-h3); /* 响应式行高 */
color: var(--o-color-info1); /* 标题文字 */
}
.body-text {
font-size: var(--o-r-font_size-text1); /* 响应式字号 */
line-height: var(--o-r-line_height-text1); /* 响应式行高 */
color: var(--o-color-info2); /* 正文 */
}
.section-gap {
padding: var(--o-r-gap-6) var(--o-r-gap-4); /* 响应式间距 */
}
.caption {
font-size: var(--o-r-font_size-tip1);
color: var(--o-color-info3); /* 辅助信息 */
}
.button:hover {
transition: all var(--o-duration-m1) var(--o-easing-standard);
box-shadow: var(--o-shadow-2);
}
.link {
color: var(--o-color-link1);
}
.link:hover {
color: var(--o-color-link2);
}
❌ Not recommended
/* 不要使用调色板 token */
.card {
background-color: rgb(var(--o-white)); /* ❌ 应使用 var(--o-color-fill2) */
border: 1px solid rgb(var(--o-grey-5)); /* ❌ 应使用 var(--o-color-control1) */
}
/* 不要硬编码字号/间距——应使用响应式 token */
.title {
font-size: 22px; /* ❌ 应使用 var(--o-r-font_size-h3) */
line-height: 30px; /* ❌ 应使用 var(--o-r-line_height-h3) */
}
.card {
padding: 16px; /* ❌ 应使用 var(--o-r-gap-4) */
border-radius: 12px; /* ❌ 应使用 var(--o-radius-m) */
box-shadow: 0 3px 8px rgba(0, 0, 0, 0.08); /* ❌ 应使用 var(--o-shadow-1) */
}
.section {
gap: 32px; /* ❌ 应使用 var(--o-r-gap-6) */
}
/* 不要用静态 token 代替响应式 token(除非确实需要固定值) */
.page-title {
font-size: var(--o-font_size-h1); /* ⚠️ 应使用 var(--o-r-font_size-h1),自动适配多端 */
}
Usage scenarios quick reference
Background color
| Scenario | Token |
|---|---|
| Page background | --o-color-fill1 |
| Card/block background | --o-color-fill2(Most commonly used) |
| Nested card | --o-color-fill3 |
| Pure white (special) | --o-color-white |
Text color
| Scenario | Token |
|---|---|
| Title/emphasis | --o-color-info1 |
| Body text | --o-color-info2 |
| Auxiliary information | --o-color-info3 |
| Disabled/placeholder | --o-color-info4 |
| White text on dark background | --o-color-info1-inverse |
Border color
| Scenario | Token |
|---|---|
| Default border | --o-color-control1 |
| Hover border | --o-color-control2 |
| Active/focus border | --o-color-primary1 or --o-color-control3 |
| Disabled border | --o-color-control4 |
Spacing
For page-level spacing, prefer responsive token
--o-r-gap-*; for fixed spacing inside components, use static--o-gap-*。
| Scenario | Token (responsive preferred) | Desktop value |
|---|---|---|
| Icon-to-text spacing | --o-r-gap-1 / --o-gap-1 |
4px |
| Component internal elements | --o-r-gap-2 / --o-gap-2 |
8px |
| Between related elements | --o-r-gap-3 |
12px |
| Default padding | --o-r-gap-4 |
16px |
| Block spacing | --o-r-gap-5 |
24px |
| Page layout | --o-r-gap-6 |
32px |
Font size
For font size and line height, prefer responsive token
--o-r-font_size-*/--o-r-line_height-*。
| Scenario | Token (responsive preferred) | Desktop value |
|---|---|---|
| Page large title | --o-r-font_size-h1 + --o-r-line_height-h1 |
32/44px |
| Block title | --o-r-font_size-h3 + --o-r-line_height-h3 |
22/30px |
| Body text | --o-r-font_size-text1 + --o-r-line_height-text1 |
16/24px |
| Auxiliary/hint | --o-r-font_size-tip1 + --o-r-line_height-tip1 |
14/22px |
Color value reverse lookup (hard-coded color value in design draft → Token)
The design draft may contain hard-coded color values (such as #002FA7、rgba(0,0,0,0.25)), which need to be reverse-matched to the corresponding CSS variable.
Operation process
1. 确认截取色值时的模式(light / dark)
2. 确认项目使用的主题(e / a / k / m / g / u)
3. 用 CLI 自动反查:node scripts/bin.mjs convert '#XXX' -t <主题> -m <模式>
或在下方通用表 / 对应主题 reference 中手动查找
4. 将写死的值替换为 var(--o-xxx)
5. 字号/行高/间距优先替换为响应式 token var(--o-r-xxx)
CLI
convertcommand dynamically builds the reverse table from the CSS output of@opensig/opendesign-token. The matching result is always in sync with the actual package version, with no need to maintain a static mapping table. The table below is an offline quick-reference.
Note: The same token corresponds to different color values in light and dark modes, so make sure to match the correct mode.
General color value reverse lookup (same across all six themes)
The color values of the following tokens are exactly the sameacross all six themes, so they can be reverse-looked up directly.
Functional colors (Light mode)
| Hex | RGB | Token | Semantic |
|---|---|---|---|
#0BB151 |
rgb(11, 177, 81) |
--o-color-success1 |
Success color |
#54D07F |
rgb(84, 208, 127) |
--o-color-success2 |
Success hover |
#07984A |
rgb(7, 152, 72) |
--o-color-success3 |
Success active |
#80E09E |
rgb(128, 224, 158) |
--o-color-success4 |
Success disabled |
#B1EFC3 |
rgb(177, 239, 195) |
--o-color-success1-light |
Success light background |
#FA7305 |
rgb(250, 115, 5) |
--o-color-warning1 |
Warning color |
#FCB05F |
rgb(252, 176, 95) |
--o-color-warning2 |
Warning hover |
#CF5803 |
rgb(207, 88, 3) |
--o-color-warning3 |
Warning active |
#FDCA8C |
rgb(253, 202, 140) |
--o-color-warning4 |
Warning disabled |
#FEE2BA |
rgb(254, 226, 186) |
--o-color-warning1-light |
Warning light background |
#E60012 |
rgb(230, 0, 18) |
--o-color-danger1 |
Danger color |
#F0575A |
rgb(240, 87, 90) |
--o-color-danger2 |
Danger hover |
#C00016 |
rgb(192, 0, 22) |
--o-color-danger3 |
Danger active |
#F58886 |
rgb(245, 136, 134) |
--o-color-danger4 |
Danger disabled |
#FAB9B6 |
rgb(250, 185, 182) |
--o-color-danger1-light |
Danger light background |
Text color (opacity notation, Light mode)
| Common notation in design files | Token | Semantics |
|---|---|---|
rgba(0,0,0,1) or #000000 |
--o-color-info1 |
Primary text/heading |
rgba(0,0,0,0.8) or #000000 80% |
--o-color-info2 |
Secondary text/body |
rgba(0,0,0,0.6) or #000000 60% |
--o-color-info3 |
Tertiary text/auxiliary |
rgba(0,0,0,0.4) or #000000 40% |
--o-color-info4 |
Quaternary text/disabled |
rgba(255,255,255,1) |
--o-color-info1-inverse |
White text on dark background |
rgba(255,255,255,0.8) |
--o-color-info2-inverse |
Secondary white text on dark background |
Mask and border (Light mode)
| Common notation in design files | Token | Semantics |
|---|---|---|
rgba(0,0,0,0.4) |
--o-color-mask1 |
Global mask |
rgba(255,255,255,0.2) |
--o-color-mask2 |
Local mask |
rgba(0,0,0,0.25) |
--o-color-control1 |
Default border |
rgba(0,0,0,0.1) |
--o-color-control4 |
Disabled border |
Spacing (identical across all six themes)
Hardcoded spacing should preferentially be replaced with responsive tokens
--o-r-gap-*。
| Hardcoded value | Responsive Token (recommended) | Static Token |
|---|---|---|
4px |
--o-r-gap-1 |
--o-gap-1 |
8px |
--o-r-gap-2 |
--o-gap-2 |
12px |
--o-r-gap-3 |
--o-gap-3 |
16px |
--o-r-gap-4 |
--o-gap-4 |
24px |
--o-r-gap-5 |
--o-gap-5 |
32px |
--o-r-gap-6 |
--o-gap-6 |
40px |
--o-r-gap-7 |
--o-gap-7 |
48px |
--o-r-gap-8 |
--o-gap-8 |
64px |
--o-r-gap-9 |
--o-gap-9 |
72px |
--o-r-gap-10 |
--o-gap-10 |
Note: The hardcoded values in the table above correspond to the responsive values at the Desktop breakpoint (>1680px). On small screens, responsive tokens will automatically scale down.
Font size / line height (identical across all six themes)
Hardcoded font sizes should preferentially be replaced with responsive tokens
--o-r-font_size-*+--o-r-line_height-*。
| Hardcoded font-size | Responsive Token (recommended) | Static Token |
|---|---|---|
56px |
--o-r-font_size-display1 |
--o-font_size-display1 |
48px |
--o-r-font_size-display2 |
--o-font_size-display2 |
40px |
--o-r-font_size-display3 |
--o-font_size-display3 |
32px |
--o-r-font_size-h1 |
--o-font_size-h1 |
24px |
--o-r-font_size-h2 |
--o-font_size-h2 |
22px |
--o-r-font_size-h3 |
--o-font_size-h3 |
20px |
--o-r-font_size-h4 |
--o-font_size-h4 |
18px |
--o-r-font_size-text2 |
--o-font_size-text2 |
16px |
--o-r-font_size-text1 |
--o-font_size-text1 |
14px |
--o-r-font_size-tip1 |
--o-font_size-tip1 |
12px |
--o-r-font_size-tip2 |
--o-font_size-tip2 |
Theme-specific color value reverse lookup
Brand colors, Primary colors, Fill colors, border radius, etc. vary by theme. Please refer to the corresponding reference file:
- openEuler (e):references/tokens-openeuler.md → "Reverse Lookup Quick Reference" at the end
- Ascend (a):references/tokens-ascend.md → "Reverse Lookup Quick Reference" at the end
- Kunpeng (k):references/tokens-kunpeng.md → "Reverse Lookup Quick Reference" at the end
- Mindspore (m):references/tokens-mindspore.md → "Reverse Lookup Quick Reference" at the end
- openGauss (g):references/tokens-opengauss.md → "Reverse Lookup Quick Reference" at the end
- openUBMC (u):references/tokens-openubmc.md → "Reverse Lookup Quick Reference" at the end
Token CLI (validation + reverse lookup)
Check here before writing code: This repository includes a zero-dependency Node.js CLI for verifying the
var(--o-*)variables used in code actually exist in the@opensig/opendesign-tokenpackage, and for reverse-matching hex/rgb color values, px/ms dimensions, etc. from design files to the corresponding tokens. After generating OpenDesign-related code with a large model, it is strongly recommended to scan it with this tool to remove fabricated variable names(e.g., mistakenly writing--o-color-fill2as--o-color-bg2, or--o-r-font_size-h4as--o-r-font_size-h5)。
Why validation is needed
OpenDesign's token naming follows its own conventions and is inconsistent:
| Common mistakes (fabricated) | Reason it does not actually exist | Correct replacement |
|---|---|---|
--o-color-bg1 / --o-color-bg2 / --o-color-bg3 |
opendesign uses fill , not bg |
--o-color-fill1 / fill2 / fill3 |
--o-color-border1 |
Borders use control , not border |
--o-color-control1 |
--o-r-font_size-h5 / --o-r-font_size-h6 |
Responsive headings only have h1–h4 | --o-r-font_size-h4 |
--o-color-text1 / --o-color-text2 |
Text uses info , not text |
--o-color-info1 / info2 |
--o-radius-medium / --o-radius-large |
Border radius uses size abbreviations (xs/s/m/l/xl) | --o-radius-m / --o-radius-l |
--o-color-primary5 |
Primary colors only have levels 1–4 | --o-color-primary4 |
--o-r-gap-11 / --o-r-gap-12 |
Responsive spacing only has levels 1–10 | --o-r-gap-10 |
These erroneous variable names will be parsed in CSS as transparent / 0 / initial, causing styles to silently fail, which is very hard to troubleshoot.
CLI location
skills/opendesign-tokens/scripts/
├── bin.mjs ← 统一入口(所有命令)
├── check-tokens.mjs ← 向后兼容入口(等价于 bin.mjs)
├── lib/
│ ├── package-resolver.mjs ← npm 包解析 + 下载 + 缓存
│ ├── registry.mjs ← CSS 解析 + token 注册表
│ ├── lookup.mjs ← token 查找 + 归一化 + 建议
│ ├── convert.mjs ← 值→token 反向映射(动态构建)
│ ├── file-scan.mjs ← 文件扫描
│ └── shared.mjs ← 注册表单例 + 输出格式化
└── package.json
Zero external dependencies (only Node.js ≥ 18 built-in modules); on first run, downloads from the npm registry @opensig/opendesign-token tarball and caches it to
~/.cache/opendesign-token-cache/(Windows: %LOCALAPPDATA%/opendesign-token-cache/), and subsequent runs use the cache directly.
The two entry files are equivalent—check-tokens.mjs is backward compatible with the old invocation method,bin.mjs is the unified entry point (including convert and other new commands).
Source of truth: CSS artifacts, not JSON source
CLI Using themes/*.css artifacts as the sole source of truth—variable existence, values, and responsive values for each breakpoint are all parsed from CSS (@media block tracking + JSDoc comments
@group/@description/@type extraction).tokens/*.json is only used as optional enrichment (supplementing the missing @name, breakpoint label mappings, etc. in CSS comments),
JSON schema changes or absence do not affect core functionality. The reason for this design: CSS variable names are a stable contract for users, while JSON is an internal intermediate artifact of the package, and the schema may differ between versions (e.g., v0.0.3 has no responsive-token.json, and before v0.0.4 the filename casing was inconsistent).
Package resolution: local first, download as fallback
The CLI determines which package version to use for validation according to the following priority:
--version <ver>explicitly specified (e.g.,--version 0.0.3) → download or use that version from the cache- Look for local
node_modulesnearby → start from the directory of the scanned file layer by layer upwardsearch fornode_modules/@opensig/opendesign-token/, and if found, use that local package directly (no network, no cache needed) - Not found locally +
--offline→ use the highest version in the cache - If none of the above are found → download from the npm registry
latest(cached after the first download)
Nearby lookupis the core strategy—not relying on process.cwd(), but starting the search from the location of the scanned file. This naturally supports monorepos:
- pnpm workspace: packages are usually symlinked in the subpackage's
node_modules/, and the real files are under the root's.pnpm/down - npm/yarn hoisting: the package is in the monorepo root's
node_modules/, and the subpackage directory can find it by going upward layer by layer
scan src/App.vue , the CLI starts from src/App.vue and searches upward from the directory containing it; whether the CLI is invoked from the project root or from outside the monorepo, it can correctly locate the package version that the project depends on.
If the project has v0.0.3 installed (no responsive tokens),--o-r-font_size-h1 will be judged as nonexistent—this is exactly the expected behavior.
Command quick reference
# ① 校验单个 token(接受三种输入形式)
node skills/opendesign-tokens/scripts/bin.mjs check --o-color-fill2
node skills/opendesign-tokens/scripts/bin.mjs check "var(--o-color-bg1)"
node skills/opendesign-tokens/scripts/bin.mjs check color-primary1
# ② 扫描文件/目录,找出所有捏造的 var(--o-*) 用法
node skills/opendesign-tokens/scripts/bin.mjs scan src/App.vue
node skills/opendesign-tokens/scripts/bin.mjs scan src/ --theme e --strict
node skills/opendesign-tokens/scripts/bin.mjs scan src/components/ --json
# ③ 列出所有 token(支持 glob 模式)
node skills/opendesign-tokens/scripts/bin.mjs list "--o-color-*"
node skills/opendesign-tokens/scripts/bin.mjs list "--o-r-*" --json
# ④ 查看单个 token 的完整信息(跨主题 light/dark 值)
node skills/opendesign-tokens/scripts/bin.mjs info --o-brand-6
# ⑤ 设计稿值 → token 反查(颜色 / 尺寸 / 时长 / 缓动 / 阴影)
node skills/opendesign-tokens/scripts/bin.mjs convert '#FFFFFF'
node skills/opendesign-tokens/scripts/bin.mjs convert 'rgb(0, 47, 167)'
node skills/opendesign-tokens/scripts/bin.mjs convert 16px
node skills/opendesign-tokens/scripts/bin.mjs convert 200ms
node skills/opendesign-tokens/scripts/bin.mjs convert 'cubic-bezier(0.2, 0, 0, 1)' --all
node skills/opendesign-tokens/scripts/bin.mjs convert '0 3px 8px rgba(var(--o-grey-14), 0.08)'
# ⑥ 列出包的所有版本
node skills/opendesign-tokens/scripts/bin.mjs versions
# ⑦ 清空本地缓存
node skills/opendesign-tokens/scripts/bin.mjs clear-cache
check-tokens.mjsis backward compatible with the old invocation method (node check-tokens.mjs check ...), and is equivalent tobin.mjs.
Common options
| Option | Description | Default value |
|---|---|---|
-V, --version <ver> |
Specify package version | Auto-resolve |
-t, --theme <e|a|k|m|g|u> |
Theme | e |
-m, --mode <light|dark> |
Mode | light |
--json |
Output JSON (convenient for programmatic consumption by LLMs) | Off |
--offline |
Use cache only, no network | Off |
--strict |
Exit with code 1 if an invalid token is found during scan | Off |
--no-suggest |
Do not compute suggestions | Off |
-v, --verbose |
Detailed output | Off |
--color |
convert-specific: force parsing as color | Off |
--value |
convert-specific: force parsing as a normal value | Off |
--tolerance <n> |
convert-specific: color tolerance | 5 |
--all |
convert-specific: show all matches | Off |
Workflow recommendations
- Scan immediately after generating code: after writing a style block containing
var(--o-*), use thescancommand to check the file it is in.node skills/opendesign-tokens/scripts/bin.mjs scan path/to/your.vue --theme e - CI / git hook: add
--strictso that the scan exits nonzero when it finds invalid tokens, blocking the commit.node skills/opendesign-tokens/scripts/bin.mjs scan src/ --theme e --strict - When unsure of a token name: use
checkto check a single one; the CLI will give the 3 closest real tokens as suggestions.node skills/opendesign-tokens/scripts/bin.mjs check --o-color-bg2 # ❌ --o-color-bg2 does not exist # 💡 closest: --o-color-fill2 (d=4), --o-color-info2 (d=4), ... - Design-spec value → token reverse lookup: after getting a color value or dimension from Pixso/Figma, use
convertto look up the corresponding token. The CLI will dynamically build a reverse table from the@opensig/opendesign-tokenCSS output, so match results always stay in sync with the actual package version.# 色值反查 node skills/opendesign-tokens/scripts/bin.mjs convert '#FFFFFF' # → var(--o-color-fill2) [fill] 二级填充:区块、卡片 # 尺寸反查(响应式 token 优先) node skills/opendesign-tokens/scripts/bin.mjs convert 16px # → var(--o-r-font_size-text1) [font_size] 响应式常规正文 # 缓动曲线反查 node skills/opendesign-tokens/scripts/bin.mjs convert 'cubic-bezier(0.2, 0, 0, 1)' # → var(--o-easing-emphasized) [easing] 用于大卡片、场景切换 # 显示全部匹配(一个值可能对应多个 token) node skills/opendesign-tokens/scripts/bin.mjs convert 16px --all - JSON mode: add
--jsonto output the results in a structured form, making it easy for other tools or LLMs to parse. - Offline environment: the first run requires network access to download the package; afterward
--offlineallows offline validation.
Theme-specific notes
Some tokens are not defined in all themes. For example, --o-brand-1 ~ --o-brand-10 exists only in the e/m/g/u four themes; Ascend (a) and Kunpeng
(k) define only --o-brand-6. When using -t to specify a theme, the CLI validates according to that theme:
node skills/opendesign-tokens/scripts/check-tokens.mjs check --o-brand-1 -t e # ✅ exists
node skills/opendesign-tokens/scripts/check-tokens.mjs check --o-brand-1 -t a # ❌ not in theme a
What the CLI does not do
- Does not modify your code: it only reads files and outputs reports; it will not automatically replace variable names.
- Does not validate SCSS mixins: it only validates
var(--o-*)-form CSS variable references.@include h1;Mixin calls like this are outside the scan scope (the validity of mixins is governed by theopendesign-applicationskill'sstyles-infrastructureconstraints).