@fastwork/xosmoz-theme 0.42.0 → 0.46.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/llms.txt CHANGED
@@ -1,17 +1,21 @@
1
- # @fastwork/xosmoz-theme
1
+ # @fastwork/xosmoz-theme — Color Tokens & Usage Guide
2
2
 
3
- > Design tokens and theming system for the Xosmoz design system. Uses OKLCH color space for perceptually uniform colors. Supports light and dark themes via CSS variables with `data-theme` attribute switching.
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
- ## Installation
5
+ ---
6
+
7
+ ## Setup
8
+
9
+ ### Install
6
10
 
7
11
  ```bash
8
12
  npm install @fastwork/xosmoz-theme
9
13
  ```
10
14
 
11
- ## CSS Imports
15
+ ### CSS Imports
12
16
 
13
17
  ```css
14
- /* Base styles: CSS reset, font imports, typography/spacing/shadow tokens */
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,241 @@ npm install @fastwork/xosmoz-theme
22
26
  @import '@fastwork/xosmoz-theme/themes/dark.css';
23
27
  ```
24
28
 
25
- ## Theme Switching
29
+ ### Theme Switching
26
30
 
27
- Set the theme via the `data-theme` attribute on the `<html>` element. Light theme is the default (no attribute needed).
31
+ Light theme is the default. Set `data-theme="dark"` on `<html>` for dark mode.
28
32
 
29
33
  ```html
30
- <html>...</html> <!-- Light theme (default) -->
31
- <html data-theme="dark">...</html> <!-- Dark theme -->
34
+ <html>...</html> <!-- Light theme (default) -->
35
+ <html data-theme="dark">...</html> <!-- Dark theme -->
32
36
  ```
33
37
 
34
38
  ```javascript
35
- // Switch theme at runtime
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
- // Remove attribute to return to light
39
- document.documentElement.removeAttribute('data-theme');
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
- ## CSS Variables Reference
64
+ **Rule: Do not use palette tokens directly in UI.** They exist as internal primitives. Always use semantic tokens instead.
43
65
 
44
- All variables use the `--xz-` prefix.
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
- ### Base Colors
69
+ Pattern: `--xz-color-{category}-{property}-{scale}`
47
70
 
48
- Surface colors that adapt between light and dark themes.
71
+ ---
49
72
 
50
- | Variable | Purpose |
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
- ### Semantic Colors
75
+ Base tokens cover surfaces, text, borders, and neutral overlays. They are theme-aware (change in dark mode).
68
76
 
69
- Six semantic categories: `primary`, `danger`, `success`, `warning`, `info`, `neutral`.
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
- Each category follows the same token structure. Replace `{name}` with the category name:
96
+ ---
72
97
 
73
- | Variable | Purpose |
74
- |----------|---------|
75
- | `--xz-color-{name}-soft-100` | Lightest tinted background |
76
- | `--xz-color-{name}-soft-200` | Stronger tinted background (hover states) |
98
+ ## Semantic Tokens
99
+
100
+ Eight categories. Categories: `primary`, `danger`, `success`, `warning`, `info`, `neutral`, `orange`, `purple`. Most categories have 11 tokens; `neutral` has 12 (includes an extra `text-200`).
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 (e.g. button bg) |
81
- | `--xz-color-{name}-bg-200` | Darker solid fill (e.g. hover state) |
82
- | `--xz-color-{name}-fg-100` | Text on solid bg — use over `{name}-bg-100`/`bg-200` (typically white) |
83
- | `--xz-color-{name}-text-100` | Colored text on surfaces (links, status labels) |
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
- **Important: `fg-100` is the foreground color for text on solid backgrounds (`bg-100`/`bg-200`).** Use `--xz-color-primary-fg-100` as the text color on a `--xz-color-primary-bg-100` button. This is typically white.
120
+ > **`neutral` exception:** also includes `--xz-color-neutral-text-200` Muted neutral text, lighter than `text-100`. Use for supporting content, secondary labels.
86
121
 
87
- ### Raw Color Palettes
122
+ ### Key Rules for Semantic Tokens
88
123
 
89
- 10-step scales (100–1000) for each palette. Available palettes: `fastwork`, `gray`, `green`, `mint`, `amber`, `red`, `orange`, `purple`, `cyan`, `black-alpha`, `white-alpha`.
124
+ - **`bg-100` + `fg-100`**: Solid fill components (buttons, solid badges). `fg-100` provides correct contrast (white or dark depending on the category color).
125
+ - **`soft-100` + `text-100` + `line-100`**: Soft/tinted style (alerts, soft badges, highlighted rows).
126
+ - **`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).
127
+ - **`text-100`**: Use for colored text that sits on surface backgrounds (not on solid fills). Examples: link text, status label text, tag text.
128
+ - **`line-*`**: Colored borders. Use `line-200` as the default, `line-100` for subtle, `line-300` for strong/emphasized.
90
129
 
91
- ```
92
- --xz-color-{palette}-100 (lightest)
93
- --xz-color-{palette}-200
94
- ...
95
- --xz-color-{palette}-1000 (darkest)
96
- ```
130
+ ---
97
131
 
98
- Alpha palettes (`black-alpha`, `white-alpha`) use opacity steps from 0.1 to 1.0.
132
+ ## Alpha & Overlay Tokens
99
133
 
100
- ### Typography
134
+ These use a 100–1000 scale representing opacity from 0.1 to 1.0.
101
135
 
102
136
  ```
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
- ```
137
+ --xz-color-black-alpha-100 (black at 10% opacity)
138
+ --xz-color-black-alpha-200 (black at 20% opacity)
139
+ ...
140
+ --xz-color-black-alpha-1000 (black at 100% opacity)
131
141
 
132
- **Font shorthand tokens** (responsive desktop sizes, scales down on mobile ≤768px):
142
+ --xz-color-white-alpha-100 (white at 10% opacity)
143
+ ...
144
+ --xz-color-white-alpha-1000 (white at 100% opacity)
133
145
 
134
- ```
135
- --xz-font-heading1 through --xz-font-heading6 (secondary font, bold)
136
- --xz-font-title1 through --xz-font-title4 (primary font, bold)
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)
146
+ --xz-color-overlay-100 (dark overlay at 10% opacity)
147
+ ...
148
+ --xz-color-overlay-1000 (dark overlay at 100% opacity)
141
149
  ```
142
150
 
143
- Usage: `font: var(--xz-font-heading1);`
151
+ Use `overlay-*` for modal/drawer backdrops. Use `black-alpha-*` / `white-alpha-*` for scrim layers or icon fills with transparency.
144
152
 
145
- ### Box Shadows
153
+ ---
146
154
 
147
- ```
148
- --xz-box-shadow-100 (subtle: 0 1px 2px)
149
- --xz-box-shadow-200 (small: 0 2px 6px)
150
- --xz-box-shadow-300 (medium: 0 4px 16px)
151
- --xz-box-shadow-400 (large: 0 8px 20px)
152
- ```
155
+ ## Usage Guidelines
153
156
 
154
- ## JavaScript/TypeScript API
157
+ ### Backgrounds & Surfaces
155
158
 
156
- ### Theme objects
159
+ | Situation | Use |
160
+ |---|---|
161
+ | Page background | `--xz-color-surface-100` |
162
+ | Card, modal, dialog | `--xz-color-surface-200` |
163
+ | Nested card or secondary panel | `--xz-color-surface-300` |
164
+ | Popover, dropdown, tooltip | `--xz-color-surface-400` |
165
+ | Inverted/dark block on page | `--xz-color-bg-100` |
166
+ | Text on inverted block | `--xz-color-fg-100` |
157
167
 
158
- ```typescript
159
- import { lightTheme, darkTheme, themes, getTheme, getThemeNames } from '@fastwork/xosmoz-theme';
168
+ ### Text
160
169
 
161
- // Access raw palette colors
162
- lightTheme.colors.fastwork[600] // 'oklch(0.613 0.233 260.608)'
163
- lightTheme.colors.gray[300] // raw palette value
170
+ | Situation | Use |
171
+ |---|---|
172
+ | Body text, headings | `--xz-color-text-100` |
173
+ | Secondary / helper text | `--xz-color-text-200` |
174
+ | Placeholder / disabled text | `--xz-color-text-300` |
175
+ | Colored status text (link, tag, label) | `--xz-color-{name}-text-100` |
164
176
 
165
- // Access semantic colors
166
- lightTheme.colors.primary.bg[100] // solid fill color
167
- lightTheme.colors.primary.fg[100] // white text for solid bg
168
- lightTheme.colors.primary.text[100] // colored text on surfaces
169
- lightTheme.colors.primary.soft[100] // tinted background
170
- lightTheme.colors.primary.line[200] // border color
177
+ ### Borders
171
178
 
172
- // Access base tokens
173
- lightTheme.colors.surface[200] // card background
174
- lightTheme.colors.text[100] // primary text
179
+ | Situation | Use |
180
+ |---|---|
181
+ | Subtle separator, divider | `--xz-color-line-100` |
182
+ | Default input or card border | `--xz-color-line-200` |
183
+ | Strong border, active outline | `--xz-color-line-300` |
184
+ | Colored border (semantic) | `--xz-color-{name}-line-100/200/300` |
175
185
 
176
- // Access box shadows (on theme objects)
177
- lightTheme.boxShadows[100] // '0 1px 2px 0 rgba(0, 0, 0, 0.08)'
178
- lightTheme.boxShadows[200] // '0 2px 6px 0 rgba(0, 0, 0, 0.10)'
179
- lightTheme.boxShadows[300] // '0 4px 16px 0 rgba(0, 0, 0, 0.12)'
180
- lightTheme.boxShadows[400] // '0 8px 20px 0 rgba(0, 0, 0, 0.14)'
186
+ ### Solid Components (Buttons, Solid Badges)
181
187
 
182
- // Get theme by name
183
- const theme = getTheme('dark');
188
+ ```
189
+ background: --xz-color-{name}-bg-100
190
+ color: --xz-color-{name}-fg-100 ← always use fg-100 on bg-100
191
+ hover bg: --xz-color-{name}-bg-200
192
+ ```
184
193
 
185
- // List available themes
186
- const names = getThemeNames(); // ['light', 'dark']
194
+ ### Soft/Tinted Components (Alerts, Soft Badges)
195
+
196
+ ```
197
+ background: --xz-color-{name}-soft-100
198
+ color: --xz-color-{name}-text-100
199
+ border: 1px solid --xz-color-{name}-line-100
187
200
  ```
188
201
 
189
- ### Design tokens
202
+ ### Outline/Ghost Components
190
203
 
191
- ```typescript
192
- import { fontSize, fontWeight, fontFamily, lineHeight, font, typography } from '@fastwork/xosmoz-theme/tokens';
204
+ ```
205
+ background: transparent
206
+ color: --xz-color-{name}-text-100
207
+ border: 1px solid --xz-color-{name}-line-200
208
+ ```
193
209
 
194
- fontSize[400] // '1rem'
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'
210
+ ### Focus Ring
200
211
 
201
- font.heading1 // { fontFamily, fontSize: { desktop, mobile }, fontWeight, lineHeight }
202
- font.title2
203
- font.subtitle1Bold
204
- font.body1
212
+ ```
213
+ border-color: --xz-color-{name}-line-200
214
+ box-shadow: 0 0 0 3px --xz-color-{name}-soft-100
205
215
  ```
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';
217
+ ### Modal Backdrop
218
+
219
+ ```
220
+ background: --xz-color-overlay-600
219
221
  ```
220
222
 
221
- ## Common Patterns
223
+ ---
222
224
 
223
- ### Primary button
225
+ ## Common UI Patterns
226
+
227
+ ### Primary Button
224
228
 
225
229
  ```css
226
- .button-primary {
230
+ .btn-primary {
227
231
  background: var(--xz-color-primary-bg-100);
228
- color: var(--xz-color-primary-fg-100); /* white text on solid bg */
229
- font: var(--xz-font-subtitle1-bold);
232
+ color: var(--xz-color-primary-fg-100);
230
233
  border: none;
231
- border-radius: 0.5rem;
232
234
  }
233
- .button-primary:hover {
235
+ .btn-primary:hover {
234
236
  background: var(--xz-color-primary-bg-200);
235
237
  }
236
238
  ```
237
239
 
238
- ### Secondary/outline button
240
+ ### Outline Button
239
241
 
240
242
  ```css
241
- .button-secondary {
243
+ .btn-outline {
242
244
  background: transparent;
243
245
  color: var(--xz-color-primary-text-100);
244
246
  border: 1px solid var(--xz-color-primary-line-200);
245
247
  }
248
+ .btn-outline:hover {
249
+ background: var(--xz-color-primary-soft-100);
250
+ }
251
+ ```
252
+
253
+ ### Danger Button
254
+
255
+ ```css
256
+ .btn-danger {
257
+ background: var(--xz-color-danger-bg-100);
258
+ color: var(--xz-color-danger-fg-100);
259
+ border: none;
260
+ }
261
+ .btn-danger:hover {
262
+ background: var(--xz-color-danger-bg-200);
263
+ }
246
264
  ```
247
265
 
248
266
  ### Card
@@ -252,44 +270,233 @@ import type {
252
270
  background: var(--xz-color-surface-200);
253
271
  color: var(--xz-color-text-100);
254
272
  border: 1px solid var(--xz-color-line-100);
255
- border-radius: 0.75rem;
256
- box-shadow: var(--xz-box-shadow-200);
257
273
  }
258
274
  ```
259
275
 
260
- ### Alert / status badge
276
+ ### Alert (soft style)
261
277
 
262
278
  ```css
279
+ /* Replace {name} with: success | danger | warning | info */
263
280
  .alert-success {
264
281
  background: var(--xz-color-success-soft-100);
265
282
  color: var(--xz-color-success-text-100);
266
283
  border: 1px solid var(--xz-color-success-line-100);
267
284
  }
285
+ .alert-danger {
286
+ background: var(--xz-color-danger-soft-100);
287
+ color: var(--xz-color-danger-text-100);
288
+ border: 1px solid var(--xz-color-danger-line-100);
289
+ }
290
+ .alert-warning {
291
+ background: var(--xz-color-warning-soft-100);
292
+ color: var(--xz-color-warning-text-100);
293
+ border: 1px solid var(--xz-color-warning-line-100);
294
+ }
295
+ .alert-info {
296
+ background: var(--xz-color-info-soft-100);
297
+ color: var(--xz-color-info-text-100);
298
+ border: 1px solid var(--xz-color-info-line-100);
299
+ }
300
+ ```
301
+
302
+ ### Badge — Soft
303
+
304
+ ```css
305
+ .badge-success {
306
+ background: var(--xz-color-success-soft-100);
307
+ color: var(--xz-color-success-text-100);
308
+ }
309
+ ```
268
310
 
269
- .badge-danger {
311
+ ### Badge — Solid
312
+
313
+ ```css
314
+ .badge-danger-solid {
270
315
  background: var(--xz-color-danger-bg-100);
271
- color: var(--xz-color-danger-fg-100); /* white text on solid bg */
316
+ color: var(--xz-color-danger-fg-100);
272
317
  }
273
318
  ```
274
319
 
275
- ### Form input
320
+ ### Form Input
276
321
 
277
322
  ```css
278
323
  .input {
279
324
  background: var(--xz-color-surface-100);
280
325
  color: var(--xz-color-text-100);
281
326
  border: 1px solid var(--xz-color-line-200);
282
- font: var(--xz-font-body1);
327
+ }
328
+ .input::placeholder {
329
+ color: var(--xz-color-text-300);
283
330
  }
284
331
  .input:focus {
285
332
  border-color: var(--xz-color-primary-line-200);
286
333
  box-shadow: 0 0 0 3px var(--xz-color-primary-soft-100);
334
+ outline: none;
335
+ }
336
+ .input.error {
337
+ border-color: var(--xz-color-danger-line-200);
338
+ box-shadow: 0 0 0 3px var(--xz-color-danger-soft-100);
287
339
  }
288
340
  ```
289
341
 
290
- ### Muted/secondary text
342
+ ### Text Hierarchy
291
343
 
292
344
  ```css
293
- .text-muted { color: var(--xz-color-text-200); }
294
- .text-disabled { color: var(--xz-color-text-300); }
345
+ .text-primary { color: var(--xz-color-text-100); }
346
+ .text-muted { color: var(--xz-color-text-200); }
347
+ .text-disabled { color: var(--xz-color-text-300); }
348
+ .text-link { color: var(--xz-color-primary-text-100); }
349
+ .text-danger { color: var(--xz-color-danger-text-100); }
350
+ .text-success { color: var(--xz-color-success-text-100); }
295
351
  ```
352
+
353
+ ---
354
+
355
+ ## Figma Variables Guide
356
+
357
+ Figma variables mirror the CSS token system exactly. Every CSS variable has a corresponding Figma variable in the same collection.
358
+
359
+ ### Collection Structure
360
+
361
+ - **Collection name**: `colors`
362
+ - **Modes**: `Light` and `Dark`
363
+ - **Total variables**: ~160 color variables
364
+
365
+ ### Naming Pattern
366
+
367
+ Figma uses slash-separated paths. The mapping to CSS is direct:
368
+
369
+ | Variable type | Figma path | CSS variable |
370
+ |---|---|---|
371
+ | Base theme token | `theme/base/{property}/{scale}` | `--xz-color-{property}-{scale}` |
372
+ | Semantic theme token | `theme/{category}/{property}/{scale}` | `--xz-color-{category}-{property}-{scale}` |
373
+ | Alpha token | `theme/blackAlpha/{scale}` | `--xz-color-black-alpha-{scale}` |
374
+ | Alpha token | `theme/whiteAlpha/{scale}` | `--xz-color-white-alpha-{scale}` |
375
+ | Overlay token | `theme/overlay/{scale}` | `--xz-color-overlay-{scale}` |
376
+ | Palette primitive | `palette/{name}` | `--xz-color-{name}` |
377
+
378
+ ### Complete Figma → CSS Mapping
379
+
380
+ #### Base (16 variables)
381
+
382
+ | Figma Variable | CSS Variable |
383
+ |---|---|
384
+ | `theme/base/bg/100` | `--xz-color-bg-100` |
385
+ | `theme/base/bg/200` | `--xz-color-bg-200` |
386
+ | `theme/base/surface/50` | `--xz-color-surface-50` |
387
+ | `theme/base/surface/100` | `--xz-color-surface-100` |
388
+ | `theme/base/surface/200` | `--xz-color-surface-200` |
389
+ | `theme/base/surface/300` | `--xz-color-surface-300` |
390
+ | `theme/base/surface/400` | `--xz-color-surface-400` |
391
+ | `theme/base/fg/100` | `--xz-color-fg-100` |
392
+ | `theme/base/soft/100` | `--xz-color-soft-100` |
393
+ | `theme/base/soft/200` | `--xz-color-soft-200` |
394
+ | `theme/base/text/100` | `--xz-color-text-100` |
395
+ | `theme/base/text/200` | `--xz-color-text-200` |
396
+ | `theme/base/text/300` | `--xz-color-text-300` |
397
+ | `theme/base/line/100` | `--xz-color-line-100` |
398
+ | `theme/base/line/200` | `--xz-color-line-200` |
399
+ | `theme/base/line/300` | `--xz-color-line-300` |
400
+
401
+ #### Semantic Categories (11 variables each; neutral has 12)
402
+
403
+ Same pattern for all 8 categories: `primary`, `danger`, `success`, `warning`, `info`, `neutral`, `orange`, `purple`.
404
+
405
+ | Figma Variable | CSS Variable |
406
+ |---|---|
407
+ | `theme/{name}/soft/100` | `--xz-color-{name}-soft-100` |
408
+ | `theme/{name}/soft/200` | `--xz-color-{name}-soft-200` |
409
+ | `theme/{name}/softSolid/100` | `--xz-color-{name}-soft-solid-100` |
410
+ | `theme/{name}/softSolid/200` | `--xz-color-{name}-soft-solid-200` |
411
+ | `theme/{name}/line/100` | `--xz-color-{name}-line-100` |
412
+ | `theme/{name}/line/200` | `--xz-color-{name}-line-200` |
413
+ | `theme/{name}/line/300` | `--xz-color-{name}-line-300` |
414
+ | `theme/{name}/bg/100` | `--xz-color-{name}-bg-100` |
415
+ | `theme/{name}/bg/200` | `--xz-color-{name}-bg-200` |
416
+ | `theme/{name}/fg/100` | `--xz-color-{name}-fg-100` |
417
+ | `theme/{name}/text/100` | `--xz-color-{name}-text-100` |
418
+
419
+ > **`neutral` exception:** also includes `theme/neutral/text/200` → `--xz-color-neutral-text-200`.
420
+
421
+ #### Black Alpha (10 variables)
422
+
423
+ | Figma Variable | CSS Variable |
424
+ |---|---|
425
+ | `theme/blackAlpha/100` | `--xz-color-black-alpha-100` |
426
+ | `theme/blackAlpha/200` | `--xz-color-black-alpha-200` |
427
+ | `theme/blackAlpha/300` | `--xz-color-black-alpha-300` |
428
+ | `theme/blackAlpha/400` | `--xz-color-black-alpha-400` |
429
+ | `theme/blackAlpha/500` | `--xz-color-black-alpha-500` |
430
+ | `theme/blackAlpha/600` | `--xz-color-black-alpha-600` |
431
+ | `theme/blackAlpha/700` | `--xz-color-black-alpha-700` |
432
+ | `theme/blackAlpha/800` | `--xz-color-black-alpha-800` |
433
+ | `theme/blackAlpha/900` | `--xz-color-black-alpha-900` |
434
+ | `theme/blackAlpha/1000` | `--xz-color-black-alpha-1000` |
435
+
436
+ #### White Alpha (10 variables)
437
+
438
+ | Figma Variable | CSS Variable |
439
+ |---|---|
440
+ | `theme/whiteAlpha/100` | `--xz-color-white-alpha-100` |
441
+ | `theme/whiteAlpha/200` | `--xz-color-white-alpha-200` |
442
+ | `theme/whiteAlpha/300` | `--xz-color-white-alpha-300` |
443
+ | `theme/whiteAlpha/400` | `--xz-color-white-alpha-400` |
444
+ | `theme/whiteAlpha/500` | `--xz-color-white-alpha-500` |
445
+ | `theme/whiteAlpha/600` | `--xz-color-white-alpha-600` |
446
+ | `theme/whiteAlpha/700` | `--xz-color-white-alpha-700` |
447
+ | `theme/whiteAlpha/800` | `--xz-color-white-alpha-800` |
448
+ | `theme/whiteAlpha/900` | `--xz-color-white-alpha-900` |
449
+ | `theme/whiteAlpha/1000` | `--xz-color-white-alpha-1000` |
450
+
451
+ #### Overlay (10 variables)
452
+
453
+ | Figma Variable | CSS Variable |
454
+ |---|---|
455
+ | `theme/overlay/100` | `--xz-color-overlay-100` |
456
+ | `theme/overlay/200` | `--xz-color-overlay-200` |
457
+ | `theme/overlay/300` | `--xz-color-overlay-300` |
458
+ | `theme/overlay/400` | `--xz-color-overlay-400` |
459
+ | `theme/overlay/500` | `--xz-color-overlay-500` |
460
+ | `theme/overlay/600` | `--xz-color-overlay-600` |
461
+ | `theme/overlay/700` | `--xz-color-overlay-700` |
462
+ | `theme/overlay/800` | `--xz-color-overlay-800` |
463
+ | `theme/overlay/900` | `--xz-color-overlay-900` |
464
+ | `theme/overlay/1000` | `--xz-color-overlay-1000` |
465
+
466
+ #### Palette (8 variables)
467
+
468
+ | Figma Variable | CSS Variable |
469
+ |---|---|
470
+ | `palette/fastwork` | `--xz-color-fastwork` |
471
+ | `palette/gray` | `--xz-color-gray` |
472
+ | `palette/green` | `--xz-color-green` |
473
+ | `palette/yellow` | `--xz-color-yellow` |
474
+ | `palette/red` | `--xz-color-red` |
475
+ | `palette/orange` | `--xz-color-orange` |
476
+ | `palette/purple` | `--xz-color-purple` |
477
+ | `palette/cyan` | `--xz-color-cyan` |
478
+
479
+ ### How to Use Figma Variables in Designs
480
+
481
+ 1. Select a layer in Figma (frame, text, shape, etc.)
482
+ 2. In the Fill or Stroke panel, click the color swatch
483
+ 3. Switch to the **Variables** tab in the color picker
484
+ 4. Pick from the `colors` collection
485
+
486
+ **Rules for Figma:**
487
+ - Always use `theme/*` variables for component fills, text colors, and stroke colors
488
+ - Use `palette/*` variables only as references — not directly on components
489
+ - Use `theme/base/surface/100` for page backgrounds, `theme/base/surface/200` for cards
490
+ - Use `theme/{name}/bg/100` for solid-filled elements and `theme/{name}/fg/100` for text on top of them
491
+ - Switch between Light/Dark previews using the **Mode** toggle on the variable collection
492
+
493
+ ### Keeping Figma in Sync with Code
494
+
495
+ Variables are synced from the npm package via the **XOSMOZ Theme Sync** plugin:
496
+
497
+ 1. Open **Plugins → Development → XOSMOZ Theme Sync** in Figma
498
+ 2. Select your variable collection from the dropdown
499
+ 3. Click **"Check for Updates"** to see if any colors changed
500
+ 4. Click **"Update Variables"** to apply changes to both Light and Dark modes at once
501
+
502
+ If starting a new Figma file, use **"Create New Collection"** to generate all variables from scratch.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fastwork/xosmoz-theme",
3
- "version": "0.42.0",
3
+ "version": "0.46.0",
4
4
  "description": "Xosmoz Theme - Design tokens and theming system for Xosmoz",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",