@fastwork/xosmoz-theme 0.42.0 → 0.45.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/dart/xz_colors.generated.dart +108 -0
- package/dist/figma-plugin.zip +0 -0
- package/dist/figma-tokens/Dark.json +971 -217
- package/dist/figma-tokens/Light.json +977 -223
- package/dist/index.js +32 -16
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +32 -16
- package/dist/index.mjs.map +1 -1
- package/dist/themes/dark.css +8 -0
- package/dist/themes/light.css +8 -0
- package/dist/themes.css +16 -0
- package/llms.txt +371 -168
- package/package.json +1 -1
package/llms.txt
CHANGED
|
@@ -1,17 +1,21 @@
|
|
|
1
|
-
# @fastwork/xosmoz-theme
|
|
1
|
+
# @fastwork/xosmoz-theme — Color Tokens & Usage Guide
|
|
2
2
|
|
|
3
|
-
> Design
|
|
3
|
+
> Design token system for Xosmoz. Uses OKLCH color space. Supports light and dark themes via CSS variables and `data-theme` attribute. This guide covers color tokens only (CSS variables).
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Setup
|
|
8
|
+
|
|
9
|
+
### Install
|
|
6
10
|
|
|
7
11
|
```bash
|
|
8
12
|
npm install @fastwork/xosmoz-theme
|
|
9
13
|
```
|
|
10
14
|
|
|
11
|
-
|
|
15
|
+
### CSS Imports
|
|
12
16
|
|
|
13
17
|
```css
|
|
14
|
-
/* Base styles: CSS reset, font imports, typography/spacing
|
|
18
|
+
/* Base styles: CSS reset, font imports, typography/spacing tokens */
|
|
15
19
|
@import '@fastwork/xosmoz-theme/base.css';
|
|
16
20
|
|
|
17
21
|
/* All themes (light + dark) */
|
|
@@ -22,227 +26,239 @@ npm install @fastwork/xosmoz-theme
|
|
|
22
26
|
@import '@fastwork/xosmoz-theme/themes/dark.css';
|
|
23
27
|
```
|
|
24
28
|
|
|
25
|
-
|
|
29
|
+
### Theme Switching
|
|
26
30
|
|
|
27
|
-
|
|
31
|
+
Light theme is the default. Set `data-theme="dark"` on `<html>` for dark mode.
|
|
28
32
|
|
|
29
33
|
```html
|
|
30
|
-
<html>...</html>
|
|
31
|
-
<html data-theme="dark">...</html>
|
|
34
|
+
<html>...</html> <!-- Light theme (default) -->
|
|
35
|
+
<html data-theme="dark">...</html> <!-- Dark theme -->
|
|
32
36
|
```
|
|
33
37
|
|
|
34
38
|
```javascript
|
|
35
|
-
// Switch
|
|
39
|
+
// Switch at runtime
|
|
36
40
|
document.documentElement.setAttribute('data-theme', 'dark');
|
|
41
|
+
document.documentElement.removeAttribute('data-theme'); // back to light
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
---
|
|
37
45
|
|
|
38
|
-
|
|
39
|
-
|
|
46
|
+
## Color Token Architecture
|
|
47
|
+
|
|
48
|
+
The system has two layers:
|
|
49
|
+
|
|
50
|
+
### Layer 1 — Palette Tokens (primitives)
|
|
51
|
+
Eight raw color values. These are single CSS variables (no numbered scales). They are the same in both light and dark themes.
|
|
52
|
+
|
|
53
|
+
```
|
|
54
|
+
--xz-color-fastwork (brand blue-purple)
|
|
55
|
+
--xz-color-gray
|
|
56
|
+
--xz-color-green
|
|
57
|
+
--xz-color-yellow
|
|
58
|
+
--xz-color-red
|
|
59
|
+
--xz-color-orange
|
|
60
|
+
--xz-color-purple
|
|
61
|
+
--xz-color-cyan
|
|
40
62
|
```
|
|
41
63
|
|
|
42
|
-
|
|
64
|
+
**Rule: Do not use palette tokens directly in UI.** They exist as internal primitives. Always use semantic tokens instead.
|
|
43
65
|
|
|
44
|
-
|
|
66
|
+
### Layer 2 — Semantic Tokens (theme-aware)
|
|
67
|
+
These tokens change values between light and dark themes. Always use these for UI components, text, borders, and backgrounds.
|
|
45
68
|
|
|
46
|
-
|
|
69
|
+
Pattern: `--xz-color-{category}-{property}-{scale}`
|
|
47
70
|
|
|
48
|
-
|
|
71
|
+
---
|
|
49
72
|
|
|
50
|
-
|
|
51
|
-
|----------|---------|
|
|
52
|
-
| `--xz-color-surface-100` | Page background |
|
|
53
|
-
| `--xz-color-surface-200` | Elevated surface (cards, modals) |
|
|
54
|
-
| `--xz-color-surface-300` | Secondary surface |
|
|
55
|
-
| `--xz-color-surface-400` | Tertiary surface / popovers |
|
|
56
|
-
| `--xz-color-text-100` | Primary text color |
|
|
57
|
-
| `--xz-color-text-200` | Secondary/muted text (70% opacity) |
|
|
58
|
-
| `--xz-color-text-300` | Tertiary/disabled text (50% opacity) |
|
|
59
|
-
| `--xz-color-bg-100` | Extreme base background (near-black in light, near-white in dark) |
|
|
60
|
-
| `--xz-color-fg-100` | Text on bg-100 (white in light, black in dark) |
|
|
61
|
-
| `--xz-color-soft-100` | Very subtle overlay (5% opacity of bg) |
|
|
62
|
-
| `--xz-color-soft-200` | Subtle overlay (10% opacity of bg) |
|
|
63
|
-
| `--xz-color-line-100` | Subtle borders |
|
|
64
|
-
| `--xz-color-line-200` | Default borders |
|
|
65
|
-
| `--xz-color-line-300` | Strong/emphasized borders |
|
|
73
|
+
## Base Tokens
|
|
66
74
|
|
|
67
|
-
|
|
75
|
+
Base tokens cover surfaces, text, borders, and neutral overlays. They are theme-aware (change in dark mode).
|
|
68
76
|
|
|
69
|
-
|
|
77
|
+
| CSS Variable | Purpose |
|
|
78
|
+
|---|---|
|
|
79
|
+
| `--xz-color-surface-50` | Absolute white/darkest background (page canvas extreme) |
|
|
80
|
+
| `--xz-color-surface-100` | Default page background |
|
|
81
|
+
| `--xz-color-surface-200` | Elevated surface — cards, modals |
|
|
82
|
+
| `--xz-color-surface-300` | Secondary elevated surface |
|
|
83
|
+
| `--xz-color-surface-400` | Tertiary elevated surface — popovers, dropdowns |
|
|
84
|
+
| `--xz-color-bg-100` | Extreme base (near-black in light / near-white in dark) |
|
|
85
|
+
| `--xz-color-bg-200` | Secondary extreme base |
|
|
86
|
+
| `--xz-color-fg-100` | Text/icon on bg-100 and bg-200 |
|
|
87
|
+
| `--xz-color-text-100` | Primary text |
|
|
88
|
+
| `--xz-color-text-200` | Secondary / muted text (70% opacity) |
|
|
89
|
+
| `--xz-color-text-300` | Disabled / placeholder text (60% opacity) |
|
|
90
|
+
| `--xz-color-soft-100` | Very subtle neutral overlay (5% opacity) |
|
|
91
|
+
| `--xz-color-soft-200` | Subtle neutral overlay (10% opacity) |
|
|
92
|
+
| `--xz-color-line-100` | Subtle border |
|
|
93
|
+
| `--xz-color-line-200` | Default border |
|
|
94
|
+
| `--xz-color-line-300` | Emphasized border |
|
|
70
95
|
|
|
71
|
-
|
|
96
|
+
---
|
|
72
97
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
98
|
+
## Semantic Tokens
|
|
99
|
+
|
|
100
|
+
Eight categories, each with 11 tokens. Categories: `primary`, `danger`, `success`, `warning`, `info`, `neutral`, `orange`, `purple`.
|
|
101
|
+
|
|
102
|
+
### Token Pattern per Category
|
|
103
|
+
|
|
104
|
+
Replace `{name}` with the category:
|
|
105
|
+
|
|
106
|
+
| CSS Variable | Purpose |
|
|
107
|
+
|---|---|
|
|
108
|
+
| `--xz-color-{name}-soft-100` | Tinted transparent background — lightest (10% opacity of base color) |
|
|
109
|
+
| `--xz-color-{name}-soft-200` | Tinted transparent background — stronger (16% opacity), use for hover |
|
|
110
|
+
| `--xz-color-{name}-soft-solid-100` | Opaque version of soft-100 (mixed into surface-100) — use on overlapping surfaces |
|
|
111
|
+
| `--xz-color-{name}-soft-solid-200` | Opaque version of soft-200 |
|
|
77
112
|
| `--xz-color-{name}-line-100` | Subtle colored border |
|
|
78
113
|
| `--xz-color-{name}-line-200` | Default colored border |
|
|
79
114
|
| `--xz-color-{name}-line-300` | Strong colored border |
|
|
80
|
-
| `--xz-color-{name}-bg-100` | Solid fill background
|
|
81
|
-
| `--xz-color-{name}-bg-200` |
|
|
82
|
-
| `--xz-color-{name}-fg-100` | Text on solid bg —
|
|
83
|
-
| `--xz-color-{name}-text-100` | Colored text on surfaces
|
|
115
|
+
| `--xz-color-{name}-bg-100` | Solid fill background — buttons, chips, badges |
|
|
116
|
+
| `--xz-color-{name}-bg-200` | Solid fill hover/pressed state |
|
|
117
|
+
| `--xz-color-{name}-fg-100` | Text/icon on solid bg — **always pair with bg-100 / bg-200** |
|
|
118
|
+
| `--xz-color-{name}-text-100` | Colored text on light surfaces — links, status labels |
|
|
84
119
|
|
|
85
|
-
|
|
120
|
+
### Key Rules for Semantic Tokens
|
|
86
121
|
|
|
87
|
-
|
|
122
|
+
- **`bg-100` + `fg-100`**: Solid fill components (buttons, solid badges). `fg-100` provides correct contrast (white or dark depending on the category color).
|
|
123
|
+
- **`soft-100` + `text-100` + `line-100`**: Soft/tinted style (alerts, soft badges, highlighted rows).
|
|
124
|
+
- **`soft-solid-*`**: Use instead of `soft-*` when the component sits on a non-transparent surface (e.g., inside a card that has its own background).
|
|
125
|
+
- **`text-100`**: Use for colored text that sits on surface backgrounds (not on solid fills). Examples: link text, status label text, tag text.
|
|
126
|
+
- **`line-*`**: Colored borders. Use `line-200` as the default, `line-100` for subtle, `line-300` for strong/emphasized.
|
|
88
127
|
|
|
89
|
-
|
|
128
|
+
---
|
|
90
129
|
|
|
91
|
-
|
|
92
|
-
--xz-color-{palette}-100 (lightest)
|
|
93
|
-
--xz-color-{palette}-200
|
|
94
|
-
...
|
|
95
|
-
--xz-color-{palette}-1000 (darkest)
|
|
96
|
-
```
|
|
130
|
+
## Alpha & Overlay Tokens
|
|
97
131
|
|
|
98
|
-
|
|
132
|
+
These use a 100–1000 scale representing opacity from 0.1 to 1.0.
|
|
99
133
|
|
|
100
|
-
### Typography
|
|
101
|
-
|
|
102
|
-
```
|
|
103
|
-
--xz-font-size-50 (0.5rem / 8px)
|
|
104
|
-
--xz-font-size-100 (0.625rem / 10px)
|
|
105
|
-
--xz-font-size-200 (0.75rem / 12px)
|
|
106
|
-
--xz-font-size-300 (0.875rem / 14px)
|
|
107
|
-
--xz-font-size-400 (1rem / 16px)
|
|
108
|
-
--xz-font-size-500 (1.125rem / 18px)
|
|
109
|
-
--xz-font-size-600 (1.25rem / 20px)
|
|
110
|
-
--xz-font-size-700 (1.5rem / 24px)
|
|
111
|
-
--xz-font-size-800 (1.625rem / 26px)
|
|
112
|
-
--xz-font-size-900 (2rem / 32px)
|
|
113
|
-
--xz-font-size-1000 (2.375rem / 38px)
|
|
114
|
-
--xz-font-size-1100 (2.5rem / 40px)
|
|
115
|
-
--xz-font-size-1200 (2.6875rem / 43px)
|
|
116
|
-
--xz-font-size-1300 (3rem / 48px)
|
|
117
|
-
--xz-font-size-1400 (3.5rem / 56px)
|
|
118
|
-
--xz-font-size-1500 (4rem / 64px)
|
|
119
|
-
--xz-font-size-1600 (4.5rem / 72px)
|
|
120
|
-
|
|
121
|
-
--xz-font-family-primary (system-ui sans-serif stack)
|
|
122
|
-
--xz-font-family-secondary ("Fastwork" + "Noto Sans Thai" + system fallbacks)
|
|
123
|
-
|
|
124
|
-
--xz-line-height-100pct (1)
|
|
125
|
-
--xz-line-height-125pct (1.25)
|
|
126
|
-
--xz-line-height-135pct (1.35)
|
|
127
|
-
--xz-line-height-150pct (1.5)
|
|
128
|
-
--xz-line-height-165pct (1.65)
|
|
129
|
-
--xz-line-height-200pct (2)
|
|
130
134
|
```
|
|
135
|
+
--xz-color-black-alpha-100 (black at 10% opacity)
|
|
136
|
+
--xz-color-black-alpha-200 (black at 20% opacity)
|
|
137
|
+
...
|
|
138
|
+
--xz-color-black-alpha-1000 (black at 100% opacity)
|
|
131
139
|
|
|
132
|
-
|
|
140
|
+
--xz-color-white-alpha-100 (white at 10% opacity)
|
|
141
|
+
...
|
|
142
|
+
--xz-color-white-alpha-1000 (white at 100% opacity)
|
|
133
143
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
--xz-
|
|
137
|
-
--xz-font-subtitle1-bold, --xz-font-subtitle1-regular
|
|
138
|
-
--xz-font-subtitle2-bold, --xz-font-subtitle2-regular
|
|
139
|
-
--xz-font-subtitle3-bold, --xz-font-subtitle3-regular
|
|
140
|
-
--xz-font-body1 through --xz-font-body4 (primary font, regular)
|
|
144
|
+
--xz-color-overlay-100 (dark overlay at 10% opacity)
|
|
145
|
+
...
|
|
146
|
+
--xz-color-overlay-1000 (dark overlay at 100% opacity)
|
|
141
147
|
```
|
|
142
148
|
|
|
143
|
-
|
|
149
|
+
Use `overlay-*` for modal/drawer backdrops. Use `black-alpha-*` / `white-alpha-*` for scrim layers or icon fills with transparency.
|
|
144
150
|
|
|
145
|
-
|
|
151
|
+
---
|
|
146
152
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
--xz-box-shadow-300 (medium: 0 4px 16px)
|
|
151
|
-
--xz-box-shadow-400 (large: 0 8px 20px)
|
|
152
|
-
```
|
|
153
|
+
## Usage Guidelines
|
|
154
|
+
|
|
155
|
+
### Backgrounds & Surfaces
|
|
153
156
|
|
|
154
|
-
|
|
157
|
+
| Situation | Use |
|
|
158
|
+
|---|---|
|
|
159
|
+
| Page background | `--xz-color-surface-100` |
|
|
160
|
+
| Card, modal, dialog | `--xz-color-surface-200` |
|
|
161
|
+
| Nested card or secondary panel | `--xz-color-surface-300` |
|
|
162
|
+
| Popover, dropdown, tooltip | `--xz-color-surface-400` |
|
|
163
|
+
| Inverted/dark block on page | `--xz-color-bg-100` |
|
|
164
|
+
| Text on inverted block | `--xz-color-fg-100` |
|
|
155
165
|
|
|
156
|
-
###
|
|
166
|
+
### Text
|
|
157
167
|
|
|
158
|
-
|
|
159
|
-
|
|
168
|
+
| Situation | Use |
|
|
169
|
+
|---|---|
|
|
170
|
+
| Body text, headings | `--xz-color-text-100` |
|
|
171
|
+
| Secondary / helper text | `--xz-color-text-200` |
|
|
172
|
+
| Placeholder / disabled text | `--xz-color-text-300` |
|
|
173
|
+
| Colored status text (link, tag, label) | `--xz-color-{name}-text-100` |
|
|
160
174
|
|
|
161
|
-
|
|
162
|
-
lightTheme.colors.fastwork[600] // 'oklch(0.613 0.233 260.608)'
|
|
163
|
-
lightTheme.colors.gray[300] // raw palette value
|
|
175
|
+
### Borders
|
|
164
176
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
177
|
+
| Situation | Use |
|
|
178
|
+
|---|---|
|
|
179
|
+
| Subtle separator, divider | `--xz-color-line-100` |
|
|
180
|
+
| Default input or card border | `--xz-color-line-200` |
|
|
181
|
+
| Strong border, active outline | `--xz-color-line-300` |
|
|
182
|
+
| Colored border (semantic) | `--xz-color-{name}-line-100/200/300` |
|
|
171
183
|
|
|
172
|
-
|
|
173
|
-
lightTheme.colors.surface[200] // card background
|
|
174
|
-
lightTheme.colors.text[100] // primary text
|
|
184
|
+
### Solid Components (Buttons, Solid Badges)
|
|
175
185
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
186
|
+
```
|
|
187
|
+
background: --xz-color-{name}-bg-100
|
|
188
|
+
color: --xz-color-{name}-fg-100 ← always use fg-100 on bg-100
|
|
189
|
+
hover bg: --xz-color-{name}-bg-200
|
|
190
|
+
```
|
|
181
191
|
|
|
182
|
-
|
|
183
|
-
const theme = getTheme('dark');
|
|
192
|
+
### Soft/Tinted Components (Alerts, Soft Badges)
|
|
184
193
|
|
|
185
|
-
|
|
186
|
-
|
|
194
|
+
```
|
|
195
|
+
background: --xz-color-{name}-soft-100
|
|
196
|
+
color: --xz-color-{name}-text-100
|
|
197
|
+
border: 1px solid --xz-color-{name}-line-100
|
|
187
198
|
```
|
|
188
199
|
|
|
189
|
-
###
|
|
200
|
+
### Outline/Ghost Components
|
|
190
201
|
|
|
191
|
-
```
|
|
192
|
-
|
|
202
|
+
```
|
|
203
|
+
background: transparent
|
|
204
|
+
color: --xz-color-{name}-text-100
|
|
205
|
+
border: 1px solid --xz-color-{name}-line-200
|
|
206
|
+
```
|
|
193
207
|
|
|
194
|
-
|
|
195
|
-
fontSize[700] // '1.5rem'
|
|
196
|
-
fontWeight[700] // 700
|
|
197
|
-
fontFamily.primary // system sans-serif stack
|
|
198
|
-
fontFamily.secondary // "Fastwork" + fallbacks
|
|
199
|
-
lineHeight['150pct'] // '1.5'
|
|
208
|
+
### Focus Ring
|
|
200
209
|
|
|
201
|
-
font.heading1 // { fontFamily, fontSize: { desktop, mobile }, fontWeight, lineHeight }
|
|
202
|
-
font.title2
|
|
203
|
-
font.subtitle1Bold
|
|
204
|
-
font.body1
|
|
205
210
|
```
|
|
211
|
+
border-color: --xz-color-{name}-line-200
|
|
212
|
+
box-shadow: 0 0 0 3px --xz-color-{name}-soft-100
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
### Modal Backdrop
|
|
206
216
|
|
|
207
|
-
### Types
|
|
208
|
-
|
|
209
|
-
```typescript
|
|
210
|
-
import type {
|
|
211
|
-
ThemeConfig,
|
|
212
|
-
ThemeName,
|
|
213
|
-
ThemeRegistry,
|
|
214
|
-
ColorToken,
|
|
215
|
-
TypographyToken,
|
|
216
|
-
TypographyScale,
|
|
217
|
-
FontWeights,
|
|
218
|
-
} from '@fastwork/xosmoz-theme';
|
|
219
217
|
```
|
|
218
|
+
background: --xz-color-overlay-600
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
---
|
|
220
222
|
|
|
221
|
-
## Common Patterns
|
|
223
|
+
## Common UI Patterns
|
|
222
224
|
|
|
223
|
-
### Primary
|
|
225
|
+
### Primary Button
|
|
224
226
|
|
|
225
227
|
```css
|
|
226
|
-
.
|
|
228
|
+
.btn-primary {
|
|
227
229
|
background: var(--xz-color-primary-bg-100);
|
|
228
|
-
color: var(--xz-color-primary-fg-100);
|
|
229
|
-
font: var(--xz-font-subtitle1-bold);
|
|
230
|
+
color: var(--xz-color-primary-fg-100);
|
|
230
231
|
border: none;
|
|
231
|
-
border-radius: 0.5rem;
|
|
232
232
|
}
|
|
233
|
-
.
|
|
233
|
+
.btn-primary:hover {
|
|
234
234
|
background: var(--xz-color-primary-bg-200);
|
|
235
235
|
}
|
|
236
236
|
```
|
|
237
237
|
|
|
238
|
-
###
|
|
238
|
+
### Outline Button
|
|
239
239
|
|
|
240
240
|
```css
|
|
241
|
-
.
|
|
241
|
+
.btn-outline {
|
|
242
242
|
background: transparent;
|
|
243
243
|
color: var(--xz-color-primary-text-100);
|
|
244
244
|
border: 1px solid var(--xz-color-primary-line-200);
|
|
245
245
|
}
|
|
246
|
+
.btn-outline:hover {
|
|
247
|
+
background: var(--xz-color-primary-soft-100);
|
|
248
|
+
}
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
### Danger Button
|
|
252
|
+
|
|
253
|
+
```css
|
|
254
|
+
.btn-danger {
|
|
255
|
+
background: var(--xz-color-danger-bg-100);
|
|
256
|
+
color: var(--xz-color-danger-fg-100);
|
|
257
|
+
border: none;
|
|
258
|
+
}
|
|
259
|
+
.btn-danger:hover {
|
|
260
|
+
background: var(--xz-color-danger-bg-200);
|
|
261
|
+
}
|
|
246
262
|
```
|
|
247
263
|
|
|
248
264
|
### Card
|
|
@@ -252,44 +268,231 @@ import type {
|
|
|
252
268
|
background: var(--xz-color-surface-200);
|
|
253
269
|
color: var(--xz-color-text-100);
|
|
254
270
|
border: 1px solid var(--xz-color-line-100);
|
|
255
|
-
border-radius: 0.75rem;
|
|
256
|
-
box-shadow: var(--xz-box-shadow-200);
|
|
257
271
|
}
|
|
258
272
|
```
|
|
259
273
|
|
|
260
|
-
### Alert
|
|
274
|
+
### Alert (soft style)
|
|
261
275
|
|
|
262
276
|
```css
|
|
277
|
+
/* Replace {name} with: success | danger | warning | info */
|
|
263
278
|
.alert-success {
|
|
264
279
|
background: var(--xz-color-success-soft-100);
|
|
265
280
|
color: var(--xz-color-success-text-100);
|
|
266
281
|
border: 1px solid var(--xz-color-success-line-100);
|
|
267
282
|
}
|
|
283
|
+
.alert-danger {
|
|
284
|
+
background: var(--xz-color-danger-soft-100);
|
|
285
|
+
color: var(--xz-color-danger-text-100);
|
|
286
|
+
border: 1px solid var(--xz-color-danger-line-100);
|
|
287
|
+
}
|
|
288
|
+
.alert-warning {
|
|
289
|
+
background: var(--xz-color-warning-soft-100);
|
|
290
|
+
color: var(--xz-color-warning-text-100);
|
|
291
|
+
border: 1px solid var(--xz-color-warning-line-100);
|
|
292
|
+
}
|
|
293
|
+
.alert-info {
|
|
294
|
+
background: var(--xz-color-info-soft-100);
|
|
295
|
+
color: var(--xz-color-info-text-100);
|
|
296
|
+
border: 1px solid var(--xz-color-info-line-100);
|
|
297
|
+
}
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
### Badge — Soft
|
|
301
|
+
|
|
302
|
+
```css
|
|
303
|
+
.badge-success {
|
|
304
|
+
background: var(--xz-color-success-soft-100);
|
|
305
|
+
color: var(--xz-color-success-text-100);
|
|
306
|
+
}
|
|
307
|
+
```
|
|
268
308
|
|
|
269
|
-
|
|
309
|
+
### Badge — Solid
|
|
310
|
+
|
|
311
|
+
```css
|
|
312
|
+
.badge-danger-solid {
|
|
270
313
|
background: var(--xz-color-danger-bg-100);
|
|
271
|
-
color: var(--xz-color-danger-fg-100);
|
|
314
|
+
color: var(--xz-color-danger-fg-100);
|
|
272
315
|
}
|
|
273
316
|
```
|
|
274
317
|
|
|
275
|
-
### Form
|
|
318
|
+
### Form Input
|
|
276
319
|
|
|
277
320
|
```css
|
|
278
321
|
.input {
|
|
279
322
|
background: var(--xz-color-surface-100);
|
|
280
323
|
color: var(--xz-color-text-100);
|
|
281
324
|
border: 1px solid var(--xz-color-line-200);
|
|
282
|
-
|
|
325
|
+
}
|
|
326
|
+
.input::placeholder {
|
|
327
|
+
color: var(--xz-color-text-300);
|
|
283
328
|
}
|
|
284
329
|
.input:focus {
|
|
285
330
|
border-color: var(--xz-color-primary-line-200);
|
|
286
331
|
box-shadow: 0 0 0 3px var(--xz-color-primary-soft-100);
|
|
332
|
+
outline: none;
|
|
333
|
+
}
|
|
334
|
+
.input.error {
|
|
335
|
+
border-color: var(--xz-color-danger-line-200);
|
|
336
|
+
box-shadow: 0 0 0 3px var(--xz-color-danger-soft-100);
|
|
287
337
|
}
|
|
288
338
|
```
|
|
289
339
|
|
|
290
|
-
###
|
|
340
|
+
### Text Hierarchy
|
|
291
341
|
|
|
292
342
|
```css
|
|
293
|
-
.text-
|
|
294
|
-
.text-
|
|
343
|
+
.text-primary { color: var(--xz-color-text-100); }
|
|
344
|
+
.text-muted { color: var(--xz-color-text-200); }
|
|
345
|
+
.text-disabled { color: var(--xz-color-text-300); }
|
|
346
|
+
.text-link { color: var(--xz-color-primary-text-100); }
|
|
347
|
+
.text-danger { color: var(--xz-color-danger-text-100); }
|
|
348
|
+
.text-success { color: var(--xz-color-success-text-100); }
|
|
295
349
|
```
|
|
350
|
+
|
|
351
|
+
---
|
|
352
|
+
|
|
353
|
+
## Figma Variables Guide
|
|
354
|
+
|
|
355
|
+
Figma variables mirror the CSS token system exactly. Every CSS variable has a corresponding Figma variable in the same collection.
|
|
356
|
+
|
|
357
|
+
### Collection Structure
|
|
358
|
+
|
|
359
|
+
- **Collection name**: `colors`
|
|
360
|
+
- **Modes**: `Light` and `Dark`
|
|
361
|
+
- **Total variables**: ~160 color variables
|
|
362
|
+
|
|
363
|
+
### Naming Pattern
|
|
364
|
+
|
|
365
|
+
Figma uses slash-separated paths. The mapping to CSS is direct:
|
|
366
|
+
|
|
367
|
+
| Variable type | Figma path | CSS variable |
|
|
368
|
+
|---|---|---|
|
|
369
|
+
| Base theme token | `theme/base/{property}/{scale}` | `--xz-color-{property}-{scale}` |
|
|
370
|
+
| Semantic theme token | `theme/{category}/{property}/{scale}` | `--xz-color-{category}-{property}-{scale}` |
|
|
371
|
+
| Alpha token | `theme/blackAlpha/{scale}` | `--xz-color-black-alpha-{scale}` |
|
|
372
|
+
| Alpha token | `theme/whiteAlpha/{scale}` | `--xz-color-white-alpha-{scale}` |
|
|
373
|
+
| Overlay token | `theme/overlay/{scale}` | `--xz-color-overlay-{scale}` |
|
|
374
|
+
| Palette primitive | `palette/{name}` | `--xz-color-{name}` |
|
|
375
|
+
|
|
376
|
+
### Complete Figma → CSS Mapping
|
|
377
|
+
|
|
378
|
+
#### Base (16 variables)
|
|
379
|
+
|
|
380
|
+
| Figma Variable | CSS Variable |
|
|
381
|
+
|---|---|
|
|
382
|
+
| `theme/base/bg/100` | `--xz-color-bg-100` |
|
|
383
|
+
| `theme/base/bg/200` | `--xz-color-bg-200` |
|
|
384
|
+
| `theme/base/surface/50` | `--xz-color-surface-50` |
|
|
385
|
+
| `theme/base/surface/100` | `--xz-color-surface-100` |
|
|
386
|
+
| `theme/base/surface/200` | `--xz-color-surface-200` |
|
|
387
|
+
| `theme/base/surface/300` | `--xz-color-surface-300` |
|
|
388
|
+
| `theme/base/surface/400` | `--xz-color-surface-400` |
|
|
389
|
+
| `theme/base/fg/100` | `--xz-color-fg-100` |
|
|
390
|
+
| `theme/base/soft/100` | `--xz-color-soft-100` |
|
|
391
|
+
| `theme/base/soft/200` | `--xz-color-soft-200` |
|
|
392
|
+
| `theme/base/text/100` | `--xz-color-text-100` |
|
|
393
|
+
| `theme/base/text/200` | `--xz-color-text-200` |
|
|
394
|
+
| `theme/base/text/300` | `--xz-color-text-300` |
|
|
395
|
+
| `theme/base/line/100` | `--xz-color-line-100` |
|
|
396
|
+
| `theme/base/line/200` | `--xz-color-line-200` |
|
|
397
|
+
| `theme/base/line/300` | `--xz-color-line-300` |
|
|
398
|
+
|
|
399
|
+
#### Semantic Categories (11 variables each)
|
|
400
|
+
|
|
401
|
+
Same pattern for all 8 categories: `primary`, `danger`, `success`, `warning`, `info`, `neutral`, `orange`, `purple`.
|
|
402
|
+
|
|
403
|
+
| Figma Variable | CSS Variable |
|
|
404
|
+
|---|---|
|
|
405
|
+
| `theme/{name}/soft/100` | `--xz-color-{name}-soft-100` |
|
|
406
|
+
| `theme/{name}/soft/200` | `--xz-color-{name}-soft-200` |
|
|
407
|
+
| `theme/{name}/softSolid/100` | `--xz-color-{name}-soft-solid-100` |
|
|
408
|
+
| `theme/{name}/softSolid/200` | `--xz-color-{name}-soft-solid-200` |
|
|
409
|
+
| `theme/{name}/line/100` | `--xz-color-{name}-line-100` |
|
|
410
|
+
| `theme/{name}/line/200` | `--xz-color-{name}-line-200` |
|
|
411
|
+
| `theme/{name}/line/300` | `--xz-color-{name}-line-300` |
|
|
412
|
+
| `theme/{name}/bg/100` | `--xz-color-{name}-bg-100` |
|
|
413
|
+
| `theme/{name}/bg/200` | `--xz-color-{name}-bg-200` |
|
|
414
|
+
| `theme/{name}/fg/100` | `--xz-color-{name}-fg-100` |
|
|
415
|
+
| `theme/{name}/text/100` | `--xz-color-{name}-text-100` |
|
|
416
|
+
|
|
417
|
+
#### Black Alpha (10 variables)
|
|
418
|
+
|
|
419
|
+
| Figma Variable | CSS Variable |
|
|
420
|
+
|---|---|
|
|
421
|
+
| `theme/blackAlpha/100` | `--xz-color-black-alpha-100` |
|
|
422
|
+
| `theme/blackAlpha/200` | `--xz-color-black-alpha-200` |
|
|
423
|
+
| `theme/blackAlpha/300` | `--xz-color-black-alpha-300` |
|
|
424
|
+
| `theme/blackAlpha/400` | `--xz-color-black-alpha-400` |
|
|
425
|
+
| `theme/blackAlpha/500` | `--xz-color-black-alpha-500` |
|
|
426
|
+
| `theme/blackAlpha/600` | `--xz-color-black-alpha-600` |
|
|
427
|
+
| `theme/blackAlpha/700` | `--xz-color-black-alpha-700` |
|
|
428
|
+
| `theme/blackAlpha/800` | `--xz-color-black-alpha-800` |
|
|
429
|
+
| `theme/blackAlpha/900` | `--xz-color-black-alpha-900` |
|
|
430
|
+
| `theme/blackAlpha/1000` | `--xz-color-black-alpha-1000` |
|
|
431
|
+
|
|
432
|
+
#### White Alpha (10 variables)
|
|
433
|
+
|
|
434
|
+
| Figma Variable | CSS Variable |
|
|
435
|
+
|---|---|
|
|
436
|
+
| `theme/whiteAlpha/100` | `--xz-color-white-alpha-100` |
|
|
437
|
+
| `theme/whiteAlpha/200` | `--xz-color-white-alpha-200` |
|
|
438
|
+
| `theme/whiteAlpha/300` | `--xz-color-white-alpha-300` |
|
|
439
|
+
| `theme/whiteAlpha/400` | `--xz-color-white-alpha-400` |
|
|
440
|
+
| `theme/whiteAlpha/500` | `--xz-color-white-alpha-500` |
|
|
441
|
+
| `theme/whiteAlpha/600` | `--xz-color-white-alpha-600` |
|
|
442
|
+
| `theme/whiteAlpha/700` | `--xz-color-white-alpha-700` |
|
|
443
|
+
| `theme/whiteAlpha/800` | `--xz-color-white-alpha-800` |
|
|
444
|
+
| `theme/whiteAlpha/900` | `--xz-color-white-alpha-900` |
|
|
445
|
+
| `theme/whiteAlpha/1000` | `--xz-color-white-alpha-1000` |
|
|
446
|
+
|
|
447
|
+
#### Overlay (10 variables)
|
|
448
|
+
|
|
449
|
+
| Figma Variable | CSS Variable |
|
|
450
|
+
|---|---|
|
|
451
|
+
| `theme/overlay/100` | `--xz-color-overlay-100` |
|
|
452
|
+
| `theme/overlay/200` | `--xz-color-overlay-200` |
|
|
453
|
+
| `theme/overlay/300` | `--xz-color-overlay-300` |
|
|
454
|
+
| `theme/overlay/400` | `--xz-color-overlay-400` |
|
|
455
|
+
| `theme/overlay/500` | `--xz-color-overlay-500` |
|
|
456
|
+
| `theme/overlay/600` | `--xz-color-overlay-600` |
|
|
457
|
+
| `theme/overlay/700` | `--xz-color-overlay-700` |
|
|
458
|
+
| `theme/overlay/800` | `--xz-color-overlay-800` |
|
|
459
|
+
| `theme/overlay/900` | `--xz-color-overlay-900` |
|
|
460
|
+
| `theme/overlay/1000` | `--xz-color-overlay-1000` |
|
|
461
|
+
|
|
462
|
+
#### Palette (8 variables)
|
|
463
|
+
|
|
464
|
+
| Figma Variable | CSS Variable |
|
|
465
|
+
|---|---|
|
|
466
|
+
| `palette/fastwork` | `--xz-color-fastwork` |
|
|
467
|
+
| `palette/gray` | `--xz-color-gray` |
|
|
468
|
+
| `palette/green` | `--xz-color-green` |
|
|
469
|
+
| `palette/yellow` | `--xz-color-yellow` |
|
|
470
|
+
| `palette/red` | `--xz-color-red` |
|
|
471
|
+
| `palette/orange` | `--xz-color-orange` |
|
|
472
|
+
| `palette/purple` | `--xz-color-purple` |
|
|
473
|
+
| `palette/cyan` | `--xz-color-cyan` |
|
|
474
|
+
|
|
475
|
+
### How to Use Figma Variables in Designs
|
|
476
|
+
|
|
477
|
+
1. Select a layer in Figma (frame, text, shape, etc.)
|
|
478
|
+
2. In the Fill or Stroke panel, click the color swatch
|
|
479
|
+
3. Switch to the **Variables** tab in the color picker
|
|
480
|
+
4. Pick from the `colors` collection
|
|
481
|
+
|
|
482
|
+
**Rules for Figma:**
|
|
483
|
+
- Always use `theme/*` variables for component fills, text colors, and stroke colors
|
|
484
|
+
- Use `palette/*` variables only as references — not directly on components
|
|
485
|
+
- Use `theme/base/surface/100` for page backgrounds, `theme/base/surface/200` for cards
|
|
486
|
+
- Use `theme/{name}/bg/100` for solid-filled elements and `theme/{name}/fg/100` for text on top of them
|
|
487
|
+
- Switch between Light/Dark previews using the **Mode** toggle on the variable collection
|
|
488
|
+
|
|
489
|
+
### Keeping Figma in Sync with Code
|
|
490
|
+
|
|
491
|
+
Variables are synced from the npm package via the **XOSMOZ Theme Sync** plugin:
|
|
492
|
+
|
|
493
|
+
1. Open **Plugins → Development → XOSMOZ Theme Sync** in Figma
|
|
494
|
+
2. Select your variable collection from the dropdown
|
|
495
|
+
3. Click **"Check for Updates"** to see if any colors changed
|
|
496
|
+
4. Click **"Update Variables"** to apply changes to both Light and Dark modes at once
|
|
497
|
+
|
|
498
|
+
If starting a new Figma file, use **"Create New Collection"** to generate all variables from scratch.
|