Skip to content

Commit fb6c874

Browse files
committed
Add examples/ gallery (4 hues, all formats) + enable live preview link
- examples/{blue,green,warm,violet}/ : real generator output, --format all (css/html/json/tailwind/scss) - examples/index.html : live gallery, light+dark mini-previews, on-brand buttons, AA badges - examples/README.md : per-hue table + regenerate command - README: live-examples badge + bilingual preview link (GitHub Pages)
1 parent bf3e02e commit fb6c874

23 files changed

Lines changed: 2389 additions & 0 deletions

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,12 @@
66
[![Input: 1 brand color](https://img.shields.io/badge/input-1%20brand%20color-orange.svg)](#what-it-can-do)
77
[![Engine: Python 3.10+](https://img.shields.io/badge/engine-Python%203.10%2B-green.svg)](#requirements)
88
[![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](LICENSE)
9+
[![Live examples](https://img.shields.io/badge/live-examples-2563EB.svg)](https://truman-t3.github.io/tinted-ui-tokens-skills/examples/)
910

1011
English | [中文](#chinese)
1112

13+
> **▶ Live examples:** https://truman-t3.github.io/tinted-ui-tokens-skills/examples/ — four brand colors (blue / green / warm / violet), light + dark, WCAG AA guaranteed. Source in [`examples/`](examples/).
14+
1215
A **cross-agent** skill that turns one brand color into a complete,
1316
production-ready **brand-tinted design-token system** — so your UI stops looking
1417
cheap from flat neutral colors. It works in Claude Code, Cursor, OpenAI Codex,
@@ -205,6 +208,8 @@ MIT
205208

206209
[English](#english) | 中文
207210

211+
> **▶ 在线预览:** https://truman-t3.github.io/tinted-ui-tokens-skills/examples/ —— 四个品牌色(蓝 / 绿 / 暖 / 紫),明暗双主题,WCAG AA 保证。源码见 [`examples/`](examples/)
212+
208213
一个**跨 agent** 的技能:输入一个品牌色,自动生成一套完整、可直接上线的「染色中性色」
209214
设计 Token 系统——让你的 UI 不再因为扁平的中性色而显得廉价。它可在 Claude Code、
210215
Cursor、OpenAI Codex、Cline、Aider、WindSurf、GitHub Copilot、Gemini CLI 与

examples/README.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# Examples
2+
3+
Four brand colors, each run through `generate_tokens.py --format all`. Every folder is a
4+
real, unedited generator output — nothing hand-tweaked.
5+
6+
| Folder | Brand | Temperature | on-brand contrast |
7+
|--------|-------|-------------|-------------------|
8+
| [`blue/`](blue/) | `#2563EB` | cool | 4.90:1 ✓ AA |
9+
| [`green/`](green/) | `#16A34A` | balanced | 5.12:1 ✓ AA |
10+
| [`warm/`](warm/) | `#C4502A` | warm | 4.56:1 ✓ AA |
11+
| [`violet/`](violet/) | `#7C3AED` | cool | 5.37:1 ✓ AA |
12+
13+
Each folder contains all five export formats:
14+
15+
- `tokens.css` — CSS custom properties, light + `[data-theme="dark"]`
16+
- `preview.html` — standalone light/dark preview page
17+
- `tokens.json`[DTCG](https://tr.designtokens.org/) design-token format
18+
- `tailwind.config.js` — Tailwind theme extension
19+
- `_tokens.scss` — SCSS variables
20+
21+
## Live gallery
22+
23+
Open [`index.html`](index.html) locally, or view the hosted version:
24+
**https://truman-t3.github.io/tinted-ui-tokens-skills/examples/**
25+
26+
## Regenerate
27+
28+
```bash
29+
python3 scripts/generate_tokens.py --brand "#2563EB" --name "Acme" --format all --out examples/blue
30+
```

examples/blue/_tokens.scss

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
// Tinted UI Tokens - generated by tinted-ui-tokens-skills
2+
3+
// ---- Light theme ----
4+
$color-brand: #2563EB;
5+
$color-brand-subtle: #E0E9FC;
6+
$color-on-brand: #F6F9FE;
7+
$color-bg: #F1F3F8;
8+
$color-surface: #FBFCFF;
9+
$color-surface-2: #E7EAF1;
10+
$color-border: #D8DCE5;
11+
$color-border-strong: #B5BCCB;
12+
$color-text: #141E34;
13+
$color-text-2: #444E64;
14+
$color-text-muted: #8590A9;
15+
$color-error: #CA3038;
16+
$color-error-subtle: #DDCDDF;
17+
$color-warning: #E09821;
18+
$color-warning-subtle: #E0DDDB;
19+
$color-success: #1C9A54;
20+
$color-success-subtle: #C3DDE3;
21+
22+
// ---- Shadows (light) ----
23+
$shadow-shadow_sm: 0 1px 3px rgba(37, 99, 235, 0.08), 0 0 0 1px rgba(37, 99, 235, 0.04);
24+
$shadow-shadow_md: 0 4px 16px rgba(37, 99, 235, 0.1), 0 1px 4px rgba(37, 99, 235, 0.06);
25+
$shadow-shadow_lg: 0 12px 40px rgba(37, 99, 235, 0.12), 0 2px 8px rgba(37, 99, 235, 0.06);
26+
27+
// ---- Dark theme ----
28+
$color-dark-bg: #11192C;
29+
$color-dark-surface: #172137;
30+
$color-dark-surface2: #1D273F;
31+
$color-dark-border: #1F2D4A;
32+
$color-dark-border_strong: #2C3C5E;
33+
$color-dark-text: #E0E7F5;
34+
$color-dark-text2: #8497B8;
35+
$color-dark-text_muted: #7388A6;
36+
$color-dark-brand_subtle: #1A2E5B;
37+
$color-dark-error_subtle: #3C293E;
38+
$color-dark-warning_subtle: #403C3A;
39+
$color-dark-success_subtle: #1D3C43;
40+
$color-dark-shadow_sm: 0 0 0 1px rgba(37, 99, 235, 0.1);
41+
$color-dark-shadow_md: 0 4px 20px rgba(0, 0, 0, 0.40), 0 0 0 1px rgba(37, 99, 235, 0.06);
42+
$color-dark-shadow_lg: 0 12px 40px rgba(0, 0, 0, 0.45), 0 0 0 1px rgba(37, 99, 235, 0.08);
43+
$shadow-dark-shadow_sm: 0 0 0 1px rgba(37, 99, 235, 0.1);
44+
$shadow-dark-shadow_md: 0 4px 20px rgba(0, 0, 0, 0.40), 0 0 0 1px rgba(37, 99, 235, 0.06);
45+
$shadow-dark-shadow_lg: 0 12px 40px rgba(0, 0, 0, 0.45), 0 0 0 1px rgba(37, 99, 235, 0.08);
46+
47+
// Map light vars onto [data-theme="dark"] (drop-in):
48+
@mixin tinted-dark {
49+
--color-bg: $color-dark-bg;
50+
--color-surface: $color-dark-surface;
51+
--color-surface2: $color-dark-surface2;
52+
--color-border: $color-dark-border;
53+
--color-border_strong: $color-dark-border_strong;
54+
--color-text: $color-dark-text;
55+
--color-text2: $color-dark-text2;
56+
--color-text_muted: $color-dark-text_muted;
57+
--color-brand_subtle: $color-dark-brand_subtle;
58+
--color-error_subtle: $color-dark-error_subtle;
59+
--color-warning_subtle: $color-dark-warning_subtle;
60+
--color-success_subtle: $color-dark-success_subtle;
61+
--color-shadow_sm: $color-dark-shadow_sm;
62+
--color-shadow_md: $color-dark-shadow_md;
63+
--color-shadow_lg: $color-dark-shadow_lg;
64+
}

examples/blue/preview.html

Lines changed: 220 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,220 @@
1+
<!DOCTYPE html>
2+
<html lang="zh">
3+
<head>
4+
<meta charset="utf-8" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1" />
6+
<title>Token Preview - #2563EB</title>
7+
<style>
8+
/* ==========================================================================
9+
Tinted UI Token System
10+
Brand : #2563EB Temperature : cool
11+
Generated : 2026-07-21
12+
Method: every neutral surface is blended a few percent toward the brand
13+
hue, so the brand "flows through" the system instead of sitting on top.
14+
No pure #FFFFFF / #000000 / #808080 anywhere. Text on each surface is
15+
checked against WCAG AA and nudged if needed, so readability always wins.
16+
========================================================================== */
17+
18+
:root,
19+
[data-theme="light"] {
20+
/* Brand */
21+
--color-brand: #2563EB;
22+
--color-brand-subtle: #E0E9FC;
23+
--color-on-brand: #F6F9FE; /* readable text placed ON --color-brand */
24+
25+
/* Surfaces - tinted by brand */
26+
--color-bg: #F1F3F8;
27+
--color-surface: #FBFCFF;
28+
--color-surface-2: #E7EAF1;
29+
--color-border: #D8DCE5;
30+
--color-border-strong:#B5BCCB;
31+
32+
/* Text - near-black/near-white with a hue lean (WCAG AA checked) */
33+
--color-text: #141E34;
34+
--color-text-2: #444E64;
35+
--color-text-muted: #8590A9;
36+
37+
/* Semantic - nudged toward brand temperature */
38+
--color-error: #CA3038;
39+
--color-error-subtle: #DDCDDF;
40+
--color-warning: #E09821;
41+
--color-warning-subtle:#E0DDDB;
42+
--color-success: #1C9A54;
43+
--color-success-subtle:#C3DDE3;
44+
45+
/* Shadows - brand hue, never pure black */
46+
--shadow-sm: 0 1px 3px rgba(37, 99, 235, 0.08), 0 0 0 1px rgba(37, 99, 235, 0.04);
47+
--shadow-md: 0 4px 16px rgba(37, 99, 235, 0.1), 0 1px 4px rgba(37, 99, 235, 0.06);
48+
--shadow-lg: 0 12px 40px rgba(37, 99, 235, 0.12), 0 2px 8px rgba(37, 99, 235, 0.06);
49+
}
50+
51+
[data-theme="dark"] {
52+
--color-brand-subtle: #1A2E5B;
53+
--color-on-brand: #F6F9FE;
54+
55+
--color-bg: #11192C;
56+
--color-surface: #172137;
57+
--color-surface-2: #1D273F;
58+
--color-border: #1F2D4A;
59+
--color-border-strong:#2C3C5E;
60+
61+
--color-text: #E0E7F5;
62+
--color-text-2: #8497B8;
63+
--color-text-muted: #7388A6;
64+
65+
--color-error-subtle: #3C293E;
66+
--color-warning-subtle:#403C3A;
67+
--color-success-subtle:#1D3C43;
68+
69+
--shadow-sm: 0 0 0 1px rgba(37, 99, 235, 0.1);
70+
--shadow-md: 0 4px 20px rgba(0, 0, 0, 0.40), 0 0 0 1px rgba(37, 99, 235, 0.06);
71+
--shadow-lg: 0 12px 40px rgba(0, 0, 0, 0.45), 0 0 0 1px rgba(37, 99, 235, 0.08);
72+
}
73+
74+
* { box-sizing: border-box; }
75+
body {
76+
margin: 0;
77+
font-family: -apple-system, "Segoe UI", "PingFang SC", "Microsoft YaHei", system-ui, sans-serif;
78+
background: var(--color-bg);
79+
color: var(--color-text);
80+
transition: background .25s ease, color .25s ease;
81+
}
82+
.wrap { max-width: 920px; margin: 0 auto; padding: 32px 24px 64px; }
83+
.topbar {
84+
display: flex; align-items: center; gap: 14px;
85+
padding: 14px 18px; margin-bottom: 28px;
86+
background: var(--color-surface); border: 1px solid var(--color-border);
87+
border-radius: 12px; box-shadow: var(--shadow-sm);
88+
}
89+
.swatch { width: 34px; height: 34px; border-radius: 8px; background: var(--color-brand);
90+
box-shadow: var(--shadow-sm); }
91+
.brand-meta { display: flex; flex-direction: column; line-height: 1.3; }
92+
.brand-meta b { font-size: .98rem; color: var(--color-text); }
93+
.brand-meta span { font-size: .72rem; color: var(--color-text-muted); letter-spacing: .04em; }
94+
.spacer { flex: 1; }
95+
.toggle {
96+
border: 1px solid var(--color-border-strong); background: var(--color-surface-2);
97+
color: var(--color-text-2); border-radius: 8px; padding: 8px 14px;
98+
font-size: .82rem; cursor: pointer; transition: all .2s ease;
99+
}
100+
.toggle:hover { color: var(--color-brand); border-color: var(--color-brand); }
101+
.grid { display: grid; grid-template-columns: 1fr 1fr; gap: 20px; }
102+
@media (max-width: 680px){ .grid { grid-template-columns: 1fr; } }
103+
.card {
104+
background: var(--color-surface); border: 1px solid var(--color-border);
105+
border-radius: 10px; box-shadow: var(--shadow-md); padding: 22px;
106+
}
107+
.card-label {
108+
font-size: .68rem; font-weight: 600; letter-spacing: .12em; text-transform: uppercase;
109+
color: var(--color-text-muted); margin-bottom: 8px;
110+
}
111+
.card-title { font-size: 1.18rem; font-weight: 600; color: var(--color-text); margin: 0 0 8px; }
112+
.card-body { font-size: .9rem; line-height: 1.65; color: var(--color-text-2); margin: 0; }
113+
.card-badge {
114+
display: inline-block; margin-top: 16px; background: var(--color-brand-subtle);
115+
color: var(--color-brand); font-size: .72rem; font-weight: 600; letter-spacing: .06em;
116+
padding: 4px 11px; border-radius: 5px;
117+
}
118+
.hero {
119+
grid-column: 1 / -1; border-radius: 14px; padding: 38px 30px;
120+
background: linear-gradient(175deg, var(--color-surface) 0%, var(--color-brand-subtle) 60%, var(--color-surface-2) 100%);
121+
border: 1px solid var(--color-border); box-shadow: var(--shadow-lg);
122+
}
123+
.hero h2 { margin: 0 0 10px; font-size: 1.5rem; color: var(--color-text); }
124+
.hero p { margin: 0; max-width: 560px; color: var(--color-text-2); line-height: 1.6; font-size: .92rem; }
125+
.btn-primary {
126+
margin-top: 22px; display: inline-block; border: none; cursor: pointer;
127+
background: var(--color-brand); color: var(--color-on-brand);
128+
border-radius: 9px; padding: 12px 22px; font-size: .92rem; font-weight: 600;
129+
box-shadow: var(--shadow-md); transition: filter .2s ease;
130+
}
131+
.btn-primary:hover { filter: brightness(1.06); }
132+
.field { margin-top: 18px; }
133+
.field label { display: block; font-size: .8rem; color: var(--color-text-2); margin-bottom: 6px; }
134+
.input {
135+
width: 100%; padding: 11px 13px; border-radius: 8px; font-size: .9rem;
136+
background: var(--color-surface); color: var(--color-text);
137+
border: 1px solid var(--color-border-strong); outline: none; transition: all .2s ease;
138+
}
139+
.input-error {
140+
border-color: var(--color-error);
141+
background: var(--color-error-subtle);
142+
box-shadow: 0 0 0 3px rgba(212,43,58,.12), 0 0 0 1px var(--color-brand);
143+
}
144+
.err-msg { margin-top: 7px; font-size: .78rem; color: var(--color-error); }
145+
.row { display: flex; gap: 14px; flex-wrap: wrap; margin-top: 18px; }
146+
.icon-box {
147+
width: 46px; height: 46px; border-radius: 10px; display: grid; place-items: center;
148+
background: var(--color-brand-subtle); color: var(--color-brand); box-shadow: var(--shadow-sm);
149+
}
150+
.icon-box svg { width: 22px; height: 22px; }
151+
.swatches { display: flex; gap: 12px; flex-wrap: wrap; margin-top: 18px; }
152+
.swatch-item { text-align: center; font-size: .68rem; color: var(--color-text-muted); }
153+
.swatch-item .box { width: 54px; height: 40px; border-radius: 8px; border: 1px solid var(--color-border); margin-bottom: 6px; }
154+
.section-title { font-size: .8rem; text-transform: uppercase; letter-spacing: .1em;
155+
color: var(--color-text-muted); margin: 30px 0 4px; }
156+
</style>
157+
</head>
158+
<body>
159+
<div class="wrap" id="stage" data-theme="light">
160+
<div class="topbar">
161+
<div class="swatch"></div>
162+
<div class="brand-meta">
163+
<b>Acme (cool blue)</b>
164+
<span>brand #2563EB &middot; cool temperature</span>
165+
</div>
166+
<div class="spacer"></div>
167+
<button class="toggle" onclick="toggleTheme()">切换 明 / 暗</button>
168+
</div>
169+
170+
<div class="grid">
171+
<div class="hero">
172+
<h2>品牌色,流进整个系统</h2>
173+
<p>背景、表面、边框、文字、阴影、语义色、渐变、图标 —— 每一层都带着同一份品牌色温。没有纯中性色,没有死黑阴影。</p>
174+
<button class="btn-primary">Get started</button>
175+
</div>
176+
177+
<div class="card">
178+
<div class="card-label">Overview</div>
179+
<div class="card-title">染色中性色</div>
180+
<p class="card-body">每张卡片、每个表面都微微偏向品牌色,所以品牌出现时不像被临时贴上去,而像本来就属于这里。</p>
181+
<span class="card-badge">BRAND SUBTLE</span>
182+
</div>
183+
184+
<div class="card">
185+
<div class="card-label">Form</div>
186+
<div class="card-title">带温度的错误态</div>
187+
<p class="card-body">错误红被轻推到品牌色温,输入框底色也偏向品牌场,focus ring 同时带着两种温度。</p>
188+
<div class="field">
189+
<label>邮箱地址</label>
190+
<input class="input input-error" value="not-an-email" />
191+
<div class="err-msg">请输入有效的邮箱地址</div>
192+
</div>
193+
</div>
194+
195+
<div class="card" style="grid-column:1/-1">
196+
<div class="card-label">Icons</div>
197+
<div class="row">
198+
<div class="icon-box"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 2l3 7h7l-5.5 4 2 7L12 16l-6.5 4 2-7L2 9h7z"/></svg></div>
199+
<div class="icon-box"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 3"/></svg></div>
200+
<div class="icon-box"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M4 12h16M4 6h16M4 18h10"/></svg></div>
201+
<div class="row" style="flex-direction:column;gap:8px;margin-top:0">
202+
<div class="swatches">
203+
<div class="swatch-item"><div class="box" style="background:var(--color-error)"></div>error</div>
204+
<div class="swatch-item"><div class="box" style="background:var(--color-error-subtle)"></div>error-sub</div>
205+
<div class="swatch-item"><div class="box" style="background:var(--color-warning)"></div>warning</div>
206+
<div class="swatch-item"><div class="box" style="background:var(--color-success)"></div>success</div>
207+
</div>
208+
</div>
209+
</div>
210+
</div>
211+
</div>
212+
</div>
213+
<script>
214+
function toggleTheme(){
215+
var s = document.getElementById('stage');
216+
s.setAttribute('data-theme', s.getAttribute('data-theme') === 'dark' ? 'light' : 'dark');
217+
}
218+
</script>
219+
</body>
220+
</html>

examples/blue/tailwind.config.js

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/** @type {import('tailwindcss').Config} */
2+
module.exports = {
3+
theme: {
4+
extend: {
5+
colors: {
6+
"brand": "#2563EB",
7+
"brand-subtle": "#E0E9FC",
8+
"on-brand": "#F6F9FE",
9+
"bg": "#F1F3F8",
10+
"surface": "#FBFCFF",
11+
"surface-2": "#E7EAF1",
12+
"border": "#D8DCE5",
13+
"border-strong": "#B5BCCB",
14+
"text": "#141E34",
15+
"text-2": "#444E64",
16+
"text-muted": "#8590A9",
17+
"error": "#CA3038",
18+
"error-subtle": "#DDCDDF",
19+
"warning": "#E09821",
20+
"warning-subtle": "#E0DDDB",
21+
"success": "#1C9A54",
22+
"success-subtle": "#C3DDE3",
23+
"dark-bg": "#11192C",
24+
"dark-surface": "#172137",
25+
"dark-surface2": "#1D273F",
26+
"dark-border": "#1F2D4A",
27+
"dark-border_strong": "#2C3C5E",
28+
"dark-text": "#E0E7F5",
29+
"dark-text2": "#8497B8",
30+
"dark-text_muted": "#7388A6",
31+
"dark-brand_subtle": "#1A2E5B",
32+
"dark-error_subtle": "#3C293E",
33+
"dark-warning_subtle": "#403C3A",
34+
"dark-success_subtle": "#1D3C43",
35+
"dark-shadow_sm": "0 0 0 1px rgba(37, 99, 235, 0.1)",
36+
"dark-shadow_md": "0 4px 20px rgba(0, 0, 0, 0.40), 0 0 0 1px rgba(37, 99, 235, 0.06)",
37+
"dark-shadow_lg": "0 12px 40px rgba(0, 0, 0, 0.45), 0 0 0 1px rgba(37, 99, 235, 0.08)",
38+
},
39+
boxShadow: {
40+
"shadow_sm": "0 1px 3px rgba(37, 99, 235, 0.08), 0 0 0 1px rgba(37, 99, 235, 0.04)",
41+
"shadow_md": "0 4px 16px rgba(37, 99, 235, 0.1), 0 1px 4px rgba(37, 99, 235, 0.06)",
42+
"shadow_lg": "0 12px 40px rgba(37, 99, 235, 0.12), 0 2px 8px rgba(37, 99, 235, 0.06)",
43+
"dark-shadow_sm": "0 0 0 1px rgba(37, 99, 235, 0.1)",
44+
"dark-shadow_md": "0 4px 20px rgba(0, 0, 0, 0.40), 0 0 0 1px rgba(37, 99, 235, 0.06)",
45+
"dark-shadow_lg": "0 12px 40px rgba(0, 0, 0, 0.45), 0 0 0 1px rgba(37, 99, 235, 0.08)",
46+
},
47+
},
48+
},
49+
}

0 commit comments

Comments
 (0)