@adia-ai/web-modules 0.3.6 → 0.4.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/CHANGELOG.md +44 -0
- package/README.md +29 -15
- package/chat/chat-shell/chat-shell.js +28 -40
- package/chat/chat-shell/css/chat-shell.empty.css +3 -3
- package/chat/chat-shell/css/chat-shell.layout.css +2 -2
- package/editor/editor-canvas/editor-canvas.examples.html +65 -0
- package/editor/editor-canvas/editor-canvas.html +43 -0
- package/editor/editor-canvas-empty/editor-canvas-empty.examples.html +65 -0
- package/editor/editor-canvas-empty/editor-canvas-empty.html +42 -0
- package/editor/editor-shell/css/editor-shell.bespoke.css +67 -2
- package/editor/editor-shell/css/editor-shell.layout.css +6 -6
- package/editor/editor-shell/editor-shell.js +19 -17
- package/editor/editor-sidebar/editor-sidebar.a2ui.json +5 -0
- package/editor/editor-sidebar/editor-sidebar.examples.html +65 -0
- package/editor/editor-sidebar/editor-sidebar.html +43 -0
- package/editor/editor-sidebar/editor-sidebar.js +30 -6
- package/editor/editor-sidebar/editor-sidebar.test.js +19 -0
- package/editor/editor-sidebar/editor-sidebar.yaml +8 -0
- package/editor/editor-statusbar/editor-statusbar.examples.html +65 -0
- package/editor/editor-statusbar/editor-statusbar.html +42 -0
- package/editor/editor-toolbar/editor-toolbar.examples.html +65 -0
- package/editor/editor-toolbar/editor-toolbar.html +43 -0
- package/index.js +1 -0
- package/package.json +8 -5
- package/shell/admin-shell/admin-shell.js +27 -243
- package/shell/admin-shell/css/admin-shell.bespoke.css +22 -26
- package/shell/admin-shell/css/admin-shell.main.css +2 -2
- package/shell/admin-shell/css/admin-shell.shell.css +2 -2
- package/shell/admin-shell/css/admin-shell.sidebar.css +35 -33
- package/simple/index.js +2 -0
- package/simple/simple-content/simple-content.a2ui.json +67 -0
- package/simple/simple-content/simple-content.css +29 -0
- package/simple/simple-content/simple-content.examples.html +13 -0
- package/simple/simple-content/simple-content.html +42 -0
- package/simple/simple-content/simple-content.yaml +54 -0
- package/simple/simple-hero/simple-hero.a2ui.json +76 -0
- package/simple/simple-hero/simple-hero.css +45 -0
- package/simple/simple-hero/simple-hero.examples.html +33 -0
- package/simple/simple-hero/simple-hero.html +42 -0
- package/simple/simple-hero/simple-hero.yaml +57 -0
- package/simple/simple-shell/simple-shell.a2ui.json +87 -0
- package/simple/simple-shell/simple-shell.css +40 -0
- package/simple/simple-shell/simple-shell.examples.html +42 -0
- package/simple/simple-shell/simple-shell.html +42 -0
- package/simple/simple-shell/simple-shell.js +47 -0
- package/simple/simple-shell/simple-shell.test.js +83 -0
- package/simple/simple-shell/simple-shell.yaml +78 -0
|
@@ -7,25 +7,21 @@
|
|
|
7
7
|
* </admin-shell>
|
|
8
8
|
*
|
|
9
9
|
* Module-tier app shell. Coordinates bespoke shell-tier children;
|
|
10
|
-
* does NOT centralize their behavior. Each child owns its own
|
|
11
|
-
*
|
|
12
|
-
* <admin-command>).
|
|
10
|
+
* does NOT centralize their behavior. Each child owns its own concern
|
|
11
|
+
* (resize/collapse on <admin-sidebar>, palette wiring on <admin-command>).
|
|
13
12
|
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
13
|
+
* **Bespoke-only since v0.4.0** (ADR-0023 Phase 3 + ADR-0024). The
|
|
14
|
+
* legacy authoring shapes (`<aside data-sidebar>`, `<dialog data-command>`,
|
|
15
|
+
* `[data-resize]`, `<aside-ui slot>`) are no longer recognized — consumers
|
|
16
|
+
* MUST use the bespoke vocabulary. The v0.3.x line carried backwards
|
|
17
|
+
* compat reads; see git history for the legacy paths.
|
|
19
18
|
*
|
|
20
19
|
* Host responsibilities (the only behavior that stays here):
|
|
21
20
|
* 1. [mode] reflection — "rounded", "borderless", or both
|
|
22
|
-
* 2. [data-sidebar-toggle="
|
|
23
|
-
*
|
|
24
|
-
* 3. [data-command-trigger] click forwarding to
|
|
25
|
-
*
|
|
26
|
-
* 4. Re-emit child events as host events for backwards compat
|
|
27
|
-
* (sidebar-toggle, sidebar-resize, command-select all bubble
|
|
28
|
-
* already, but consumers who listened on the host get them)
|
|
21
|
+
* 2. [data-sidebar-toggle="<name>"] click forwarding to the matching
|
|
22
|
+
* <admin-sidebar>'s .toggle() public method
|
|
23
|
+
* 3. [data-command-trigger] click forwarding to <admin-command>.show()
|
|
24
|
+
* 4. command-select re-emit + nav routing when a <nav-ui> is present
|
|
29
25
|
*/
|
|
30
26
|
|
|
31
27
|
import { UIElement } from '../../../web-components/core/element.js';
|
|
@@ -37,100 +33,49 @@ class AdminShell extends UIElement {
|
|
|
37
33
|
|
|
38
34
|
static template = () => null;
|
|
39
35
|
|
|
40
|
-
#cmdKeyHandler = null;
|
|
41
|
-
#legacyResizeCleanups = [];
|
|
42
|
-
#legacySidebarRO = null;
|
|
43
|
-
#legacySidebarWidths = new Map();
|
|
44
|
-
|
|
45
36
|
connected() {
|
|
46
37
|
this.#wireToggleButtons();
|
|
47
38
|
this.#wireCommandTriggers();
|
|
48
|
-
this.#setupLegacyShapes();
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
disconnected() {
|
|
52
|
-
for (const cleanup of this.#legacyResizeCleanups) cleanup();
|
|
53
|
-
this.#legacyResizeCleanups = [];
|
|
54
|
-
this.#legacySidebarRO?.disconnect();
|
|
55
|
-
this.#legacySidebarRO = null;
|
|
56
|
-
if (this.#cmdKeyHandler) {
|
|
57
|
-
document.removeEventListener('keydown', this.#cmdKeyHandler);
|
|
58
|
-
this.#cmdKeyHandler = null;
|
|
59
|
-
}
|
|
60
39
|
}
|
|
61
40
|
|
|
62
|
-
//
|
|
63
|
-
//
|
|
64
|
-
|
|
65
|
-
':is(admin-sidebar[slot="leading"], admin-sidebar[slot="trailing"], ' +
|
|
66
|
-
'[data-sidebar], aside-ui[slot="leading"], aside-ui[slot="trailing"])';
|
|
67
|
-
|
|
68
|
-
#sidebarName(el) {
|
|
69
|
-
return (
|
|
70
|
-
el.getAttribute('name') ??
|
|
71
|
-
el.getAttribute('data-sidebar') ??
|
|
72
|
-
el.getAttribute('slot')
|
|
73
|
-
);
|
|
74
|
-
}
|
|
41
|
+
// No #disconnected — children own their own cleanup; the host registers
|
|
42
|
+
// no document-level listeners and no observers. Element-level listeners
|
|
43
|
+
// are auto-cleaned when the element disconnects.
|
|
75
44
|
|
|
76
45
|
#findSidebar(name) {
|
|
77
46
|
return this.querySelector(
|
|
78
|
-
|
|
79
|
-
`admin-sidebar[slot="${name}"], admin-sidebar[name="${name}"], ` +
|
|
80
|
-
`[data-sidebar="${name}"], aside-ui[slot="${name}"]` +
|
|
81
|
-
')'
|
|
47
|
+
`admin-sidebar[slot="${name}"], admin-sidebar[name="${name}"]`
|
|
82
48
|
);
|
|
83
49
|
}
|
|
84
50
|
|
|
85
|
-
// ── 1. Toggle buttons —
|
|
51
|
+
// ── 1. Toggle buttons — forward clicks to <admin-sidebar>.toggle() ──
|
|
86
52
|
|
|
87
53
|
#wireToggleButtons() {
|
|
88
54
|
for (const btn of this.querySelectorAll('[data-sidebar-toggle]')) {
|
|
89
55
|
const name = btn.getAttribute('data-sidebar-toggle');
|
|
90
56
|
btn.addEventListener('click', () => {
|
|
91
57
|
const sidebar = this.#findSidebar(name);
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
// Bespoke <admin-sidebar> has a public toggle() method
|
|
95
|
-
if (typeof sidebar.toggle === 'function') {
|
|
96
|
-
sidebar.toggle();
|
|
97
|
-
return;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
// Legacy: replicate the old in-place toggle on raw HTML
|
|
101
|
-
this.#legacyToggle(sidebar, name);
|
|
58
|
+
sidebar?.toggle?.();
|
|
102
59
|
});
|
|
103
60
|
}
|
|
104
61
|
}
|
|
105
62
|
|
|
106
|
-
// ── 2. Command triggers —
|
|
63
|
+
// ── 2. Command triggers — forward clicks to <admin-command>.show() ──
|
|
107
64
|
|
|
108
65
|
#wireCommandTriggers() {
|
|
109
66
|
const command = this.querySelector('admin-command');
|
|
110
|
-
|
|
67
|
+
if (!command) return;
|
|
111
68
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
trigger.addEventListener('click', (e) => {
|
|
118
|
-
e.stopPropagation();
|
|
119
|
-
command.show();
|
|
120
|
-
});
|
|
121
|
-
}
|
|
122
|
-
// <admin-command> owns its own keyboard shortcut; nothing more
|
|
123
|
-
// for the host to wire. We DO re-listen for command-select to
|
|
124
|
-
// wire navigation if a <nav-ui> is present.
|
|
125
|
-
this.#wireCommandSelectToNav(command);
|
|
126
|
-
return;
|
|
69
|
+
for (const trigger of this.querySelectorAll('[data-command-trigger]')) {
|
|
70
|
+
trigger.addEventListener('click', (e) => {
|
|
71
|
+
e.stopPropagation();
|
|
72
|
+
command.show();
|
|
73
|
+
});
|
|
127
74
|
}
|
|
128
75
|
|
|
129
|
-
//
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
#wireCommandSelectToNav(command) {
|
|
76
|
+
// <admin-command> owns its own Cmd+K listener. The host only wires
|
|
77
|
+
// command-select → nav routing if a <nav-ui> is present (so clicking
|
|
78
|
+
// a result in the palette navigates to that route).
|
|
134
79
|
const nav = this.querySelector('nav-ui');
|
|
135
80
|
if (!nav) return;
|
|
136
81
|
command.addEventListener('command-select', (e) => {
|
|
@@ -138,167 +83,6 @@ class AdminShell extends UIElement {
|
|
|
138
83
|
if (item) nav.select(item);
|
|
139
84
|
});
|
|
140
85
|
}
|
|
141
|
-
|
|
142
|
-
// ── 3. Legacy shape wiring (raw <aside data-sidebar>, <dialog data-command>) ──
|
|
143
|
-
|
|
144
|
-
#setupLegacyShapes() {
|
|
145
|
-
const legacySidebars = this.querySelectorAll(
|
|
146
|
-
':is([data-sidebar], aside-ui[slot="leading"], aside-ui[slot="trailing"])'
|
|
147
|
-
);
|
|
148
|
-
if (legacySidebars.length === 0) return;
|
|
149
|
-
|
|
150
|
-
this.#restoreLegacyWidths(legacySidebars);
|
|
151
|
-
this.#setupLegacyResizeHandles(legacySidebars);
|
|
152
|
-
this.#setupLegacyResizeObserver(legacySidebars);
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
#restoreLegacyWidths(sidebars) {
|
|
156
|
-
for (const sidebar of sidebars) {
|
|
157
|
-
const name = this.#sidebarName(sidebar);
|
|
158
|
-
try {
|
|
159
|
-
const saved = localStorage.getItem(`adia-sidebar-${name}`);
|
|
160
|
-
if (saved) {
|
|
161
|
-
sidebar.style.width = saved;
|
|
162
|
-
const w = parseFloat(saved);
|
|
163
|
-
if (!isNaN(w) && w > 96) {
|
|
164
|
-
this.#legacySidebarWidths.set(name, saved);
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
} catch {}
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
#legacyToggle(sidebar, name) {
|
|
172
|
-
const isCollapsed = sidebar.getBoundingClientRect().width <= 96;
|
|
173
|
-
if (isCollapsed) {
|
|
174
|
-
const prev = this.#legacySidebarWidths.get(name);
|
|
175
|
-
sidebar.style.width = prev || '';
|
|
176
|
-
try { localStorage.setItem(`adia-sidebar-${name}`, prev || ''); } catch {}
|
|
177
|
-
} else {
|
|
178
|
-
this.#legacySidebarWidths.set(name, sidebar.style.width || getComputedStyle(sidebar).width);
|
|
179
|
-
const minW = getComputedStyle(sidebar).minWidth;
|
|
180
|
-
sidebar.style.width = minW;
|
|
181
|
-
try { localStorage.setItem(`adia-sidebar-${name}`, minW); } catch {}
|
|
182
|
-
}
|
|
183
|
-
this.dispatchEvent(new CustomEvent('sidebar-toggle', {
|
|
184
|
-
bubbles: true,
|
|
185
|
-
detail: { sidebar: name, name, expanded: !isCollapsed },
|
|
186
|
-
}));
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
#setupLegacyResizeHandles(sidebars) {
|
|
190
|
-
for (const sidebar of sidebars) {
|
|
191
|
-
const handle = sidebar.querySelector(':scope > [data-resize]');
|
|
192
|
-
if (!handle) continue;
|
|
193
|
-
const name = this.#sidebarName(sidebar);
|
|
194
|
-
const isLeading = name === 'leading';
|
|
195
|
-
|
|
196
|
-
const onPointerDown = (e) => {
|
|
197
|
-
e.preventDefault();
|
|
198
|
-
handle.setPointerCapture(e.pointerId);
|
|
199
|
-
const startX = e.clientX;
|
|
200
|
-
const startW = sidebar.getBoundingClientRect().width;
|
|
201
|
-
sidebar.setAttribute('data-resizing', '');
|
|
202
|
-
document.documentElement.style.cursor = 'col-resize';
|
|
203
|
-
|
|
204
|
-
const onMove = (e) => {
|
|
205
|
-
const dx = e.clientX - startX;
|
|
206
|
-
const max = parseInt(getComputedStyle(sidebar).getPropertyValue('max-width')) || 480;
|
|
207
|
-
const w = Math.max(48, Math.min(max, startW + (isLeading ? dx : -dx)));
|
|
208
|
-
sidebar.style.width = `${w}px`;
|
|
209
|
-
};
|
|
210
|
-
|
|
211
|
-
const onUp = () => {
|
|
212
|
-
sidebar.removeAttribute('data-resizing');
|
|
213
|
-
document.documentElement.style.cursor = '';
|
|
214
|
-
handle.removeEventListener('pointermove', onMove);
|
|
215
|
-
handle.removeEventListener('pointerup', onUp);
|
|
216
|
-
|
|
217
|
-
const w = sidebar.getBoundingClientRect().width;
|
|
218
|
-
if (w <= 96) {
|
|
219
|
-
sidebar.style.width = getComputedStyle(sidebar).minWidth;
|
|
220
|
-
} else if (w < 160) {
|
|
221
|
-
sidebar.style.width = '160px';
|
|
222
|
-
}
|
|
223
|
-
try { localStorage.setItem(`adia-sidebar-${name}`, sidebar.style.width); } catch {}
|
|
224
|
-
|
|
225
|
-
this.dispatchEvent(new CustomEvent('sidebar-resize', {
|
|
226
|
-
bubbles: true,
|
|
227
|
-
detail: { sidebar: name, name, width: sidebar.getBoundingClientRect().width },
|
|
228
|
-
}));
|
|
229
|
-
};
|
|
230
|
-
|
|
231
|
-
handle.addEventListener('pointermove', onMove);
|
|
232
|
-
handle.addEventListener('pointerup', onUp);
|
|
233
|
-
};
|
|
234
|
-
|
|
235
|
-
handle.addEventListener('pointerdown', onPointerDown);
|
|
236
|
-
this.#legacyResizeCleanups.push(() => handle.removeEventListener('pointerdown', onPointerDown));
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
#setupLegacyResizeObserver(sidebars) {
|
|
241
|
-
this.#legacySidebarRO = new ResizeObserver((entries) => {
|
|
242
|
-
for (const entry of entries) {
|
|
243
|
-
const sidebar = entry.target;
|
|
244
|
-
const narrow = entry.contentBoxSize[0].inlineSize <= 96;
|
|
245
|
-
for (const sel of sidebar.querySelectorAll('select-ui')) {
|
|
246
|
-
sel.setAttribute('placement', narrow ? 'right' : 'bottom-start');
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
});
|
|
250
|
-
for (const sb of sidebars) this.#legacySidebarRO.observe(sb);
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
#wireLegacyCommand(dialog) {
|
|
254
|
-
const cmdEl = dialog.querySelector('command-ui');
|
|
255
|
-
const nav = this.querySelector('nav-ui');
|
|
256
|
-
|
|
257
|
-
const openCmd = () => {
|
|
258
|
-
dialog.showModal();
|
|
259
|
-
if (cmdEl) { cmdEl.open = true; cmdEl.value = ''; cmdEl.focus(); }
|
|
260
|
-
};
|
|
261
|
-
const closeCmd = () => {
|
|
262
|
-
dialog.close();
|
|
263
|
-
if (cmdEl) cmdEl.open = false;
|
|
264
|
-
};
|
|
265
|
-
|
|
266
|
-
for (const trigger of this.querySelectorAll('[data-command-trigger]')) {
|
|
267
|
-
trigger.addEventListener('click', (e) => {
|
|
268
|
-
e.stopPropagation();
|
|
269
|
-
openCmd();
|
|
270
|
-
});
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
dialog.addEventListener('click', (e) => {
|
|
274
|
-
if (e.target === dialog) closeCmd();
|
|
275
|
-
});
|
|
276
|
-
|
|
277
|
-
if (cmdEl) {
|
|
278
|
-
cmdEl.addEventListener('dismiss', closeCmd);
|
|
279
|
-
cmdEl.addEventListener('select', (e) => {
|
|
280
|
-
closeCmd();
|
|
281
|
-
if (nav) {
|
|
282
|
-
const item = nav.querySelector(`nav-item-ui[value="${e.detail.value}"]`);
|
|
283
|
-
if (item) nav.select(item);
|
|
284
|
-
}
|
|
285
|
-
this.dispatchEvent(new CustomEvent('command-select', {
|
|
286
|
-
bubbles: true,
|
|
287
|
-
detail: e.detail,
|
|
288
|
-
}));
|
|
289
|
-
});
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
// Cmd+K listener — only for legacy shape (bespoke <admin-command>
|
|
293
|
-
// owns its own listener)
|
|
294
|
-
this.#cmdKeyHandler = (e) => {
|
|
295
|
-
if ((e.metaKey || e.ctrlKey) && e.key === 'k') {
|
|
296
|
-
e.preventDefault();
|
|
297
|
-
dialog.open ? closeCmd() : openCmd();
|
|
298
|
-
}
|
|
299
|
-
};
|
|
300
|
-
document.addEventListener('keydown', this.#cmdKeyHandler);
|
|
301
|
-
}
|
|
302
86
|
}
|
|
303
87
|
|
|
304
88
|
customElements.define('admin-shell', AdminShell);
|
|
@@ -1,20 +1,16 @@
|
|
|
1
1
|
/* ═══════════════════════════════════════════════════════════════
|
|
2
|
-
admin-shell — Bespoke shell-tier children (
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
the
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
For Phase 2, the simplest map: each bespoke tag mimics its legacy
|
|
15
|
-
counterpart's display behavior. The host shell.css already handles
|
|
16
|
-
admin-shell flex layout; main.css handles main-as-column; sidebar.css
|
|
17
|
-
handles sidebar geometry.
|
|
2
|
+
admin-shell — Bespoke shell-tier children (canonical since v0.4.0)
|
|
3
|
+
|
|
4
|
+
Per ADR-0023 + ADR-0024 (Phase 3 deprecation, v0.4.0), this file
|
|
5
|
+
carries the canonical styling for the bespoke shell-tier children:
|
|
6
|
+
admin-content, admin-topbar, admin-statusbar, admin-scroll,
|
|
7
|
+
admin-page, admin-page-header, admin-page-body, admin-sidebar.
|
|
8
|
+
|
|
9
|
+
The legacy raw-HTML shape (<main>, <header>, <footer>, <aside-ui slot>,
|
|
10
|
+
<aside data-sidebar>, <dialog data-command>) was retired in v0.4.0;
|
|
11
|
+
the existing :is() lifts in layered files (main.css, sidebar.css,
|
|
12
|
+
templates.css) target ONLY the bespoke tags now. See git history
|
|
13
|
+
prior to v0.4.0 for the legacy paths.
|
|
18
14
|
═══════════════════════════════════════════════════════════════ */
|
|
19
15
|
|
|
20
16
|
/* ── admin-content ≡ <main> ── */
|
|
@@ -30,7 +26,7 @@ admin-shell > admin-content {
|
|
|
30
26
|
/* ── admin-topbar ≡ <header-ui> at shell tier ── */
|
|
31
27
|
admin-content > admin-topbar,
|
|
32
28
|
admin-shell > admin-topbar,
|
|
33
|
-
|
|
29
|
+
admin-sidebar > admin-topbar {
|
|
34
30
|
display: flex;
|
|
35
31
|
align-items: center;
|
|
36
32
|
gap: var(--page-header-gap);
|
|
@@ -44,7 +40,7 @@ admin-shell > admin-topbar,
|
|
|
44
40
|
/* ── admin-statusbar ≡ <footer-ui> at shell tier ── */
|
|
45
41
|
admin-content > admin-statusbar,
|
|
46
42
|
admin-shell > admin-statusbar,
|
|
47
|
-
|
|
43
|
+
admin-sidebar > admin-statusbar {
|
|
48
44
|
display: flex;
|
|
49
45
|
align-items: center;
|
|
50
46
|
gap: var(--page-header-gap);
|
|
@@ -98,13 +94,13 @@ admin-page > admin-page-body {
|
|
|
98
94
|
flex-direction: column;
|
|
99
95
|
}
|
|
100
96
|
|
|
101
|
-
/* ── admin-sidebar —
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
nav-ui colors)
|
|
107
|
-
|
|
97
|
+
/* ── admin-sidebar — geometry + resize handle + container queries ──
|
|
98
|
+
Canonical styling for <admin-sidebar> per ADR-0023. Pre-v0.4.0 this
|
|
99
|
+
bridged to legacy <aside-ui slot> / <aside data-sidebar> selectors;
|
|
100
|
+
in v0.4.0 those layered-CSS legacy lifts were stripped, so this block
|
|
101
|
+
now carries the full sidebar styling. The descendant rules in
|
|
102
|
+
sidebar.css (header/footer chrome, section, nav-ui colors) still
|
|
103
|
+
match via tag-name descendant selectors. */
|
|
108
104
|
|
|
109
105
|
:is(admin-sidebar[slot="leading"], admin-sidebar[slot="trailing"]) {
|
|
110
106
|
display: flex;
|
|
@@ -131,7 +127,7 @@ admin-sidebar[slot="trailing"] {
|
|
|
131
127
|
border-left: var(--page-border);
|
|
132
128
|
}
|
|
133
129
|
|
|
134
|
-
/* Resize handle
|
|
130
|
+
/* Resize handle */
|
|
135
131
|
:is(admin-sidebar[slot="leading"], admin-sidebar[slot="trailing"]) > [data-resize] {
|
|
136
132
|
position: absolute;
|
|
137
133
|
top: 0;
|
|
@@ -36,7 +36,7 @@ admin-shell > main {
|
|
|
36
36
|
OR a main-level chrome bar (`> main > :is(header, header-ui)` etc.).
|
|
37
37
|
Either qualifies as "chrome present" and suppresses the
|
|
38
38
|
corresponding margin. */
|
|
39
|
-
admin-shell:not(:has(> :is(
|
|
39
|
+
admin-shell:not(:has(> :is(asideadmin-sidebar[slot="trailing"], admin-sidebar[slot="trailing"]):not([hidden]))) > main > :is(section, section-ui) {
|
|
40
40
|
margin-inline-end: var(--a-space-2);
|
|
41
41
|
}
|
|
42
42
|
admin-shell:not(:has(> :is(header, header-ui):not([hidden]), > main > :is(header, header-ui):not([hidden]))) > main > :is(section, section-ui) {
|
|
@@ -49,7 +49,7 @@ admin-shell:not(:has(> :is(footer, footer-ui):not([hidden]), > main > :is(footer
|
|
|
49
49
|
/* ── Main > header (topbar) ──
|
|
50
50
|
Contains: sidebar toggle, breadcrumb, spacer, action buttons.
|
|
51
51
|
|
|
52
|
-
Slot contract (shared with > main > footer and
|
|
52
|
+
Slot contract (shared with > main > footer and admin-sidebar >
|
|
53
53
|
header/footer) — identical to card-ui / drawer-ui / editor-shell:
|
|
54
54
|
[slot="icon"] leading glyph
|
|
55
55
|
[slot="heading"] primary label; strong weight + strong fg
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
Structure (legacy raw-HTML form; slot-vocabulary equivalents in parens):
|
|
5
5
|
admin-shell — root shell (flex row, fixed viewport)
|
|
6
|
-
|
|
6
|
+
asideadmin-sidebar[slot="leading"] (or admin-sidebar[slot="leading"]) — nav sidebar (resizable, collapsible)
|
|
7
7
|
main — center column (topbar + scroll + footer)
|
|
8
8
|
header (or header-ui) — topbar
|
|
9
9
|
section (or section-ui) — scroll container
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
div[data-content-header] > header — sticky page title + tabs
|
|
12
12
|
div[data-content-body] > section — centered reading column
|
|
13
13
|
footer (or footer-ui) — status bar
|
|
14
|
-
|
|
14
|
+
asideadmin-sidebar[slot="trailing"] (or admin-sidebar[slot="trailing"]) — inspector sidebar
|
|
15
15
|
dialog[data-command] — command palette
|
|
16
16
|
|
|
17
17
|
Both authoring shapes are valid simultaneously. The CSS uses
|
|
@@ -5,12 +5,14 @@
|
|
|
5
5
|
Acts as a CSS container query provider (container-name: sidebar)
|
|
6
6
|
so children can adapt to collapsed width via @container.
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
Canonical authoring shape (since v0.4.0, ADR-0023 Phase 3):
|
|
9
|
+
<admin-sidebar slot="leading|trailing" resizable collapsible>
|
|
10
|
+
|
|
11
|
+
Pre-v0.4.0 legacy shapes (<aside data-sidebar>, <aside-ui slot>)
|
|
12
|
+
were retired; see ADR-0024 + git history for the migration recipe.
|
|
11
13
|
═══════════════════════════════════════════════════════════════ */
|
|
12
14
|
|
|
13
|
-
:is(
|
|
15
|
+
:is(admin-sidebar[slot="leading"], admin-sidebar[slot="trailing"]) {
|
|
14
16
|
display: flex;
|
|
15
17
|
flex-direction: column;
|
|
16
18
|
flex-shrink: 0;
|
|
@@ -27,7 +29,7 @@
|
|
|
27
29
|
/* ── Resize handle ──
|
|
28
30
|
6px invisible hit area straddling the sidebar edge.
|
|
29
31
|
Accent color on hover/drag. */
|
|
30
|
-
:is(
|
|
32
|
+
:is(admin-sidebar[slot="leading"], admin-sidebar[slot="trailing"]) > [data-resize] {
|
|
31
33
|
position: absolute;
|
|
32
34
|
top: 0;
|
|
33
35
|
bottom: 0;
|
|
@@ -38,29 +40,29 @@
|
|
|
38
40
|
z-index: 2;
|
|
39
41
|
}
|
|
40
42
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
+
admin-sidebar[slot="leading"] > [data-resize] { right: -3px; }
|
|
44
|
+
admin-sidebar[slot="trailing"] > [data-resize] { left: -3px; }
|
|
43
45
|
|
|
44
|
-
:is(
|
|
46
|
+
:is(admin-sidebar[slot="leading"], admin-sidebar[slot="trailing"]) > [data-resize]:hover {
|
|
45
47
|
background: var(--page-sidebar-resize-accent);
|
|
46
48
|
}
|
|
47
49
|
|
|
48
|
-
:is(
|
|
50
|
+
:is(admin-sidebar[slot="leading"], admin-sidebar[slot="trailing"])[data-resizing] > [data-resize] {
|
|
49
51
|
background: var(--page-sidebar-resize-accent);
|
|
50
52
|
}
|
|
51
53
|
|
|
52
54
|
/* During drag: disable transition + text selection */
|
|
53
|
-
:is(
|
|
55
|
+
:is(admin-sidebar[slot="leading"], admin-sidebar[slot="trailing"])[data-resizing] {
|
|
54
56
|
user-select: none;
|
|
55
57
|
transition: none;
|
|
56
58
|
}
|
|
57
59
|
|
|
58
60
|
/* ── Sidebar widths ── */
|
|
59
|
-
|
|
61
|
+
admin-sidebar[slot="leading"] {
|
|
60
62
|
width: var(--page-sidebar-width-leading);
|
|
61
63
|
}
|
|
62
64
|
|
|
63
|
-
|
|
65
|
+
admin-sidebar[slot="trailing"] {
|
|
64
66
|
width: var(--page-sidebar-width-trailing);
|
|
65
67
|
}
|
|
66
68
|
|
|
@@ -71,8 +73,8 @@
|
|
|
71
73
|
(a workspace-select or user-select) so the slot rules rarely come
|
|
72
74
|
into play — but they stay consistent for authors that compose
|
|
73
75
|
richer sidebar chromes. */
|
|
74
|
-
:is(
|
|
75
|
-
:is(
|
|
76
|
+
:is(admin-sidebar[slot="leading"], admin-sidebar[slot="trailing"]) > :is(header, header-ui),
|
|
77
|
+
:is(admin-sidebar[slot="leading"], admin-sidebar[slot="trailing"]) > :is(footer, footer-ui) {
|
|
76
78
|
display: flex;
|
|
77
79
|
align-items: center;
|
|
78
80
|
gap: var(--page-sidebar-gap);
|
|
@@ -82,49 +84,49 @@
|
|
|
82
84
|
min-width: 0;
|
|
83
85
|
}
|
|
84
86
|
|
|
85
|
-
:is(
|
|
87
|
+
:is(admin-sidebar[slot="leading"], admin-sidebar[slot="trailing"]) > :is(header, header-ui) {
|
|
86
88
|
min-height: var(--page-header-height);
|
|
87
89
|
border-bottom: var(--page-border);
|
|
88
90
|
}
|
|
89
91
|
|
|
90
|
-
:is(
|
|
92
|
+
:is(admin-sidebar[slot="leading"], admin-sidebar[slot="trailing"]) > :is(footer, footer-ui) {
|
|
91
93
|
min-height: var(--page-header-height);
|
|
92
94
|
margin-top: auto;
|
|
93
95
|
border-top: var(--page-border);
|
|
94
96
|
}
|
|
95
97
|
|
|
96
|
-
:is(
|
|
97
|
-
:is(
|
|
98
|
+
:is(admin-sidebar[slot="leading"], admin-sidebar[slot="trailing"]) > :is(header, header-ui) > [slot="icon"],
|
|
99
|
+
:is(admin-sidebar[slot="leading"], admin-sidebar[slot="trailing"]) > :is(footer, footer-ui) > [slot="icon"] {
|
|
98
100
|
display: flex;
|
|
99
101
|
align-items: center;
|
|
100
102
|
flex-shrink: 0;
|
|
101
103
|
color: var(--page-header-fg-muted);
|
|
102
104
|
}
|
|
103
|
-
:is(
|
|
104
|
-
:is(
|
|
105
|
+
:is(admin-sidebar[slot="leading"], admin-sidebar[slot="trailing"]) > :is(header, header-ui) > [slot="heading"],
|
|
106
|
+
:is(admin-sidebar[slot="leading"], admin-sidebar[slot="trailing"]) > :is(footer, footer-ui) > [slot="heading"] {
|
|
105
107
|
font-weight: var(--a-weight-medium);
|
|
106
108
|
color: var(--a-fg);
|
|
107
109
|
}
|
|
108
|
-
:is(
|
|
109
|
-
:is(
|
|
110
|
+
:is(admin-sidebar[slot="leading"], admin-sidebar[slot="trailing"]) > :is(header, header-ui) > [slot="description"],
|
|
111
|
+
:is(admin-sidebar[slot="leading"], admin-sidebar[slot="trailing"]) > :is(footer, footer-ui) > [slot="description"] {
|
|
110
112
|
color: var(--page-header-fg-muted);
|
|
111
113
|
font-size: var(--a-ui-sm);
|
|
112
114
|
}
|
|
113
|
-
:is(
|
|
114
|
-
:is(
|
|
115
|
+
:is(admin-sidebar[slot="leading"], admin-sidebar[slot="trailing"]) > :is(header, header-ui) > [slot="action"],
|
|
116
|
+
:is(admin-sidebar[slot="leading"], admin-sidebar[slot="trailing"]) > :is(footer, footer-ui) > [slot="action"] {
|
|
115
117
|
display: flex;
|
|
116
118
|
align-items: center;
|
|
117
119
|
gap: var(--page-actions-gap);
|
|
118
120
|
flex-shrink: 0;
|
|
119
121
|
margin-inline-start: auto;
|
|
120
122
|
}
|
|
121
|
-
:is(
|
|
122
|
-
:is(
|
|
123
|
+
:is(admin-sidebar[slot="leading"], admin-sidebar[slot="trailing"]) > :is(header, header-ui) > [slot="action"] ~ [slot="action"],
|
|
124
|
+
:is(admin-sidebar[slot="leading"], admin-sidebar[slot="trailing"]) > :is(footer, footer-ui) > [slot="action"] ~ [slot="action"] {
|
|
123
125
|
margin-inline-start: 0;
|
|
124
126
|
}
|
|
125
127
|
/* Dual-cluster: leading group on inline-start, trailing cluster on inline-end. */
|
|
126
|
-
:is(
|
|
127
|
-
:is(
|
|
128
|
+
:is(admin-sidebar[slot="leading"], admin-sidebar[slot="trailing"]) > :is(header, header-ui) > [slot="action-leading"],
|
|
129
|
+
:is(admin-sidebar[slot="leading"], admin-sidebar[slot="trailing"]) > :is(footer, footer-ui) > [slot="action-leading"] {
|
|
128
130
|
display: flex;
|
|
129
131
|
align-items: center;
|
|
130
132
|
gap: var(--page-actions-gap);
|
|
@@ -133,7 +135,7 @@
|
|
|
133
135
|
}
|
|
134
136
|
|
|
135
137
|
/* ── Sidebar section (scrollable body) ── */
|
|
136
|
-
:is(
|
|
138
|
+
:is(admin-sidebar[slot="leading"], admin-sidebar[slot="trailing"]) > :is(section, section-ui) {
|
|
137
139
|
flex: 1;
|
|
138
140
|
overflow-y: auto;
|
|
139
141
|
padding: var(--page-sidebar-px);
|
|
@@ -141,23 +143,23 @@
|
|
|
141
143
|
scrollbar-width: none;
|
|
142
144
|
}
|
|
143
145
|
|
|
144
|
-
:is(
|
|
146
|
+
:is(admin-sidebar[slot="leading"], admin-sidebar[slot="trailing"]) > :is(section, section-ui)::-webkit-scrollbar { display: none; }
|
|
145
147
|
|
|
146
148
|
/* span[slot="pad"] — opt-in padding wrapper for sidebar content
|
|
147
149
|
that needs inset (e.g. trailing sidebar inspector fields) */
|
|
148
|
-
:is(
|
|
150
|
+
:is(admin-sidebar[slot="leading"], admin-sidebar[slot="trailing"]) span[slot="pad"] {
|
|
149
151
|
display: block;
|
|
150
152
|
padding: var(--page-sidebar-px);
|
|
151
153
|
}
|
|
152
154
|
|
|
153
155
|
/* Reset nav-ui border/padding inside sidebars */
|
|
154
|
-
:is(
|
|
156
|
+
:is(admin-sidebar[slot="leading"], admin-sidebar[slot="trailing"]) nav-ui {
|
|
155
157
|
border: none;
|
|
156
158
|
padding: 0;
|
|
157
159
|
}
|
|
158
160
|
|
|
159
161
|
/* Sidebar-level divider (outside nav-ui scope) */
|
|
160
|
-
:is(
|
|
162
|
+
:is(admin-sidebar[slot="leading"], admin-sidebar[slot="trailing"]) > :is(section, section-ui) > hr[data-nav-divider] {
|
|
161
163
|
border: none;
|
|
162
164
|
height: 1px;
|
|
163
165
|
background: var(--page-sidebar-divider-bg);
|
package/simple/index.js
ADDED