@adia-ai/web-modules 0.8.35 → 0.8.37
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 +22 -0
- package/README.md +3 -3
- package/agent-admin/admin-roster/admin-roster.js +1 -1
- package/agent-admin/admin-settings/admin-settings.js +1 -1
- package/agent-admin/agent-admin/agent-admin.js +1 -1
- package/billing/billing-overview/billing-overview.a2ui.json +281 -0
- package/billing/billing-overview/billing-overview.class.js +838 -0
- package/billing/billing-overview/billing-overview.css +223 -0
- package/billing/billing-overview/billing-overview.js +16 -0
- package/billing/billing-overview/billing-overview.yaml +441 -0
- package/billing/index.js +21 -0
- package/billing/invoice-detail/invoice-detail.a2ui.json +276 -0
- package/billing/invoice-detail/invoice-detail.class.js +711 -0
- package/billing/invoice-detail/invoice-detail.css +305 -0
- package/billing/invoice-detail/invoice-detail.js +16 -0
- package/billing/invoice-detail/invoice-detail.yaml +411 -0
- package/billing/invoice-history/invoice-history.a2ui.json +315 -0
- package/billing/invoice-history/invoice-history.class.js +672 -0
- package/billing/invoice-history/invoice-history.css +130 -0
- package/billing/invoice-history/invoice-history.js +16 -0
- package/billing/invoice-history/invoice-history.yaml +398 -0
- package/billing/payment-method-form/payment-method-form.a2ui.json +310 -0
- package/billing/payment-method-form/payment-method-form.class.js +886 -0
- package/billing/payment-method-form/payment-method-form.css +149 -0
- package/billing/payment-method-form/payment-method-form.js +16 -0
- package/billing/payment-method-form/payment-method-form.yaml +430 -0
- package/billing/payment-method-list/payment-method-list.a2ui.json +283 -0
- package/billing/payment-method-list/payment-method-list.class.js +705 -0
- package/billing/payment-method-list/payment-method-list.css +128 -0
- package/billing/payment-method-list/payment-method-list.js +16 -0
- package/billing/payment-method-list/payment-method-list.yaml +355 -0
- package/billing/plan-picker/plan-picker.a2ui.json +349 -0
- package/billing/plan-picker/plan-picker.class.js +635 -0
- package/billing/plan-picker/plan-picker.css +227 -0
- package/billing/plan-picker/plan-picker.js +16 -0
- package/billing/plan-picker/plan-picker.yaml +453 -0
- package/chat/README.md +1 -1
- package/chat/chat-composer/chat-composer.js +2 -2
- package/chat/chat-empty/chat-empty.js +2 -2
- package/chat/chat-shell/chat-shell.js +4 -4
- package/chat/chat-sidebar/chat-sidebar.js +2 -2
- package/chat/chat-surfaces/chat-surfaces.js +2 -2
- package/chat/chat-thread/chat-thread.js +2 -2
- package/dashboard/dashboard-layout/dashboard-layout.a2ui.json +254 -0
- package/dashboard/dashboard-layout/dashboard-layout.css +190 -0
- package/dashboard/dashboard-layout/dashboard-layout.js +289 -0
- package/dashboard/dashboard-layout/dashboard-layout.yaml +374 -0
- package/dashboard/date-range-selector/date-range-selector.a2ui.json +236 -0
- package/dashboard/date-range-selector/date-range-selector.css +84 -0
- package/dashboard/date-range-selector/date-range-selector.js +686 -0
- package/dashboard/date-range-selector/date-range-selector.yaml +358 -0
- package/dashboard/index.js +14 -0
- package/dist/everything.min.js +1 -1
- package/editor/editor-canvas/editor-canvas.js +2 -2
- package/editor/editor-shell/editor-shell.js +2 -2
- package/editor/editor-sidebar/editor-sidebar.js +2 -2
- package/editor/editor-toolbar/editor-toolbar.js +2 -2
- package/feedback/confirm-dialog/confirm-dialog.a2ui.json +206 -0
- package/feedback/confirm-dialog/confirm-dialog.css +157 -0
- package/feedback/confirm-dialog/confirm-dialog.js +383 -0
- package/feedback/confirm-dialog/confirm-dialog.yaml +297 -0
- package/feedback/index.js +10 -0
- package/form/form-popover/form-popover.js +1 -1
- package/generative/index.d.ts +1 -1
- package/generative/index.js +2 -2
- package/onboarding/index.js +1 -0
- package/onboarding/onboarding-checklist/onboarding-checklist.a2ui.json +263 -0
- package/onboarding/onboarding-checklist/onboarding-checklist.css +157 -0
- package/onboarding/onboarding-checklist/onboarding-checklist.js +428 -0
- package/onboarding/onboarding-checklist/onboarding-checklist.yaml +236 -0
- package/package.json +99 -6
- package/runtime/a2ui-root/a2ui-root.js +3 -3
- package/runtime/gen-root/gen-root.js +5 -5
- package/settings/index.js +12 -0
- package/settings/integrations-page/integrations-page.a2ui.json +274 -0
- package/settings/integrations-page/integrations-page.css +177 -0
- package/settings/integrations-page/integrations-page.d.ts +77 -0
- package/settings/integrations-page/integrations-page.js +413 -0
- package/settings/integrations-page/integrations-page.yaml +317 -0
- package/settings/notification-preferences/notification-preferences.a2ui.json +245 -0
- package/settings/notification-preferences/notification-preferences.css +204 -0
- package/settings/notification-preferences/notification-preferences.js +622 -0
- package/settings/notification-preferences/notification-preferences.yaml +358 -0
- package/shell/admin-command/admin-command.js +2 -2
- package/shell/admin-shell/admin-shell.js +2 -2
- package/shell/admin-sidebar/admin-sidebar.js +2 -2
- package/shell/embed-shell/embed-shell.js +3 -3
- package/simple/simple-shell/simple-shell.js +1 -1
- package/theme/theme-panel/theme-panel.js +2 -2
|
@@ -32,8 +32,8 @@
|
|
|
32
32
|
* backwards compat.
|
|
33
33
|
*/
|
|
34
34
|
|
|
35
|
-
import { defineIfFree } from '
|
|
36
|
-
import { UIElement } from '
|
|
35
|
+
import { defineIfFree } from '@adia-ai/web-components/core/register';
|
|
36
|
+
import { UIElement } from '@adia-ai/web-components/core/element';
|
|
37
37
|
|
|
38
38
|
class ChatComposer extends UIElement {
|
|
39
39
|
static properties = {
|
|
@@ -21,8 +21,8 @@
|
|
|
21
21
|
* consumer surfaces (patient-visit), so it gets the class.
|
|
22
22
|
*/
|
|
23
23
|
|
|
24
|
-
import { defineIfFree } from '
|
|
25
|
-
import { UIElement } from '
|
|
24
|
+
import { defineIfFree } from '@adia-ai/web-components/core/register';
|
|
25
|
+
import { UIElement } from '@adia-ai/web-components/core/element';
|
|
26
26
|
|
|
27
27
|
class ChatEmpty extends UIElement {
|
|
28
28
|
static properties = {};
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import { defineIfFree } from '
|
|
2
|
-
import { UIElement } from '
|
|
3
|
-
import { renderMarkdown } from '
|
|
1
|
+
import { defineIfFree } from '@adia-ai/web-components/core/register';
|
|
2
|
+
import { UIElement } from '@adia-ai/web-components/core/element';
|
|
3
|
+
import { renderMarkdown } from '@adia-ai/web-components/core/markdown';
|
|
4
4
|
// LAZY llm import (gh#541): packages/llm/index.js is a BUILD ARTIFACT
|
|
5
5
|
// (gitignored; TS source only in a fresh checkout). A static import here
|
|
6
6
|
// rides the everything-barrel, so a missing artifact 500'd EVERY /site
|
|
7
7
|
// route with a full-viewport vite-error-overlay — the freeze-shaped dev
|
|
8
8
|
// failure. Deferred to first send: a missing build degrades chat-shell's
|
|
9
9
|
// LLM wiring with an in-thread error instead of killing the site.
|
|
10
|
-
import '
|
|
10
|
+
import '@adia-ai/web-components/components/code';
|
|
11
11
|
|
|
12
12
|
function escapeHTML(s) {
|
|
13
13
|
return s.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
|
|
@@ -37,8 +37,8 @@
|
|
|
37
37
|
* code should prefer <chat-sidebar>.
|
|
38
38
|
*/
|
|
39
39
|
|
|
40
|
-
import { defineIfFree } from '
|
|
41
|
-
import { UIElement } from '
|
|
40
|
+
import { defineIfFree } from '@adia-ai/web-components/core/register';
|
|
41
|
+
import { UIElement } from '@adia-ai/web-components/core/element';
|
|
42
42
|
|
|
43
43
|
const SNAP_THRESHOLD = 96;
|
|
44
44
|
const SNAP_MIN_USABLE = 160;
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
* (unlike `@genui/*`), so `wireAgentEvents` imports `<agent-reasoning-ui>`
|
|
30
30
|
* directly (gh#667) — the "agent inner monologue + pipeline viewer with
|
|
31
31
|
* steps, thoughts, plans, and iterations" primitive already built for
|
|
32
|
-
* exactly this shape (primitive audit,
|
|
32
|
+
* exactly this shape (primitive audit, primitive-authoring §0 — no new primitive
|
|
33
33
|
* was minted). One reasoning viewer is lazily mounted per assistant turn
|
|
34
34
|
* and renders `thinking` (→ `addThought`), `tool_use`/`tool_input_delta`/
|
|
35
35
|
* `tool_result` (→ `addStep`/`updateStep`/`completeStep`/`failStep`, with
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
* render-silent (trace is devtools' surface, not the thread's — see the
|
|
40
40
|
* event → rendering table in `packages/web-modules/chat/README.md`).
|
|
41
41
|
*/
|
|
42
|
-
import '
|
|
42
|
+
import '@adia-ai/web-components/components/agent-reasoning';
|
|
43
43
|
|
|
44
44
|
const CLOSED_ANNOTATION_TEXT = 'Closed.';
|
|
45
45
|
const PROTOCOL_VERSION = 'v1.0';
|
|
@@ -29,8 +29,8 @@
|
|
|
29
29
|
* markdown + escape rules); the thread just owns the scroll surface.
|
|
30
30
|
*/
|
|
31
31
|
|
|
32
|
-
import { defineIfFree } from '
|
|
33
|
-
import { UIElement } from '
|
|
32
|
+
import { defineIfFree } from '@adia-ai/web-components/core/register';
|
|
33
|
+
import { UIElement } from '@adia-ai/web-components/core/element';
|
|
34
34
|
|
|
35
35
|
const SCROLL_BOTTOM_TOLERANCE = 40; // px from bottom that counts as "at bottom"
|
|
36
36
|
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://adiaui.dev/a2ui/v0_9/components/DashboardLayout.json",
|
|
4
|
+
"title": "DashboardLayout",
|
|
5
|
+
"description": "Module-tier dashboard-body composite. Crystallizes the recurring\n\"toolbar + KPI grid + chart area + table\" dashboard layout into a\nsingle primitive with four named regions (toolbar / kpis / charts /\ntable) plus an optional aside column. Each region is filled by\nconsumer-supplied <card-ui>s; the composite owns band sizing,\nresponsive breakpoints, and a [density] knob that propagates to\nevery descendant primitive via the parametric --a-density cascade.\n\nSits inside an <admin-page-body>; replaces the hand-rolled\n<col-ui gap=\"4\"> + nested <grid-ui> + <card-ui> chains every\nanalytics consumer reinvents today. Per ADR-0033 (Light-DOM\nsubstrate) — slot= attributes are decorative metadata; CSS rules\nmatch `:scope > [slot=\"X\"]` to position bands in DOM order.\n\nSpec: .claude/docs/specs/implementation-ready/SPEC-018-dashboard-layout.md.\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
|
+
"chart-split": {
|
|
17
|
+
"description": "Chart-band column split. Empty string = single full-width chart;\n`2` = two equal columns; `2:1` / `3:2` / `3:1` = asymmetric\nratios. Collapses to single column at narrow widths (≤48em).\n",
|
|
18
|
+
"type": "string",
|
|
19
|
+
"enum": [
|
|
20
|
+
"",
|
|
21
|
+
"2",
|
|
22
|
+
"2:1",
|
|
23
|
+
"3:2",
|
|
24
|
+
"3:1"
|
|
25
|
+
],
|
|
26
|
+
"default": ""
|
|
27
|
+
},
|
|
28
|
+
"component": {
|
|
29
|
+
"const": "DashboardLayout"
|
|
30
|
+
},
|
|
31
|
+
"density": {
|
|
32
|
+
"description": "Spacing scale — propagates --a-density to descendant primitives\nvia CSS custom-property cascade. Empty string inherits whatever\ndensity is in effect on an ancestor (the default — respects an\napp-level density theme). `compact` / `comfortable` / `spacious`\nexplicitly override.\n",
|
|
33
|
+
"type": "string",
|
|
34
|
+
"enum": [
|
|
35
|
+
"",
|
|
36
|
+
"comfortable",
|
|
37
|
+
"compact",
|
|
38
|
+
"spacious"
|
|
39
|
+
],
|
|
40
|
+
"default": ""
|
|
41
|
+
},
|
|
42
|
+
"gap": {
|
|
43
|
+
"description": "Override band-to-band vertical gap. Empty string = the\ndensity-modulated default (--a-space-4 at comfortable). Numeric\n`1`..`6` selects the corresponding --a-space-N step.\n",
|
|
44
|
+
"type": "string",
|
|
45
|
+
"default": ""
|
|
46
|
+
},
|
|
47
|
+
"kpi-columns": {
|
|
48
|
+
"description": "Target column count for the KPI band at desktop width. Range 2-6;\nout-of-range values fall back to 4. Container-query collapse\nreduces this at narrower widths (≤48em → 2; ≤32em → 1).\n",
|
|
49
|
+
"type": "string",
|
|
50
|
+
"enum": [
|
|
51
|
+
"2",
|
|
52
|
+
"3",
|
|
53
|
+
"4",
|
|
54
|
+
"5",
|
|
55
|
+
"6"
|
|
56
|
+
],
|
|
57
|
+
"default": "4"
|
|
58
|
+
},
|
|
59
|
+
"loading": {
|
|
60
|
+
"description": "Marks the composite as data-loading. Sets aria-busy=true on the\nhost and dims slotted children to 60% opacity with pointer-events\nsuppressed. Skeletons inside slotted cards continue to render\nnormally; the dim is on top of them.\n",
|
|
61
|
+
"type": "boolean",
|
|
62
|
+
"default": false
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
"required": [
|
|
66
|
+
"component"
|
|
67
|
+
],
|
|
68
|
+
"unevaluatedProperties": false,
|
|
69
|
+
"x-adiaui": {
|
|
70
|
+
"anti_patterns": [
|
|
71
|
+
{
|
|
72
|
+
"description": "Child without a [slot] attribute. Lands in the implicit default\nregion and breaks the band layout. Every direct child MUST\ndeclare its slot — toolbar / kpis / charts / table / aside.\n",
|
|
73
|
+
"right": "<dashboard-layout-ui>\n <card-ui slot=\"kpis\">...</card-ui>\n</dashboard-layout-ui>\n",
|
|
74
|
+
"rule": "Every direct child of dashboard-layout-ui declares its slot.\n",
|
|
75
|
+
"wrong": "<dashboard-layout-ui>\n <card-ui><!-- no slot -->...</card-ui>\n</dashboard-layout-ui>\n"
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
"description": "Nested DashboardLayout. Two density containers fight over the\n--a-density cascade. The inner one re-creates a 2-column layout\ninside a charts band, which is incoherent.\n",
|
|
79
|
+
"right": "<tabs-ui>\n <tab-panel-ui><dashboard-layout-ui>...</dashboard-layout-ui></tab-panel-ui>\n <tab-panel-ui><dashboard-layout-ui>...</dashboard-layout-ui></tab-panel-ui>\n</tabs-ui>\n",
|
|
80
|
+
"rule": "For nested dashboards, use sibling DashboardLayouts switched by\nTabs — not DashboardLayout inside DashboardLayout.\n",
|
|
81
|
+
"wrong": "<dashboard-layout-ui>\n <dashboard-layout-ui slot=\"charts\">...</dashboard-layout-ui>\n</dashboard-layout-ui>\n"
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
"description": "kpi-columns out of range. Eight cards in a row is too narrow\nto be legible at typical container widths; the container-query\ncollapse (≤48em → 2 cols, ≤32em → 1 col) won't help when N is\nalready that large at desktop.\n",
|
|
85
|
+
"right": "<dashboard-layout-ui kpi-columns=\"4\">...</dashboard-layout-ui>\n",
|
|
86
|
+
"rule": "kpi-columns ∈ {2,3,4,5,6}. Split into 2 rows of 4 by composing\n2 DashboardLayouts vertically if 8 cards are truly necessary.\n",
|
|
87
|
+
"wrong": "<dashboard-layout-ui kpi-columns=\"8\">...</dashboard-layout-ui>\n"
|
|
88
|
+
}
|
|
89
|
+
],
|
|
90
|
+
"category": "layout",
|
|
91
|
+
"composes": [
|
|
92
|
+
"card-ui",
|
|
93
|
+
"grid-ui",
|
|
94
|
+
"row-ui",
|
|
95
|
+
"stat-ui",
|
|
96
|
+
"chart-ui",
|
|
97
|
+
"table-ui"
|
|
98
|
+
],
|
|
99
|
+
"events": {
|
|
100
|
+
"density-change": {
|
|
101
|
+
"description": "Fired when [density] changes (programmatic or via setDensity()).\nBubbles; detail.density carries the new value.\n",
|
|
102
|
+
"detail": {
|
|
103
|
+
"density": {
|
|
104
|
+
"description": "The new density value (comfortable / compact / spacious).",
|
|
105
|
+
"type": "string"
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
},
|
|
109
|
+
"region-empty": {
|
|
110
|
+
"description": "Fired when a slot transitions from having content to being empty\n(consumer-driven removal of the last child for that slot).\nUseful for parent-level adjust-layout logic.\n",
|
|
111
|
+
"detail": {
|
|
112
|
+
"region": {
|
|
113
|
+
"description": "The slot name that became empty (toolbar / kpis / charts / table / aside).",
|
|
114
|
+
"type": "string"
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
},
|
|
119
|
+
"examples": [
|
|
120
|
+
{
|
|
121
|
+
"description": "KPI-strip + 2:1 chart split + table band inside an admin page.\n",
|
|
122
|
+
"a2ui": "[\n {\n \"id\": \"dash-1\",\n \"component\": \"DashboardLayout\",\n \"density\": \"\",\n \"kpiColumns\": \"4\",\n \"chartSplit\": \"2:1\",\n \"children\": [\"dash-toolbar\", \"dash-kpis\", \"dash-charts\", \"dash-table\"]\n },\n {\n \"id\": \"dash-toolbar\",\n \"component\": \"Row\",\n \"slot\": \"toolbar\"\n },\n {\n \"id\": \"dash-kpis\",\n \"component\": \"Group\",\n \"slot\": \"kpis\"\n },\n {\n \"id\": \"dash-charts\",\n \"component\": \"Group\",\n \"slot\": \"charts\"\n },\n {\n \"id\": \"dash-table\",\n \"component\": \"Card\",\n \"slot\": \"table\"\n }\n]\n",
|
|
123
|
+
"name": "canonical-analytics-dashboard"
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
"description": "Six-KPI dashboard at compact density (power-user view).\n",
|
|
127
|
+
"a2ui": "[\n {\n \"id\": \"dash-2\",\n \"component\": \"DashboardLayout\",\n \"density\": \"compact\",\n \"kpiColumns\": \"6\"\n }\n]\n",
|
|
128
|
+
"name": "compact-six-kpi"
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
"description": "Dashboard with a sticky aside column carrying a live activity feed.\n",
|
|
132
|
+
"a2ui": "[\n {\n \"id\": \"dash-3\",\n \"component\": \"DashboardLayout\",\n \"chartSplit\": \"2\",\n \"children\": [\"d3-aside\"]\n },\n {\n \"id\": \"d3-aside\",\n \"component\": \"Card\",\n \"slot\": \"aside\"\n }\n]\n",
|
|
133
|
+
"name": "with-aside-feed"
|
|
134
|
+
}
|
|
135
|
+
],
|
|
136
|
+
"keywords": [
|
|
137
|
+
"dashboard",
|
|
138
|
+
"dashboard-layout",
|
|
139
|
+
"analytics",
|
|
140
|
+
"kpi-grid",
|
|
141
|
+
"chart-area",
|
|
142
|
+
"dashboard-body",
|
|
143
|
+
"admin-dashboard",
|
|
144
|
+
"reporting",
|
|
145
|
+
"metrics-page",
|
|
146
|
+
"layout-container"
|
|
147
|
+
],
|
|
148
|
+
"name": "UIDashboardLayout",
|
|
149
|
+
"related": [
|
|
150
|
+
"AdminPageBody",
|
|
151
|
+
"AdminPage",
|
|
152
|
+
"Card",
|
|
153
|
+
"Grid",
|
|
154
|
+
"Stat",
|
|
155
|
+
"Chart",
|
|
156
|
+
"Table",
|
|
157
|
+
"DateRangeSelector"
|
|
158
|
+
],
|
|
159
|
+
"slots": {
|
|
160
|
+
"aside": {
|
|
161
|
+
"description": "Optional right-side panel (e.g., live activity feed). When set,\npromotes the host to a 2-column grid with the aside as a sticky\nright column on desktop. Collapses when empty.\n"
|
|
162
|
+
},
|
|
163
|
+
"charts": {
|
|
164
|
+
"description": "Chart band — wrapper containing 1-3 <card-ui> with <chart-ui>.\n[chart-split] drives the grid columns. Collapses when empty.\n"
|
|
165
|
+
},
|
|
166
|
+
"kpis": {
|
|
167
|
+
"description": "KPI band — typically a wrapper element containing N <card-ui>\ninstances each with one <stat-ui>. The composite drives the\ngrid template via [kpi-columns]. Collapses when empty.\n"
|
|
168
|
+
},
|
|
169
|
+
"table": {
|
|
170
|
+
"description": "Table band — typically a single <card-ui slot=\"table\"> containing\n<table-ui> and optional <pagination-ui> in the footer. Full-bleed\nacross the main column. Collapses when empty.\n"
|
|
171
|
+
},
|
|
172
|
+
"toolbar": {
|
|
173
|
+
"description": "Top band — filter chips, segmented date range, global controls.\nTypically a single <row-ui> or <date-range-selector-ui> (SPEC-019).\nCollapses when empty (no row reserved).\n"
|
|
174
|
+
}
|
|
175
|
+
},
|
|
176
|
+
"states": [
|
|
177
|
+
{
|
|
178
|
+
"description": "Default; all regions interactive.",
|
|
179
|
+
"name": "idle"
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
"description": "Data fetch in progress; aria-busy=true; content dimmed.",
|
|
183
|
+
"attribute": "loading",
|
|
184
|
+
"name": "loading"
|
|
185
|
+
},
|
|
186
|
+
{
|
|
187
|
+
"description": "Compact-density variant; tighter band gaps + density cascade.",
|
|
188
|
+
"attribute": "density",
|
|
189
|
+
"name": "compact"
|
|
190
|
+
},
|
|
191
|
+
{
|
|
192
|
+
"description": "Spacious-density variant; looser band gaps + density cascade.",
|
|
193
|
+
"attribute": "density",
|
|
194
|
+
"name": "spacious"
|
|
195
|
+
}
|
|
196
|
+
],
|
|
197
|
+
"status": "experimental",
|
|
198
|
+
"synonyms": {
|
|
199
|
+
"charts": [
|
|
200
|
+
"chart-area",
|
|
201
|
+
"viz",
|
|
202
|
+
"graphs"
|
|
203
|
+
],
|
|
204
|
+
"dashboard": [
|
|
205
|
+
"analytics",
|
|
206
|
+
"report",
|
|
207
|
+
"overview",
|
|
208
|
+
"metrics"
|
|
209
|
+
],
|
|
210
|
+
"kpi": [
|
|
211
|
+
"metric",
|
|
212
|
+
"stat",
|
|
213
|
+
"measure"
|
|
214
|
+
],
|
|
215
|
+
"layout": [
|
|
216
|
+
"container",
|
|
217
|
+
"grid",
|
|
218
|
+
"frame",
|
|
219
|
+
"shell"
|
|
220
|
+
],
|
|
221
|
+
"tags": [
|
|
222
|
+
"DashboardLayout",
|
|
223
|
+
"Dashboard",
|
|
224
|
+
"AnalyticsDashboard",
|
|
225
|
+
"MetricsDashboard"
|
|
226
|
+
]
|
|
227
|
+
},
|
|
228
|
+
"tag": "dashboard-layout-ui",
|
|
229
|
+
"tokens": {
|
|
230
|
+
"--dashboard-layout-aside-width": {
|
|
231
|
+
"description": "Aside column width when [slot=\"aside\"] is present.",
|
|
232
|
+
"default": "20em"
|
|
233
|
+
},
|
|
234
|
+
"--dashboard-layout-chart-gap": {
|
|
235
|
+
"description": "Inter-card gap inside the chart band.",
|
|
236
|
+
"default": "var(--a-space-4)"
|
|
237
|
+
},
|
|
238
|
+
"--dashboard-layout-gap": {
|
|
239
|
+
"description": "Band-to-band vertical gap.",
|
|
240
|
+
"default": "var(--a-space-4)"
|
|
241
|
+
},
|
|
242
|
+
"--dashboard-layout-kpi-gap": {
|
|
243
|
+
"description": "Inter-card gap inside the KPI band.",
|
|
244
|
+
"default": "var(--a-space-2)"
|
|
245
|
+
},
|
|
246
|
+
"--dashboard-layout-padding": {
|
|
247
|
+
"description": "Outer padding around the composite.",
|
|
248
|
+
"default": "0"
|
|
249
|
+
}
|
|
250
|
+
},
|
|
251
|
+
"traits": [],
|
|
252
|
+
"version": 1
|
|
253
|
+
}
|
|
254
|
+
}
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
/* ═══════════════════════════════════════════════════════════════
|
|
2
|
+
<dashboard-layout-ui> — Module-tier dashboard-body composite.
|
|
3
|
+
|
|
4
|
+
Owns the four canonical dashboard bands (toolbar / kpis /
|
|
5
|
+
charts / table) plus an optional aside column. Children declare
|
|
6
|
+
their band via [slot="X"]; CSS rules position by tag + ancestor
|
|
7
|
+
+ DOM order (per ADR-0033 Light-DOM substrate).
|
|
8
|
+
|
|
9
|
+
The composite is a CSS-grid container with named grid-areas;
|
|
10
|
+
slotted children are placed via `grid-area`. The KPI and chart
|
|
11
|
+
bands internally drive their own grid via [kpi-columns] and
|
|
12
|
+
[chart-split] attributes. Density variants override token values
|
|
13
|
+
only — never `display`, `position`, layout shape.
|
|
14
|
+
|
|
15
|
+
Two-block @scope pattern per docs/specs/component-token-contract.md.
|
|
16
|
+
SPEC: docs/specs/implementation-ready/SPEC-018-dashboard-layout.md.
|
|
17
|
+
Zero raw color values (repo hard rule); zero raw px ≥ 3 (rem only).
|
|
18
|
+
═══════════════════════════════════════════════════════════════ */
|
|
19
|
+
|
|
20
|
+
/* ── Block 1: TOKEN DECLARATIONS ─────────────────────────────── */
|
|
21
|
+
|
|
22
|
+
dashboard-layout-ui {
|
|
23
|
+
--dashboard-layout-gap: var(--a-space-4);
|
|
24
|
+
--dashboard-layout-kpi-gap: var(--a-space-2);
|
|
25
|
+
--dashboard-layout-chart-gap: var(--a-space-4);
|
|
26
|
+
--dashboard-layout-aside-width: 20em;
|
|
27
|
+
--dashboard-layout-padding: 0;
|
|
28
|
+
|
|
29
|
+
/* Loading dim — shared opacity escalation. */
|
|
30
|
+
--dashboard-layout-loading-opacity: var(--a-opacity-disabled, 0.6);
|
|
31
|
+
|
|
32
|
+
/* Density-modulated gap overrides — applied at the [density="…"]
|
|
33
|
+
selectors below. Authors can override any of these via the
|
|
34
|
+
un-suffixed public token (--dashboard-layout-gap etc.). */
|
|
35
|
+
--dashboard-layout-gap-compact: var(--a-space-3);
|
|
36
|
+
--dashboard-layout-kpi-gap-compact: var(--a-space-2);
|
|
37
|
+
--dashboard-layout-gap-spacious: var(--a-space-5);
|
|
38
|
+
--dashboard-layout-kpi-gap-spacious: var(--a-space-3);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/* ── Block 2: SCOPED LAYOUT ──────────────────────────────────── */
|
|
42
|
+
|
|
43
|
+
@scope (dashboard-layout-ui) {
|
|
44
|
+
|
|
45
|
+
:scope {
|
|
46
|
+
display: grid;
|
|
47
|
+
grid-template-columns: 1fr;
|
|
48
|
+
grid-auto-rows: auto;
|
|
49
|
+
grid-template-areas:
|
|
50
|
+
"toolbar"
|
|
51
|
+
"kpis"
|
|
52
|
+
"charts"
|
|
53
|
+
"table";
|
|
54
|
+
gap: var(--dashboard-layout-gap);
|
|
55
|
+
padding: var(--dashboard-layout-padding);
|
|
56
|
+
/* Provide the container-query substrate so descendant primitives
|
|
57
|
+
can size against the dashboard container width. Per MEMORY
|
|
58
|
+
"Size-query provider pattern" — the composite is the
|
|
59
|
+
acknowledged provider for its descendants. */
|
|
60
|
+
container-type: inline-size;
|
|
61
|
+
container-name: dashboard-layout;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/* ── Region → grid-area mapping ──
|
|
65
|
+
Children carry [slot="X"]; CSS places them into the correct band
|
|
66
|
+
by tag + ancestor + DOM order. */
|
|
67
|
+
:scope > [slot="toolbar"] { grid-area: toolbar; }
|
|
68
|
+
:scope > [slot="kpis"] { grid-area: kpis; }
|
|
69
|
+
:scope > [slot="charts"] { grid-area: charts; }
|
|
70
|
+
:scope > [slot="table"] { grid-area: table; }
|
|
71
|
+
:scope > [slot="aside"] { grid-area: aside; }
|
|
72
|
+
|
|
73
|
+
/* ── KPI band — inner grid driven by [kpi-columns] ──
|
|
74
|
+
Default 4 columns; per-N selectors below override. Each column is
|
|
75
|
+
`1fr` — equal share of available width. Container queries below
|
|
76
|
+
(lines @container) collapse to fewer columns at narrow widths;
|
|
77
|
+
no per-column min-width floor (was minmax(16em, 1fr) — let
|
|
78
|
+
breakpoints manage responsive behavior, not minmax). */
|
|
79
|
+
:scope > [slot="kpis"] {
|
|
80
|
+
display: grid;
|
|
81
|
+
grid-template-columns: repeat(var(--dashboard-layout-kpi-cols, 4), 1fr);
|
|
82
|
+
gap: var(--dashboard-layout-kpi-gap);
|
|
83
|
+
}
|
|
84
|
+
:scope[kpi-columns="2"] > [slot="kpis"] { --dashboard-layout-kpi-cols: 2; }
|
|
85
|
+
:scope[kpi-columns="3"] > [slot="kpis"] { --dashboard-layout-kpi-cols: 3; }
|
|
86
|
+
:scope[kpi-columns="4"] > [slot="kpis"] { --dashboard-layout-kpi-cols: 4; }
|
|
87
|
+
:scope[kpi-columns="5"] > [slot="kpis"] { --dashboard-layout-kpi-cols: 5; }
|
|
88
|
+
:scope[kpi-columns="6"] > [slot="kpis"] { --dashboard-layout-kpi-cols: 6; }
|
|
89
|
+
|
|
90
|
+
/* ── Chart band — inner grid driven by [chart-split] ──
|
|
91
|
+
Empty / missing = single full-width chart. */
|
|
92
|
+
:scope > [slot="charts"] {
|
|
93
|
+
display: grid;
|
|
94
|
+
grid-template-columns: 1fr;
|
|
95
|
+
gap: var(--dashboard-layout-chart-gap);
|
|
96
|
+
}
|
|
97
|
+
:scope[chart-split="2"] > [slot="charts"] { grid-template-columns: 1fr 1fr; }
|
|
98
|
+
:scope[chart-split="2:1"] > [slot="charts"] { grid-template-columns: 2fr 1fr; }
|
|
99
|
+
:scope[chart-split="3:2"] > [slot="charts"] { grid-template-columns: 3fr 2fr; }
|
|
100
|
+
:scope[chart-split="3:1"] > [slot="charts"] { grid-template-columns: 3fr 1fr; }
|
|
101
|
+
|
|
102
|
+
/* ── Aside column — promotes the outer grid to 2 columns ──
|
|
103
|
+
When an [slot="aside"] child is present, the host becomes a
|
|
104
|
+
2-column grid with all bands stacked in the main column and
|
|
105
|
+
the aside spanning all rows on the right. */
|
|
106
|
+
:scope:has(> [slot="aside"]) {
|
|
107
|
+
grid-template-columns: 1fr var(--dashboard-layout-aside-width);
|
|
108
|
+
grid-template-areas:
|
|
109
|
+
"toolbar toolbar"
|
|
110
|
+
"kpis aside"
|
|
111
|
+
"charts aside"
|
|
112
|
+
"table aside";
|
|
113
|
+
}
|
|
114
|
+
:scope > [slot="aside"] {
|
|
115
|
+
align-self: start;
|
|
116
|
+
position: sticky;
|
|
117
|
+
top: var(--a-space-4);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/* ── Density variants — override TOKEN values only ──
|
|
121
|
+
Per the contract: variants change tokens; modes change layout.
|
|
122
|
+
Density is a token-override, not a layout-shape change. */
|
|
123
|
+
:scope[density="comfortable"] {
|
|
124
|
+
--a-density: 1;
|
|
125
|
+
}
|
|
126
|
+
:scope[density="compact"] {
|
|
127
|
+
--dashboard-layout-gap: var(--dashboard-layout-gap-compact);
|
|
128
|
+
--dashboard-layout-kpi-gap: var(--dashboard-layout-kpi-gap-compact);
|
|
129
|
+
--a-density: 0.85;
|
|
130
|
+
}
|
|
131
|
+
:scope[density="spacious"] {
|
|
132
|
+
--dashboard-layout-gap: var(--dashboard-layout-gap-spacious);
|
|
133
|
+
--dashboard-layout-kpi-gap: var(--dashboard-layout-kpi-gap-spacious);
|
|
134
|
+
--a-density: 1.15;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/* ── Loading state — dim slotted regions ──
|
|
138
|
+
The composite itself stays interactive (e.g., consumer wants to
|
|
139
|
+
swap density mid-fetch); only the band content dims + becomes
|
|
140
|
+
pointer-inert. JS sets aria-busy on the host. */
|
|
141
|
+
:scope[loading] > [slot] {
|
|
142
|
+
opacity: var(--dashboard-layout-loading-opacity);
|
|
143
|
+
pointer-events: none;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/* ── Container-query collapse ──
|
|
147
|
+
At narrow widths the KPI grid collapses regardless of
|
|
148
|
+
[kpi-columns]; the chart split collapses to single column.
|
|
149
|
+
|
|
150
|
+
The selectors mirror the [kpi-columns="N"] / [chart-split="X"]
|
|
151
|
+
scope rules above so they tie on specificity ([0,2,0]) and win
|
|
152
|
+
by source order (last-declared, same specificity, in @scope).
|
|
153
|
+
Without [kpi-columns="N"] in the selector, the higher-specificity
|
|
154
|
+
scope rule would override the container-query token write. */
|
|
155
|
+
/* Graduated collapse (bug-14): the old single <48em→2 / <32em→1 was too
|
|
156
|
+
eager — it dropped a 3-col KPI band to 2 while ~552px still fits 3 cards
|
|
157
|
+
comfortably. Now the dense bands (5/6) thin first, the authored count
|
|
158
|
+
holds until cards approach a ~9rem floor, then steps down. */
|
|
159
|
+
@container dashboard-layout (inline-size < 44em) {
|
|
160
|
+
:scope[kpi-columns="5"] > [slot="kpis"],
|
|
161
|
+
:scope[kpi-columns="6"] > [slot="kpis"] {
|
|
162
|
+
--dashboard-layout-kpi-cols: 3;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
@container dashboard-layout (inline-size < 40em) {
|
|
166
|
+
:scope[chart-split="2"] > [slot="charts"],
|
|
167
|
+
:scope[chart-split="2:1"] > [slot="charts"],
|
|
168
|
+
:scope[chart-split="3:2"] > [slot="charts"],
|
|
169
|
+
:scope[chart-split="3:1"] > [slot="charts"] {
|
|
170
|
+
grid-template-columns: 1fr;
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
@container dashboard-layout (inline-size < 32em) {
|
|
174
|
+
:scope[kpi-columns="3"] > [slot="kpis"],
|
|
175
|
+
:scope[kpi-columns="4"] > [slot="kpis"],
|
|
176
|
+
:scope[kpi-columns="5"] > [slot="kpis"],
|
|
177
|
+
:scope[kpi-columns="6"] > [slot="kpis"] {
|
|
178
|
+
--dashboard-layout-kpi-cols: 2;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
@container dashboard-layout (inline-size < 20em) {
|
|
182
|
+
:scope[kpi-columns="2"] > [slot="kpis"],
|
|
183
|
+
:scope[kpi-columns="3"] > [slot="kpis"],
|
|
184
|
+
:scope[kpi-columns="4"] > [slot="kpis"],
|
|
185
|
+
:scope[kpi-columns="5"] > [slot="kpis"],
|
|
186
|
+
:scope[kpi-columns="6"] > [slot="kpis"] {
|
|
187
|
+
--dashboard-layout-kpi-cols: 1;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|