@xforge-dev/forge-kit 0.19.0 → 0.20.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.
@@ -14,8 +14,8 @@ import { useForgeTheme } from './theme-provider.js';
14
14
  import { useCurrentUrl } from './use-current-url.js';
15
15
  export const isNavGroup = (item) => 'sections' in item;
16
16
  const navPill = (active) => active
17
- ? 'rounded-md bg-primary px-3 py-1.5 text-sm font-medium text-primary-foreground'
18
- : 'rounded-md px-3 py-1.5 text-sm font-medium text-muted-foreground transition-colors hover:bg-accent hover:text-foreground';
17
+ ? 'rounded-lg bg-primary-tint px-3 py-1.5 text-sm font-semibold text-primary-text'
18
+ : 'rounded-lg px-3 py-1.5 text-sm font-medium text-muted-foreground transition-colors hover:bg-accent hover:text-foreground';
19
19
  /**
20
20
  * The header every xForge app shares: app switcher, page links, app buttons,
21
21
  * and an avatar that opens the account panel with the theme settings.
package/dist/tokens.css CHANGED
@@ -46,6 +46,16 @@
46
46
  --color-border: var(--border);
47
47
  --color-input: var(--input);
48
48
  --color-ring: var(--ring);
49
+ --color-primary-text: var(--primary-text);
50
+ --color-primary-muted: var(--primary-muted);
51
+ --color-primary-tint: var(--primary-tint);
52
+ --color-primary-border: var(--primary-border);
53
+ --color-primary-surface: var(--primary-surface);
54
+ --color-primary-surface-border: var(--primary-surface-border);
55
+ --color-inset: var(--inset);
56
+ --color-divider: var(--divider);
57
+ --color-chip: var(--chip);
58
+ --color-track: var(--track);
49
59
 
50
60
  --radius-lg: var(--radius);
51
61
  --radius-md: calc(var(--radius) - 2px);
@@ -75,6 +85,14 @@
75
85
  --border: hsl(0 0% 89.8%);
76
86
  --input: hsl(0 0% 89.8%);
77
87
  --ring: hsl(38 100% 65%);
88
+ /* The accent as small text (11–14px): at least 4.5:1 on --card. Each theme tunes it per mode below;
89
+ big bold figures can use it too. Gold on white needs it far darker than the swatch. */
90
+ --primary-text: hsl(38 100% 29%);
91
+ /* Neutral roles inside panels: rows set into a card, the rules between rows, chips, empty meter tracks. */
92
+ --inset: hsl(0 0% 96.1%);
93
+ --divider: hsl(0 0% 92%);
94
+ --chip: hsl(0 0% 93%);
95
+ --track: hsl(0 0% 89.8%);
78
96
  --radius: 0.5rem;
79
97
  /* Explicit Tailwind v4 utility vars (ensures runtime overrides work) */
80
98
  --color-primary: hsl(38 100% 65%);
@@ -103,24 +121,51 @@
103
121
  --border: hsl(0 0% 20%);
104
122
  --input: hsl(0 0% 20%);
105
123
  --ring: hsl(38 100% 65%);
124
+ --primary-text: hsl(38 100% 65%);
125
+ --inset: hsl(0 0% 10.5%);
126
+ --divider: hsl(0 0% 17%);
127
+ --chip: hsl(0 0% 19%);
128
+ --track: hsl(0 0% 18%);
106
129
  --color-primary: hsl(38 100% 65%);
107
130
  --color-primary-foreground: hsl(38 100% 10%);
108
131
  --color-ring: hsl(38 100% 65%);
109
132
  }
110
133
 
111
- /* ── Solid colour themes (one per FORGE_COLOR_THEMES entry; see theme.ts) ── */
112
- html[data-color="blue"] { --primary: hsl(217 91% 60%); --color-primary: hsl(217 91% 60%); --ring: hsl(217 91% 60%); --color-ring: hsl(217 91% 60%); }
113
- html[data-color="green"] { --primary: hsl(142 71% 45%); --color-primary: hsl(142 71% 45%); --ring: hsl(142 71% 45%); --color-ring: hsl(142 71% 45%); }
114
- html[data-color="rose"] { --primary: hsl(346 72% 58%); --color-primary: hsl(346 72% 58%); --ring: hsl(346 72% 58%); --color-ring: hsl(346 72% 58%); }
115
- html[data-color="violet"] { --primary: hsl(262 83% 58%); --color-primary: hsl(262 83% 58%); --ring: hsl(262 83% 58%); --color-ring: hsl(262 83% 58%); }
116
- html[data-color="sunset"] { --primary: hsl(27 100% 74%); --color-primary: hsl(27 100% 74%); --ring: hsl(27 100% 74%); --color-ring: hsl(27 100% 74%); }
117
- html[data-color="ocean"] { --primary: hsl(209 100% 50%); --color-primary: hsl(209 100% 50%); --ring: hsl(209 100% 50%); --color-ring: hsl(209 100% 50%); }
118
- html[data-color="lush"] { --primary: hsl(130 52% 52%); --color-primary: hsl(130 52% 52%); --ring: hsl(130 52% 52%); --color-ring: hsl(130 52% 52%); }
119
- html[data-color="passion"] { --primary: hsl(7 99% 62%); --color-primary: hsl(7 99% 62%); --ring: hsl(7 99% 62%); --color-ring: hsl(7 99% 62%); }
120
- html[data-color="royal"] { --primary: hsl(276 86% 57%); --color-primary: hsl(276 86% 57%); --ring: hsl(276 86% 57%); --color-ring: hsl(276 86% 57%); }
121
- html[data-color="steel"] { --primary: hsl(0 0% 60%); --color-primary: hsl(0 0% 60%); --ring: hsl(0 0% 60%); --color-ring: hsl(0 0% 60%); }
122
- html[data-color="mono"]:not(.dark) { --primary: hsl(0 0% 9%); --color-primary: hsl(0 0% 9%); --primary-foreground: hsl(0 0% 98%); --color-primary-foreground: hsl(0 0% 98%); --ring: hsl(0 0% 9%); --color-ring: hsl(0 0% 9%); }
123
- html[data-color="mono"].dark { --primary: hsl(0 0% 98%); --color-primary: hsl(0 0% 98%); --primary-foreground: hsl(0 0% 9%); --color-primary-foreground: hsl(0 0% 9%); --ring: hsl(0 0% 98%); --color-ring: hsl(0 0% 98%); }
134
+ /* Everything else accent-coloured derives from --primary / --primary-text, so a theme is one swatch. */
135
+ :root {
136
+ --primary-muted: color-mix(in oklab, var(--primary-text) 65%, var(--muted-foreground));
137
+ --primary-tint: color-mix(in oklab, var(--primary) 12%, transparent);
138
+ --primary-border: color-mix(in oklab, var(--primary) 35%, transparent);
139
+ --primary-surface: color-mix(in oklab, var(--primary) 7%, var(--card));
140
+ --primary-surface-border: color-mix(in oklab, var(--primary) 25%, var(--border));
141
+ }
142
+
143
+ /* ── Solid colour themes (one per FORGE_COLOR_THEMES entry; see theme.ts) ──
144
+ Each sets the swatch, the ink on a solid fill of it (--primary-foreground: dark ink, or white where that reads
145
+ better), and --primary-text per mode, stepped until it reaches 4.5:1 on --card. Gradient themes use one solid
146
+ representative colour here: never put a gradient on text or a thin bar. */
147
+ html[data-color="blue"] { --primary: hsl(217 91% 60%); --color-primary: hsl(217 91% 60%); --ring: hsl(217 91% 60%); --color-ring: hsl(217 91% 60%); --primary-foreground: hsl(0 0% 4%); --color-primary-foreground: hsl(0 0% 4%); --primary-text: hsl(217 91% 49%); }
148
+ html[data-color="blue"].dark { --primary-text: hsl(217 91% 65%); }
149
+ html[data-color="green"] { --primary: hsl(142 71% 45%); --color-primary: hsl(142 71% 45%); --ring: hsl(142 71% 45%); --color-ring: hsl(142 71% 45%); --primary-text: hsl(142 71% 27%); }
150
+ html[data-color="green"].dark { --primary-text: hsl(142 71% 47%); }
151
+ html[data-color="rose"] { --primary: hsl(346 72% 58%); --color-primary: hsl(346 72% 58%); --ring: hsl(346 72% 58%); --color-ring: hsl(346 72% 58%); --primary-foreground: hsl(0 0% 4%); --color-primary-foreground: hsl(0 0% 4%); --primary-text: hsl(346 72% 49%); }
152
+ html[data-color="rose"].dark { --primary-text: hsl(346 72% 66%); }
153
+ html[data-color="violet"] { --primary: hsl(262 83% 58%); --color-primary: hsl(262 83% 58%); --ring: hsl(262 83% 58%); --color-ring: hsl(262 83% 58%); --primary-foreground: hsl(0 0% 98%); --color-primary-foreground: hsl(0 0% 98%); --primary-text: hsl(262 83% 55%); }
154
+ html[data-color="violet"].dark { --primary-text: hsl(262 83% 72%); }
155
+ html[data-color="sunset"] { --primary: hsl(27 100% 74%); --color-primary: hsl(27 100% 74%); --ring: hsl(27 100% 74%); --color-ring: hsl(27 100% 74%); --primary-text: hsl(27 100% 34%); }
156
+ html[data-color="sunset"].dark { --primary-text: hsl(27 100% 74%); }
157
+ html[data-color="ocean"] { --primary: hsl(209 100% 50%); --color-primary: hsl(209 100% 50%); --ring: hsl(209 100% 50%); --color-ring: hsl(209 100% 50%); --primary-foreground: hsl(0 0% 4%); --color-primary-foreground: hsl(0 0% 4%); --primary-text: hsl(209 100% 40%); }
158
+ html[data-color="ocean"].dark { --primary-text: hsl(209 100% 56%); }
159
+ html[data-color="lush"] { --primary: hsl(130 52% 52%); --color-primary: hsl(130 52% 52%); --ring: hsl(130 52% 52%); --color-ring: hsl(130 52% 52%); --primary-text: hsl(130 52% 31%); }
160
+ html[data-color="lush"].dark { --primary-text: hsl(130 52% 54%); }
161
+ html[data-color="passion"] { --primary: hsl(7 99% 62%); --color-primary: hsl(7 99% 62%); --ring: hsl(7 99% 62%); --color-ring: hsl(7 99% 62%); --primary-text: hsl(7 99% 42%); }
162
+ html[data-color="passion"].dark { --primary-text: hsl(7 99% 64%); }
163
+ html[data-color="royal"] { --primary: hsl(276 86% 57%); --color-primary: hsl(276 86% 57%); --ring: hsl(276 86% 57%); --color-ring: hsl(276 86% 57%); --primary-foreground: hsl(0 0% 98%); --color-primary-foreground: hsl(0 0% 98%); --primary-text: hsl(276 86% 54%); }
164
+ html[data-color="royal"].dark { --primary-text: hsl(276 86% 70%); }
165
+ html[data-color="steel"] { --primary: hsl(0 0% 60%); --color-primary: hsl(0 0% 60%); --ring: hsl(0 0% 60%); --color-ring: hsl(0 0% 60%); --primary-text: hsl(0 0% 42%); }
166
+ html[data-color="steel"].dark { --primary-text: hsl(0 0% 62%); }
167
+ html[data-color="mono"]:not(.dark) { --primary: hsl(0 0% 9%); --color-primary: hsl(0 0% 9%); --primary-foreground: hsl(0 0% 98%); --color-primary-foreground: hsl(0 0% 98%); --ring: hsl(0 0% 9%); --color-ring: hsl(0 0% 9%); --primary-text: hsl(0 0% 9%); }
168
+ html[data-color="mono"].dark { --primary: hsl(0 0% 98%); --color-primary: hsl(0 0% 98%); --primary-foreground: hsl(0 0% 9%); --color-primary-foreground: hsl(0 0% 9%); --ring: hsl(0 0% 98%); --color-ring: hsl(0 0% 98%); --primary-text: hsl(0 0% 98%); }
124
169
 
125
170
  /* ── Gradient themes: replace the accent fill with a gradient ──
126
171
  Unlayered on purpose: in Tailwind 4, cascade layers beat specificity, so
@@ -139,8 +184,12 @@ html:is([data-color="sunset"], [data-color="ocean"], [data-color="lush"], [data-
139
184
  }
140
185
 
141
186
  /* ── Base ── */
142
- *, *::before, *::after {
143
- border-color: var(--border);
187
+ /* Layered so Tailwind's border-color utilities (border-primary, border-amber-400/50) still win: unlayered, this
188
+ beat every one of them. */
189
+ @layer base {
190
+ *, *::before, *::after {
191
+ border-color: var(--border);
192
+ }
144
193
  }
145
194
 
146
195
  body {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xforge-dev/forge-kit",
3
- "version": "0.19.0",
3
+ "version": "0.20.0",
4
4
  "description": "Shared auth, app registry and UI for xForge apps",
5
5
  "license": "MIT",
6
6
  "repository": {