aeon-ui-engine 1.2.0 → 1.3.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.
package/CHANGELOG.md CHANGED
@@ -5,6 +5,22 @@ All notable changes to **aeon-ui-engine** are documented here.
5
5
  Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
6
6
  Versioning follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [1.3.0] - 2026-07-30
9
+
10
+ ### Changed
11
+
12
+ - **Consumer shell defaults** aligned with dense Electron wallet chrome:
13
+ - Headless Dialog backdrop / positioner / content (so Prompt works without `@aeon-ui/ui` recipe classes)
14
+ - Prompt title + description typography (`--aeon-font-display`)
15
+ - StatusBanner sticky top placement
16
+ - AppNav dense 28px breadcrumb / back rail
17
+ - **`applyBrandPalette` fonts** also set `--fonts-ui`, `--fonts-body`, `--fonts-display` so recipes pick up brand typefaces
18
+ - **Electron CSS** — fill-height `.app-shell` / `.stage`, `.titlebar` alias, compact 3px scrollbars, hover-reveal scroll helper
19
+
20
+ ### Docs
21
+
22
+ - [PRODUCT_SHELL.md](./docs/PRODUCT_SHELL.md) — headless Prompt requires consumer-shell; do not re-copy shell CSS into products
23
+
8
24
  ## [1.2.0] - 2026-07-30
9
25
 
10
26
  ### Added
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aeon-ui-engine",
3
- "version": "1.2.0",
3
+ "version": "1.3.0",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "bin": {
@@ -623,9 +623,19 @@ function brandPaletteToCssVars(palette) {
623
623
  "--shadows-focus-ring": palette.focusRing,
624
624
  "--aeon-grid-line": palette.gridLine
625
625
  };
626
- if (palette.font) vars["--aeon-font"] = palette.font;
627
- if (palette.fontDisplay) vars["--aeon-font-display"] = palette.fontDisplay;
628
- if (palette.radius) vars["--aeon-radius"] = palette.radius;
626
+ if (palette.font) {
627
+ vars["--aeon-font"] = palette.font;
628
+ vars["--fonts-ui"] = palette.font;
629
+ vars["--fonts-body"] = palette.font;
630
+ }
631
+ if (palette.fontDisplay) {
632
+ vars["--aeon-font-display"] = palette.fontDisplay;
633
+ vars["--fonts-display"] = palette.fontDisplay;
634
+ }
635
+ if (palette.radius) {
636
+ vars["--aeon-radius"] = palette.radius;
637
+ vars["--radii-aeon"] = palette.radius;
638
+ }
629
639
  return vars;
630
640
  }
631
641
  function applyBrandPalette(input, options = {}) {
@@ -97,9 +97,20 @@ export function brandPaletteToCssVars(palette: BrandPalette): Record<string, str
97
97
  '--shadows-focus-ring': palette.focusRing,
98
98
  '--aeon-grid-line': palette.gridLine,
99
99
  }
100
- if (palette.font) vars['--aeon-font'] = palette.font
101
- if (palette.fontDisplay) vars['--aeon-font-display'] = palette.fontDisplay
102
- if (palette.radius) vars['--aeon-radius'] = palette.radius
100
+ if (palette.font) {
101
+ // Recipes read --fonts-ui / --fonts-body; also expose --aeon-font for shells.
102
+ vars['--aeon-font'] = palette.font
103
+ vars['--fonts-ui'] = palette.font
104
+ vars['--fonts-body'] = palette.font
105
+ }
106
+ if (palette.fontDisplay) {
107
+ vars['--aeon-font-display'] = palette.fontDisplay
108
+ vars['--fonts-display'] = palette.fontDisplay
109
+ }
110
+ if (palette.radius) {
111
+ vars['--aeon-radius'] = palette.radius
112
+ vars['--radii-aeon'] = palette.radius
113
+ }
103
114
  return vars
104
115
  }
105
116
 
@@ -1,21 +1,93 @@
1
1
  /**
2
- * Consumer shell recipes — baseline look for Prompt, StatusBanner, AppNav chrome.
2
+ * Consumer shell recipes — baseline look for Prompt, StatusBanner, AppNav,
3
+ * and headless Dialog chrome.
3
4
  * Opt into brand color via applyBrandPalette(); these rules only use Aeon CSS vars.
4
5
  * Intentionally restrained — products still own marketing atmosphere.
5
6
  */
6
7
 
8
+ /* ── Headless Dialog (Prompt composes Dialog without recipe class names) ── */
9
+
10
+ [data-aeon-scope='dialog'][data-aeon-part='backdrop'] {
11
+ position: fixed;
12
+ inset: 0;
13
+ z-index: 1000;
14
+ background: color-mix(in srgb, #000 72%, transparent);
15
+ animation: aeon-shell-rise 200ms ease both;
16
+ }
17
+
18
+ [data-aeon-scope='dialog'][data-aeon-part='positioner'] {
19
+ position: fixed;
20
+ inset: 0;
21
+ z-index: 1001;
22
+ display: flex;
23
+ align-items: center;
24
+ justify-content: center;
25
+ padding: 16px;
26
+ overflow-y: auto;
27
+ overscroll-behavior: contain;
28
+ }
29
+
30
+ [data-aeon-scope='dialog'][data-aeon-part='content'] {
31
+ position: relative;
32
+ width: min(440px, 100%);
33
+ margin: auto;
34
+ flex-shrink: 0;
35
+ max-height: calc(100vh - 32px);
36
+ overflow-y: auto;
37
+ border-radius: calc(var(--aeon-radius, 0.5rem) + 4px);
38
+ border: 1px solid var(--colors-aeon-border);
39
+ background: var(--colors-aeon-surface, var(--colors-aeon-bg));
40
+ color: var(--colors-aeon-text);
41
+ box-shadow: 0 24px 64px rgba(0, 0, 0, 0.55);
42
+ padding: 20px 22px;
43
+ }
44
+
45
+ @keyframes aeon-shell-rise {
46
+ from {
47
+ opacity: 0;
48
+ transform: translateY(6px);
49
+ }
50
+ to {
51
+ opacity: 1;
52
+ transform: none;
53
+ }
54
+ }
55
+
56
+ /* ── Prompt ── */
57
+
7
58
  [data-aeon-scope='prompt'][data-aeon-part='root'] {
8
59
  display: contents;
9
60
  }
10
61
 
62
+ [data-aeon-scope='dialog'][data-aeon-part='title'],
63
+ [data-aeon-scope='prompt'][data-aeon-part='title'] {
64
+ margin: 0;
65
+ font-family: var(--aeon-font-display, var(--fonts-display, inherit));
66
+ font-size: 1.05rem;
67
+ font-weight: 700;
68
+ letter-spacing: 0.06em;
69
+ text-transform: uppercase;
70
+ color: var(--colors-aeon-text);
71
+ line-height: 1.25;
72
+ }
73
+
11
74
  [data-aeon-scope='prompt'][data-aeon-part='eyebrow'] {
12
75
  margin: 0 0 8px;
13
76
  color: var(--colors-aeon-accent);
77
+ font-family: var(--aeon-font-display, var(--fonts-display, inherit));
14
78
  font-size: 0.72rem;
15
79
  letter-spacing: 0.14em;
16
80
  text-transform: uppercase;
17
81
  }
18
82
 
83
+ [data-aeon-scope='prompt'][data-aeon-part='description'],
84
+ [data-aeon-scope='dialog'][data-aeon-part='description'] {
85
+ margin: 8px 0 0;
86
+ color: var(--colors-aeon-muted);
87
+ font-size: 0.9rem;
88
+ line-height: 1.45;
89
+ }
90
+
19
91
  [data-aeon-scope='prompt'][data-aeon-part='meta'] {
20
92
  display: grid;
21
93
  gap: 10px;
@@ -45,6 +117,8 @@
45
117
  border-radius: var(--aeon-radius, 10px);
46
118
  padding: 10px 14px;
47
119
  border: 1px solid transparent;
120
+ letter-spacing: 0.02em;
121
+ text-transform: none;
48
122
  }
49
123
 
50
124
  [data-aeon-scope='prompt'][data-aeon-part='primary'] {
@@ -59,7 +133,19 @@
59
133
  border-color: var(--colors-aeon-border);
60
134
  }
61
135
 
136
+ /* Product `.btn` inside Prompt / StatusBanner — sentence case, not all-caps CTAs */
137
+ [data-aeon-scope='statusBanner'] button.btn,
138
+ [data-aeon-scope='prompt'] button.btn {
139
+ text-transform: none;
140
+ letter-spacing: 0.02em;
141
+ }
142
+
143
+ /* ── StatusBanner (sticky top chrome) ── */
144
+
62
145
  [data-aeon-scope='statusBanner'][data-aeon-part='root'] {
146
+ position: sticky;
147
+ top: 0;
148
+ z-index: 40;
63
149
  display: flex;
64
150
  align-items: center;
65
151
  justify-content: space-between;
@@ -90,11 +176,24 @@
90
176
  flex-shrink: 0;
91
177
  }
92
178
 
179
+ /* ── AppNav breadcrumb / back (dense 28px rail) ── */
180
+
93
181
  [data-aeon-scope='appNav'][data-aeon-part='breadcrumb'] {
94
182
  display: flex;
95
- flex-wrap: wrap;
96
- gap: 6px;
183
+ flex-wrap: nowrap;
97
184
  align-items: center;
185
+ gap: 0;
186
+ min-width: 0;
187
+ overflow: hidden;
188
+ margin: 0;
189
+ height: 28px;
190
+ font-family: var(--aeon-font-display, var(--fonts-display, inherit));
191
+ font-size: 0.78rem;
192
+ font-weight: 700;
193
+ letter-spacing: 0.1em;
194
+ text-transform: uppercase;
195
+ line-height: 28px;
196
+ color: var(--colors-aeon-text);
98
197
  }
99
198
 
100
199
  [data-aeon-scope='appNav'][data-aeon-part='crumb'] {
@@ -104,26 +203,48 @@
104
203
  color: var(--colors-aeon-muted);
105
204
  cursor: pointer;
106
205
  padding: 0;
206
+ height: 28px;
207
+ line-height: 28px;
208
+ letter-spacing: inherit;
209
+ text-transform: inherit;
210
+ }
211
+
212
+ [data-aeon-scope='appNav'][data-aeon-part='crumb']:hover {
213
+ color: var(--colors-aeon-accent);
107
214
  }
108
215
 
109
216
  [data-aeon-scope='appNav'][data-aeon-part='crumb'][data-aeon-state~='current'] {
110
217
  color: var(--colors-aeon-text);
111
- font-weight: 600;
218
+ font-weight: 700;
112
219
  cursor: default;
113
220
  }
114
221
 
115
222
  [data-aeon-scope='appNav'][data-aeon-part='crumb']:not(:last-child)::after {
116
223
  content: '/';
117
- margin-left: 6px;
118
- color: var(--colors-aeon-border);
224
+ margin: 0 0.45em;
225
+ color: var(--colors-aeon-muted);
226
+ font-weight: 500;
119
227
  pointer-events: none;
120
228
  }
121
229
 
122
230
  [data-aeon-scope='appNav'][data-aeon-part='back'] {
123
- font: inherit;
124
- background: transparent;
231
+ appearance: none;
232
+ flex-shrink: 0;
233
+ width: 28px;
234
+ height: 28px;
235
+ margin: 0;
236
+ padding: 0;
125
237
  border: 0;
126
- color: var(--colors-aeon-accent);
238
+ border-radius: var(--aeon-radius, 0.5rem);
239
+ background: transparent;
240
+ color: var(--colors-aeon-muted);
241
+ display: inline-grid;
242
+ place-items: center;
127
243
  cursor: pointer;
128
- padding: 0;
244
+ transition: color 140ms ease, background 140ms ease;
245
+ }
246
+
247
+ [data-aeon-scope='appNav'][data-aeon-part='back']:hover {
248
+ color: var(--colors-aeon-accent);
249
+ background: color-mix(in srgb, var(--colors-aeon-accent) 10%, transparent);
129
250
  }
@@ -1,9 +1,66 @@
1
1
  /**
2
2
  * Optional Electron chrome helpers.
3
3
  * Import only in desktop shells: import '@aeon-ui/panda/electron.css'
4
+ *
5
+ * Defaults aligned with dense wallet / Electron fill-height layouts.
4
6
  */
5
7
 
6
- .aeon-titlebar {
8
+ /* Compact scrollbars on Electron platforms */
9
+ html[data-aeon-platform],
10
+ html.platform-darwin {
11
+ --aeon-scrollbar-size: 3px;
12
+ --aeon-scrollbar-track: transparent;
13
+ --aeon-scrollbar-thumb: color-mix(in srgb, var(--colors-aeon-muted, #a1a1aa) 35%, transparent);
14
+ --aeon-scrollbar-thumb-hover: color-mix(in srgb, var(--colors-aeon-muted, #a1a1aa) 55%, transparent);
15
+ --aeon-scrollbar-corner: transparent;
16
+ }
17
+
18
+ html[data-aeon-platform],
19
+ html[data-aeon-platform] body,
20
+ html[data-aeon-platform] #root,
21
+ html.platform-darwin,
22
+ html.platform-darwin body,
23
+ html.platform-darwin #root {
24
+ height: 100%;
25
+ min-height: 100%;
26
+ }
27
+
28
+ html[data-aeon-platform] body,
29
+ html.platform-darwin body {
30
+ margin: 0;
31
+ overflow: hidden;
32
+ font-family: var(--aeon-font, var(--fonts-ui, system-ui, sans-serif));
33
+ color: var(--colors-aeon-text);
34
+ background: var(--colors-aeon-bg);
35
+ -webkit-font-smoothing: antialiased;
36
+ letter-spacing: 0.01em;
37
+ }
38
+
39
+ .aeon-app-shell,
40
+ .app-shell {
41
+ height: 100%;
42
+ display: grid;
43
+ grid-template-rows: auto 1fr;
44
+ min-height: 0;
45
+ }
46
+
47
+ .aeon-stage,
48
+ .stage {
49
+ height: 100%;
50
+ min-height: 0;
51
+ overflow: auto;
52
+ padding: 20px clamp(14px, 3vw, 28px) 28px;
53
+ }
54
+
55
+ @media (max-width: 640px) {
56
+ .aeon-stage,
57
+ .stage {
58
+ padding: 16px 12px 24px;
59
+ }
60
+ }
61
+
62
+ .aeon-titlebar,
63
+ .titlebar {
7
64
  display: flex;
8
65
  align-items: center;
9
66
  justify-content: space-between;
@@ -18,13 +75,40 @@
18
75
  .aeon-titlebar button,
19
76
  .aeon-titlebar a,
20
77
  .aeon-titlebar input,
21
- .aeon-titlebar [data-aeon-no-drag] {
78
+ .aeon-titlebar [data-aeon-no-drag],
79
+ .titlebar button,
80
+ .titlebar a,
81
+ .titlebar input,
82
+ .titlebar [data-aeon-no-drag] {
22
83
  -webkit-app-region: no-drag;
23
84
  app-region: no-drag;
24
85
  }
25
86
 
26
87
  html.platform-darwin .aeon-titlebar,
27
- html[data-aeon-platform='darwin'] .aeon-titlebar {
88
+ html.platform-darwin .titlebar,
89
+ html[data-aeon-platform='darwin'] .aeon-titlebar,
90
+ html[data-aeon-platform='darwin'] .titlebar {
28
91
  /* hiddenInset traffic lights */
29
92
  padding-top: 36px;
30
93
  }
94
+
95
+ /* Hover-reveal scrollbars for dense nav stages */
96
+ .aeon-scroll-hover,
97
+ [data-aeon-scroll='hover'] {
98
+ scrollbar-color: transparent transparent;
99
+ }
100
+
101
+ .aeon-scroll-hover::-webkit-scrollbar-thumb,
102
+ [data-aeon-scroll='hover']::-webkit-scrollbar-thumb {
103
+ background: transparent;
104
+ }
105
+
106
+ .aeon-scroll-hover:hover,
107
+ [data-aeon-scroll='hover']:hover {
108
+ scrollbar-color: var(--aeon-scrollbar-thumb) transparent;
109
+ }
110
+
111
+ .aeon-scroll-hover:hover::-webkit-scrollbar-thumb,
112
+ [data-aeon-scroll='hover']:hover::-webkit-scrollbar-thumb {
113
+ background: var(--aeon-scrollbar-thumb);
114
+ }