@nebutra/tokens 0.1.0 → 0.1.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/.turbo/turbo-build.log +5 -0
- package/.turbo/turbo-typecheck.log +4 -0
- package/CHANGELOG.md +10 -0
- package/DESIGN.md +3 -1
- package/package.json +4 -4
- package/src/theme-provider.tsx +16 -3
- package/styles.css +16 -22
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
|
|
2
|
+
> @nebutra/tokens@0.1.1 build /home/runner/work/Nebutra-Sailor/Nebutra-Sailor/packages/design/tokens
|
|
3
|
+
> node -e "const fs=require('node:fs'),src='../design-tokens/build/css/styles.generated.css';if(fs.existsSync(src)){fs.copyFileSync(src,'./styles.css');console.log('styles.css refreshed from @nebutra/design-tokens')}else{console.log('styles.css kept (committed copy used; design-tokens build/ absent — likely Turbo cache restore without files)')}"
|
|
4
|
+
|
|
5
|
+
styles.css refreshed from @nebutra/design-tokens
|
package/CHANGELOG.md
ADDED
package/DESIGN.md
CHANGED
|
@@ -109,7 +109,8 @@ Scales: `--neutral-{1..12}`, `--blue-{1..12}`, `--cyan-{1..12}`. Light values ar
|
|
|
109
109
|
| `--brand-primary` | `var(--blue-9)` → `#0033FE` | Primary brand |
|
|
110
110
|
| `--brand-accent` | `var(--cyan-9)` → `#0BF1C3` | Accent |
|
|
111
111
|
| `--brand-tertiary` | `#8B5CF6` | Data viz / infra tags only |
|
|
112
|
-
| `--brand-gradient` | `linear-gradient(135deg,
|
|
112
|
+
| `--brand-gradient` | `linear-gradient(135deg, #254BFA → #057963)` | UI usage gradient for CTAs, badges, hero text |
|
|
113
|
+
| `--brand-gradient-logo` | `linear-gradient(135deg, #0033FE → #0BF1C3)` | VI/logo assets only |
|
|
113
114
|
|
|
114
115
|
### 2.4 Semantic theme tokens (HSL triplets — Tailwind compatible)
|
|
115
116
|
|
|
@@ -304,6 +305,7 @@ For the **multi-theme product feature** (6 oklch presets), see [`packages/design
|
|
|
304
305
|
| Surface | Status |
|
|
305
306
|
|--------|--------|
|
|
306
307
|
| Brand color hex anchors (`#0033FE`, `#0BF1C3`, `--nebutra-neutral-{50..950}`) | **Locked** |
|
|
308
|
+
| UI brand gradient (`--brand-gradient`) | Extensible — may tune saturation/contrast while preserving locked brand anchors |
|
|
307
309
|
| 12-step semantic ladder positions (1–12 meaning) | **Locked** |
|
|
308
310
|
| Container widths | **Locked** |
|
|
309
311
|
| Radius scale values | **Locked** |
|
package/package.json
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nebutra/tokens",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "Unified theme tokens and theme-provider entry for Nebutra apps",
|
|
5
5
|
"private": false,
|
|
6
|
-
"license": "
|
|
6
|
+
"license": "MIT",
|
|
7
7
|
"type": "module",
|
|
8
8
|
"sideEffects": [
|
|
9
9
|
"./styles.css"
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
},
|
|
17
17
|
"dependencies": {
|
|
18
18
|
"next-themes": "^0.4.6",
|
|
19
|
-
"@nebutra/design-tokens": "0.1.
|
|
19
|
+
"@nebutra/design-tokens": "0.1.1"
|
|
20
20
|
},
|
|
21
21
|
"peerDependencies": {
|
|
22
22
|
"react": "^19"
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
},
|
|
40
40
|
"scripts": {
|
|
41
41
|
"build": "node -e \"const fs=require('node:fs'),src='../design-tokens/build/css/styles.generated.css';if(fs.existsSync(src)){fs.copyFileSync(src,'./styles.css');console.log('styles.css refreshed from @nebutra/design-tokens')}else{console.log('styles.css kept (committed copy used; design-tokens build/ absent — likely Turbo cache restore without files)')}\"",
|
|
42
|
-
"sync": "pnpm --filter @nebutra/design-tokens build && node -e \"require('node:fs').copyFileSync('../design-tokens/build/css/styles.generated.css', './styles.css')\"",
|
|
42
|
+
"sync": "corepack pnpm --filter @nebutra/design-tokens build && node -e \"require('node:fs').copyFileSync('../design-tokens/build/css/styles.generated.css', './styles.css')\"",
|
|
43
43
|
"typecheck": "tsc --noEmit"
|
|
44
44
|
}
|
|
45
45
|
}
|
package/src/theme-provider.tsx
CHANGED
|
@@ -42,8 +42,12 @@ const THEMES = ["light", "dark", "system"] as const satisfies readonly Theme[];
|
|
|
42
42
|
export const THEME_STORAGE_KEY = "theme";
|
|
43
43
|
|
|
44
44
|
interface ThemeContextValue {
|
|
45
|
+
/** Whether a real ThemeProvider is present above the consumer. */
|
|
46
|
+
isProviderBound: boolean;
|
|
45
47
|
/** The raw user preference. May be "system". */
|
|
46
48
|
theme: Theme;
|
|
49
|
+
/** Provider-level override for demos, locked routes, or embedded previews. */
|
|
50
|
+
forcedTheme?: Theme | undefined;
|
|
47
51
|
/** The concretely-applied theme — always "light" or "dark". */
|
|
48
52
|
resolvedTheme: ResolvedTheme;
|
|
49
53
|
/** The OS-level preference (always concrete). */
|
|
@@ -62,7 +66,9 @@ export function useTheme(): ThemeContextValue {
|
|
|
62
66
|
const ctx = useContext(ThemeContext);
|
|
63
67
|
if (ctx) return ctx;
|
|
64
68
|
return {
|
|
69
|
+
isProviderBound: false,
|
|
65
70
|
theme: "system",
|
|
71
|
+
forcedTheme: undefined,
|
|
66
72
|
resolvedTheme: "light",
|
|
67
73
|
systemTheme: "light",
|
|
68
74
|
setTheme: () => {
|
|
@@ -145,6 +151,8 @@ export interface ThemeProviderProps {
|
|
|
145
151
|
defaultTheme?: Theme;
|
|
146
152
|
/** Whether `"system"` is a valid theme that tracks `prefers-color-scheme`. */
|
|
147
153
|
enableSystem?: boolean;
|
|
154
|
+
/** Lock the rendered theme and expose read-only state to controls. */
|
|
155
|
+
forcedTheme?: Theme | undefined;
|
|
148
156
|
/** Suppress CSS transitions during the swap. Default: `true`. */
|
|
149
157
|
disableTransitionOnChange?: boolean;
|
|
150
158
|
/** Storage key under which the preference is persisted. */
|
|
@@ -158,17 +166,20 @@ export function ThemeProvider({
|
|
|
158
166
|
attribute = "class",
|
|
159
167
|
defaultTheme = "system",
|
|
160
168
|
enableSystem = true,
|
|
169
|
+
forcedTheme,
|
|
161
170
|
disableTransitionOnChange = true,
|
|
162
171
|
storageKey = THEME_STORAGE_KEY,
|
|
163
172
|
}: ThemeProviderProps) {
|
|
164
173
|
const [theme, setThemeState] = useState<Theme>(() => readStoredTheme(storageKey, defaultTheme));
|
|
165
174
|
const [systemTheme, setSystemTheme] = useState<ResolvedTheme>(() => resolveSystemTheme());
|
|
166
175
|
|
|
176
|
+
const effectiveTheme = forcedTheme ?? theme;
|
|
167
177
|
const resolvedTheme: ResolvedTheme =
|
|
168
|
-
|
|
178
|
+
effectiveTheme === "system" ? (enableSystem ? systemTheme : "light") : effectiveTheme;
|
|
169
179
|
|
|
170
180
|
const setTheme = useCallback(
|
|
171
181
|
(next: Theme) => {
|
|
182
|
+
if (forcedTheme !== undefined) return;
|
|
172
183
|
setThemeState(next);
|
|
173
184
|
try {
|
|
174
185
|
if (next === "system") {
|
|
@@ -180,7 +191,7 @@ export function ThemeProvider({
|
|
|
180
191
|
// localStorage may be disabled — accept the loss
|
|
181
192
|
}
|
|
182
193
|
},
|
|
183
|
-
[storageKey],
|
|
194
|
+
[forcedTheme, storageKey],
|
|
184
195
|
);
|
|
185
196
|
|
|
186
197
|
// Apply the resolved theme to the DOM AND sync the cookie so the next
|
|
@@ -218,13 +229,15 @@ export function ThemeProvider({
|
|
|
218
229
|
|
|
219
230
|
const value = useMemo<ThemeContextValue>(
|
|
220
231
|
() => ({
|
|
232
|
+
isProviderBound: true,
|
|
221
233
|
theme,
|
|
234
|
+
forcedTheme,
|
|
222
235
|
resolvedTheme,
|
|
223
236
|
systemTheme,
|
|
224
237
|
setTheme,
|
|
225
238
|
themes: THEMES,
|
|
226
239
|
}),
|
|
227
|
-
[theme, resolvedTheme, systemTheme, setTheme],
|
|
240
|
+
[theme, forcedTheme, resolvedTheme, systemTheme, setTheme],
|
|
228
241
|
);
|
|
229
242
|
|
|
230
243
|
return <ThemeContext.Provider value={value}>{children}</ThemeContext.Provider>;
|
package/styles.css
CHANGED
|
@@ -69,13 +69,6 @@
|
|
|
69
69
|
--nebutra-gray-800: #262626;
|
|
70
70
|
--nebutra-gray-900: #171717;
|
|
71
71
|
--nebutra-gray-950: #0a0a0a;
|
|
72
|
-
--brand-tertiary: #8b5cf6; /** Tertiary accent — data viz, infrastructure tags */
|
|
73
|
-
--status-danger: #ef4444;
|
|
74
|
-
--status-warning: #f59e0b;
|
|
75
|
-
--status-success: #22c55e; /** Tailwind green-500 — VI manual canonical success color (replaces drifted #10b981 emerald). */
|
|
76
|
-
--container-text: 896px; /** Reading-focused (hero copy, FAQ) */
|
|
77
|
-
--container-content: 1152px; /** Pricing, blog */
|
|
78
|
-
--container-wide: 1400px; /** Feature bento, navbar */
|
|
79
72
|
--radius-none: 0;
|
|
80
73
|
--radius-sm: 0.25rem;
|
|
81
74
|
--radius-md: 0.375rem;
|
|
@@ -112,10 +105,12 @@
|
|
|
112
105
|
--brand-primary: #0033fe; /** Brand primary — 云毓蓝 */
|
|
113
106
|
--brand-accent: #0bf1c3; /** Brand accent — 云毓青 */
|
|
114
107
|
--brand-tertiary: #8b5cf6;
|
|
115
|
-
--brand-gradient: linear-gradient(135deg, #
|
|
116
|
-
--brand-gradient-reverse: linear-gradient(135deg, #
|
|
117
|
-
--brand-gradient-vertical: linear-gradient(180deg, #
|
|
118
|
-
--brand-gradient-radial: radial-gradient(circle, #
|
|
108
|
+
--brand-gradient: linear-gradient(135deg, #254bfa 0%, #057963 100%); /** UI brand gradient — usage-adjusted from the locked VI blue/cyan anchors to reduce saturation and preserve white-text contrast. */
|
|
109
|
+
--brand-gradient-reverse: linear-gradient(135deg, #057963 0%, #254bfa 100%);
|
|
110
|
+
--brand-gradient-vertical: linear-gradient(180deg, #254bfa 0%, #057963 100%);
|
|
111
|
+
--brand-gradient-radial: radial-gradient(circle, #057963 0%, #254bfa 100%);
|
|
112
|
+
--brand-gradient-logo: linear-gradient(135deg, #0033fe 0%, #0bf1c3 100%); /** Logo/VI standard gradient. Use for brand assets only; product UI should use --brand-gradient. */
|
|
113
|
+
--brand-gradient-logo-reverse: linear-gradient(135deg, #0bf1c3 0%, #0033fe 100%);
|
|
119
114
|
--status-danger: #ef4444;
|
|
120
115
|
--status-warning: #f59e0b;
|
|
121
116
|
--status-success: #22c55e;
|
|
@@ -259,6 +254,8 @@
|
|
|
259
254
|
--gradient-brand-reverse: var(--brand-gradient-reverse);
|
|
260
255
|
--gradient-brand-radial: var(--brand-gradient-radial);
|
|
261
256
|
--gradient-brand-glow: var(--brand-gradient-radial);
|
|
257
|
+
--gradient-brand-logo: var(--brand-gradient-logo);
|
|
258
|
+
--gradient-brand-logo-reverse: var(--brand-gradient-logo-reverse);
|
|
262
259
|
--gradient-section: var(--brand-gradient-vertical);
|
|
263
260
|
--gradient-glow: var(--brand-gradient-radial);
|
|
264
261
|
}
|
|
@@ -342,13 +339,6 @@
|
|
|
342
339
|
--nebutra-gray-800: #262626;
|
|
343
340
|
--nebutra-gray-900: #171717;
|
|
344
341
|
--nebutra-gray-950: #0a0a0a;
|
|
345
|
-
--brand-tertiary: #8b5cf6; /** Tertiary accent — data viz, infrastructure tags */
|
|
346
|
-
--status-danger: #ef4444;
|
|
347
|
-
--status-warning: #f59e0b;
|
|
348
|
-
--status-success: #22c55e; /** Tailwind green-500 — VI manual canonical success color (replaces drifted #10b981 emerald). */
|
|
349
|
-
--container-text: 896px; /** Reading-focused (hero copy, FAQ) */
|
|
350
|
-
--container-content: 1152px; /** Pricing, blog */
|
|
351
|
-
--container-wide: 1400px; /** Feature bento, navbar */
|
|
352
342
|
--radius-none: 0;
|
|
353
343
|
--radius-sm: 0.25rem;
|
|
354
344
|
--radius-md: 0.375rem;
|
|
@@ -385,10 +375,12 @@
|
|
|
385
375
|
--brand-primary: #5c7cfa; /** Dark-mode brand primary — visible against dark surfaces (uses --blue-9 = nebutra-blue-400). */
|
|
386
376
|
--brand-accent: #1af7c8; /** Dark-mode brand accent — visible against dark surfaces (uses --cyan-9 = nebutra-cyan-400). */
|
|
387
377
|
--brand-tertiary: #8b5cf6;
|
|
388
|
-
--brand-gradient: linear-gradient(135deg, #
|
|
389
|
-
--brand-gradient-reverse: linear-gradient(135deg, #
|
|
390
|
-
--brand-gradient-vertical: linear-gradient(180deg, #
|
|
391
|
-
--brand-gradient-radial: radial-gradient(circle, #
|
|
378
|
+
--brand-gradient: linear-gradient(135deg, #254bfa 0%, #057963 100%); /** UI brand gradient — usage-adjusted from the locked VI blue/cyan anchors to reduce saturation and preserve white-text contrast. */
|
|
379
|
+
--brand-gradient-reverse: linear-gradient(135deg, #057963 0%, #254bfa 100%);
|
|
380
|
+
--brand-gradient-vertical: linear-gradient(180deg, #254bfa 0%, #057963 100%);
|
|
381
|
+
--brand-gradient-radial: radial-gradient(circle, #057963 0%, #254bfa 100%);
|
|
382
|
+
--brand-gradient-logo: linear-gradient(135deg, #0033fe 0%, #0bf1c3 100%); /** Logo/VI standard gradient. Use for brand assets only; product UI should use --brand-gradient. */
|
|
383
|
+
--brand-gradient-logo-reverse: linear-gradient(135deg, #0bf1c3 0%, #0033fe 100%);
|
|
392
384
|
--status-danger: #ef4444;
|
|
393
385
|
--status-warning: #f59e0b;
|
|
394
386
|
--status-success: #22c55e;
|
|
@@ -526,6 +518,8 @@
|
|
|
526
518
|
--gradient-brand-reverse: var(--brand-gradient-reverse);
|
|
527
519
|
--gradient-brand-radial: var(--brand-gradient-radial);
|
|
528
520
|
--gradient-brand-glow: var(--brand-gradient-radial);
|
|
521
|
+
--gradient-brand-logo: var(--brand-gradient-logo);
|
|
522
|
+
--gradient-brand-logo-reverse: var(--brand-gradient-logo-reverse);
|
|
529
523
|
--gradient-section: var(--brand-gradient-vertical);
|
|
530
524
|
--gradient-glow: var(--brand-gradient-radial);
|
|
531
525
|
}
|