@adia-ai/web-modules 0.6.19 → 0.6.20
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 +26 -0
- package/package.json +1 -1
- package/shell/admin-entity-item/admin-entity-item.a2ui.json +79 -0
- package/shell/admin-entity-item/admin-entity-item.yaml +84 -0
- package/shell/admin-shell/admin-shell.css +1 -0
- package/shell/admin-shell/admin-shell.js +32 -0
- package/shell/admin-shell/admin-shell.test.js +6 -1
- package/shell/admin-shell/css/admin-shell.bespoke.css +9 -2
- package/shell/admin-shell/css/admin-shell.collapsed.css +20 -1
- package/shell/admin-shell/css/admin-shell.entity-item.css +82 -0
- package/shell/admin-shell/css/admin-shell.tokens.css +1 -1
- package/shell/admin-statusbar/admin-statusbar.a2ui.json +1 -0
- package/shell/admin-statusbar/admin-statusbar.yaml +12 -0
- package/shell/admin-topbar/admin-topbar.a2ui.json +1 -0
- package/shell/admin-topbar/admin-topbar.yaml +13 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,31 @@
|
|
|
1
1
|
# Changelog — @adia-ai/web-modules
|
|
2
2
|
|
|
3
|
+
## [0.6.20] — 2026-05-21
|
|
4
|
+
|
|
5
|
+
### Added — `<admin-entity-item>` shell identity-row primitive (FEEDBACK-38)
|
|
6
|
+
|
|
7
|
+
- **New CSS-only shell-tier primitive: a composable icon + label + badge identity row.** A leading `<icon-ui>` (or `<img>` avatar), a truncating `[slot="label"]`, and an optional trailing `[slot="badge"]` travel as one slottable unit — slot it whole into `[slot="heading"]` of an `<admin-topbar>` / `<admin-statusbar>` for workspace or user identity. Geometry mirrors `<select-ui>`'s trigger row (`icon` ≡ `leading`, `label` ≡ `display`, `badge` ≡ `caret`). Inside a collapsible `<admin-sidebar>` the label + badge hide when the rail collapses and the icon survives, so one markup serves both states — closing the gap consumers were filling with ad-hoc `<span>` / `<div>` wrappers. New files: `shell/admin-entity-item/admin-entity-item.{yaml,a2ui.json,html,examples.html}` + `css/admin-shell.entity-item.css`. `admin-topbar.yaml` / `admin-statusbar.yaml` gain `a2ui.rules` pointing at it.
|
|
8
|
+
|
|
9
|
+
### Added — `admin-shell` warns when `<admin-topbar>` / `<admin-statusbar>` is missing its slot (FEEDBACK-37)
|
|
10
|
+
|
|
11
|
+
- **`<admin-shell>` now logs a one-shot `console.warn` when an `<admin-topbar>` or `<admin-statusbar>` is a direct child of `<admin-sidebar>` / `<admin-content>` without `slot="header"` / `slot="footer"`.** Both are CSS-only elements; omitting the slot lands them in the default body slot — rendering them in the content column instead of the chrome band, previously with zero diagnostics. The check runs once at connect, `WeakSet`-guarded per element. Same silent-misuse-warn discipline `drawer-ui` / `chart-ui` / `segmented-ui` received in 0.6.19. Files: `admin-shell.js`.
|
|
12
|
+
|
|
13
|
+
### Changed — `<admin-page-header>` background rebased to `--a-canvas-0`
|
|
14
|
+
|
|
15
|
+
- **`--page-content-header-bg` token: `--a-canvas-1` → `--a-canvas-0`.** The sticky page-header band now matches the page-body content surface (`--page-content-bg`), so the header reads as a flush extension of the content area rather than as separate chrome. This is the third iteration of the page-header treatment: v0.6.14 used `--a-canvas-2` (ΔL=0.08, "elevated step over content"); v0.6.16 rebased to `--a-canvas-1` ("shell-chrome continuation"); both still read as not-quite-flush against dense dark-mode layouts. `canvas-0` settles it — fully flush. Consumers who want a raised or contrasting band override `--page-content-header-bg` at `:root`. Files: `admin-shell.tokens.css` (token value + history comment).
|
|
16
|
+
|
|
17
|
+
### Fixed — `admin-topbar` / `admin-statusbar` inline padding aligns with sibling `<section-ui>`
|
|
18
|
+
|
|
19
|
+
- **The topbar/statusbar inline padding now matches the sibling `<section-ui>`'s, so chrome and content share one gutter.** In the content column the bars took `--page-header-px` (`a-space-3`) while the content `<section-ui>` uses `--page-content-inset` (`a-space-10`) — the topbar title and the body content were misaligned. They now use `--page-content-inset`. The shared rule also covered the sidebar context, where the sidebar's `<section-ui>` uses the tighter `--page-sidebar-px`; a new `admin-sidebar > :is(admin-topbar, admin-statusbar)` rule scopes that case so each context aligns with its own `<section-ui>`. Files: `css/admin-shell.bespoke.css`.
|
|
20
|
+
|
|
21
|
+
### Fixed — collapsed sidebar `[slot="heading"]` hide no longer wipes composed wrappers (FEEDBACK-38 addendum)
|
|
22
|
+
|
|
23
|
+
- **`collapsed.css`'s `[slot="heading"] { display: none }` rail-cleanup rule is now scoped to leaf text headings.** The unscoped rule hid *any* `slot="heading"` child in a collapsed sidebar — including composed wrappers like `<admin-entity-item slot="heading">`, wiping their icon along with the label text. It now matches `:is(span, p, div, h1–h6)[slot="heading"]` plus `[slot="heading"]:not(:has(> [slot]))` — a heading whose children are themselves slotted (a composed unit) survives collapse and manages its own children. Backward-compatible: bare `<span slot="heading">` text labels still hide. Files: `css/admin-shell.collapsed.css`.
|
|
24
|
+
|
|
25
|
+
### Fixed — `nav-item-ui` collapsed hit area fills the 48px rail (FEEDBACK-39)
|
|
26
|
+
|
|
27
|
+
- **In a collapsed sidebar, `nav-item-ui` now stretches to the full rail width instead of shrinking to its ~30px icon box.** Previously the centred 30px item left ~9px dead gutters on each side — clicks there hit `section-ui`, not the nav item (~37% of the rail was dead space). `collapsed.css` now sets `width: 100%` on both `nav-item-ui` and `nav-ui` — the latter is required because the collapsed section shrink-wraps its children, so the item's `width: 100%` would otherwise resolve against the 30px content box. `justify-content: center` keeps the glyph centred. Files: `css/admin-shell.collapsed.css`.
|
|
28
|
+
|
|
3
29
|
## [0.6.19] — 2026-05-21
|
|
4
30
|
|
|
5
31
|
### Added — `./shell/with-css` opt-in export (FEEDBACK-25)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adia-ai/web-modules",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.20",
|
|
4
4
|
"description": "AdiaUI composite custom elements \u2014 shell, chat, editor, runtime clusters built from @adia-ai/web-components primitives. Subpath exports per cluster.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://adiaui.dev/a2ui/v0_9/components/AdminEntityItem.json",
|
|
4
|
+
"title": "AdminEntityItem",
|
|
5
|
+
"description": "Module-tier shell identity row. CSS-only — no behavior, no JS.\nA composable icon + label + badge unit: a leading icon (or avatar),\na truncating label, and an optional trailing badge that travel\ntogether as one slottable element.\n\nUse it wherever a shell surface shows an entity identity — workspace\nidentity in an <admin-topbar slot=\"header\">, user identity in an\n<admin-statusbar>, the leading item of a breadcrumb, a flyout header,\nor a user row. Inside a collapsible <admin-sidebar> the label and\nbadge hide when the rail collapses; the icon survives — so the same\nmarkup works expanded and collapsed without authoring two shapes.\n\nGeometry mirrors <select-ui>'s trigger row: [slot=\"icon\"] is fixed\n(like [slot=\"leading\"]), [slot=\"label\"] flexes + truncates (like\n[slot=\"display\"]), [slot=\"badge\"] is fixed trailing (like\n[slot=\"caret\"]).\n",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"allOf": [
|
|
8
|
+
{
|
|
9
|
+
"$ref": "common_types.json#/$defs/ComponentCommon"
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"$ref": "common_types.json#/$defs/CatalogComponentCommon"
|
|
13
|
+
}
|
|
14
|
+
],
|
|
15
|
+
"properties": {
|
|
16
|
+
"component": {
|
|
17
|
+
"const": "AdminEntityItem"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"required": [
|
|
21
|
+
"component"
|
|
22
|
+
],
|
|
23
|
+
"unevaluatedProperties": false,
|
|
24
|
+
"x-adiaui": {
|
|
25
|
+
"anti_patterns": [],
|
|
26
|
+
"category": "layout",
|
|
27
|
+
"composes": [],
|
|
28
|
+
"events": {},
|
|
29
|
+
"examples": [],
|
|
30
|
+
"keywords": [
|
|
31
|
+
"admin-entity-item",
|
|
32
|
+
"entity-item",
|
|
33
|
+
"identity-row",
|
|
34
|
+
"workspace-identity",
|
|
35
|
+
"user-identity",
|
|
36
|
+
"icon-label-badge"
|
|
37
|
+
],
|
|
38
|
+
"name": "AdminEntityItem",
|
|
39
|
+
"related": [
|
|
40
|
+
"AdminTopbar",
|
|
41
|
+
"AdminStatusbar",
|
|
42
|
+
"AdminSidebar",
|
|
43
|
+
"Select",
|
|
44
|
+
"Badge",
|
|
45
|
+
"Icon"
|
|
46
|
+
],
|
|
47
|
+
"slots": {
|
|
48
|
+
"default": {
|
|
49
|
+
"description": "Default content — unslotted children flow inline. Prefer the named slots for the canonical icon + label + badge composition."
|
|
50
|
+
},
|
|
51
|
+
"badge": {
|
|
52
|
+
"description": "Optional trailing chip — environment (staging / beta) or role badge. Fixed width. Hidden when a collapsible sidebar collapses."
|
|
53
|
+
},
|
|
54
|
+
"icon": {
|
|
55
|
+
"description": "Leading visual — an <icon-ui> glyph or an <img> avatar (img is given a circular crop). Fixed width; survives sidebar collapse."
|
|
56
|
+
},
|
|
57
|
+
"label": {
|
|
58
|
+
"description": "Primary text. Flexes to fill the remaining width and truncates with an ellipsis. Hidden when a collapsible sidebar collapses."
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
"states": [
|
|
62
|
+
{
|
|
63
|
+
"description": "Default, the only state.",
|
|
64
|
+
"name": "idle"
|
|
65
|
+
}
|
|
66
|
+
],
|
|
67
|
+
"synonyms": {
|
|
68
|
+
"entity-item": [
|
|
69
|
+
"identity-row",
|
|
70
|
+
"entity-row",
|
|
71
|
+
"identity-item"
|
|
72
|
+
]
|
|
73
|
+
},
|
|
74
|
+
"tag": "admin-entity-item",
|
|
75
|
+
"tokens": {},
|
|
76
|
+
"traits": [],
|
|
77
|
+
"version": 1
|
|
78
|
+
}
|
|
79
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# Edit this file; run `npm run build:components` to regenerate a2ui.json.
|
|
2
|
+
$schema: ../../../../scripts/schemas/component.yaml.schema.json
|
|
3
|
+
name: AdminEntityItem
|
|
4
|
+
tag: admin-entity-item
|
|
5
|
+
component: AdminEntityItem
|
|
6
|
+
category: layout
|
|
7
|
+
version: 1
|
|
8
|
+
description: |
|
|
9
|
+
Module-tier shell identity row. CSS-only — no behavior, no JS.
|
|
10
|
+
A composable icon + label + badge unit: a leading icon (or avatar),
|
|
11
|
+
a truncating label, and an optional trailing badge that travel
|
|
12
|
+
together as one slottable element.
|
|
13
|
+
|
|
14
|
+
Use it wherever a shell surface shows an entity identity — workspace
|
|
15
|
+
identity in an <admin-topbar slot="header">, user identity in an
|
|
16
|
+
<admin-statusbar>, the leading item of a breadcrumb, a flyout header,
|
|
17
|
+
or a user row. Inside a collapsible <admin-sidebar> the label and
|
|
18
|
+
badge hide when the rail collapses; the icon survives — so the same
|
|
19
|
+
markup works expanded and collapsed without authoring two shapes.
|
|
20
|
+
|
|
21
|
+
Geometry mirrors <select-ui>'s trigger row: [slot="icon"] is fixed
|
|
22
|
+
(like [slot="leading"]), [slot="label"] flexes + truncates (like
|
|
23
|
+
[slot="display"]), [slot="badge"] is fixed trailing (like
|
|
24
|
+
[slot="caret"]).
|
|
25
|
+
|
|
26
|
+
props: {}
|
|
27
|
+
|
|
28
|
+
events: {}
|
|
29
|
+
|
|
30
|
+
slots:
|
|
31
|
+
default:
|
|
32
|
+
description: >-
|
|
33
|
+
Default content — unslotted children flow inline. Prefer the
|
|
34
|
+
named slots for the canonical icon + label + badge composition.
|
|
35
|
+
icon:
|
|
36
|
+
description: >-
|
|
37
|
+
Leading visual — an <icon-ui> glyph or an <img> avatar (img is
|
|
38
|
+
given a circular crop). Fixed width; survives sidebar collapse.
|
|
39
|
+
label:
|
|
40
|
+
description: >-
|
|
41
|
+
Primary text. Flexes to fill the remaining width and truncates
|
|
42
|
+
with an ellipsis. Hidden when a collapsible sidebar collapses.
|
|
43
|
+
badge:
|
|
44
|
+
description: >-
|
|
45
|
+
Optional trailing chip — environment (staging / beta) or role
|
|
46
|
+
badge. Fixed width. Hidden when a collapsible sidebar collapses.
|
|
47
|
+
|
|
48
|
+
states:
|
|
49
|
+
- name: idle
|
|
50
|
+
description: Default, the only state.
|
|
51
|
+
|
|
52
|
+
traits: []
|
|
53
|
+
|
|
54
|
+
a2ui:
|
|
55
|
+
rules:
|
|
56
|
+
- >-
|
|
57
|
+
admin-entity-item is the canonical icon + label + badge identity
|
|
58
|
+
row for shell surfaces. Slot it whole into [slot="heading"] of an
|
|
59
|
+
<admin-topbar> / <admin-statusbar> so the icon + label + badge
|
|
60
|
+
collapse together inside a collapsible <admin-sidebar>. Do NOT
|
|
61
|
+
re-implement it with a bare <span> or an ad-hoc flex <div> — those
|
|
62
|
+
have no shared collapse boundary.
|
|
63
|
+
- >-
|
|
64
|
+
For an INTERACTIVE workspace switcher use <select-ui variant="ghost">
|
|
65
|
+
instead — admin-entity-item is read-only identity display.
|
|
66
|
+
|
|
67
|
+
keywords:
|
|
68
|
+
- admin-entity-item
|
|
69
|
+
- entity-item
|
|
70
|
+
- identity-row
|
|
71
|
+
- workspace-identity
|
|
72
|
+
- user-identity
|
|
73
|
+
- icon-label-badge
|
|
74
|
+
|
|
75
|
+
synonyms:
|
|
76
|
+
entity-item: [identity-row, entity-row, identity-item]
|
|
77
|
+
|
|
78
|
+
related:
|
|
79
|
+
- AdminTopbar
|
|
80
|
+
- AdminStatusbar
|
|
81
|
+
- AdminSidebar
|
|
82
|
+
- Select
|
|
83
|
+
- Badge
|
|
84
|
+
- Icon
|
|
@@ -40,6 +40,10 @@ class AdminShell extends UIElement {
|
|
|
40
40
|
|
|
41
41
|
static template = () => null;
|
|
42
42
|
|
|
43
|
+
// FEEDBACK-37: one-shot per-element warn for <admin-topbar>/<admin-statusbar>
|
|
44
|
+
// mounted without their slot. WeakSet so it never pins the element from GC.
|
|
45
|
+
static #warnedSlots = new WeakSet();
|
|
46
|
+
|
|
43
47
|
connected() {
|
|
44
48
|
// Apply the v0.6.13 default mode if (and only if) the author did
|
|
45
49
|
// not supply a `mode` attribute on the tag. `hasAttribute` returns
|
|
@@ -48,6 +52,7 @@ class AdminShell extends UIElement {
|
|
|
48
52
|
if (!this.hasAttribute('mode')) this.mode = DEFAULT_MODE;
|
|
49
53
|
this.#wireToggleButtons();
|
|
50
54
|
this.#wireCommandTriggers();
|
|
55
|
+
this.#checkSlotContracts();
|
|
51
56
|
}
|
|
52
57
|
|
|
53
58
|
// No #disconnected — children own their own cleanup; the host registers
|
|
@@ -95,6 +100,33 @@ class AdminShell extends UIElement {
|
|
|
95
100
|
if (item) nav.select(item);
|
|
96
101
|
});
|
|
97
102
|
}
|
|
103
|
+
|
|
104
|
+
// ── 3. Slot-contract diagnostics (FEEDBACK-37) ──
|
|
105
|
+
// <admin-topbar>/<admin-statusbar> are CSS-only — placed inside
|
|
106
|
+
// <admin-sidebar>/<admin-content> without slot="header"/"footer" they
|
|
107
|
+
// land in the default slot and render in the body column instead of the
|
|
108
|
+
// chrome band, with no diagnostic. One-shot warn per misused element.
|
|
109
|
+
// (admin-statusbar folded in — identical failure mode to admin-topbar.)
|
|
110
|
+
#checkSlotContracts() {
|
|
111
|
+
const want = { 'admin-topbar': 'header', 'admin-statusbar': 'footer' };
|
|
112
|
+
for (const parent of this.querySelectorAll('admin-sidebar, admin-content')) {
|
|
113
|
+
for (const child of parent.children) {
|
|
114
|
+
const slot = want[child.localName];
|
|
115
|
+
if (slot
|
|
116
|
+
&& child.getAttribute('slot') !== slot
|
|
117
|
+
&& !AdminShell.#warnedSlots.has(child)) {
|
|
118
|
+
AdminShell.#warnedSlots.add(child);
|
|
119
|
+
// eslint-disable-next-line no-console
|
|
120
|
+
console.warn(
|
|
121
|
+
`[admin-shell] <${child.localName}> inside <${parent.localName}> is missing ` +
|
|
122
|
+
`slot="${slot}" — it renders in the default body slot instead of the chrome ` +
|
|
123
|
+
`band. Add slot="${slot}". See ${child.localName}.yaml.`,
|
|
124
|
+
child,
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
98
130
|
}
|
|
99
131
|
|
|
100
132
|
customElements.define('admin-shell', AdminShell);
|
|
@@ -87,7 +87,12 @@ describe('admin-shell.collapsed.css — vanilla HTML fallback (v0.6.17)', () =>
|
|
|
87
87
|
// text labels don't overflow the 48px rail when the consumer doesn't
|
|
88
88
|
// use AdiaUI <nav-item-ui> primitives.
|
|
89
89
|
expect(collapsedCSS).toMatch(/Vanilla-HTML fallback/);
|
|
90
|
-
|
|
90
|
+
// v0.6.20 (FEEDBACK-38 addendum): the heading-hide rule narrowed from a
|
|
91
|
+
// blanket `[slot="heading"]` to plain-text headings + headings without
|
|
92
|
+
// slotted children, so composed wrappers (<admin-entity-item slot="heading">)
|
|
93
|
+
// survive collapse. The rule still resolves to `display: none`.
|
|
94
|
+
expect(collapsedCSS).toMatch(/\[slot="heading"\][^{]*\{\s*display:\s*none/);
|
|
95
|
+
expect(collapsedCSS).toMatch(/\[slot="heading"\]:not\(:has\(>\s*\[slot\]\)\)/);
|
|
91
96
|
expect(collapsedCSS).toMatch(/button\.nav-item/);
|
|
92
97
|
expect(collapsedCSS).toMatch(/text-indent:\s*-9999px/);
|
|
93
98
|
});
|
|
@@ -34,7 +34,7 @@ admin-sidebar > admin-topbar {
|
|
|
34
34
|
display: flex;
|
|
35
35
|
align-items: center;
|
|
36
36
|
gap: var(--page-header-gap);
|
|
37
|
-
padding: 0 var(--page-
|
|
37
|
+
padding: 0 var(--page-content-inset);
|
|
38
38
|
height: var(--page-header-height);
|
|
39
39
|
font-size: var(--page-header-font);
|
|
40
40
|
border-bottom: var(--page-border);
|
|
@@ -48,7 +48,7 @@ admin-sidebar > admin-statusbar {
|
|
|
48
48
|
display: flex;
|
|
49
49
|
align-items: center;
|
|
50
50
|
gap: var(--page-header-gap);
|
|
51
|
-
padding: 0 var(--page-
|
|
51
|
+
padding: 0 var(--page-content-inset);
|
|
52
52
|
height: var(--page-header-height);
|
|
53
53
|
font-size: var(--page-header-font);
|
|
54
54
|
color: var(--page-header-fg-muted);
|
|
@@ -56,6 +56,13 @@ admin-sidebar > admin-statusbar {
|
|
|
56
56
|
flex-shrink: 0;
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
+
/* Sidebar header/footer chrome takes the sidebar's tighter inline inset
|
|
60
|
+
(--page-sidebar-px) so it aligns with the sidebar's own <section-ui>
|
|
61
|
+
body — not the content column's wider --page-content-inset. */
|
|
62
|
+
admin-sidebar > :is(admin-topbar, admin-statusbar) {
|
|
63
|
+
padding-inline: var(--page-sidebar-px);
|
|
64
|
+
}
|
|
65
|
+
|
|
59
66
|
/* ── admin-scroll ≡ <section> child of <main> ── */
|
|
60
67
|
admin-content > admin-scroll {
|
|
61
68
|
flex: 1;
|
|
@@ -71,6 +71,19 @@
|
|
|
71
71
|
padding: 0;
|
|
72
72
|
min-height: var(--nav-item-row-height);
|
|
73
73
|
min-width: var(--nav-item-row-height);
|
|
74
|
+
/* FEEDBACK-39: fill the rail width so the whole 48px column is the hit
|
|
75
|
+
area — without this the item shrinks to its ~30px icon box, leaving
|
|
76
|
+
~9px dead gutters on each side. justify-content keeps the glyph
|
|
77
|
+
centred within the now-full-width item. */
|
|
78
|
+
width: 100%;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/* FEEDBACK-39: nav-ui itself must fill the rail — the collapsed section
|
|
82
|
+
centres + shrink-wraps its children, so without an explicit width
|
|
83
|
+
nav-ui collapses to its ~30px content box and `width: 100%` on the
|
|
84
|
+
items would resolve against 30px, not the 48px rail. */
|
|
85
|
+
nav-ui {
|
|
86
|
+
width: 100%;
|
|
74
87
|
}
|
|
75
88
|
|
|
76
89
|
/* Button: icon-only mode */
|
|
@@ -111,7 +124,13 @@
|
|
|
111
124
|
<admin-topbar slot="header">) — keeps the rail clean in collapsed mode.
|
|
112
125
|
Authors who want a brand mark visible when collapsed should put an
|
|
113
126
|
<icon-ui> or logo image in [slot="leading"] instead. */
|
|
114
|
-
|
|
127
|
+
/* FEEDBACK-38 (addendum): scope the hide to leaf text headings — a bare
|
|
128
|
+
<span slot="heading">Brand</span> — not composed wrappers (e.g. an
|
|
129
|
+
<admin-entity-item slot="heading">) that carry their own internal slot
|
|
130
|
+
contract. `:not(:has(> [slot]))` preserves any heading element whose
|
|
131
|
+
children are themselves slotted, so its icon survives collapse. */
|
|
132
|
+
:is(span, p, div, h1, h2, h3, h4, h5, h6)[slot="heading"],
|
|
133
|
+
[slot="heading"]:not(:has(> [slot])) {
|
|
115
134
|
display: none;
|
|
116
135
|
}
|
|
117
136
|
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/* ═══════════════════════════════════════════════════════════════
|
|
2
|
+
admin-shell — <admin-entity-item> (FEEDBACK-38)
|
|
3
|
+
|
|
4
|
+
CSS-only shell-tier primitive: a composable icon + label + badge
|
|
5
|
+
identity row. The leading icon, a truncating label, and an
|
|
6
|
+
optional trailing badge travel as one unit, so they can be
|
|
7
|
+
slotted whole into <admin-topbar>, <admin-statusbar>, breadcrumb
|
|
8
|
+
leading items, flyout headers, and user-identity rows.
|
|
9
|
+
|
|
10
|
+
Geometry mirrors <select-ui>'s trigger row:
|
|
11
|
+
[slot="icon"] ≡ select-ui [slot="leading"] — fixed, flex-shrink:0
|
|
12
|
+
[slot="label"] ≡ select-ui [slot="display"] — flexible, truncates
|
|
13
|
+
[slot="badge"] ≡ select-ui [slot="caret"] — fixed trailing
|
|
14
|
+
|
|
15
|
+
Collapse: inside a collapsed <admin-sidebar> (@container sidebar,
|
|
16
|
+
≤96px) the label + badge hide and the icon survives. This is why
|
|
17
|
+
the element is a wrapper: collapsed.css's [slot="heading"] hide
|
|
18
|
+
rule is scoped to preserve any heading that carries slotted
|
|
19
|
+
children (`:not(:has(> [slot]))`, see FEEDBACK-38 addendum), so a
|
|
20
|
+
<admin-entity-item slot="heading"> survives collapse and manages
|
|
21
|
+
its own label/badge here — a bare <span slot="heading"> cannot.
|
|
22
|
+
═══════════════════════════════════════════════════════════════ */
|
|
23
|
+
|
|
24
|
+
admin-entity-item {
|
|
25
|
+
/* ── tunable tokens ── */
|
|
26
|
+
--entity-item-gap: var(--a-space-2);
|
|
27
|
+
--entity-item-icon-size: 1rem;
|
|
28
|
+
--entity-item-icon-color: var(--a-fg-muted);
|
|
29
|
+
--entity-item-avatar-size: 1.5rem;
|
|
30
|
+
|
|
31
|
+
display: inline-flex;
|
|
32
|
+
align-items: center;
|
|
33
|
+
gap: var(--entity-item-gap);
|
|
34
|
+
min-width: 0;
|
|
35
|
+
overflow: hidden;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/* Leading visual — <icon-ui> glyph or <img> avatar. Never shrinks. */
|
|
39
|
+
admin-entity-item > [slot="icon"] {
|
|
40
|
+
flex-shrink: 0;
|
|
41
|
+
display: inline-flex;
|
|
42
|
+
align-items: center;
|
|
43
|
+
line-height: 1;
|
|
44
|
+
color: var(--entity-item-icon-color);
|
|
45
|
+
--a-icon-size: var(--entity-item-icon-size);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/* <img slot="icon"> → circular avatar treatment. */
|
|
49
|
+
admin-entity-item > img[slot="icon"] {
|
|
50
|
+
width: var(--entity-item-avatar-size);
|
|
51
|
+
height: var(--entity-item-avatar-size);
|
|
52
|
+
border-radius: var(--a-radius-full);
|
|
53
|
+
object-fit: cover;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/* Truncating label — takes the remaining width, ellipsises overflow. */
|
|
57
|
+
admin-entity-item > [slot="label"] {
|
|
58
|
+
flex: 1;
|
|
59
|
+
min-width: 0;
|
|
60
|
+
overflow: hidden;
|
|
61
|
+
text-overflow: ellipsis;
|
|
62
|
+
white-space: nowrap;
|
|
63
|
+
font-size: var(--a-ui-sm);
|
|
64
|
+
font-weight: var(--a-weight-medium, 500);
|
|
65
|
+
color: var(--a-fg);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/* Optional trailing badge — environment / role chip. Never shrinks. */
|
|
69
|
+
admin-entity-item > [slot="badge"] {
|
|
70
|
+
flex-shrink: 0;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/* ── Collapsed sidebar (icon-only rail) ──
|
|
74
|
+
Hide the label + badge; the icon survives. The enclosing
|
|
75
|
+
<admin-topbar>/<admin-statusbar> collapsed rule (justify-content:
|
|
76
|
+
center, in collapsed.css) centres the now-icon-only item. */
|
|
77
|
+
@container sidebar (max-width: 96px) {
|
|
78
|
+
admin-entity-item > [slot="label"],
|
|
79
|
+
admin-entity-item > [slot="badge"] {
|
|
80
|
+
display: none;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
|
|
39
39
|
/* Content area — scroll region inside main */
|
|
40
40
|
--page-content-bg: var(--a-canvas-0); /* content surface (lighter than chrome) */
|
|
41
|
-
--page-content-header-bg: var(--a-canvas-
|
|
41
|
+
--page-content-header-bg: var(--a-canvas-0); /* sticky page-header band — canvas-0, matching the page-body content surface (--page-content-bg) so the header reads as a flush extension of the content area, not as separate chrome. History: v0.6.14 used canvas-2 (ΔL=0.08, "elevated step over content"); v0.6.16 rebased to canvas-1 ("shell-chrome continuation"); both still read as not-quite-flush against dense dark-mode layouts, so the band is now canvas-0 — fully flush with the body content surface. Consumers who want a raised/contrasting band override this token at :root. */
|
|
42
42
|
--page-content-radius: var(--a-radius-lg); /* used by "rounded" mode */
|
|
43
43
|
--page-content-inset: var(--a-space-10); /* padding for header/body/footer */
|
|
44
44
|
--page-content-max-width: 1540px; /* max-width for content children */
|
|
@@ -50,6 +50,17 @@ a2ui:
|
|
|
50
50
|
admin-statusbar replaces <footer-ui> at shell-tier. Same slot
|
|
51
51
|
vocabulary as <admin-topbar>; visual treatment differs (the
|
|
52
52
|
shell css applies a top-border instead of bottom).
|
|
53
|
+
- >-
|
|
54
|
+
When placed inside <admin-sidebar> or <admin-content>, admin-statusbar
|
|
55
|
+
MUST carry slot="footer". Without it the statusbar lands in the
|
|
56
|
+
default body slot instead of the chrome footer band. Canonical:
|
|
57
|
+
<admin-statusbar slot="footer">…</admin-statusbar>. admin-shell logs
|
|
58
|
+
a one-shot console.warn when the slot is missing.
|
|
59
|
+
- >-
|
|
60
|
+
For a user-identity row (avatar + name + role badge), slot a single
|
|
61
|
+
<admin-entity-item slot="heading"> rather than separate slot="icon" +
|
|
62
|
+
slot="heading" children — the wrapper collapses the name + badge
|
|
63
|
+
together inside a collapsible <admin-sidebar>, keeping the avatar.
|
|
53
64
|
|
|
54
65
|
keywords:
|
|
55
66
|
- admin-statusbar
|
|
@@ -65,4 +76,5 @@ related:
|
|
|
65
76
|
- AdminShell
|
|
66
77
|
- AdminContent
|
|
67
78
|
- AdminTopbar
|
|
79
|
+
- AdminEntityItem
|
|
68
80
|
- Footer
|
|
@@ -56,6 +56,18 @@ a2ui:
|
|
|
56
56
|
admin-topbar replaces <header-ui> at shell-tier — use it for
|
|
57
57
|
chrome bars inside admin-shell, admin-content, admin-sidebar.
|
|
58
58
|
Use <header-ui> for primitive containers (Card / Drawer / Modal).
|
|
59
|
+
- >-
|
|
60
|
+
When placed inside <admin-sidebar> or <admin-content>, admin-topbar
|
|
61
|
+
MUST carry slot="header". Without it the topbar lands in the default
|
|
62
|
+
body slot and renders below the content instead of as the chrome
|
|
63
|
+
header band. Canonical: <admin-topbar slot="header">…</admin-topbar>.
|
|
64
|
+
admin-shell logs a one-shot console.warn when the slot is missing.
|
|
65
|
+
- >-
|
|
66
|
+
For an icon + label (+ optional badge) identity row — workspace or
|
|
67
|
+
product identity — slot a single <admin-entity-item slot="heading">
|
|
68
|
+
rather than separate slot="icon" + slot="heading" children. The
|
|
69
|
+
wrapper keeps the icon and label as one unit so they truncate and
|
|
70
|
+
collapse together inside a collapsible <admin-sidebar>.
|
|
59
71
|
|
|
60
72
|
keywords:
|
|
61
73
|
- admin-topbar
|
|
@@ -72,4 +84,5 @@ related:
|
|
|
72
84
|
- AdminContent
|
|
73
85
|
- AdminSidebar
|
|
74
86
|
- AdminStatusbar
|
|
87
|
+
- AdminEntityItem
|
|
75
88
|
- Header
|