@nebutra/theme 0.1.1 → 0.2.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.
@@ -1,177 +1,10 @@
1
1
 
2
- > @nebutra/theme@0.1.1 prebuild /home/runner/work/Nebutra-Sailor/Nebutra-Sailor/packages/design/theme
3
- > corepack pnpm --filter @nebutra/design-tokens build
4
-
5
-
6
- > @nebutra/design-tokens@0.1.1 build /home/runner/work/Nebutra-Sailor/Nebutra-Sailor/packages/design/design-tokens
7
- > node style-dictionary.config.mjs
8
-
9
-
10
- css
11
- - build/css/light.css
12
-
13
- ts
14
- - build/ts/light.ts
15
- - build/ts/light.d.ts
16
-
17
- tailwind
18
- - build/tailwind/light.preset.cjs
19
-
20
- css
21
- ✔︎ build/css/light.css
22
-
23
- ts
24
- ✔︎ build/ts/light.ts
25
- ✔︎ build/ts/light.d.ts
26
-
27
- tailwind
28
- ✔︎ build/tailwind/light.preset.cjs
29
-
30
- css
31
- - build/css/dark.css
32
-
33
- ts
34
- - build/ts/dark.ts
35
- - build/ts/dark.d.ts
36
-
37
- tailwind
38
- - build/tailwind/dark.preset.cjs
39
-
40
- css
41
- ✔︎ build/css/dark.css
42
-
43
- ts
44
- ✔︎ build/ts/dark.ts
45
- ✔︎ build/ts/dark.d.ts
46
-
47
- tailwind
48
- ✔︎ build/tailwind/dark.preset.cjs
49
-
50
- css
51
- - build/css/neon.css
52
-
53
- ts
54
- - build/ts/neon.ts
55
- - build/ts/neon.d.ts
56
-
57
- tailwind
58
- - build/tailwind/neon.preset.cjs
59
-
60
- css
61
- ✔︎ build/css/neon.css
62
-
63
- ts
64
- ✔︎ build/ts/neon.ts
65
- ✔︎ build/ts/neon.d.ts
66
-
67
- tailwind
68
- ✔︎ build/tailwind/neon.preset.cjs
69
-
70
- css
71
- - build/css/gradient.css
72
-
73
- ts
74
- - build/ts/gradient.ts
75
- - build/ts/gradient.d.ts
76
-
77
- tailwind
78
- - build/tailwind/gradient.preset.cjs
79
-
80
- css
81
- ✔︎ build/css/gradient.css
82
-
83
- ts
84
- ✔︎ build/ts/gradient.ts
85
- ✔︎ build/ts/gradient.d.ts
86
-
87
- tailwind
88
- ✔︎ build/tailwind/gradient.preset.cjs
89
-
90
- css
91
- - build/css/dark-dense.css
92
-
93
- ts
94
- - build/ts/dark-dense.ts
95
- - build/ts/dark-dense.d.ts
96
-
97
- tailwind
98
- - build/tailwind/dark-dense.preset.cjs
99
-
100
- css
101
- ✔︎ build/css/dark-dense.css
102
-
103
- ts
104
- ✔︎ build/ts/dark-dense.ts
105
- ✔︎ build/ts/dark-dense.d.ts
106
-
107
- tailwind
108
- ✔︎ build/tailwind/dark-dense.preset.cjs
109
-
110
- css
111
- - build/css/minimal.css
112
-
113
- ts
114
- - build/ts/minimal.ts
115
- - build/ts/minimal.d.ts
116
-
117
- tailwind
118
- - build/tailwind/minimal.preset.cjs
119
-
120
- css
121
- ✔︎ build/css/minimal.css
122
-
123
- ts
124
- ✔︎ build/ts/minimal.ts
125
- ✔︎ build/ts/minimal.d.ts
126
-
127
- tailwind
128
- ✔︎ build/tailwind/minimal.preset.cjs
129
-
130
- css
131
- - build/css/vibrant.css
132
-
133
- ts
134
- - build/ts/vibrant.ts
135
- - build/ts/vibrant.d.ts
136
-
137
- tailwind
138
- - build/tailwind/vibrant.preset.cjs
139
-
140
- css
141
- ✔︎ build/css/vibrant.css
142
-
143
- ts
144
- ✔︎ build/ts/vibrant.ts
145
- ✔︎ build/ts/vibrant.d.ts
146
-
147
- tailwind
148
- ✔︎ build/tailwind/vibrant.preset.cjs
149
-
150
- css
151
- - build/css/ocean.css
152
-
153
- ts
154
- - build/ts/ocean.ts
155
- - build/ts/ocean.d.ts
156
-
157
- tailwind
158
- - build/tailwind/ocean.preset.cjs
159
-
160
- css
161
- ✔︎ build/css/ocean.css
162
-
163
- ts
164
- ✔︎ build/ts/ocean.ts
165
- ✔︎ build/ts/ocean.d.ts
166
-
167
- tailwind
168
- ✔︎ build/tailwind/ocean.preset.cjs
169
-
170
- [design-tokens] build complete
171
- → build/css/styles.generated.css (replaces packages/design/tokens/styles.css)
172
- → build/css/themes.generated.css (replaces packages/design/theme/themes.css)
173
-
174
- > @nebutra/theme@0.1.1 build /home/runner/work/Nebutra-Sailor/Nebutra-Sailor/packages/design/theme
175
- > node -e "require('node:fs').copyFileSync('../design-tokens/build/css/themes.generated.css', './themes.css'); console.log('themes.css regenerated from @nebutra/design-tokens')"
176
-
177
- themes.css regenerated from @nebutra/design-tokens
2
+ > @nebutra/theme@0.2.0 build /Users/tseka_luk/Documents/Nebutra-SaaS-Lab/Nebutra-Sailor/packages/design/theme
3
+ > node scripts/sync-languages.mjs && node ../tokens/scripts/emit-skins.mjs && node scripts/sync-skins.mjs
4
+
5
+ sync-languages:
6
+ languages.json: 8 languages (7 skins + factory)
7
+ built-in-packages.generated.ts: 7 packages
8
+ emit-skins: 7 skins from brand.json → skins/*.css
9
+ gsap, linear, notion, raycast, stripe, vanta, vercel
10
+ skins.css refreshed: 7 languages -> /Users/tseka_luk/Documents/Nebutra-SaaS-Lab/Nebutra-Sailor/packages/design/theme/skins.css
@@ -1,4 +1,4 @@
1
1
 
2
- > @nebutra/theme@0.1.1 typecheck /home/runner/work/Nebutra-Sailor/Nebutra-Sailor/packages/design/theme
2
+ > @nebutra/theme@0.2.0 typecheck /Users/tseka_luk/Documents/Nebutra-SaaS-Lab/Nebutra-Sailor/packages/design/theme
3
3
  > tsc --noEmit
4
4
 
package/AGENTS.md CHANGED
@@ -1,41 +1,28 @@
1
- # AGENTS.md — packages/theme
2
-
3
- Execution contract for Nebutra's multi-theme preset package.
1
+ # AGENTS.md — packages/design/theme
4
2
 
5
3
  ## Scope
6
4
 
7
- Applies to everything under `packages/design/theme/`.
8
-
9
- This package owns the named product-theme layer that sits above base runtime
10
- tokens. It is CSS-first and intentionally small.
11
-
12
- ## Source Of Truth
13
-
14
- - Public package surface and exports: `package.json`, `src/index.ts`
15
- - Canonical named theme selectors and CSS theme payloads: `themes.css`
5
+ `@nebutra/theme` is the **design-language switch surface**.
16
6
 
17
- ## Contract Boundaries
7
+ ## Do not reintroduce
18
8
 
19
- - Treat `themes.css` as the canonical source for theme-specific CSS behavior.
20
- Do not duplicate theme selector logic in apps.
21
- - Keep `THEME_IDS` in `src/index.ts` aligned with the `[data-theme]` selectors
22
- defined in `themes.css`. Adding, renaming, or removing a theme requires
23
- updating both in the same change.
24
- - This package re-exports `next-themes` as a convenience boundary. Do not add
25
- unrelated runtime policy, product gating, or token definitions here.
26
- - Keep this package distinct from `@nebutra/tokens`. `@nebutra/theme` owns
27
- named presets such as `ocean` or `minimal`; `@nebutra/tokens` owns the base
28
- semantic token system.
9
+ - Multi-mood oklch `[data-theme]` catalogs (deleted 2026.07)
10
+ - Root `@theme { --color-primary: … }` dual-truth against `@nebutra/tokens`
11
+ - “Theme = recolor primary only” product thinking
29
12
 
30
- ## Generated And Derived Files
13
+ ## Source Of Truth
31
14
 
32
- - `tsconfig.tsbuildinfo` and similar compiler artifacts are derived files.
33
- - Treat consumer app theme state and compiled CSS output as derived from
34
- `themes.css` and `src/index.ts`.
15
+ | Concern | Source |
16
+ |---------|--------|
17
+ | Product chrome (factory) | `@nebutra/tokens` |
18
+ | Design language catalog | `src/languages.json` |
19
+ | Brand Package fixtures | `packages/design/tokens/brands/*` |
20
+ | Multi-language CSS | `skins.css` (`html[data-brand]`) |
21
+ | Keyframes only | `keyframes.css` (`themes.css` = deprecated alias) |
35
22
 
36
23
  ## Validation
37
24
 
38
- - Theme surface or type changes:
39
- `pnpm --filter @nebutra/theme typecheck`
40
- - When selector changes matter, verify a consumer imports `@nebutra/theme/themes.css`
41
- instead of patching compiled output.
25
+ ```bash
26
+ pnpm --filter @nebutra/theme test
27
+ pnpm --filter @nebutra/theme sync:skins
28
+ ```
package/DESIGN.md CHANGED
@@ -1,203 +1,124 @@
1
1
  # `@nebutra/theme` — Design Spec
2
2
 
3
- > Multi-theme engine of the Nebutra-Sailor design system.
4
- > Part of the [root DESIGN.md](../../DESIGN.md). Spec format: `design-md@2026.05`.
3
+ > Design-language catalog for **global product chrome swap**.
4
+ > Part of the [root DESIGN.md](../../DESIGN.md). Spec format: `design-md@2026.07`.
5
5
 
6
6
  | Field | Value |
7
7
  |------|------|
8
8
  | Package | `@nebutra/theme` |
9
- | Status | Stable — 6 themes shipped, more allowed via governance |
10
- | Source files | `packages/design/theme/src/registry.json` and generated `packages/design/theme/themes.css` |
11
- | Activation | `[data-theme="…"]` attribute on `<html>` |
12
- | Default theme | `neon` (no `data-theme` attribute) |
9
+ | Status | Design languages only — oklch multi-mood catalog **deleted** |
10
+ | Primary catalog | `src/languages.json` + generated `skins.css` |
11
+ | Brand Package fixtures | `packages/design/tokens/brands/*` |
12
+ | keyframes.css | Keyframes only (no color moods); themes.css is a deprecated alias |
13
+ | Product SSOT | Always `@nebutra/tokens` |
13
14
 
14
15
  ---
15
16
 
16
17
  ## 1. Identity
17
18
 
18
- A **product feature**: the SaaS preset system (`@nebutra/preset`) lets end customers and self-hosters choose a theme that matches their product mood. Switching is CSS-only (no JS rebuild) — token values are overridden per `[data-theme]` selector.
19
+ **What users mean by “换主题” in Create Center** is swapping a full **design language**:
20
+ action vs brand-mark, button recipe, free elevation stacks, radii slots, type zones — not recoloring `--primary` alone.
19
21
 
20
- **Boundary**: this package is for the multi-theme product feature. For light/dark of the *base* `neon` look, use `class="dark"` from `next-themes`. The two systems compose.
22
+ That product surface lives here. The stress-test loop (Linear → GSAP → Raycast → Vercel → Vanta) is how we grow **carrier capacity**, not an infinite preset zoo.
21
23
 
22
- The theme catalogue is governed through `src/registry.json`. Consumers must import from
23
- `@nebutra/theme/registry` instead of copying theme names. The Style Dictionary pipeline,
24
- `@nebutra/preset`, CLI commands, docs, and future Figma/playground publishing all use this registry.
24
+ **Not this package:** factory semantic HSL (tokens), VI logo lock (brand), component class strings (ui).
25
+
26
+ ### 1.1 Single catalog
27
+
28
+ | Catalog | Attribute | Payload |
29
+ |---------|-----------|---------|
30
+ | **Design language** | `html[data-brand]` | Brand Package CSS |
31
+
32
+ Oklch multi-mood `[data-theme]` catalog was removed — dual-truth and weak design quality.
25
33
 
26
34
  ---
27
35
 
28
- ## 2. Tokens (per theme)
36
+ ## 2. Design language contract
29
37
 
30
- Each preset overrides the same set of tokens; only values differ. The base set:
38
+ Each entry in `languages.json` maps to a Brand Package:
31
39
 
32
40
  ```
33
- Brand: --color-primary, --color-secondary, --color-accent (+ -foreground each)
34
- Surfaces: --color-background, --color-foreground, --color-card, --color-popover, --color-muted, --color-border, --color-input, --color-ring
35
- Status: --color-destructive, --color-success, --color-warning, --color-info (+ -foreground each)
36
- Derived: --color-primary-hover, --color-primary-active (via color-mix in oklch)
37
- Radius: --radius-{sm,md,lg,xl,full}
38
- Typography: --font-sans, --font-mono, --font-heading
39
- Shadows: --shadow-{sm,md,lg,xl}
40
- Transitions: --transition-{fast,normal,slow}
41
+ roles.action → --primary (CTA)
42
+ roles.brand → --brand-mark (logo / AI badge)
43
+ recipe → --btn-default-*, --badge-default-*, radii
44
+ elevationTokens → --elevation-card|control|raised (free CSS)
45
+ zones → product vs marketing type scales
46
+ typography.faces → @font-face
41
47
  ```
42
48
 
43
- All color values are **oklch** for perceptual uniformity. Hover/active states are derived via `color-mix(in oklch, …)` — no JS.
44
-
45
- ### 2.1 Theme catalogue
49
+ ### 2.1 Fixture matrix (acceptance bar)
46
50
 
47
- | `data-theme` | Mood | Background | Primary | Use case |
48
- |------|------|-----------|---------|----------|
49
- | `neon` *(default)* | Vibrant dark, electric blue | `oklch(0.141 0.005 285.9)` ≈ #09090b | `oklch(0.452 0.313 264.1)` ≈ vivid blue | AI SaaS dashboards |
50
- | `gradient` | Soft light, blue spectrum | `oklch(1 0 0)` (white) | `oklch(0.546 0.245 262.9)` | Marketing / growth |
51
- | `dark-dense` | High-density dark | near-black | desaturated blue | Pro tools, terminals |
52
- | `minimal` | Neutral, low chroma | white / off-white | low-chroma blue | Document apps |
53
- | `vibrant` | Saturated multicolor | white | vivid magenta-blue | Creator / consumer |
54
- | `ocean` | Cool teal/blue | white | teal | B2B finance, infra |
51
+ | id | Proves |
52
+ |----|--------|
53
+ | factory | No override — tokens SSOT |
54
+ | linear | Chromatic solid CTA + **dual-mode** dark/light |
55
+ | gsap | Non-solid CTA recipe + zones |
56
+ | raycast | action ≠ brand-mark + elev=key |
57
+ | vercel | Light mono + elev=hairline + **dual-mode** light/dark palettes |
58
+ | vanta | Chromatic action≠brand + elev=none + pills + dual fonts |
55
59
 
56
- > Exact oklch tuples for every theme are in `packages/design/theme/themes.css`. Designer-readable per-theme tables are deferred to Storybook (Foundation/Themes) — adding them here would duplicate the source of truth.
60
+ ### 2.2 CSS modes
57
61
 
58
- ### 2.2 Default (neon) — illustrative
59
-
60
- ```css
61
- @theme {
62
- --color-primary: oklch(0.452 0.313 264.1);
63
- --color-secondary: oklch(0.715 0.143 215.2);
64
- --color-accent: oklch(0.714 0.203 264.1);
65
- --color-background: oklch(0.141 0.005 285.9);
66
- --color-foreground: oklch(0.985 0 0);
67
- --color-card: oklch(0.212 0.006 285.9);
68
- --color-border: oklch(0.274 0.006 286);
69
- --color-destructive: oklch(0.577 0.245 27.3);
70
- --color-success: oklch(0.723 0.219 149.6);
71
- --color-warning: oklch(0.769 0.189 70.1);
72
- --color-info: oklch(0.623 0.214 259.1);
73
-
74
- --color-primary-hover: color-mix(in oklch, oklch(0.452 0.313 264.1), white 15%);
75
- --color-primary-active: color-mix(in oklch, oklch(0.452 0.313 264.1), black 10%);
76
-
77
- --radius-md: 0.375rem;
78
- --font-sans: "Inter", ui-sans-serif, system-ui, sans-serif;
79
- --transition-fast: 150ms cubic-bezier(0.4, 0, 0.2, 1);
80
- }
81
- ```
62
+ | Emit mode | Selector | Use |
63
+ |-----------|----------|-----|
64
+ | `global` (darkDefault) | `:root, .dark, html[data-brand]` | Dark-first single-skin demos |
65
+ | `global` (light) | `:root, html[data-brand]` | Light packs — never bind `.dark` |
66
+ | `scoped` | `html[data-brand]` only | `skins.css` multi-language catalog |
82
67
 
83
68
  ---
84
69
 
85
70
  ## 3. Patterns
86
71
 
87
- ### 3.1 Wiring up a Next.js app
88
-
89
- ```tsx
90
- // apps/{app}/src/app/globals.css
91
- @import "tailwindcss";
92
- @import "@nebutra/tokens/styles.css"; /* base tokens */
93
- @import "@nebutra/theme/themes.css"; /* multi-theme overrides */
72
+ ### 3.1 App wiring
94
73
 
95
- // apps/{app}/src/app/layout.tsx
96
- import { ThemeProvider } from "@nebutra/tokens";
97
-
98
- <ThemeProvider attribute="data-theme" defaultTheme="neon" themes={["neon","gradient","dark-dense","minimal","vibrant","ocean"]}>
99
- {children}
100
- </ThemeProvider>
101
- ```
102
-
103
- ### 3.2 Switching themes at runtime
104
-
105
- ```tsx
106
- "use client";
107
- import { useTheme } from "@nebutra/tokens";
108
-
109
- function ThemeSwitch() {
110
- const { theme, setTheme } = useTheme();
111
- return (
112
- <select value={theme} onChange={(e) => setTheme(e.target.value)}>
113
- <option value="neon">Neon</option>
114
- <option value="gradient">Gradient</option>
115
- <option value="dark-dense">Dark Dense</option>
116
- <option value="minimal">Minimal</option>
117
- <option value="vibrant">Vibrant</option>
118
- <option value="ocean">Ocean</option>
119
- </select>
120
- );
121
- }
74
+ ```css
75
+ @import "@nebutra/tokens/styles.css";
76
+ @import "@nebutra/tokens/recipe.css";
77
+ @import "@nebutra/theme/skins.css"; /* optional catalog */
122
78
  ```
123
79
 
124
- ### 3.3 Adding a new theme
80
+ ```ts
81
+ import { applyLanguage, clearLanguage } from "@nebutra/theme";
125
82
 
126
- 1. Add the DTCG file under `packages/design/design-tokens/tokens/themes/my-theme.json`.
127
- 2. Add the registry entry to `packages/design/theme/src/registry.json`.
128
- 3. Provide every token defined in §2.
129
- 4. Run `pnpm --filter @nebutra/design-tokens build` to regenerate theme CSS.
130
- 5. Validate with theme tests, preset tests, and the CLI smoke checks.
131
- 6. Add the playground/Storybook visual entry before publishing the theme.
132
- 7. Open a PR; design-system maintainer reviews perceptual coherence, contrast, and component coverage.
133
-
134
- ---
83
+ applyLanguage("vanta", { persist: true }); // built-in Brand Package
84
+ clearLanguage(); // factory
85
+ ```
135
86
 
136
- ## 4. Imports & Conventions
87
+ ### 3.2 Compile pipeline
137
88
 
138
- ```css
139
- @import "@nebutra/theme/themes.css";
89
+ ```bash
90
+ pnpm --filter @nebutra/tokens compile-brand -- ~/Desktop/Design-System/Foo --id foo
91
+ # edit languages.json
92
+ pnpm --filter @nebutra/theme sync:skins
140
93
  ```
141
94
 
142
- Themes are CSS at runtime, but their catalogue metadata is exported from `@nebutra/theme/registry`.
143
- Theme names are registry-derived; do not introduce new handwritten enums.
95
+ ### 3.3 Light/dark
144
96
 
145
- ### Forbidden
97
+ Independent of design-language **id**. Use `@nebutra/tokens` ThemeProvider (`class="dark"`).
146
98
 
147
- ```tsx
148
- // ❌ Hardcoding theme-specific colors in components
149
- <div className="bg-[#7C3AED]" />
99
+ | Pack shape | Emit behavior |
100
+ |------------|----------------|
101
+ | Single-mode (most fixtures) | One palette; `darkDefault` may bind `.dark` so dark shells keep the skin |
102
+ | Dual-mode (`modes.light` + `modes.dark`) | Light under `:root` / `html[data-brand]`; dark under `.dark` / `html.dark[data-brand]` (e.g. **vercel**) |
150
103
 
151
- // ❌ Skipping a token override when defining a new theme
152
- [data-theme="my-theme"] { --color-primary: oklch(…); /* missing background, etc. */ }
153
- ```
104
+ Recipe, typography, and zones are shared across modes; only color roles/semantic flip.
154
105
 
155
106
  ---
156
107
 
157
- ## 5. Theming (composition with light/dark)
158
-
159
- Light/dark and multi-theme are **orthogonal**:
108
+ ## 4. Anti-goals
160
109
 
161
- | `class` (next-themes) | `data-theme` (preset) | Result |
162
- |-----------------------|----------------------|--------|
163
- | (none) | (none) | base tokens from `@nebutra/tokens`, light |
164
- | `dark` | (none) | base tokens, dark variant |
165
- | (none) | `gradient` | gradient theme overrides |
166
- | `dark` | `dark-dense` | dark-dense theme overrides (dark by design) |
167
-
168
- Themes that define their own background/foreground supersede the `.dark` overrides for those tokens — designers should pick one mode per theme intent.
110
+ - Do not treat 78 oklch moods as the product roadmap.
111
+ - Do not dual-write root `@theme --color-primary` against tokens.
112
+ - Do not map brand-mark into `--primary` for “branded buttons”.
113
+ - Do not add a language that only changes hue without a new **capacity** proof.
169
114
 
170
115
  ---
171
116
 
172
- ## 6. Versioning & Governance
173
-
174
- | Surface | Status |
175
- |--------|--------|
176
- | Default theme name (`neon`) | **Locked** |
177
- | Token *names* listed in §2 | **Locked** — every theme must define all of them |
178
- | Adding a new theme preset | Extensible — design-system maintainer review |
179
- | Renaming an existing theme | **Forbidden** without a migration alias |
180
- | Per-theme oklch values | Extensible — adjust freely with PR + visual diff |
181
-
182
- ### Governance scripts
117
+ ## 5. Validation
183
118
 
184
119
  ```bash
185
120
  pnpm --filter @nebutra/theme test
186
- pnpm --filter @nebutra/theme typecheck
187
- pnpm --filter @nebutra/design-tokens build
188
- pnpm --filter @nebutra/preset test
189
- pnpm --filter nebutra build
190
- node packages/ops/cli/dist/index.js theme list --format json
191
- pnpm tsx scripts/validate-ui-governance-policy.ts
121
+ pnpm --filter @nebutra/tokens test
122
+ nebutra theme list
123
+ nebutra theme inspect vanta
192
124
  ```
193
-
194
- ---
195
-
196
- ## 7. Open questions / review notes
197
-
198
- - Per-theme oklch tables are not enumerated here to avoid duplicating `themes.css`. Storybook's Foundation/Themes panel is the canonical visual reference — add it if missing.
199
-
200
- ---
201
-
202
- ← back to [root DESIGN.md](../../DESIGN.md) ·
203
- peer specs: [brand](../brand/DESIGN.md) · [tokens](../tokens/DESIGN.md) · [ui](../ui/DESIGN.md)