astralkit 0.8.0 → 0.9.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.
@@ -45,17 +45,21 @@ export const THEME_PALETTES = [
45
45
  description: 'The default AstralKit violet theme',
46
46
  mode: 'light',
47
47
  colors: {
48
- background: '#FAF9F7',
49
- surface: '#FFFFFF',
48
+ /* Neutrals ride the cal-neutral base family (white cards on the
49
+ tinted canvas, near-white panels) — the palette's voice is the
50
+ violet accent, not a competing warm neutral set. Re-based
51
+ 2026-08-24 when the default theme moved to cal-neutral. */
52
+ background: '#FFFFFF',
53
+ surface: '#F6F8FB',
50
54
  foreground: '#150A35',
51
55
  foregroundMuted: '#544D6B',
52
56
  primary: '#6933FF',
53
57
  secondary: '#7C3AED',
54
58
  accent: '#3523BD',
55
59
  onAccent: '#FFFFFF',
56
- border: '#E6E3EE',
60
+ border: '#E5E7EB',
57
61
  ring: '#A585FF',
58
- muted: '#F4F2F9',
62
+ muted: '#F9FAFB',
59
63
  destructive: '#DC2626',
60
64
  brandGradient: {
61
65
  from: '#A585FF',
@@ -73,12 +77,13 @@ export const THEME_PALETTES = [
73
77
  description: 'Teal primary with coral-red highlights — Happy Hues #8',
74
78
  mode: 'light',
75
79
  colors: {
76
- background: '#F8F5F2',
77
- surface: '#FFFFFF',
80
+ background: '#FFFFFF',
81
+ surface: '#F8F5F2',
78
82
  foreground: '#232323',
79
83
  foregroundMuted: '#222525',
80
84
  primary: '#078080',
81
- secondary: '#F45D48',
85
+ onPrimary: '#FFFFFF',
86
+ secondary: '#D8260D',
82
87
  accent: '#F45D48',
83
88
  border: '#E8E2DB',
84
89
  ring: '#078080',
@@ -92,10 +97,10 @@ export const THEME_PALETTES = [
92
97
  description: 'Professional gray with blue accent',
93
98
  mode: 'light',
94
99
  colors: {
95
- background: '#F8FAFC',
96
- surface: '#FFFFFF',
100
+ background: '#FFFFFF',
101
+ surface: '#F8FAFC',
97
102
  foreground: '#0F172A',
98
- foregroundMuted: '#64748B',
103
+ foregroundMuted: '#5D6B80',
99
104
  primary: '#2563EB',
100
105
  secondary: '#E2E8F0',
101
106
  accent: '#7C3AED',
@@ -111,10 +116,10 @@ export const THEME_PALETTES = [
111
116
  description: 'Warm neutral with indigo primary',
112
117
  mode: 'light',
113
118
  colors: {
114
- background: '#FAFAF9',
115
- surface: '#FFFFFF',
119
+ background: '#FFFFFF',
120
+ surface: '#FAFAF9',
116
121
  foreground: '#1C1917',
117
- foregroundMuted: '#78716C',
122
+ foregroundMuted: '#6E6762',
118
123
  primary: '#4F46E5',
119
124
  secondary: '#EEF2FF',
120
125
  accent: '#EC4899',
@@ -130,15 +135,16 @@ export const THEME_PALETTES = [
130
135
  description: 'Clean white with emerald primary and mint washes — healthcare CRM',
131
136
  mode: 'light',
132
137
  colors: {
133
- background: '#F7F9F8',
134
- surface: '#FFFFFF',
138
+ background: '#FFFFFF',
139
+ surface: '#F7F9F8',
135
140
  foreground: '#17211D',
136
141
  foregroundMuted: '#5B6661',
137
- primary: '#0FA47A',
138
- secondary: '#0FA47A',
139
- accent: '#0FA47A',
142
+ primary: '#0C8663',
143
+ onPrimary: '#FFFFFF',
144
+ secondary: '#0C8160',
145
+ accent: '#0C8663',
140
146
  border: '#E2E8E5',
141
- ring: '#0FA47A',
147
+ ring: '#0C8663',
142
148
  muted: '#ECF2EF',
143
149
  destructive: '#E5484D',
144
150
  },
@@ -149,12 +155,13 @@ export const THEME_PALETTES = [
149
155
  description: 'Lavender-white canvas with vivid periwinkle — fitness SaaS',
150
156
  mode: 'light',
151
157
  colors: {
152
- background: '#F4F3FB',
153
- surface: '#FFFFFF',
158
+ background: '#FFFFFF',
159
+ surface: '#F4F3FB',
154
160
  foreground: '#1B1A2E',
155
161
  foregroundMuted: '#5A5874',
156
162
  primary: '#6F5CF1',
157
- secondary: '#6F5CF1',
163
+ onPrimary: '#FFFFFF',
164
+ secondary: '#6955F0',
158
165
  accent: '#6F5CF1',
159
166
  border: '#E4E2F0',
160
167
  ring: '#6F5CF1',
@@ -168,15 +175,16 @@ export const THEME_PALETTES = [
168
175
  description: 'Crisp white with deep sky-cyan — referral dashboard',
169
176
  mode: 'light',
170
177
  colors: {
171
- background: '#F6FAFC',
172
- surface: '#FFFFFF',
178
+ background: '#FFFFFF',
179
+ surface: '#F6FAFC',
173
180
  foreground: '#14262D',
174
181
  foregroundMuted: '#587077',
175
- primary: '#0E96C4',
176
- secondary: '#0E96C4',
177
- accent: '#0E96C4',
182
+ primary: '#0C7EA5',
183
+ onPrimary: '#FFFFFF',
184
+ secondary: '#0C7AA0',
185
+ accent: '#0C7EA5',
178
186
  border: '#DEE9EE',
179
- ring: '#0E96C4',
187
+ ring: '#0C7EA5',
180
188
  muted: '#EAF3F7',
181
189
  destructive: '#E5484D',
182
190
  },
@@ -188,8 +196,8 @@ export const THEME_PALETTES = [
188
196
  description: 'Bone neutrals, ink CTAs, volt-lime selection — fitness app energy',
189
197
  mode: 'light',
190
198
  colors: {
191
- background: '#F3F3EF',
192
- surface: '#FFFFFF',
199
+ background: '#FFFFFF',
200
+ surface: '#F3F3EF',
193
201
  foreground: '#0B0B0B',
194
202
  foregroundMuted: '#55564F',
195
203
  primary: '#D7FA4B',
@@ -209,19 +217,61 @@ export const THEME_PALETTES = [
209
217
  description: 'Warm paper with Zap Blue accent — brand design system experiment',
210
218
  mode: 'light',
211
219
  colors: {
212
- background: '#FAFAF7',
213
- surface: '#FFFFFF',
220
+ background: '#FFFFFF',
221
+ surface: '#FAFAF7',
214
222
  foreground: '#0A0A0A',
215
223
  foregroundMuted: '#5A5A5A',
216
- primary: '#1E7BFF',
224
+ primary: '#076DFF',
225
+ onPrimary: '#FFFFFF',
217
226
  secondary: '#CFE3FF',
218
227
  accent: '#0B4FD9',
219
228
  border: '#E4E2DA',
220
- ring: '#1E7BFF',
229
+ ring: '#076DFF',
221
230
  muted: '#F0EFEA',
222
231
  destructive: '#EF4444',
223
232
  },
224
233
  },
234
+ {
235
+ id: 'blue-beacon',
236
+ name: 'Blue Beacon Creative',
237
+ description: 'Warm cream canvas with electric royal blue — Blue Beacon Creative studio',
238
+ mode: 'light',
239
+ colors: {
240
+ // seed.background → ak-surface (canvas band), seed.surface → ak-bg/elevated (paper)
241
+ // cards white like every light palette; the warm mood lives in
242
+ // the canvas and the whisper-ivory side panel
243
+ background: '#FFFFFF',
244
+ surface: '#F6F3EC',
245
+ foreground: '#14130F',
246
+ foregroundMuted: '#514D45',
247
+ primary: '#2238FF',
248
+ // pure white on royal blue — the computed fallback would pick the cream paper
249
+ onPrimary: '#FFFFFF',
250
+ secondary: '#1726B8',
251
+ // accent == primary on purpose: keeps border-focus on the royal blue
252
+ accent: '#2238FF',
253
+ onAccent: '#FFFFFF',
254
+ border: '#D9D3C4',
255
+ ring: '#2238FF',
256
+ muted: '#FDFBF0',
257
+ destructive: '#EF4444',
258
+ brandGradient: {
259
+ from: '#8E9BFF',
260
+ via: '#2238FF',
261
+ to: '#04429E',
262
+ hoverFrom: '#A9B4FF',
263
+ hoverVia: '#3D51FF',
264
+ hoverTo: '#0A3FBF',
265
+ },
266
+ },
267
+ effects: {
268
+ glowPrimary: '#2238FF',
269
+ glowSecondary: '#8E9BFF',
270
+ glowTertiary: '#F6C955',
271
+ glowWarm: '#F6C955',
272
+ meshBase: '#F6F3EC',
273
+ },
274
+ },
225
275
  /* ─── Dark Palettes ─── */
226
276
  {
227
277
  id: 'volt-noir',
@@ -253,7 +303,8 @@ export const THEME_PALETTES = [
253
303
  foreground: '#EDEAF6',
254
304
  foregroundMuted: '#9D97B8',
255
305
  primary: '#8B7CF7',
256
- secondary: '#8B7CF7',
306
+ onPrimary: '#171717',
307
+ secondary: '#6F5DF5',
257
308
  accent: '#8B7CF7',
258
309
  border: '#2B2542',
259
310
  ring: '#8B7CF7',
@@ -271,16 +322,16 @@ export const THEME_PALETTES = [
271
322
  surface: '#111024',
272
323
  foreground: '#F8F5FF',
273
324
  foregroundMuted: '#AAA2C8',
274
- primary: '#6D5DFF',
275
- secondary: '#A855F7',
325
+ primary: '#5B48F7',
326
+ secondary: '#9E42F6',
276
327
  accent: '#FF7A5C',
277
328
  border: '#2B2545',
278
- ring: '#6D5DFF',
329
+ ring: '#5B48F7',
279
330
  muted: '#1B1830',
280
331
  destructive: '#FF5A6E',
281
332
  brandGradient: {
282
333
  from: '#A78BFA',
283
- via: '#6D5DFF',
334
+ via: '#5B48F7',
284
335
  to: '#5B21B6',
285
336
  hoverFrom: '#C4B5FD',
286
337
  hoverVia: '#8B7CFF',
@@ -288,7 +339,7 @@ export const THEME_PALETTES = [
288
339
  },
289
340
  },
290
341
  effects: {
291
- glowPrimary: '#6D5DFF',
342
+ glowPrimary: '#5B48F7',
292
343
  glowSecondary: '#A855F7',
293
344
  glowTertiary: '#7C3AED',
294
345
  glowWarm: '#FF7A5C',
@@ -305,16 +356,17 @@ export const THEME_PALETTES = [
305
356
  surface: '#0B1020',
306
357
  foreground: '#F4F8FF',
307
358
  foregroundMuted: '#9AA8C7',
308
- primary: '#16A3FF',
359
+ primary: '#0079C8',
360
+ onPrimary: '#FFFFFF',
309
361
  secondary: '#6D5DFF',
310
362
  accent: '#22D3EE',
311
363
  border: '#1A2440',
312
- ring: '#16A3FF',
364
+ ring: '#0079C8',
313
365
  muted: '#101831',
314
366
  destructive: '#FF5A7A',
315
367
  brandGradient: {
316
368
  from: '#22D3EE',
317
- via: '#16A3FF',
369
+ via: '#0079C8',
318
370
  to: '#6D5DFF',
319
371
  hoverFrom: '#67E8F9',
320
372
  hoverVia: '#38BDF8',
@@ -322,7 +374,7 @@ export const THEME_PALETTES = [
322
374
  },
323
375
  },
324
376
  effects: {
325
- glowPrimary: '#16A3FF',
377
+ glowPrimary: '#0079C8',
326
378
  glowSecondary: '#22D3EE',
327
379
  glowTertiary: '#6D5DFF',
328
380
  glowWarm: '#8B5CF6',
@@ -340,7 +392,7 @@ export const THEME_PALETTES = [
340
392
  foreground: '#F7F7EC',
341
393
  foregroundMuted: '#A8A49A',
342
394
  primary: '#E9FF5B',
343
- secondary: '#8B7CF7',
395
+ secondary: '#6F5DF5',
344
396
  accent: '#E9FF5B',
345
397
  border: '#2C2A33',
346
398
  ring: '#E9FF5B',
@@ -373,11 +425,12 @@ export const THEME_PALETTES = [
373
425
  surface: '#141016',
374
426
  foreground: '#FFF7FB',
375
427
  foregroundMuted: '#B7A9B7',
376
- primary: '#E43DDC',
377
- secondary: '#8B5CF6',
428
+ primary: '#CF1DC6',
429
+ onPrimary: '#FFFFFF',
430
+ secondary: '#8452F5',
378
431
  accent: '#FF5AA8',
379
432
  border: '#2C1C2E',
380
- ring: '#E43DDC',
433
+ ring: '#CF1DC6',
381
434
  muted: '#1F1721',
382
435
  destructive: '#FF4D6D',
383
436
  brandGradient: {
@@ -390,7 +443,7 @@ export const THEME_PALETTES = [
390
443
  },
391
444
  },
392
445
  effects: {
393
- glowPrimary: '#E43DDC',
446
+ glowPrimary: '#CF1DC6',
394
447
  glowSecondary: '#8B5CF6',
395
448
  glowTertiary: '#FF5AA8',
396
449
  glowWarm: '#22C55E',
@@ -450,6 +503,22 @@ function contrastRatio(a, b) {
450
503
  function onColor(fill, darkOption, lightOption) {
451
504
  return luminance(fill) > 0.45 ? darkOption : lightOption;
452
505
  }
506
+ /**
507
+ * CTA text over a brand fill: prefer the palette's own ink/paper, but when the
508
+ * tinted paper falls short of 4.5:1 and pure white clears it, use white — the
509
+ * white-CTA-text rule (2026-08-24) applied at the bridge level.
510
+ */
511
+ function ctaOnColor(fill, darkOption, lightOption) {
512
+ const contrast = (a, b) => {
513
+ const [l1, l2] = [luminance(a), luminance(b)].sort((x, y) => y - x);
514
+ return (l1 + 0.05) / (l2 + 0.05);
515
+ };
516
+ const first = onColor(fill, darkOption, lightOption);
517
+ if (contrast(fill, first) >= 4.5) return first;
518
+ if (contrast(fill, '#ffffff') >= 4.5) return '#ffffff';
519
+ if (contrast(fill, '#111113') >= 4.5) return '#111113';
520
+ return first;
521
+ }
453
522
  /**
454
523
  * Keeps the chosen brand colors while swapping surface, text, border, and muted
455
524
  * scaffolding to the current UI mode.
@@ -488,10 +557,12 @@ export function paletteToAkVariables(palette, options) {
488
557
  // (volt lime, yellow, etc. need ink text — not the background color).
489
558
  const ink = isDark ? c.background : c.foreground;
490
559
  const paper = isDark ? c.foreground : c.surface;
491
- const onPrimary = onColor(p, ink, paper);
560
+ // Explicit palette override first: mid-luminance primaries need ink
561
+ // text and the auto-picker chooses wrong there.
562
+ const onPrimary = c.onPrimary ?? onColor(p, ink, paper);
492
563
  const secondary = c.secondary || c.accent;
493
564
  const onAccent = c.onAccent ?? onColor(c.accent, ink, paper);
494
- const onSecondary = onColor(secondary, ink, paper);
565
+ const onSecondary = ctaOnColor(secondary, ink, paper);
495
566
  const accentSoft = mixColor(c.accent, c.surface, isDark ? 0.78 : 0.82);
496
567
  const secondaryContainer = mixColor(secondary, c.surface, isDark ? 0.78 : 0.82);
497
568
  const primaryContainer = isDark ? mixColor(p, c.surface, 0.76) : lighten(p, 0.88);
@@ -634,23 +705,30 @@ export function paletteToAkVariables(palette, options) {
634
705
  '--color-ak-tertiary-container': accentSoft,
635
706
  '--color-ak-on-tertiary-container': onAccentSoft,
636
707
  // Status colors
637
- '--color-ak-success': '#22C55E',
638
- '--color-ak-success-subtle': lighten('#22C55E', 0.88),
639
- '--color-ak-success-text': darken('#22C55E', 0.2),
640
- '--color-ak-warning': '#F59E0B',
641
- '--color-ak-warning-subtle': lighten('#F59E0B', 0.88),
642
- '--color-ak-warning-text': darken('#F59E0B', 0.2),
643
- '--color-ak-danger': c.destructive,
644
- '--color-ak-on-error': onColor(c.destructive, isDark ? c.background : c.foreground, isDark ? c.foreground : c.surface),
708
+ // Status ladders are SEMANTIC, not brand: fixed AA-safe pairs (the
709
+ // generated lighten/darken pairs measured ~3:1, and the light pastels
710
+ // leaked into dark mode). Same values as the SDK default theme.
711
+ '--color-ak-success': isDark ? '#4ade80' : '#16a34a',
712
+ '--color-ak-success-subtle': isDark ? 'rgba(34, 197, 94, 0.12)' : '#f0fdf4',
713
+ '--color-ak-success-text': isDark ? '#86efac' : '#15803d',
714
+ '--color-ak-warning': isDark ? '#fbbf24' : '#d97706',
715
+ '--color-ak-warning-subtle': isDark ? 'rgba(251, 191, 36, 0.12)' : '#fffbeb',
716
+ '--color-ak-warning-text': isDark ? '#fcd34d' : '#b45309',
717
+ // Danger + info are SEMANTIC like success/warning: fixed AA pairs,
718
+ // mode-aware (generated pairs measured ~2.3:1 and leaked light
719
+ // pastels into dark). c.destructive still drives error-container.
720
+ '--color-ak-danger': isDark ? '#f87171' : '#dc2626',
721
+ '--color-ak-on-error': isDark ? '#111113' : '#ffffff',
645
722
  ...(isDark ? { '--color-ak-pink': '#f472b6', '--color-ak-pink-subtle': 'rgba(244,114,182,.12)' } : {}),
646
- '--color-ak-danger-subtle': errorContainer,
647
- '--color-ak-danger-text': darken(c.destructive, 0.2),
648
- '--color-ak-error': c.destructive,
723
+ '--color-ak-error': isDark ? '#f87171' : '#dc2626',
649
724
  '--color-ak-error-container': errorContainer,
650
725
  '--color-ak-on-error-container': onErrorContainer,
651
- '--color-ak-info': '#3B82F6',
652
- '--color-ak-info-subtle': lighten('#3B82F6', 0.88),
653
- '--color-ak-info-text': darken('#3B82F6', 0.2),
726
+ '--color-ak-danger-hover': isDark ? '#ef4444' : '#b91c1c',
727
+ '--color-ak-danger-subtle': isDark ? '#301a1a' : '#fef2f2',
728
+ '--color-ak-danger-text': isDark ? '#fca5a5' : '#b91c1c',
729
+ '--color-ak-info': isDark ? '#60a5fa' : '#2563eb',
730
+ '--color-ak-info-subtle': isDark ? 'rgba(96, 165, 250, 0.12)' : '#eff6ff',
731
+ '--color-ak-info-text': isDark ? '#93c5fd' : '#1d4ed8',
654
732
  // Overlay
655
733
  '--color-ak-overlay': isDark ? 'rgba(0,0,0,0.7)' : 'rgba(0,0,0,0.5)',
656
734
  // Dark mode: disable shadows (they don't read on dark surfaces)
package/package.json CHANGED
@@ -1,65 +1,65 @@
1
- {
2
- "name": "astralkit",
3
- "version": "0.8.0",
4
- "description": "Design tokens and component primitives for accessible UI — Tailwind CSS v3 & v4",
5
- "type": "module",
6
- "exports": {
7
- "./theme": "./astralkit-theme.css",
8
- "./theme-v4": "./astralkit-theme-v4.css",
9
- "./utilities": "./astralkit-utilities.css",
10
- "./tailwind": "./tailwind.cjs",
11
- "./tailwind.cjs": "./tailwind.cjs",
12
- "./utils": "./lib/utils.js",
13
- "./motion": "./lib/motion.js",
14
- "./theme-context": "./lib/theme-context.js",
15
- "./ai-rules": "./ai-rules.md",
16
- "./palettes": "./palettes.css",
17
- "./presets": "./lib/presets/index.js"
18
- },
19
- "files": [
20
- "astralkit-theme.css",
21
- "astralkit-theme-v4.css",
22
- "astralkit-utilities.css",
23
- "palettes.css",
24
- "primitives/",
25
- "tailwind.cjs",
26
- "ai-rules.md",
27
- "lib/",
28
- "LICENSE",
29
- "README.md",
30
- "CHANGELOG.md"
31
- ],
32
- "dependencies": {
33
- "clsx": "^2.1.0",
34
- "tailwind-merge": "^2.2.0 || ^3.0.0"
35
- },
36
- "peerDependencies": {
37
- "tailwindcss": ">=3.0.0",
38
- "react": ">=18.0.0"
39
- },
40
- "peerDependenciesMeta": {
41
- "tailwindcss": {
42
- "optional": false
43
- },
44
- "react": {
45
- "optional": true
46
- }
47
- },
48
- "keywords": [
49
- "astralkit",
50
- "design-tokens",
51
- "tailwind",
52
- "css",
53
- "ui"
54
- ],
55
- "homepage": "https://astralkit.com",
56
- "repository": {
57
- "type": "git",
58
- "url": "git+https://github.com/astral-kit/astralkit.git"
59
- },
60
- "license": "SEE LICENSE IN LICENSE",
61
- "author": "Blue Beacon Creative LLC",
62
- "publishConfig": {
63
- "access": "public"
64
- }
65
- }
1
+ {
2
+ "name": "astralkit",
3
+ "version": "0.9.0",
4
+ "description": "Design tokens and component primitives for accessible UI — Tailwind CSS v3 & v4",
5
+ "type": "module",
6
+ "exports": {
7
+ "./theme": "./astralkit-theme.css",
8
+ "./theme-v4": "./astralkit-theme-v4.css",
9
+ "./utilities": "./astralkit-utilities.css",
10
+ "./tailwind": "./tailwind.cjs",
11
+ "./tailwind.cjs": "./tailwind.cjs",
12
+ "./utils": "./lib/utils.js",
13
+ "./motion": "./lib/motion.js",
14
+ "./theme-context": "./lib/theme-context.js",
15
+ "./ai-rules": "./ai-rules.md",
16
+ "./palettes": "./palettes.css",
17
+ "./presets": "./lib/presets/index.js"
18
+ },
19
+ "files": [
20
+ "astralkit-theme.css",
21
+ "astralkit-theme-v4.css",
22
+ "astralkit-utilities.css",
23
+ "palettes.css",
24
+ "primitives/",
25
+ "tailwind.cjs",
26
+ "ai-rules.md",
27
+ "lib/",
28
+ "LICENSE",
29
+ "README.md",
30
+ "CHANGELOG.md"
31
+ ],
32
+ "dependencies": {
33
+ "clsx": "^2.1.0",
34
+ "tailwind-merge": "^2.2.0 || ^3.0.0"
35
+ },
36
+ "peerDependencies": {
37
+ "tailwindcss": ">=3.0.0",
38
+ "react": ">=18.0.0"
39
+ },
40
+ "peerDependenciesMeta": {
41
+ "tailwindcss": {
42
+ "optional": false
43
+ },
44
+ "react": {
45
+ "optional": true
46
+ }
47
+ },
48
+ "keywords": [
49
+ "astralkit",
50
+ "design-tokens",
51
+ "tailwind",
52
+ "css",
53
+ "ui"
54
+ ],
55
+ "homepage": "https://astralkit.com",
56
+ "repository": {
57
+ "type": "git",
58
+ "url": "git+https://github.com/astral-kit/astralkit.git"
59
+ },
60
+ "license": "SEE LICENSE IN LICENSE",
61
+ "author": "Blue Beacon Creative LLC",
62
+ "publishConfig": {
63
+ "access": "public"
64
+ }
65
+ }