@molecule/app-theme 1.0.0 → 1.0.1
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/README.md +464 -0
- package/package.json +5 -4
package/README.md
ADDED
|
@@ -0,0 +1,464 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
AUTO-GENERATED — DO NOT EDIT THIS FILE.
|
|
3
|
+
Generated by `mlcl sync-docs` from the package's src/index.ts JSDoc + mlcl/registry.json.
|
|
4
|
+
Edits here are overwritten on the next commit (molecule's pre-commit hook regenerates).
|
|
5
|
+
To change this document, edit the module-level JSDoc in src/index.ts.
|
|
6
|
+
Generated: 2026-08-04T01:52:55.409Z
|
|
7
|
+
-->
|
|
8
|
+
|
|
9
|
+
# @molecule/app-theme
|
|
10
|
+
|
|
11
|
+
> **Auto-generated, AI-first package reference** for the [molecule.dev](https://molecule.dev) ecosystem.
|
|
12
|
+
> It is written to be read by coding agents as much as by people, and is generated from this
|
|
13
|
+
> package's source — edit `src/index.ts` JSDoc, not this file.
|
|
14
|
+
|
|
15
|
+
Theme interface and utilities for molecule.dev.
|
|
16
|
+
|
|
17
|
+
Framework-agnostic theme contract — a {@link Theme} (colors, spacing,
|
|
18
|
+
typography, radii, shadows, z-index) plus a {@link ThemeProvider} bond for
|
|
19
|
+
reading/switching themes, dark/light toggling, and change subscriptions.
|
|
20
|
+
Bond a provider (e.g. `@molecule/app-theme-css-variables`, which applies the
|
|
21
|
+
palette as CSS variables) at startup; {@link lightTheme}/{@link darkTheme}
|
|
22
|
+
are the base defaults.
|
|
23
|
+
|
|
24
|
+
## Quick Start
|
|
25
|
+
|
|
26
|
+
```typescript
|
|
27
|
+
import { getProvider } from '@molecule/app-theme'
|
|
28
|
+
|
|
29
|
+
const theme = getProvider() // null until a bond is wired at startup
|
|
30
|
+
theme?.toggleMode() // light <-> dark
|
|
31
|
+
const unsubscribe = theme?.subscribe((t) => applyBranding(t))
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Type
|
|
35
|
+
|
|
36
|
+
`core`
|
|
37
|
+
|
|
38
|
+
## Installation
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
npm install @molecule/app-theme @molecule/app-bond
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## API
|
|
45
|
+
|
|
46
|
+
### Interfaces
|
|
47
|
+
|
|
48
|
+
#### `Theme`
|
|
49
|
+
|
|
50
|
+
Complete theme definition.
|
|
51
|
+
|
|
52
|
+
```typescript
|
|
53
|
+
interface Theme {
|
|
54
|
+
name: string
|
|
55
|
+
mode: 'light' | 'dark'
|
|
56
|
+
colors: ThemeColors
|
|
57
|
+
breakpoints: ThemeBreakpoints
|
|
58
|
+
spacing: ThemeSpacing
|
|
59
|
+
typography: ThemeTypography
|
|
60
|
+
borderRadius: ThemeBorderRadius
|
|
61
|
+
shadows: ThemeShadows
|
|
62
|
+
transitions: ThemeTransitions
|
|
63
|
+
zIndex: ThemeZIndex
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
#### `ThemeBorderRadius`
|
|
68
|
+
|
|
69
|
+
Border radius scale.
|
|
70
|
+
|
|
71
|
+
```typescript
|
|
72
|
+
interface ThemeBorderRadius {
|
|
73
|
+
none: string
|
|
74
|
+
sm: string
|
|
75
|
+
md: string
|
|
76
|
+
lg: string
|
|
77
|
+
xl: string
|
|
78
|
+
full: string
|
|
79
|
+
}
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
#### `ThemeBreakpoints`
|
|
83
|
+
|
|
84
|
+
Responsive viewport breakpoints from mobileS (320px) to desktop (2560px).
|
|
85
|
+
|
|
86
|
+
```typescript
|
|
87
|
+
interface ThemeBreakpoints {
|
|
88
|
+
mobileS: string // 320px
|
|
89
|
+
mobileM: string // 375px
|
|
90
|
+
mobileL: string // 425px
|
|
91
|
+
tablet: string // 768px
|
|
92
|
+
laptop: string // 1024px
|
|
93
|
+
laptopL: string // 1440px
|
|
94
|
+
desktop: string // 2560px
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
#### `ThemeColors`
|
|
99
|
+
|
|
100
|
+
Color palette definition.
|
|
101
|
+
|
|
102
|
+
```typescript
|
|
103
|
+
interface ThemeColors {
|
|
104
|
+
// Base colors
|
|
105
|
+
background: string
|
|
106
|
+
backgroundSecondary: string
|
|
107
|
+
backgroundTertiary: string
|
|
108
|
+
surface: string
|
|
109
|
+
surfaceSecondary: string
|
|
110
|
+
inputBackground: string
|
|
111
|
+
|
|
112
|
+
// Text colors
|
|
113
|
+
text: string
|
|
114
|
+
textSecondary: string
|
|
115
|
+
textTertiary: string
|
|
116
|
+
textInverse: string
|
|
117
|
+
|
|
118
|
+
// Brand colors
|
|
119
|
+
primary: string
|
|
120
|
+
primaryLight: string
|
|
121
|
+
primaryDark: string
|
|
122
|
+
secondary: string
|
|
123
|
+
secondaryLight: string
|
|
124
|
+
secondaryDark: string
|
|
125
|
+
|
|
126
|
+
// Semantic colors
|
|
127
|
+
success: string
|
|
128
|
+
successLight: string
|
|
129
|
+
warning: string
|
|
130
|
+
warningLight: string
|
|
131
|
+
error: string
|
|
132
|
+
errorLight: string
|
|
133
|
+
info: string
|
|
134
|
+
infoLight: string
|
|
135
|
+
|
|
136
|
+
// Border colors
|
|
137
|
+
border: string
|
|
138
|
+
borderSecondary: string
|
|
139
|
+
borderFocus: string
|
|
140
|
+
|
|
141
|
+
// Other
|
|
142
|
+
overlay: string
|
|
143
|
+
shadow: string
|
|
144
|
+
}
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
#### `ThemeProvider`
|
|
148
|
+
|
|
149
|
+
Manages theme state including the active theme, mode toggling,
|
|
150
|
+
and change subscriptions.
|
|
151
|
+
|
|
152
|
+
```typescript
|
|
153
|
+
interface ThemeProvider {
|
|
154
|
+
/**
|
|
155
|
+
* Returns the currently active theme.
|
|
156
|
+
*/
|
|
157
|
+
getTheme(): Theme
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Sets the active theme by reference or by name.
|
|
161
|
+
*
|
|
162
|
+
* @param theme - A `Theme` object or a theme name string to activate.
|
|
163
|
+
*/
|
|
164
|
+
setTheme(theme: Theme | string): void
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Toggles between light and dark mode for the active theme.
|
|
168
|
+
*/
|
|
169
|
+
toggleMode(): void
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Subscribes to theme changes. The callback fires whenever
|
|
173
|
+
* `setTheme()` or `toggleMode()` is called.
|
|
174
|
+
*
|
|
175
|
+
* @param callback - Invoked with the new theme after each change.
|
|
176
|
+
* @returns An unsubscribe function.
|
|
177
|
+
*/
|
|
178
|
+
subscribe(callback: (theme: Theme) => void): () => void
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Returns all registered themes. Optional — not all providers
|
|
182
|
+
* support multiple themes.
|
|
183
|
+
*/
|
|
184
|
+
getThemes?(): Theme[]
|
|
185
|
+
}
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
#### `ThemeShadows`
|
|
189
|
+
|
|
190
|
+
Box-shadow scale from none to xl for elevation levels.
|
|
191
|
+
|
|
192
|
+
```typescript
|
|
193
|
+
interface ThemeShadows {
|
|
194
|
+
none: string
|
|
195
|
+
sm: string
|
|
196
|
+
md: string
|
|
197
|
+
lg: string
|
|
198
|
+
xl: string
|
|
199
|
+
}
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
#### `ThemeSpacing`
|
|
203
|
+
|
|
204
|
+
Theme spacing scale mapping size tokens (xs–3xl) to CSS values (e.g. '4px', '16px').
|
|
205
|
+
|
|
206
|
+
```typescript
|
|
207
|
+
interface ThemeSpacing {
|
|
208
|
+
xs: string // 4px
|
|
209
|
+
sm: string // 8px
|
|
210
|
+
md: string // 16px
|
|
211
|
+
lg: string // 24px
|
|
212
|
+
xl: string // 32px
|
|
213
|
+
xxl: string // 48px
|
|
214
|
+
xxxl: string // 64px
|
|
215
|
+
}
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
#### `ThemeTransitions`
|
|
219
|
+
|
|
220
|
+
CSS transition duration presets (fast, normal, slow).
|
|
221
|
+
|
|
222
|
+
```typescript
|
|
223
|
+
interface ThemeTransitions {
|
|
224
|
+
fast: string
|
|
225
|
+
normal: string
|
|
226
|
+
slow: string
|
|
227
|
+
}
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
#### `ThemeTypography`
|
|
231
|
+
|
|
232
|
+
Typography scale (font families, sizes, weights, and line heights).
|
|
233
|
+
|
|
234
|
+
```typescript
|
|
235
|
+
interface ThemeTypography {
|
|
236
|
+
fontFamily: {
|
|
237
|
+
sans: string
|
|
238
|
+
serif: string
|
|
239
|
+
mono: string
|
|
240
|
+
}
|
|
241
|
+
fontSize: {
|
|
242
|
+
xs: string // 12px
|
|
243
|
+
sm: string // 14px
|
|
244
|
+
base: string // 16px
|
|
245
|
+
lg: string // 18px
|
|
246
|
+
xl: string // 20px
|
|
247
|
+
'2xl': string // 24px
|
|
248
|
+
'3xl': string // 30px
|
|
249
|
+
'4xl': string // 36px
|
|
250
|
+
'5xl': string // 48px
|
|
251
|
+
}
|
|
252
|
+
fontWeight: {
|
|
253
|
+
light: number
|
|
254
|
+
normal: number
|
|
255
|
+
medium: number
|
|
256
|
+
semibold: number
|
|
257
|
+
bold: number
|
|
258
|
+
}
|
|
259
|
+
lineHeight: {
|
|
260
|
+
tight: number
|
|
261
|
+
normal: number
|
|
262
|
+
relaxed: number
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
#### `ThemeZIndex`
|
|
268
|
+
|
|
269
|
+
Theme z-index scale for layering UI elements (dropdowns, modals, toasts, etc.).
|
|
270
|
+
|
|
271
|
+
```typescript
|
|
272
|
+
interface ThemeZIndex {
|
|
273
|
+
hide: number
|
|
274
|
+
base: number
|
|
275
|
+
dropdown: number
|
|
276
|
+
sticky: number
|
|
277
|
+
fixed: number
|
|
278
|
+
modal: number
|
|
279
|
+
popover: number
|
|
280
|
+
tooltip: number
|
|
281
|
+
toast: number
|
|
282
|
+
}
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
### Functions
|
|
286
|
+
|
|
287
|
+
#### `createDarkTheme(overrides)`
|
|
288
|
+
|
|
289
|
+
Creates a dark theme by merging default dark-mode tokens with
|
|
290
|
+
optional overrides for colors, spacing, typography, etc.
|
|
291
|
+
|
|
292
|
+
```typescript
|
|
293
|
+
function createDarkTheme(overrides?: Partial<Theme>): Theme
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
- `overrides` — Partial theme tokens to merge over the defaults.
|
|
297
|
+
|
|
298
|
+
**Returns:** A complete `Theme` object with `mode: 'dark'`.
|
|
299
|
+
|
|
300
|
+
#### `createLightTheme(overrides)`
|
|
301
|
+
|
|
302
|
+
Creates a light theme by merging default light-mode tokens with
|
|
303
|
+
optional overrides for colors, spacing, typography, etc.
|
|
304
|
+
|
|
305
|
+
```typescript
|
|
306
|
+
function createLightTheme(overrides?: Partial<Theme>): Theme
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
- `overrides` — Partial theme tokens to merge over the defaults.
|
|
310
|
+
|
|
311
|
+
**Returns:** A complete `Theme` object with `mode: 'light'`.
|
|
312
|
+
|
|
313
|
+
#### `getProvider()`
|
|
314
|
+
|
|
315
|
+
Retrieves the bonded theme provider, or `null` if none is configured.
|
|
316
|
+
|
|
317
|
+
```typescript
|
|
318
|
+
function getProvider(): ThemeProvider | null
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
**Returns:** The bonded theme provider, or `null`.
|
|
322
|
+
|
|
323
|
+
#### `hasProvider()`
|
|
324
|
+
|
|
325
|
+
Checks whether a theme provider is currently bonded.
|
|
326
|
+
|
|
327
|
+
```typescript
|
|
328
|
+
function hasProvider(): boolean
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
**Returns:** `true` if a theme provider is bonded.
|
|
332
|
+
|
|
333
|
+
#### `setProvider(provider)`
|
|
334
|
+
|
|
335
|
+
Registers a theme provider as the active singleton.
|
|
336
|
+
|
|
337
|
+
```typescript
|
|
338
|
+
function setProvider(provider: ThemeProvider): void
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
- `provider` — The theme provider implementation to bond.
|
|
342
|
+
|
|
343
|
+
### Constants
|
|
344
|
+
|
|
345
|
+
#### `darkColors`
|
|
346
|
+
|
|
347
|
+
Default dark theme colors.
|
|
348
|
+
|
|
349
|
+
```typescript
|
|
350
|
+
const darkColors: ThemeColors
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
#### `darkTheme`
|
|
354
|
+
|
|
355
|
+
Default dark theme.
|
|
356
|
+
|
|
357
|
+
```typescript
|
|
358
|
+
const darkTheme: Theme
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
#### `defaultBorderRadius`
|
|
362
|
+
|
|
363
|
+
Default border radius.
|
|
364
|
+
|
|
365
|
+
```typescript
|
|
366
|
+
const defaultBorderRadius: ThemeBorderRadius
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
#### `defaultBreakpoints`
|
|
370
|
+
|
|
371
|
+
Default responsive breakpoints (320px mobileS → 2560px desktop).
|
|
372
|
+
|
|
373
|
+
```typescript
|
|
374
|
+
const defaultBreakpoints: ThemeBreakpoints
|
|
375
|
+
```
|
|
376
|
+
|
|
377
|
+
#### `defaultShadows`
|
|
378
|
+
|
|
379
|
+
Default box-shadow scale (none → xl, rgba-based).
|
|
380
|
+
|
|
381
|
+
```typescript
|
|
382
|
+
const defaultShadows: ThemeShadows
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
#### `defaultSpacing`
|
|
386
|
+
|
|
387
|
+
Default spacing scale (4px xs → 64px xxxl).
|
|
388
|
+
|
|
389
|
+
```typescript
|
|
390
|
+
const defaultSpacing: ThemeSpacing
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
#### `defaultTransitions`
|
|
394
|
+
|
|
395
|
+
Default CSS transition durations (150ms fast, 250ms normal, 350ms slow).
|
|
396
|
+
|
|
397
|
+
```typescript
|
|
398
|
+
const defaultTransitions: ThemeTransitions
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
#### `defaultTypography`
|
|
402
|
+
|
|
403
|
+
Default typography scale (system font stacks, rem-based sizes, weight/line-height presets).
|
|
404
|
+
|
|
405
|
+
```typescript
|
|
406
|
+
const defaultTypography: ThemeTypography
|
|
407
|
+
```
|
|
408
|
+
|
|
409
|
+
#### `defaultZIndex`
|
|
410
|
+
|
|
411
|
+
Default z-index scale.
|
|
412
|
+
|
|
413
|
+
```typescript
|
|
414
|
+
const defaultZIndex: ThemeZIndex
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
#### `lightColors`
|
|
418
|
+
|
|
419
|
+
Default light theme colors.
|
|
420
|
+
|
|
421
|
+
```typescript
|
|
422
|
+
const lightColors: ThemeColors
|
|
423
|
+
```
|
|
424
|
+
|
|
425
|
+
#### `lightTheme`
|
|
426
|
+
|
|
427
|
+
Default light theme.
|
|
428
|
+
|
|
429
|
+
```typescript
|
|
430
|
+
const lightTheme: Theme
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
## Available Providers
|
|
434
|
+
|
|
435
|
+
| Provider | Package |
|
|
436
|
+
| ------------- | ------------------------------------------------ |
|
|
437
|
+
| CSS Variables | `@molecule/app-theme-css-variables` |
|
|
438
|
+
| Liquid Glass | `@molecule/app-theme-css-variables-liquid-glass` |
|
|
439
|
+
|
|
440
|
+
## Injection Notes
|
|
441
|
+
|
|
442
|
+
### Requirements
|
|
443
|
+
|
|
444
|
+
Peer dependencies:
|
|
445
|
+
|
|
446
|
+
- `@molecule/app-bond` ^1.0.1
|
|
447
|
+
|
|
448
|
+
### Runtime Dependencies
|
|
449
|
+
|
|
450
|
+
- `@molecule/app-bond`
|
|
451
|
+
|
|
452
|
+
- **Recoloring: find the REAL source of truth first.** Apps scaffolded from a
|
|
453
|
+
template ship a per-app stylesheet (e.g. `app/src/theme.css`) that
|
|
454
|
+
hardcodes the `--color-*` variables and loads AFTER the bond — its values
|
|
455
|
+
win, and editing this package's `Theme` objects (or the bond's palette) has
|
|
456
|
+
NO visible effect there. Precedence: per-app theme stylesheet > theme
|
|
457
|
+
bond > base defaults. Recolor by editing whichever file actually defines
|
|
458
|
+
the variables; the bond's `Theme` palette applies only when no per-app
|
|
459
|
+
stylesheet defines colors.
|
|
460
|
+
- Read theme values through the provider or the CSS variables it emits —
|
|
461
|
+
never hardcode hex values in components; surfaces and status colors come
|
|
462
|
+
from the theme so light AND dark both work.
|
|
463
|
+
- {@link getProvider} returns `null` when nothing is bonded — theme switching
|
|
464
|
+
is optional; guard rather than throw.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@molecule/app-theme",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"description": "Theme interface and utilities for molecule.dev",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -17,7 +17,8 @@
|
|
|
17
17
|
}
|
|
18
18
|
},
|
|
19
19
|
"files": [
|
|
20
|
-
"dist"
|
|
20
|
+
"dist",
|
|
21
|
+
"README.md"
|
|
21
22
|
],
|
|
22
23
|
"keywords": [
|
|
23
24
|
"molecule",
|
|
@@ -27,10 +28,10 @@
|
|
|
27
28
|
],
|
|
28
29
|
"license": "Apache-2.0",
|
|
29
30
|
"peerDependencies": {
|
|
30
|
-
"@molecule/app-bond": "^1.0.
|
|
31
|
+
"@molecule/app-bond": "^1.0.1"
|
|
31
32
|
},
|
|
32
33
|
"devDependencies": {
|
|
33
|
-
"@molecule/app-bond": "1.0.
|
|
34
|
+
"@molecule/app-bond": "1.0.1",
|
|
34
35
|
"@types/node": "26.1.2",
|
|
35
36
|
"typescript": "6.0.3",
|
|
36
37
|
"vitest": "4.1.10"
|