@nebutra/theme 0.1.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.
@@ -0,0 +1,177 @@
1
+
2
+ > @nebutra/theme@0.1.0 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.0 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.0 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
@@ -0,0 +1,14 @@
1
+
2
+ > @nebutra/theme@0.1.0 test /home/runner/work/Nebutra-Sailor/Nebutra-Sailor/packages/design/theme
3
+ > vitest run
4
+
5
+
6
+  RUN  v4.1.4 /home/runner/work/Nebutra-Sailor/Nebutra-Sailor/packages/design/theme
7
+
8
+ ✓ src/__tests__/theme-registry.test.ts (4 tests) 87ms
9
+
10
+  Test Files  1 passed (1)
11
+  Tests  4 passed (4)
12
+  Start at  16:50:59
13
+  Duration  1.40s (transform 329ms, setup 0ms, import 481ms, tests 87ms, environment 0ms)
14
+
@@ -0,0 +1,4 @@
1
+
2
+ > @nebutra/theme@0.1.0 typecheck /home/runner/work/Nebutra-Sailor/Nebutra-Sailor/packages/design/theme
3
+ > tsc --noEmit
4
+
package/AGENTS.md ADDED
@@ -0,0 +1,41 @@
1
+ # AGENTS.md — packages/theme
2
+
3
+ Execution contract for Nebutra's multi-theme preset package.
4
+
5
+ ## Scope
6
+
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`
16
+
17
+ ## Contract Boundaries
18
+
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.
29
+
30
+ ## Generated And Derived Files
31
+
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`.
35
+
36
+ ## Validation
37
+
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.
package/DESIGN.md ADDED
@@ -0,0 +1,203 @@
1
+ # `@nebutra/theme` — Design Spec
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`.
5
+
6
+ | Field | Value |
7
+ |------|------|
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) |
13
+
14
+ ---
15
+
16
+ ## 1. Identity
17
+
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
+
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.
21
+
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.
25
+
26
+ ---
27
+
28
+ ## 2. Tokens (per theme)
29
+
30
+ Each preset overrides the same set of tokens; only values differ. The base set:
31
+
32
+ ```
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
+ ```
42
+
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
46
+
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 |
55
+
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.
57
+
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
+ ```
82
+
83
+ ---
84
+
85
+ ## 3. Patterns
86
+
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 */
94
+
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
+ }
122
+ ```
123
+
124
+ ### 3.3 Adding a new theme
125
+
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
+ ---
135
+
136
+ ## 4. Imports & Conventions
137
+
138
+ ```css
139
+ @import "@nebutra/theme/themes.css";
140
+ ```
141
+
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.
144
+
145
+ ### Forbidden
146
+
147
+ ```tsx
148
+ // ❌ Hardcoding theme-specific colors in components
149
+ <div className="bg-[#7C3AED]" />
150
+
151
+ // ❌ Skipping a token override when defining a new theme
152
+ [data-theme="my-theme"] { --color-primary: oklch(…); /* missing background, etc. */ }
153
+ ```
154
+
155
+ ---
156
+
157
+ ## 5. Theming (composition with light/dark)
158
+
159
+ Light/dark and multi-theme are **orthogonal**:
160
+
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.
169
+
170
+ ---
171
+
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
183
+
184
+ ```bash
185
+ 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
192
+ ```
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)