Skip to content

Commit d515c39

Browse files
authored
feat: design token governance (#93)
* feat: init migration * feat: refactor theme editor * fix: migrate the tokens * feat: update theme studio * feat: grid and grid system * fix: styles * chore: lint * chore: update docs * chore: add changeset for design token governance * chore: update css format
1 parent 423312e commit d515c39

File tree

283 files changed

+20562
-5840
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

283 files changed

+20562
-5840
lines changed
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"@tiny-design/react": minor
3+
"@tiny-design/tokens": minor
4+
---
5+
6+
Add design token governance with JSON source registry, migrate all component SCSS to token variables, introduce CSS Grid layout system, and rebuild Theme Studio

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333

3434
<p align="center">
3535
<a href="https://wangdicoder.github.io/tiny-design/"><strong>Documentation</strong></a> &nbsp;&bull;&nbsp;
36-
<a href="https://wangdicoder.github.io/tiny-design/theme/theme-editor"><strong>Theme Editor</strong></a> &nbsp;&bull;&nbsp;
36+
<a href="https://wangdicoder.github.io/tiny-design/theme/theme-studio"><strong>Theme Editor</strong></a> &nbsp;&bull;&nbsp;
3737
<a href="https://wangdicoder.github.io/tiny-design/theme/customise-theme"><strong>Theming Guide</strong></a>
3838
</p>
3939

@@ -73,7 +73,7 @@ No separate CSS import needed — styles are bundled with each component and tre
7373

7474
### Visual Theme Editor
7575

76-
The built-in [Theme Editor](https://wangdicoder.github.io/tiny-design/theme/theme-editor) lets you pick from 20+ preset themes or fine-tune individual tokens — colours, typography, border radius, spacing — and see changes live on real components. Export as CSS or SCSS when you're done.
76+
The built-in [Theme Editor](https://wangdicoder.github.io/tiny-design/theme/theme-studio) lets you pick from 20+ preset themes or fine-tune individual tokens — colours, typography, border radius, spacing — and see changes live on real components. Export as CSS or SCSS when you're done.
7777

7878
### Dark mode
7979

apps/docs/guides/customise-theme.md

Lines changed: 101 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
# Customise Theme
22

3-
Tiny UI provides three ways to customise the look and feel:
3+
Tiny UI now uses a v2 token system with one primary runtime model:
44

5-
1. **Theme Editor** — a visual, no-code tool for real-time theming (great for exploration and quick customisation).
6-
2. **Design tokens** — CSS custom properties that power light and dark mode. These are the runtime values every component reads.
7-
3. **SCSS constants** — compile-time structural constants (padding, transitions, arrow sizes, etc.) that can be overridden when you build your own stylesheet.
5+
1. **CSS custom properties** for direct runtime overrides.
6+
2. **ThemeDocument** for portable theme JSON.
7+
3. **ConfigProvider `theme.tokens`** for React-scoped theming.
8+
9+
SCSS constants still exist, but they are only for compile-time structural overrides.
810

911
## Theme Editor
1012

11-
The built-in [Theme Editor](/theme/theme-editor) lets you visually customise design tokens in real time. You can:
13+
The built-in [Theme Editor](/theme/theme-studio) lets you visually customise design tokens in real time. You can:
1214

1315
- Pick from **20+ preset themes** (e.g. Catppuccin, Mocha Mousse, Cyberpunk) or start from scratch.
1416
- Adjust primary, success, warning, danger, and info colours, background, text, and border colours.
@@ -18,6 +20,8 @@ The built-in [Theme Editor](/theme/theme-editor) lets you visually customise des
1820

1921
Changes are applied instantly via CSS custom properties — no rebuild required.
2022

23+
The editor exports the same v2 token model used by the runtime, so the result can be applied as CSS variables, stored as a `ThemeDocument`, or passed into `ConfigProvider`.
24+
2125
## Dark mode
2226

2327
Tiny UI ships with built-in light and dark themes. Light mode is the default. To enable dark mode, set `data-tiny-theme` on the `<html>` element:
@@ -55,13 +59,17 @@ The hook returns:
5559

5660
## Design tokens (CSS custom properties)
5761

58-
Every colour, shadow, and visual state is exposed as a `--ty-*` CSS custom property on `:root`. This is the **primary way** to customise Tiny UI. You can override any token in your own stylesheet:
62+
Every semantic token and component token is exposed as a `--ty-*` CSS custom property. This is the lowest-level runtime API and works in any stack.
63+
64+
You can override tokens directly in your own stylesheet:
5965

6066
```css
6167
:root {
6268
--ty-color-primary: #007bff;
6369
--ty-color-primary-hover: #3d9bff;
6470
--ty-color-primary-active: #0062d6;
71+
--ty-button-radius: 999px;
72+
--ty-card-header-padding: 20px;
6573
}
6674
```
6775

@@ -72,9 +80,17 @@ html[data-tiny-theme='dark'] {
7280
--ty-color-primary: #3d9bff;
7381
--ty-color-primary-hover: #66b3ff;
7482
--ty-color-primary-active: #007bff;
83+
--ty-color-bg-container: #111827;
84+
--ty-color-text: rgba(249, 250, 251, 0.92);
7585
}
7686
```
7787

88+
### Naming rules
89+
90+
- Semantic token keys use kebab-case, for example `color-primary`.
91+
- Component token keys use dot paths, for example `button.radius` or `card.header-padding`.
92+
- Runtime CSS variables are the same keys with dots converted to hyphens, for example `--ty-button-radius` and `--ty-card-header-padding`.
93+
7894
### Commonly used tokens
7995

8096
| Token | Light default | Description |
@@ -92,9 +108,77 @@ html[data-tiny-theme='dark'] {
92108
| `--ty-height-md` | `32px` | Medium control height |
93109
| `--ty-height-lg` | `42px` | Large control height |
94110

95-
Every component also has its own tokens for fine-grained control. For example, Button uses `--ty-btn-default-bg`, `--ty-btn-default-color`, etc. The full list of tokens can be found in the source:
96-
- [Light theme tokens](https://github.com/wangdicoder/tiny-design/blob/master/packages/tokens/scss/themes/_light.scss)
97-
- [Dark theme tokens](https://github.com/wangdicoder/tiny-design/blob/master/packages/tokens/scss/themes/_dark.scss)
111+
Every component also has its own tokens for fine-grained control. For example, Button uses `--ty-button-bg-default`, `--ty-button-text-default`, and `--ty-button-radius`. The full list of supported tokens is generated from the v2 registry and component sources:
112+
- [Token registry](https://github.com/wangdicoder/tiny-design/blob/master/packages/tokens/dist/registry.json)
113+
- [Component token sources](https://github.com/wangdicoder/tiny-design/tree/master/packages/tokens/source/components)
114+
115+
## ThemeDocument
116+
117+
`ThemeDocument` is the canonical JSON format for sharing, exporting, saving, and applying themes.
118+
119+
```json
120+
{
121+
"meta": {
122+
"id": "brand-ocean",
123+
"name": "Brand Ocean",
124+
"schemaVersion": 1
125+
},
126+
"mode": "light",
127+
"extends": "tiny-light",
128+
"tokens": {
129+
"semantic": {
130+
"color-primary": "#0ea5e9",
131+
"border-radius": "12px"
132+
},
133+
"components": {
134+
"button.radius": "999px",
135+
"card.header-padding": "20px"
136+
}
137+
}
138+
}
139+
```
140+
141+
Use `ThemeDocument` when you need:
142+
143+
- a serializable theme file
144+
- import/export between tools
145+
- community themes or preset themes
146+
- mode-aware overrides built on top of `tiny-light` or `tiny-dark`
147+
148+
## React: ConfigProvider
149+
150+
In React apps, the recommended API is `ConfigProvider theme={{ tokens: ... }}`.
151+
152+
```tsx
153+
import { ConfigProvider } from '@tiny-design/react';
154+
155+
<ConfigProvider
156+
theme={{
157+
mode: 'light',
158+
extends: 'tiny-light',
159+
tokens: {
160+
semantic: {
161+
'color-primary': '#0ea5e9',
162+
'border-radius': '12px',
163+
},
164+
components: {
165+
'button.radius': '999px',
166+
'card.header-padding': '20px',
167+
},
168+
},
169+
}}
170+
>
171+
<App />
172+
</ConfigProvider>
173+
```
174+
175+
Use this when you want:
176+
177+
- scoped theming for part of the React tree
178+
- nested theme overrides
179+
- popup / portal content to inherit the same token scope
180+
181+
`ConfigProvider` no longer uses the old `theme.token` or `theme.components` API. Use `theme.tokens.semantic` and `theme.tokens.components` only.
98182

99183
## SCSS constants
100184

@@ -146,6 +230,13 @@ $card-body-padding: 16px !default;
146230
$notification-width: 380px !default;
147231
```
148232

149-
> **Note:** Colours, font sizes, border radii, shadows, and all other visual tokens should be customised via CSS custom properties (see above), not SCSS variables. SCSS constants are only for structural values like padding and sizing.
233+
> **Note:** Colours, typography, radii, shadows, and all other visual tokens should be customised through v2 tokens, not SCSS variables. SCSS constants are only for compile-time structural values like padding and sizing.
234+
235+
## Recommended approach
236+
237+
- Use CSS variables when you want the simplest runtime override.
238+
- Use `ThemeDocument` when you need a portable JSON theme format.
239+
- Use `ConfigProvider` when you need scoped theming in React.
240+
- Use SCSS constants only when a value must be decided at build time.
150241

151242
Please report an issue if the existing list of tokens or constants is not enough for you.

apps/docs/guides/customise-theme.zh_CN.md

Lines changed: 101 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
# 自定义主题
22

3-
Tiny UI 提供三种方式来定制外观
3+
Tiny UI 现在使用 v2 token 系统,推荐的主题自定义方式收敛为一套主模型
44

5-
1. **主题编辑器** — 一个可视化的实时主题工具,无需编写代码(非常适合探索和快速定制)。
6-
2. **设计令牌(Design tokens)** — 驱动亮色/暗色模式的 CSS 自定义属性,所有组件在运行时读取这些值。
7-
3. **SCSS 常量** — 编译时结构常量(内边距、过渡动画、箭头尺寸等),可在构建自定义样式表时覆盖。
5+
1. **CSS 自定义属性**,用于直接做运行时覆盖。
6+
2. **ThemeDocument**,用于可移植的主题 JSON。
7+
3. **ConfigProvider `theme.tokens`**,用于 React 作用域主题。
8+
9+
SCSS 常量仍然保留,但它只用于编译期的结构性覆盖。
810

911
## 主题编辑器
1012

11-
内置的[主题编辑器](/theme/theme-editor)让你可以实时可视化定制设计令牌。你可以:
13+
内置的[主题编辑器](/theme/theme-studio)让你可以实时可视化定制设计令牌。你可以:
1214

1315
-**20+ 个预设主题**中选择(如 Catppuccin、摩卡慕斯、赛博朋克等),或从零开始。
1416
- 调整主色、成功色、警告色、危险色和信息色,以及背景色、文本色和边框色。
@@ -18,6 +20,8 @@ Tiny UI 提供三种方式来定制外观:
1820

1921
更改通过 CSS 自定义属性即时生效 — 无需重新构建。
2022

23+
主题编辑器导出的也是同一套 v2 token 模型,因此结果既可以作为 CSS 变量使用,也可以保存为 `ThemeDocument`,或者传给 `ConfigProvider`
24+
2125
## 暗色模式
2226

2327
Tiny UI 内置亮色和暗色主题。默认为亮色模式。要启用暗色模式,请在 `<html>` 元素上设置 `data-tiny-theme`
@@ -55,13 +59,17 @@ const App = () => {
5559

5660
## 设计令牌(CSS 自定义属性)
5761

58-
所有颜色、阴影和视觉状态都以 `--ty-*` CSS 自定义属性的形式暴露在 `:root` 上。这是定制 Tiny UI 的**主要方式**。你可以在自己的样式表中覆盖任意令牌:
62+
所有语义令牌和组件令牌都会以 `--ty-*` CSS 自定义属性的形式暴露出来。这是最底层、最通用的运行时接口。
63+
64+
你可以直接在自己的样式表里覆盖:
5965

6066
```css
6167
:root {
6268
--ty-color-primary: #007bff;
6369
--ty-color-primary-hover: #3d9bff;
6470
--ty-color-primary-active: #0062d6;
71+
--ty-button-radius: 999px;
72+
--ty-card-header-padding: 20px;
6573
}
6674
```
6775

@@ -72,9 +80,17 @@ html[data-tiny-theme='dark'] {
7280
--ty-color-primary: #3d9bff;
7381
--ty-color-primary-hover: #66b3ff;
7482
--ty-color-primary-active: #007bff;
83+
--ty-color-bg-container: #111827;
84+
--ty-color-text: rgba(249, 250, 251, 0.92);
7585
}
7686
```
7787

88+
### 命名规则
89+
90+
- semantic token 使用 kebab-case,例如 `color-primary`
91+
- component token 使用点分路径,例如 `button.radius``card.header-padding`
92+
- 运行时 CSS 变量就是把点替换成连字符,例如 `--ty-button-radius``--ty-card-header-padding`
93+
7894
### 常用令牌
7995

8096
| 令牌 | 亮色默认值 | 说明 |
@@ -92,9 +108,77 @@ html[data-tiny-theme='dark'] {
92108
| `--ty-height-md` | `32px` | 中尺寸控件高度 |
93109
| `--ty-height-lg` | `42px` | 大尺寸控件高度 |
94110

95-
每个组件也有自己的令牌,用于细粒度控制。例如,Button 使用 `--ty-btn-default-bg``--ty-btn-default-color` 等。完整的令牌列表请参考源码:
96-
- [亮色主题令牌](https://github.com/wangdicoder/tiny-design/blob/master/packages/tokens/scss/themes/_light.scss)
97-
- [暗色主题令牌](https://github.com/wangdicoder/tiny-design/blob/master/packages/tokens/scss/themes/_dark.scss)
111+
每个组件也有自己的令牌,用于细粒度控制。例如,Button 使用 `--ty-button-bg-default``--ty-button-text-default``--ty-button-radius`。完整的受支持令牌列表来自 v2 registry 和组件 source:
112+
- [Token registry](https://github.com/wangdicoder/tiny-design/blob/master/packages/tokens/dist/registry.json)
113+
- [组件 token 源文件](https://github.com/wangdicoder/tiny-design/tree/master/packages/tokens/source/components)
114+
115+
## ThemeDocument
116+
117+
`ThemeDocument` 是主题导出、导入、保存和分发时使用的标准 JSON 格式。
118+
119+
```json
120+
{
121+
"meta": {
122+
"id": "brand-ocean",
123+
"name": "Brand Ocean",
124+
"schemaVersion": 1
125+
},
126+
"mode": "light",
127+
"extends": "tiny-light",
128+
"tokens": {
129+
"semantic": {
130+
"color-primary": "#0ea5e9",
131+
"border-radius": "12px"
132+
},
133+
"components": {
134+
"button.radius": "999px",
135+
"card.header-padding": "20px"
136+
}
137+
}
138+
}
139+
```
140+
141+
适合用在这些场景:
142+
143+
- 主题文件持久化
144+
- 工具之间导入导出
145+
- 社区主题 / 预设主题
146+
-`tiny-light``tiny-dark` 之上做模式化覆盖
147+
148+
## React: ConfigProvider
149+
150+
在 React 应用里,推荐使用 `ConfigProvider theme={{ tokens: ... }}`
151+
152+
```tsx
153+
import { ConfigProvider } from '@tiny-design/react';
154+
155+
<ConfigProvider
156+
theme={{
157+
mode: 'light',
158+
extends: 'tiny-light',
159+
tokens: {
160+
semantic: {
161+
'color-primary': '#0ea5e9',
162+
'border-radius': '12px',
163+
},
164+
components: {
165+
'button.radius': '999px',
166+
'card.header-padding': '20px',
167+
},
168+
},
169+
}}
170+
>
171+
<App />
172+
</ConfigProvider>
173+
```
174+
175+
适合用在这些场景:
176+
177+
- 只对 React 树中的一部分做作用域主题
178+
- 需要嵌套主题覆盖
179+
- 需要让弹层 / portal 内容继承同一个 token 作用域
180+
181+
`ConfigProvider` 已经不再使用旧的 `theme.token``theme.components` API。现在只使用 `theme.tokens.semantic``theme.tokens.components`
98182

99183
## SCSS 常量
100184

@@ -146,6 +230,13 @@ $card-body-padding: 16px !default;
146230
$notification-width: 380px !default;
147231
```
148232

149-
> **注意:** 颜色、字号、圆角、阴影等所有视觉令牌应通过 CSS 自定义属性定制(见上方),而非 SCSS 变量。SCSS 常量仅用于内边距、尺寸等结构性值。
233+
> **注意:** 颜色、排版、圆角、阴影等所有视觉令牌,都应该通过 v2 token 定制,而不是通过 SCSS 变量。SCSS 常量只适用于内边距、尺寸等编译期结构值。
234+
235+
## 推荐用法
236+
237+
- 想最快做运行时覆盖,用 CSS 变量
238+
- 需要可移植的 JSON 主题格式,用 `ThemeDocument`
239+
- 需要 React 局部主题,用 `ConfigProvider`
240+
- 只有在值必须在构建期决定时,才使用 SCSS 常量
150241

151242
如果现有的令牌或常量列表无法满足你的需求,请提交 issue 反馈。

apps/docs/src/components/header/header.scss

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,8 +125,9 @@
125125
&__version {
126126
font-size: 11px;
127127
font-weight: 600;
128-
color: $docs-accent;
129-
background: $docs-accent-subtle;
128+
color: var(--ty-color-primary);
129+
background: color-mix(in srgb, var(--ty-color-primary) 10%, transparent);
130+
border: 1px solid color-mix(in srgb, var(--ty-color-primary) 18%, transparent);
130131
border-radius: 6px;
131132
padding: 3px 10px;
132133
letter-spacing: 0.02em;

apps/docs/src/containers/components/component-icons.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ const icons: Record<string, IconFn> = {
1616
'aspect-ratio': () => <svg viewBox="0 0 24 24" fill="none"><rect x="3" y="5" width="18" height="14" rx="2" {...s} /><path d="M7 15l3-3 3 3" {...s} /></svg>,
1717
divider: () => <svg viewBox="0 0 24 24" fill="none"><line x1="3" y1="12" x2="21" y2="12" {...s} /><line x1="12" y1="5" x2="12" y2="9" {...s} /><line x1="12" y1="15" x2="12" y2="19" {...s} /></svg>,
1818
flex: () => <svg viewBox="0 0 24 24" fill="none"><rect x="3" y="8" width="5" height="8" rx="1" {...s} /><rect x="10" y="5" width="5" height="14" rx="1" {...s} /><rect x="17" y="9" width="5" height="6" rx="1" {...s} /></svg>,
19+
'grid-system': () => <svg viewBox="0 0 24 24" fill="none"><rect x="3" y="4" width="18" height="7" rx="1" {...s} /><rect x="3" y="13" width="5" height="7" rx="1" {...s} /><rect x="10" y="13" width="5" height="7" rx="1" {...s} /><rect x="17" y="13" width="4" height="7" rx="1" {...s} /></svg>,
1920
grid: () => <svg viewBox="0 0 24 24" fill="none"><rect x="3" y="3" width="7" height="7" rx="1" {...s} /><rect x="14" y="3" width="7" height="7" rx="1" {...s} /><rect x="3" y="14" width="7" height="7" rx="1" {...s} /><rect x="14" y="14" width="7" height="7" rx="1" {...s} /></svg>,
2021
layout: () => <svg viewBox="0 0 24 24" fill="none"><rect x="3" y="3" width="18" height="18" rx="2" {...s} /><line x1="3" y1="9" x2="21" y2="9" {...s} /><line x1="9" y1="9" x2="9" y2="21" {...s} /></svg>,
2122
space: () => <svg viewBox="0 0 24 24" fill="none"><rect x="3" y="9" width="4" height="6" rx="1" {...s} /><rect x="10" y="9" width="4" height="6" rx="1" {...s} /><rect x="17" y="9" width="4" height="6" rx="1" {...s} /></svg>,

0 commit comments

Comments
 (0)