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.
@@ -8,7 +8,7 @@
8
8
  * container's style. Nothing here imports React or the DOM.
9
9
  *
10
10
  * Dials:
11
- * THEME_PALETTES — 16 authored color palettes (+ dark handling)
11
+ * THEME_PALETTES — 17 authored color palettes (+ dark handling)
12
12
  * FONT_PAIRINGS — miniature type systems (per-role family + weight)
13
13
  * CHART_PALETTES — authored 6-color series sets
14
14
  * RADIUS_OPTIONS — the one-knob radius system's named stops
@@ -1,245 +1,27 @@
1
1
  /**
2
2
  * astralkit/presets — material appearances.
3
3
  *
4
- * An APPEARANCE is a design language: the physical properties of the UI —
5
- * surface fill/blur, border weight, shadow character, press behavior, type
6
- * weight — expressed as a pack of --ak-material slots. Components consume
7
- * the slots via the SDK recipes (.ak-material-control / .ak-material-surface
8
- * / .ak-press); switching packs re-materializes a RUNNING app.
9
- *
10
- * Composability is the point: Appearance × Palette × Radius × Type Scale,
11
- * all runtime. shadcn's styles are frozen skins baked at scaffold time —
12
- * this dial is the thing that architecture cannot do.
13
- *
14
- * Each pack: light `variables`, authored `darkVariables`, and a suggested
15
- * `radius` (applied only while the Radius dial sits on Default — an explicit
16
- * radius pick always wins).
4
+ * ❌ KILLED 2026-08-24 (Fred): the appearance dial (soft/flat/glassmorphic/
5
+ * brutal/neon) added a whole axis of complexity for little payoff — every
6
+ * component had to be authored and QA'd five ways. The house look ("soft")
7
+ * is now simply THE look, carried by the SDK's default --ak-material slot
8
+ * values; the .ak-material-control / .ak-material-surface recipes remain.
9
+ * These exports stay as inert stubs so stray imports keep compiling.
17
10
  */
18
11
 
19
12
  export const DEFAULT_MATERIAL_ID = 'soft'
20
13
 
21
- const INK = '#0a0a0a'
22
- const PAPER = '#f4f4f5'
23
-
24
14
  export const MATERIAL_APPEARANCES = [
25
15
  {
26
16
  id: 'soft',
27
17
  name: 'Soft',
28
- description: 'The house default — quiet borders, calm surfaces.',
18
+ description: 'The house look — quiet borders, calm surfaces.',
29
19
  radius: null,
30
20
  variables: {},
31
21
  darkVariables: {},
32
22
  },
33
- {
34
- id: 'flat',
35
- name: 'Flat',
36
- description: 'Zero elevation, crisp hairlines, sharp corners.',
37
- radius: '0.375rem',
38
- variables: {
39
- '--ak-control-shadow': 'none',
40
- '--ak-surface-shadow': 'none',
41
- '--ak-surface-border-color': 'var(--color-ak-border-strong)',
42
- '--ak-press-transform': 'scale(0.99)',
43
- // Zero elevation extends to the small parts: crisp bordered thumb,
44
- // shadowless knob, flat tracks, no hover theatrics.
45
- '--ak-knob-shadow': 'none',
46
- '--ak-thumb-shadow': 'none',
47
- '--ak-thumb-border-w': '1px',
48
- '--ak-thumb-border-color': 'var(--color-ak-border-strong)',
49
- '--ak-thumb-hover-transform': 'none',
50
- '--ak-track-shadow': '0 0 0 0 transparent',
51
- '--ak-effect-mesh-opacity': '0',
52
- '--ak-effect-grain-opacity': '0',
53
- '--ak-effect-backlight-opacity': '0',
54
- },
55
- darkVariables: {
56
- '--ak-control-shadow': 'none',
57
- '--ak-surface-shadow': 'none',
58
- '--ak-surface-border-color': 'rgba(255,255,255,0.22)',
59
- '--ak-press-transform': 'scale(0.99)',
60
- '--ak-knob-shadow': 'none',
61
- '--ak-thumb-shadow': 'none',
62
- '--ak-thumb-border-w': '1px',
63
- '--ak-thumb-border-color': 'rgba(255,255,255,0.22)',
64
- '--ak-thumb-hover-transform': 'none',
65
- '--ak-track-shadow': '0 0 0 0 transparent',
66
- '--ak-effect-mesh-opacity': '0',
67
- '--ak-effect-grain-opacity': '0',
68
- '--ak-effect-backlight-opacity': '0',
69
- },
70
- },
71
- {
72
- id: 'glass',
73
- name: 'Glassmorphic',
74
- description: 'White glass — one top-left light source; sheen, rim and speculars all agree on it.',
75
- radius: '0.875rem',
76
- variables: {
77
- // Fred's Glass v2 reference: sheen falls off from the light (125deg),
78
- // rim burns hot near it and dies opposite, specular inset on the lit
79
- // edge + faint bounce on the shadow side. Standard 18px thickness.
80
- '--ak-surface-fill': 'rgba(255,255,255,0.11)',
81
- '--ak-surface-fill-2': 'rgba(255,255,255,0.18)',
82
- '--ak-surface-sheen': 'linear-gradient(125deg, rgba(255,255,255,0.20), rgba(255,255,255,0.04) 38%, rgba(255,255,255,0) 62%)',
83
- '--ak-surface-blur': 'blur(18px) saturate(1.6)',
84
- '--ak-surface-border-w': '0px',
85
- '--ak-surface-rim': 'linear-gradient(125deg, rgba(255,255,255,0.9) 0%, rgba(255,255,255,0.25) 30%, rgba(255,255,255,0.08) 55%, rgba(255,255,255,0.18) 100%)',
86
- '--ak-surface-shadow': '0 24px 48px -16px rgba(0,0,0,0.28), inset 1px 1px 1px rgba(255,255,255,0.45), inset -1px -1px 1px rgba(255,255,255,0.08)',
87
- '--ak-surface-shadow-2': '0 10px 22px -10px rgba(0,0,0,0.28), inset 1px 1px 1px rgba(255,255,255,0.4)',
88
- '--ak-control-shadow': '0 4px 14px rgba(15,15,20,0.10)',
89
- '--ak-press-transform': 'scale(0.97)',
90
- // Law 4: glass is for surfaces — small-control active parts stay FLAT
91
- // SOLID. Knob/thumb = plain white with a real drop; slider track = a
92
- // carved groove (dark inset + light bottom edge). Spring per the ref.
93
- '--ak-knob-fill': '#ffffff',
94
- '--ak-knob-fill-checked': '#ffffff',
95
- '--ak-knob-shadow': '0 2px 5px rgba(0,0,0,0.4)',
96
- '--ak-control-spring': 'cubic-bezier(0.34, 1.4, 0.5, 1)',
97
- '--ak-thumb-fill': '#ffffff',
98
- '--ak-thumb-shadow': '0 2px 5px rgba(0,0,0,0.4)',
99
- '--ak-thumb-hover-transform': 'scale(1.1)',
100
- '--ak-thumb-active-transform': 'scale(0.96)',
101
- '--ak-track-shadow': 'inset 0 2px 3px rgba(0,0,0,0.35), inset 0 -1px 1px rgba(255,255,255,0.25)',
102
- '--ak-effect-mesh-opacity': '0.18',
103
- '--ak-effect-grain-opacity': '0.015',
104
- '--ak-effect-backlight-opacity': '0.08',
105
- },
106
- darkVariables: {
107
- // Smoked glass — dark material, locks in text contrast regardless of
108
- // the backdrop. Dimmer sheen and rim, calmer saturation.
109
- '--ak-surface-fill': 'rgba(16,17,22,0.45)',
110
- '--ak-surface-fill-2': 'rgba(22,24,30,0.55)',
111
- '--ak-surface-sheen': 'linear-gradient(125deg, rgba(255,255,255,0.09), rgba(255,255,255,0.02) 38%, rgba(255,255,255,0) 62%)',
112
- '--ak-surface-blur': 'blur(18px) saturate(1.2)',
113
- '--ak-surface-border-w': '0px',
114
- '--ak-surface-rim': 'linear-gradient(125deg, rgba(255,255,255,0.35) 0%, rgba(255,255,255,0.12) 30%, rgba(255,255,255,0.04) 55%, rgba(255,255,255,0.10) 100%)',
115
- '--ak-surface-shadow': '0 24px 48px -16px rgba(0,0,0,0.5), inset 1px 1px 1px rgba(255,255,255,0.18), inset -1px -1px 1px rgba(255,255,255,0.04)',
116
- '--ak-surface-shadow-2': '0 10px 22px -10px rgba(0,0,0,0.5), inset 1px 1px 1px rgba(255,255,255,0.14)',
117
- '--ak-control-shadow': '0 4px 14px rgba(0,0,0,0.35)',
118
- '--ak-press-transform': 'scale(0.97)',
119
- '--ak-knob-fill': '#ffffff',
120
- '--ak-knob-fill-checked': '#ffffff',
121
- '--ak-knob-shadow': '0 2px 5px rgba(0,0,0,0.55)',
122
- '--ak-control-spring': 'cubic-bezier(0.34, 1.4, 0.5, 1)',
123
- '--ak-thumb-fill': '#ffffff',
124
- '--ak-thumb-shadow': '0 2px 5px rgba(0,0,0,0.55)',
125
- '--ak-thumb-hover-transform': 'scale(1.1)',
126
- '--ak-thumb-active-transform': 'scale(0.96)',
127
- '--ak-track-shadow': 'inset 0 2px 3px rgba(0,0,0,0.5), inset 0 -1px 1px rgba(255,255,255,0.12)',
128
- '--ak-effect-mesh-opacity': '0.14',
129
- '--ak-effect-grain-opacity': '0.015',
130
- '--ak-effect-backlight-opacity': '0.10',
131
- },
132
- },
133
- {
134
- id: 'brutal',
135
- name: 'Neo-Brutal',
136
- description: 'The house brutalism — ink borders, hard offsets, the push-into-shadow press.',
137
- // House brutal keeps FRIENDLY corners (--radius-ak-brutal = 0.5rem) —
138
- // hard geometry, soft radius. That contrast IS the AstralKit brutal look.
139
- radius: '0.5rem',
140
- variables: {
141
- // The authored ak-brutal token ladder (ink #000, 4/3/6px offsets) and
142
- // the three-act ak-brutal-press choreography, expressed as slots:
143
- // rest 4px → hover: slide 2px into a 3px shadow → active: fully
144
- // pressed, shadow collapses to zero.
145
- // Control shadows use SOFTENED ink (mixed toward the page color) so a
146
- // fill that matches the ink — the B&W palette's primary — still reads
147
- // against its shadow (Fred's call: tone separation, not rings). Card
148
- // shadows stay pure ink; faces are always lighter there.
149
- '--ak-control-shadow': '4px 4px 0 0 color-mix(in srgb, #000000 72%, var(--color-ak-bg))',
150
- '--ak-control-hover-transform': 'translate(2px, 2px)',
151
- '--ak-control-shadow-hover': '3px 3px 0 0 color-mix(in srgb, #000000 72%, var(--color-ak-bg))',
152
- '--ak-press-transform': 'translate(4px, 4px)',
153
- '--ak-control-shadow-active': '0 0 0 0 #000000',
154
- '--ak-surface-border-w': 'var(--border-ak-brutal)',
155
- '--ak-surface-border-color': '#000000',
156
- '--ak-surface-shadow': '6px 6px 0 0 #000000',
157
- '--ak-weight-ui': '700',
158
- '--ak-weight-ui-strong': '800',
159
- '--ak-weight-heading': '800',
160
- '--ak-weight-label': '700',
161
- '--ak-tracking-label': '0.05em',
162
- // Quiet hover = the brutal backface, bottom edge only: a THICK ink
163
- // underline pushed away from the text (not a hairline text-decoration).
164
- '--ak-quiet-hover-line': 'underline',
165
- '--ak-quiet-hover-thickness': '3px',
166
- '--ak-quiet-hover-offset': '2px',
167
- '--ak-quiet-hover-bg': 'transparent',
168
- '--ak-quiet-hover-color': '#000000',
169
- // Brutal focus is dashed ink; nested brutal surfaces go FLAT (border
170
- // only) — shadow lives at the top level, per the reference doctrine.
171
- '--ak-focus-outline': '3px dashed #000000',
172
- '--ak-focus-offset': '4px',
173
- '--ak-surface-shadow-2': 'none',
174
- // Batch-2 control slots — the squish is the juice: solid ink knob that
175
- // stretches on press, square-ish thumb that tilts on hover, loud
176
- // bordered tracks. Thumb shadow uses the same softened ink as controls.
177
- '--ak-knob-fill': '#000000',
178
- '--ak-knob-fill-checked': 'var(--color-ak-bg)',
179
- '--ak-knob-shadow': 'none',
180
- '--ak-knob-press': 'scaleX(1.25)',
181
- '--ak-control-spring': 'cubic-bezier(0.6, 1.6, 0.4, 1)',
182
- '--ak-thumb-fill': 'var(--color-ak-bg)',
183
- '--ak-thumb-radius': '8px',
184
- '--ak-thumb-border-w': '3px',
185
- '--ak-thumb-border-color': '#000000',
186
- '--ak-thumb-shadow': '2px 2px 0 0 color-mix(in srgb, #000000 72%, var(--color-ak-bg))',
187
- '--ak-thumb-hover-transform': 'rotate(8deg) scale(1.08)',
188
- '--ak-thumb-active-transform': 'scale(0.94)',
189
- '--ak-track-shadow': '0 0 0 0 transparent',
190
- '--ak-track-border-w': '2px',
191
- '--ak-track-border-color': '#000000',
192
- '--ak-effect-mesh-opacity': '0',
193
- '--ak-effect-grain-opacity': '0',
194
- '--ak-effect-backlight-opacity': '0',
195
- },
196
- darkVariables: {
197
- // Explicit paper values — the :root substitution rule means overriding
198
- // --color-ak-brutal-ink here would never reach the shadow tokens.
199
- '--ak-control-shadow': '4px 4px 0 0 color-mix(in srgb, #f4f4f5 68%, var(--color-ak-bg))',
200
- '--ak-control-hover-transform': 'translate(2px, 2px)',
201
- '--ak-control-shadow-hover': '3px 3px 0 0 color-mix(in srgb, #f4f4f5 68%, var(--color-ak-bg))',
202
- '--ak-press-transform': 'translate(4px, 4px)',
203
- '--ak-control-shadow-active': '0 0 0 0 #f4f4f5',
204
- '--ak-surface-border-w': 'var(--border-ak-brutal)',
205
- '--ak-surface-border-color': '#f4f4f5',
206
- '--ak-surface-shadow': '6px 6px 0 0 #f4f4f5',
207
- '--ak-weight-ui': '700',
208
- '--ak-weight-ui-strong': '800',
209
- '--ak-weight-heading': '800',
210
- '--ak-weight-label': '700',
211
- '--ak-tracking-label': '0.05em',
212
- '--ak-quiet-hover-line': 'underline',
213
- '--ak-quiet-hover-thickness': '3px',
214
- '--ak-quiet-hover-offset': '2px',
215
- '--ak-quiet-hover-bg': 'transparent',
216
- '--ak-quiet-hover-color': '#f4f4f5',
217
- '--ak-focus-outline': '3px dashed #f4f4f5',
218
- '--ak-focus-offset': '4px',
219
- '--ak-surface-shadow-2': 'none',
220
- '--ak-knob-fill': '#f4f4f5',
221
- '--ak-knob-fill-checked': 'var(--color-ak-bg)',
222
- '--ak-knob-shadow': 'none',
223
- '--ak-knob-press': 'scaleX(1.25)',
224
- '--ak-control-spring': 'cubic-bezier(0.6, 1.6, 0.4, 1)',
225
- '--ak-thumb-fill': 'var(--color-ak-bg)',
226
- '--ak-thumb-radius': '8px',
227
- '--ak-thumb-border-w': '3px',
228
- '--ak-thumb-border-color': '#f4f4f5',
229
- '--ak-thumb-shadow': '2px 2px 0 0 color-mix(in srgb, #f4f4f5 68%, var(--color-ak-bg))',
230
- '--ak-thumb-hover-transform': 'rotate(8deg) scale(1.08)',
231
- '--ak-thumb-active-transform': 'scale(0.94)',
232
- '--ak-track-shadow': '0 0 0 0 transparent',
233
- '--ak-track-border-w': '2px',
234
- '--ak-track-border-color': '#f4f4f5',
235
- '--ak-effect-mesh-opacity': '0',
236
- '--ak-effect-grain-opacity': '0',
237
- '--ak-effect-backlight-opacity': '0',
238
- },
239
- },
240
23
  ]
241
24
 
242
25
  export function materialToVariables(material, opts) {
243
- const mode = (opts && opts.mode) || 'light'
244
- return { ...(mode === 'dark' ? material.darkVariables : material.variables) }
26
+ return {}
245
27
  }
@@ -34,6 +34,8 @@ export interface ThemePalette {
34
34
  accent: string;
35
35
  /** Optional text color for filled accent elements. Defaults to computed contrast. */
36
36
  onAccent?: string;
37
+ /** Optional text color on primary fills. Defaults to computed contrast (ink vs paper). */
38
+ onPrimary?: string;
37
39
  border: string;
38
40
  ring: string;
39
41
  muted: string;