@adia-ai/web-components 0.0.27 → 0.0.29
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/README.md +4 -8
- package/a2ui/index.js +1 -1
- package/components/agent-questions/agent-questions.css +20 -1
- package/components/agent-trace/agent-trace.css +17 -12
- package/components/badge/badge.js +9 -1
- package/components/breadcrumb/breadcrumb.a2ui.json +16 -1
- package/components/breadcrumb/breadcrumb.css +27 -0
- package/components/breadcrumb/breadcrumb.js +95 -17
- package/components/breadcrumb/breadcrumb.yaml +15 -1
- package/components/canvas/canvas.js +1 -1
- package/components/chart/chart.css +20 -13
- package/components/chart/chart.js +49 -17
- package/components/chart-legend/chart-legend.css +30 -54
- package/components/chart-legend/chart-legend.js +48 -30
- package/components/command/command.js +52 -1
- package/components/feed/feed-item.yaml +50 -0
- package/components/feed/feed.a2ui.json +59 -0
- package/components/feed/feed.css +150 -0
- package/components/feed/feed.js +385 -0
- package/components/feed/feed.yaml +33 -0
- package/components/index.js +2 -0
- package/components/swatch/swatch.a2ui.json +116 -0
- package/components/swatch/swatch.css +141 -0
- package/components/swatch/swatch.js +121 -0
- package/components/swatch/swatch.yaml +101 -0
- package/components/timeline/timeline.css +5 -1
- package/components/toast/toast.js +48 -178
- package/components/tooltip/tooltip.css +3 -3
- package/core/provider.js +1 -0
- package/index.css +3 -2
- package/index.js +15 -7
- package/package.json +1 -5
- package/styles/components.css +1 -0
- package/patterns/a2ui-root/a2ui-root.a2ui.json +0 -125
- package/patterns/a2ui-root/a2ui-root.js +0 -191
- package/patterns/a2ui-root/a2ui-root.yaml +0 -87
- package/patterns/adia-chat/adia-chat.a2ui.json +0 -149
- package/patterns/adia-chat/adia-chat.css +0 -10
- package/patterns/adia-chat/adia-chat.js +0 -297
- package/patterns/adia-chat/adia-chat.yaml +0 -118
- package/patterns/adia-chat/css/adia-chat.empty.css +0 -12
- package/patterns/adia-chat/css/adia-chat.layout.css +0 -60
- package/patterns/adia-chat/css/adia-chat.markdown.css +0 -74
- package/patterns/adia-chat/css/adia-chat.messages.css +0 -87
- package/patterns/adia-chat/css/adia-chat.streaming.css +0 -30
- package/patterns/adia-chat/css/adia-chat.tokens.css +0 -95
- package/patterns/adia-editor/adia-editor.a2ui.json +0 -73
- package/patterns/adia-editor/adia-editor.css +0 -6
- package/patterns/adia-editor/adia-editor.js +0 -56
- package/patterns/adia-editor/adia-editor.yaml +0 -59
- package/patterns/adia-editor/css/adia-editor.layout.css +0 -171
- package/patterns/adia-editor/css/adia-editor.tokens.css +0 -28
- package/patterns/app-nav/app-nav.a2ui.json +0 -89
- package/patterns/app-nav/app-nav.css +0 -92
- package/patterns/app-nav/app-nav.js +0 -112
- package/patterns/app-nav/app-nav.yaml +0 -54
- package/patterns/app-nav-group/app-nav-group.a2ui.json +0 -82
- package/patterns/app-nav-group/app-nav-group.css +0 -264
- package/patterns/app-nav-group/app-nav-group.js +0 -116
- package/patterns/app-nav-group/app-nav-group.yaml +0 -59
- package/patterns/app-nav-item/app-nav-item.a2ui.json +0 -83
- package/patterns/app-nav-item/app-nav-item.css +0 -162
- package/patterns/app-nav-item/app-nav-item.js +0 -42
- package/patterns/app-nav-item/app-nav-item.yaml +0 -62
- package/patterns/app-shell/app-shell.a2ui.json +0 -129
- package/patterns/app-shell/app-shell.css +0 -14
- package/patterns/app-shell/app-shell.js +0 -251
- package/patterns/app-shell/app-shell.yaml +0 -89
- package/patterns/app-shell/css/app-shell.collapsed.css +0 -86
- package/patterns/app-shell/css/app-shell.helpers.css +0 -42
- package/patterns/app-shell/css/app-shell.main.css +0 -172
- package/patterns/app-shell/css/app-shell.shell.css +0 -44
- package/patterns/app-shell/css/app-shell.sidebar.css +0 -161
- package/patterns/app-shell/css/app-shell.templates.css +0 -214
- package/patterns/app-shell/css/app-shell.tokens.css +0 -119
- package/patterns/gen-ui/gen-ui.a2ui.json +0 -72
- package/patterns/gen-ui/gen-ui.css +0 -83
- package/patterns/gen-ui/gen-ui.js +0 -136
- package/patterns/gen-ui/gen-ui.yaml +0 -43
- package/patterns/index.js +0 -11
- package/patterns/section-nav/section-nav.a2ui.json +0 -91
- package/patterns/section-nav/section-nav.css +0 -60
- package/patterns/section-nav/section-nav.js +0 -42
- package/patterns/section-nav/section-nav.yaml +0 -58
- package/patterns/section-nav-group/section-nav-group.a2ui.json +0 -95
- package/patterns/section-nav-group/section-nav-group.css +0 -74
- package/patterns/section-nav-group/section-nav-group.js +0 -84
- package/patterns/section-nav-group/section-nav-group.yaml +0 -66
- package/patterns/section-nav-item/section-nav-item.a2ui.json +0 -97
- package/patterns/section-nav-item/section-nav-item.css +0 -106
- package/patterns/section-nav-item/section-nav-item.js +0 -66
- package/patterns/section-nav-item/section-nav-item.yaml +0 -70
- package/styles/layouts/admin.css +0 -7
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* <app-nav-ui> — Collapsible navigation sidebar.
|
|
3
|
-
*
|
|
4
|
-
* Structure:
|
|
5
|
-
* <app-nav-ui>
|
|
6
|
-
* <app-nav-group-ui icon="gear" text="Settings" badge="3">
|
|
7
|
-
* <app-nav-item-ui text="General" value="/settings/general"></app-nav-item-ui>
|
|
8
|
-
* </app-nav-group-ui>
|
|
9
|
-
* <app-nav-item-ui icon="user" text="Profile" value="/profile"></app-nav-item-ui>
|
|
10
|
-
* </app-nav-ui>
|
|
11
|
-
*
|
|
12
|
-
* When [collapsed], labels and badges hide; groups open a popover with their
|
|
13
|
-
* children instead of expanding inline.
|
|
14
|
-
*
|
|
15
|
-
* Event: nav-select (detail: { item, text, value })
|
|
16
|
-
*/
|
|
17
|
-
|
|
18
|
-
import { AdiaElement } from '../../core/element.js';
|
|
19
|
-
|
|
20
|
-
class AdiaAppNav extends AdiaElement {
|
|
21
|
-
static properties = {
|
|
22
|
-
collapsed: { type: Boolean, default: false, reflect: true },
|
|
23
|
-
divider: { type: Boolean, default: false, reflect: true },
|
|
24
|
-
};
|
|
25
|
-
|
|
26
|
-
static template = () => null;
|
|
27
|
-
|
|
28
|
-
#ro = null;
|
|
29
|
-
|
|
30
|
-
connected() {
|
|
31
|
-
this.setAttribute('role', 'navigation');
|
|
32
|
-
this.addEventListener('click', this.#onClick);
|
|
33
|
-
this.#ro = new ResizeObserver(() => this.#updateTooltips());
|
|
34
|
-
this.#ro.observe(this);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
render() {
|
|
38
|
-
this.#updateTooltips();
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
#updateTooltips() {
|
|
42
|
-
const isCollapsed = this.collapsed || this.getBoundingClientRect().width <= 96;
|
|
43
|
-
for (const group of this.querySelectorAll(':scope > app-nav-group-ui')) {
|
|
44
|
-
const header = group.querySelector(':scope > [slot="header"]');
|
|
45
|
-
if (header) header.title = isCollapsed ? group.text : '';
|
|
46
|
-
}
|
|
47
|
-
for (const item of this.querySelectorAll(':scope > app-nav-item-ui')) {
|
|
48
|
-
item.title = isCollapsed ? item.text : '';
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
get selectedItem() {
|
|
53
|
-
return this.querySelector('app-nav-item-ui[selected]');
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
select(item) {
|
|
57
|
-
const prev = this.selectedItem;
|
|
58
|
-
if (prev && prev !== item) prev.removeAttribute('selected');
|
|
59
|
-
item.setAttribute('selected', '');
|
|
60
|
-
this.dispatchEvent(new CustomEvent('nav-select', {
|
|
61
|
-
bubbles: true,
|
|
62
|
-
detail: { item, text: item.text, value: item.value },
|
|
63
|
-
}));
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
toggle() {
|
|
67
|
-
this.collapsed = !this.collapsed;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
#onClick = (e) => {
|
|
71
|
-
const item = e.target.closest('app-nav-item-ui');
|
|
72
|
-
if (item && this.contains(item)) {
|
|
73
|
-
this.select(item);
|
|
74
|
-
this.#flushHoverState();
|
|
75
|
-
return;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
const group = e.target.closest('app-nav-group-ui');
|
|
79
|
-
if (group && this.contains(group)) {
|
|
80
|
-
const isCollapsed = this.collapsed || this.getBoundingClientRect().width <= 96;
|
|
81
|
-
if (isCollapsed) {
|
|
82
|
-
group.showPopover();
|
|
83
|
-
} else {
|
|
84
|
-
const header = group.querySelector(':scope > [slot="header"]');
|
|
85
|
-
if (header && (e.target === header || header.contains(e.target))) {
|
|
86
|
-
group.open = !group.open;
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
};
|
|
91
|
-
|
|
92
|
-
// Safari macOS leaves `:hover` stuck on items the cursor passed through
|
|
93
|
-
// when the DOM mutates during click+route navigation (no `mouseleave`
|
|
94
|
-
// fires). Toggling pointer-events on the container forces Safari to
|
|
95
|
-
// re-evaluate hover state on next paint without flickering layout.
|
|
96
|
-
// Documented in docs/BROWSER-COMPAT.md §3a.
|
|
97
|
-
#flushHoverState() {
|
|
98
|
-
this.style.pointerEvents = 'none';
|
|
99
|
-
requestAnimationFrame(() => {
|
|
100
|
-
this.style.pointerEvents = '';
|
|
101
|
-
});
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
disconnected() {
|
|
105
|
-
this.removeEventListener('click', this.#onClick);
|
|
106
|
-
this.#ro?.disconnect();
|
|
107
|
-
this.#ro = null;
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
customElements.define('app-nav-ui', AdiaAppNav);
|
|
111
|
-
|
|
112
|
-
export { AdiaAppNav };
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
$schema: ../../../../scripts/schemas/component.yaml.schema.json
|
|
2
|
-
name: AdiaAppNav
|
|
3
|
-
tag: app-nav-ui
|
|
4
|
-
component: AppNav
|
|
5
|
-
category: nav
|
|
6
|
-
version: 1
|
|
7
|
-
description: |
|
|
8
|
-
Collapsible navigation sidebar. Manages selection state across
|
|
9
|
-
app-nav-item-ui children and opens popover menus for app-nav-group-ui
|
|
10
|
-
children when collapsed.
|
|
11
|
-
|
|
12
|
-
props:
|
|
13
|
-
collapsed:
|
|
14
|
-
type: boolean
|
|
15
|
-
default: false
|
|
16
|
-
reflect: true
|
|
17
|
-
description: When true, labels and badges hide; only icons show. Groups use popovers instead of inline expansion.
|
|
18
|
-
|
|
19
|
-
divider:
|
|
20
|
-
type: boolean
|
|
21
|
-
default: false
|
|
22
|
-
reflect: true
|
|
23
|
-
description: Render auto-dividers between groups.
|
|
24
|
-
|
|
25
|
-
events:
|
|
26
|
-
nav-select:
|
|
27
|
-
description: Fired when a child app-nav-item-ui is selected (via click or the .select() method).
|
|
28
|
-
detail:
|
|
29
|
-
item: HTMLElement
|
|
30
|
-
text: string
|
|
31
|
-
value: string
|
|
32
|
-
|
|
33
|
-
slots:
|
|
34
|
-
default:
|
|
35
|
-
description: app-nav-group-ui and app-nav-item-ui children.
|
|
36
|
-
|
|
37
|
-
states:
|
|
38
|
-
- name: idle
|
|
39
|
-
description: Default, interactive.
|
|
40
|
-
- name: collapsed
|
|
41
|
-
attribute: collapsed
|
|
42
|
-
description: Narrow-width mode; groups open popovers instead of expanding.
|
|
43
|
-
|
|
44
|
-
traits: []
|
|
45
|
-
|
|
46
|
-
a2ui:
|
|
47
|
-
rules:
|
|
48
|
-
- app-nav-ui is the only valid parent of app-nav-group-ui.
|
|
49
|
-
- app-nav-item-ui may be a direct child of app-nav-ui OR nested inside app-nav-group-ui.
|
|
50
|
-
|
|
51
|
-
keywords: [app-nav, sidebar, navigation, nav, menu]
|
|
52
|
-
synonyms:
|
|
53
|
-
sidebar: [app-nav, nav, navigation]
|
|
54
|
-
related: [AppShell, AppNavGroup, AppNavItem]
|
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
-
"$id": "https://adiaui.dev/a2ui/v0_9/components/AppNavGroup.json",
|
|
4
|
-
"title": "AppNavGroup",
|
|
5
|
-
"description": "Collapsible group inside app-nav-ui. Has icon, label, optional badge, and\na caret indicating open/closed. When the parent app-nav-ui is collapsed,\nclicking the group opens a popover with its children instead of toggling\ninline expansion.\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
|
-
"badge": {
|
|
17
|
-
"description": "Optional badge text (e.g. unread count).",
|
|
18
|
-
"type": "string",
|
|
19
|
-
"default": ""
|
|
20
|
-
},
|
|
21
|
-
"component": {
|
|
22
|
-
"const": "AppNavGroup"
|
|
23
|
-
},
|
|
24
|
-
"icon": {
|
|
25
|
-
"description": "Phosphor icon name rendered in the group header.",
|
|
26
|
-
"type": "string",
|
|
27
|
-
"default": ""
|
|
28
|
-
},
|
|
29
|
-
"open": {
|
|
30
|
-
"description": "Expanded state. Toggled by header click; ignored when parent nav is collapsed (popover used instead).",
|
|
31
|
-
"type": "boolean",
|
|
32
|
-
"default": false
|
|
33
|
-
},
|
|
34
|
-
"text": {
|
|
35
|
-
"description": "Group label text.",
|
|
36
|
-
"type": "string",
|
|
37
|
-
"default": ""
|
|
38
|
-
}
|
|
39
|
-
},
|
|
40
|
-
"required": [
|
|
41
|
-
"component"
|
|
42
|
-
],
|
|
43
|
-
"unevaluatedProperties": false,
|
|
44
|
-
"x-adiaui": {
|
|
45
|
-
"anti_patterns": [],
|
|
46
|
-
"category": "nav",
|
|
47
|
-
"events": {},
|
|
48
|
-
"examples": [],
|
|
49
|
-
"keywords": [
|
|
50
|
-
"app-nav-group",
|
|
51
|
-
"nav",
|
|
52
|
-
"group",
|
|
53
|
-
"menu-section"
|
|
54
|
-
],
|
|
55
|
-
"name": "AdiaAppNavGroup",
|
|
56
|
-
"related": [
|
|
57
|
-
"AppNav",
|
|
58
|
-
"AppNavItem"
|
|
59
|
-
],
|
|
60
|
-
"slots": {
|
|
61
|
-
"default": {
|
|
62
|
-
"description": "app-nav-item-ui children rendered beneath the group header."
|
|
63
|
-
}
|
|
64
|
-
},
|
|
65
|
-
"states": [
|
|
66
|
-
{
|
|
67
|
-
"description": "Default, collapsed or open based on [open].",
|
|
68
|
-
"name": "idle"
|
|
69
|
-
},
|
|
70
|
-
{
|
|
71
|
-
"description": "Group is expanded; children visible.",
|
|
72
|
-
"attribute": "open",
|
|
73
|
-
"name": "open"
|
|
74
|
-
}
|
|
75
|
-
],
|
|
76
|
-
"synonyms": {},
|
|
77
|
-
"tag": "app-nav-group-ui",
|
|
78
|
-
"tokens": {},
|
|
79
|
-
"traits": [],
|
|
80
|
-
"version": 1
|
|
81
|
-
}
|
|
82
|
-
}
|
|
@@ -1,264 +0,0 @@
|
|
|
1
|
-
@scope (app-nav-group-ui) {
|
|
2
|
-
:where(:scope) {
|
|
3
|
-
--nav-group-row-height: var(--a-size);
|
|
4
|
-
--nav-group-row-height-sm: var(--a-size-sm);
|
|
5
|
-
--nav-group-row-height-lg: var(--a-size-lg);
|
|
6
|
-
--nav-group-row-px: var(--a-ui-px);
|
|
7
|
-
--nav-group-row-gap: var(--a-space-1);
|
|
8
|
-
--nav-group-row-radius: var(--a-radius-md);
|
|
9
|
-
--nav-group-font-size: var(--a-ui-size);
|
|
10
|
-
--nav-group-font-size-sm: var(--a-ui-sm);
|
|
11
|
-
--nav-group-font-size-lg: var(--a-ui-lg);
|
|
12
|
-
--nav-group-fg: var(--a-fg);
|
|
13
|
-
--nav-group-fg-hover: var(--a-fg-strong);
|
|
14
|
-
--nav-group-fg-muted: var(--a-fg-muted);
|
|
15
|
-
--nav-group-fg-selected: var(--a-fg-strong);
|
|
16
|
-
--nav-group-bg-hover: var(--a-bg-muted);
|
|
17
|
-
--nav-group-icon-size: calc(var(--nav-group-row-height) - var(--a-space-2));
|
|
18
|
-
--nav-group-badge-size: var(--a-ui-sm);
|
|
19
|
-
|
|
20
|
-
--nav-item-child-height: var(--a-size-sm);
|
|
21
|
-
--nav-item-child-font: var(--nav-group-font-size);
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
:scope {
|
|
25
|
-
box-sizing: border-box;
|
|
26
|
-
display: flex;
|
|
27
|
-
flex-direction: column;
|
|
28
|
-
gap: var(--nav-gap);
|
|
29
|
-
position: relative;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
/* Continuous indent rail */
|
|
33
|
-
:scope[open]::after {
|
|
34
|
-
content: '';
|
|
35
|
-
position: absolute;
|
|
36
|
-
left: calc(var(--nav-group-row-px) + var(--nav-group-icon-size) / 2);
|
|
37
|
-
transform: translateX(-50%);
|
|
38
|
-
top: var(--nav-group-row-height);
|
|
39
|
-
bottom: calc(var(--nav-group-row-height) / 2);
|
|
40
|
-
width: 1px;
|
|
41
|
-
background: var(--nav-group-indent-rail-bg);
|
|
42
|
-
pointer-events: none;
|
|
43
|
-
}
|
|
44
|
-
:scope[open] > [slot="header"],
|
|
45
|
-
:scope[open] > [slot="header"] [slot="icon"] {
|
|
46
|
-
color: var(--nav-group-fg-selected);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
/* Header row */
|
|
50
|
-
[slot="header"] {
|
|
51
|
-
display: flex;
|
|
52
|
-
align-items: center;
|
|
53
|
-
gap: var(--nav-group-row-gap);
|
|
54
|
-
height: var(--nav-group-row-height);
|
|
55
|
-
padding: 0 var(--nav-group-row-px);
|
|
56
|
-
border-radius: var(--nav-group-row-radius);
|
|
57
|
-
font-size: var(--nav-group-font-size);
|
|
58
|
-
color: var(--nav-group-fg);
|
|
59
|
-
cursor: pointer;
|
|
60
|
-
user-select: none;
|
|
61
|
-
white-space: nowrap;
|
|
62
|
-
transition:
|
|
63
|
-
background var(--nav-duration-fast) var(--nav-easing),
|
|
64
|
-
color var(--nav-duration-fast) var(--nav-easing);
|
|
65
|
-
outline: none;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
[slot="header"]:hover {
|
|
69
|
-
background: var(--nav-group-bg-hover);
|
|
70
|
-
color: var(--nav-group-fg-hover);
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
[slot="header"]:hover [slot="icon"] {
|
|
74
|
-
color: var(--nav-group-fg-hover);
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
[slot="header"]:focus-visible {
|
|
78
|
-
background: var(--nav-group-bg-hover);
|
|
79
|
-
color: var(--nav-group-fg-hover);
|
|
80
|
-
outline: none;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
[slot="header"] [slot="icon"] {
|
|
84
|
-
width: var(--nav-group-icon-size);
|
|
85
|
-
height: var(--nav-group-icon-size);
|
|
86
|
-
flex-shrink: 0;
|
|
87
|
-
color: var(--nav-group-fg-muted);
|
|
88
|
-
transition: color var(--nav-duration-fast) var(--nav-easing);
|
|
89
|
-
display: flex;
|
|
90
|
-
align-items: center;
|
|
91
|
-
justify-content: center;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
[slot="header"] [slot="icon"] icon-ui {
|
|
95
|
-
--a-icon-size: calc(var(--nav-group-icon-font-size) + 2px);
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
[slot="header"] [slot="text"] {
|
|
99
|
-
flex: 1;
|
|
100
|
-
min-width: 0;
|
|
101
|
-
overflow: hidden;
|
|
102
|
-
text-overflow: ellipsis;
|
|
103
|
-
font-weight: var(--nav-group-text-weight);
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
[slot="header"] [slot="badge"] {
|
|
107
|
-
font-size: var(--nav-group-badge-size);
|
|
108
|
-
color: var(--nav-group-fg-muted);
|
|
109
|
-
background: var(--nav-group-badge-bg);
|
|
110
|
-
padding: 1px var(--nav-group-badge-px);
|
|
111
|
-
border-radius: var(--nav-group-badge-radius);
|
|
112
|
-
line-height: 1.4;
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
[slot="header"] [slot="caret"] {
|
|
116
|
-
/*--a-icon-size: 0.5rem;*/
|
|
117
|
-
color: var(--nav-group-fg-muted);
|
|
118
|
-
transition:
|
|
119
|
-
transform var(--nav-duration-fast) var(--nav-easing),
|
|
120
|
-
color var(--nav-duration-fast) var(--nav-easing);
|
|
121
|
-
transform: rotate(90deg);
|
|
122
|
-
flex-shrink: 0;
|
|
123
|
-
|
|
124
|
-
--a-icon-size: var(--a-caret-size);
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
[slot="header"]:hover [slot="caret"] {
|
|
128
|
-
color: var(--nav-group-fg-hover);
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
:scope:not([open]) > [slot="header"] [slot="caret"] {
|
|
132
|
-
transform: rotate(0deg);
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
/* Children — hidden when collapsed */
|
|
136
|
-
:scope:not([open]) > app-nav-item-ui {
|
|
137
|
-
display: none;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
/* Child items default to sm for visual hierarchy */
|
|
141
|
-
:scope > app-nav-item-ui:not([size]) {
|
|
142
|
-
height: var(--nav-item-child-height);
|
|
143
|
-
font-size: var(--nav-item-child-font);
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
/* ── Collapsed nav: hide text, badge, caret ── */
|
|
147
|
-
app-nav-ui[collapsed] & [slot="text"],
|
|
148
|
-
app-nav-ui[collapsed] & [slot="badge"],
|
|
149
|
-
app-nav-ui[collapsed] & [slot="caret"] {
|
|
150
|
-
display: none;
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
app-nav-ui[collapsed] & [slot="header"] {
|
|
154
|
-
justify-content: center;
|
|
155
|
-
padding: 0;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
app-nav-ui[collapsed] & {
|
|
159
|
-
align-self: stretch;
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
app-nav-ui[collapsed] &::after {
|
|
163
|
-
display: none;
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
@container sidebar (max-width: 96px) {
|
|
167
|
-
[slot="text"], [slot="badge"], [slot="caret"] {
|
|
168
|
-
display: none !important;
|
|
169
|
-
}
|
|
170
|
-
app-nav-item-ui {
|
|
171
|
-
display: none !important;
|
|
172
|
-
}
|
|
173
|
-
[slot="header"] {
|
|
174
|
-
justify-content: center;
|
|
175
|
-
padding: 0;
|
|
176
|
-
}
|
|
177
|
-
[slot="icon"] icon-ui {
|
|
178
|
-
--a-icon-size: --a-icon-size;
|
|
179
|
-
}
|
|
180
|
-
[slot="caret"] icon-ui {
|
|
181
|
-
--a-icon-size: --a-caret-size;
|
|
182
|
-
}
|
|
183
|
-
:scope {
|
|
184
|
-
align-self: stretch;
|
|
185
|
-
}
|
|
186
|
-
:scope::after {
|
|
187
|
-
display: none;
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
/* ── Size variants ── */
|
|
192
|
-
:scope[size="sm"] {
|
|
193
|
-
--nav-group-row-height: var(--nav-group-row-height-sm);
|
|
194
|
-
--nav-group-font-size: var(--nav-group-font-size-sm);
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
:scope[size="lg"] {
|
|
198
|
-
--nav-group-row-height: var(--nav-group-row-height-lg);
|
|
199
|
-
--nav-group-font-size: var(--nav-group-font-size-lg);
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
/* Nav-group popover (outside @scope — lives in top layer)
|
|
204
|
-
Popovers are promoted to the top layer and cannot inherit
|
|
205
|
-
pattern-level custom properties, so raw --a-* tokens are
|
|
206
|
-
used intentionally here. */
|
|
207
|
-
app-nav-group-ui [slot="popover"] {
|
|
208
|
-
margin: 0;
|
|
209
|
-
padding: var(--a-space-1);
|
|
210
|
-
border: 1px solid var(--a-border-subtle);
|
|
211
|
-
border-radius: var(--a-radius);
|
|
212
|
-
background: var(--a-bg-subtle);
|
|
213
|
-
box-shadow: var(--a-shadow-lg);
|
|
214
|
-
min-width: 160px;
|
|
215
|
-
max-height: calc(100vh - 3rem);
|
|
216
|
-
overflow-y: auto;
|
|
217
|
-
font-size: var(--a-ui-size);
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
app-nav-group-ui [slot="popover-label"] {
|
|
221
|
-
padding: var(--a-space-1) var(--a-space-2);
|
|
222
|
-
font-weight: var(--a-weight-medium);
|
|
223
|
-
color: var(--a-fg-muted);
|
|
224
|
-
font-size: var(--a-ui-tiny);
|
|
225
|
-
text-transform: uppercase;
|
|
226
|
-
letter-spacing: 0.06em;
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
app-nav-group-ui [slot="popover"] [role="option"] {
|
|
230
|
-
padding: var(--a-space-1) var(--a-space-2);
|
|
231
|
-
border-radius: var(--a-radius);
|
|
232
|
-
color: var(--a-fg-subtle);
|
|
233
|
-
cursor: pointer;
|
|
234
|
-
white-space: nowrap;
|
|
235
|
-
transition:
|
|
236
|
-
background var(--a-duration-fast) var(--a-easing),
|
|
237
|
-
color var(--a-duration-fast) var(--a-easing);
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
app-nav-group-ui [slot="popover"] [role="option"]:hover {
|
|
241
|
-
background: var(--a-bg-hover);
|
|
242
|
-
color: var(--a-fg-strong);
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
/* Selected / current option — mirrors the main rail's nav-item selection:
|
|
246
|
-
muted fill + leading 2px accent bar. */
|
|
247
|
-
app-nav-group-ui [slot="popover"] [role="option"][aria-current="page"],
|
|
248
|
-
app-nav-group-ui [slot="popover"] [role="option"][aria-selected="true"] {
|
|
249
|
-
position: relative;
|
|
250
|
-
background: var(--a-bg-hover);
|
|
251
|
-
color: var(--a-fg-strong);
|
|
252
|
-
font-weight: var(--a-weight-medium);
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
app-nav-group-ui [slot="popover"] [role="option"][aria-current="page"]::before,
|
|
256
|
-
app-nav-group-ui [slot="popover"] [role="option"][aria-selected="true"]::before {
|
|
257
|
-
content: '';
|
|
258
|
-
position: absolute;
|
|
259
|
-
inset-inline-start: calc(var(--a-space-2) * -0.5);
|
|
260
|
-
inset-block: 25%;
|
|
261
|
-
width: 2px;
|
|
262
|
-
border-radius: 1px;
|
|
263
|
-
background: var(--a-accent);
|
|
264
|
-
}
|
|
@@ -1,116 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* <app-nav-group-ui> — Collapsible group of nav items inside app-nav-ui.
|
|
3
|
-
*
|
|
4
|
-
* Has icon, label, optional badge, and a caret indicating open/closed.
|
|
5
|
-
* When the parent app-nav-ui is collapsed, clicking the group opens a
|
|
6
|
-
* popover with its children instead of toggling inline expansion.
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
import { AdiaElement } from '../../core/element.js';
|
|
10
|
-
import { anchorPopover } from '../../core/anchor.js';
|
|
11
|
-
|
|
12
|
-
class AdiaAppNavGroup extends AdiaElement {
|
|
13
|
-
static properties = {
|
|
14
|
-
text: { type: String, default: '', reflect: true },
|
|
15
|
-
icon: { type: String, default: '', reflect: true },
|
|
16
|
-
badge: { type: String, default: '', reflect: true },
|
|
17
|
-
open: { type: Boolean, default: false, reflect: true },
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
static template = () => null;
|
|
21
|
-
|
|
22
|
-
#popover = null;
|
|
23
|
-
#anchorCleanup = null;
|
|
24
|
-
|
|
25
|
-
connected() {
|
|
26
|
-
this.setAttribute('role', 'group');
|
|
27
|
-
|
|
28
|
-
if (!this.querySelector(':scope > [slot="header"]')) {
|
|
29
|
-
const header = document.createElement('div');
|
|
30
|
-
header.setAttribute('slot', 'header');
|
|
31
|
-
header.setAttribute('tabindex', '0');
|
|
32
|
-
header.innerHTML = `
|
|
33
|
-
<span slot="icon">${this.icon ? `<icon-ui name="${this.icon}"></icon-ui>` : ''}</span>
|
|
34
|
-
<span slot="text">${this.text}</span>
|
|
35
|
-
${this.badge ? `<span slot="badge">${this.badge}</span>` : ''}
|
|
36
|
-
<icon-ui slot="caret" name="caret-right"></icon-ui>
|
|
37
|
-
`;
|
|
38
|
-
this.prepend(header);
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
render() {
|
|
43
|
-
const textEl = this.querySelector('[slot="header"] [slot="text"]');
|
|
44
|
-
if (textEl) textEl.textContent = this.text;
|
|
45
|
-
|
|
46
|
-
const badgeEl = this.querySelector('[slot="header"] [slot="badge"]');
|
|
47
|
-
if (badgeEl) badgeEl.textContent = this.badge;
|
|
48
|
-
|
|
49
|
-
this.setAttribute('aria-expanded', String(this.open));
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
showPopover() {
|
|
53
|
-
if (!this.#popover) {
|
|
54
|
-
this.#popover = document.createElement('div');
|
|
55
|
-
this.#popover.setAttribute('slot', 'popover');
|
|
56
|
-
this.#popover.setAttribute('popover', 'auto');
|
|
57
|
-
|
|
58
|
-
const label = document.createElement('div');
|
|
59
|
-
label.setAttribute('slot', 'popover-label');
|
|
60
|
-
label.textContent = this.text;
|
|
61
|
-
this.#popover.appendChild(label);
|
|
62
|
-
|
|
63
|
-
for (const child of this.querySelectorAll(':scope > app-nav-item-ui')) {
|
|
64
|
-
const clone = document.createElement('div');
|
|
65
|
-
clone.setAttribute('role', 'option');
|
|
66
|
-
clone.dataset.sourceValue = child.getAttribute('value') || '';
|
|
67
|
-
clone.textContent = child.text;
|
|
68
|
-
clone.addEventListener('click', () => {
|
|
69
|
-
const nav = this.closest('app-nav-ui');
|
|
70
|
-
if (nav) nav.select(child);
|
|
71
|
-
this.#popover.hidePopover();
|
|
72
|
-
});
|
|
73
|
-
this.#popover.appendChild(clone);
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
this.appendChild(this.#popover);
|
|
77
|
-
|
|
78
|
-
this.#popover.addEventListener('toggle', (e) => {
|
|
79
|
-
if (e.newState === 'closed') {
|
|
80
|
-
this.#anchorCleanup?.();
|
|
81
|
-
this.#anchorCleanup = null;
|
|
82
|
-
}
|
|
83
|
-
});
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
for (const opt of this.#popover.querySelectorAll('[role="option"]')) {
|
|
87
|
-
const srcValue = opt.dataset.sourceValue;
|
|
88
|
-
const src = srcValue
|
|
89
|
-
? this.querySelector(`:scope > app-nav-item-ui[value="${srcValue}"]`)
|
|
90
|
-
: null;
|
|
91
|
-
if (src?.hasAttribute('selected')) {
|
|
92
|
-
opt.setAttribute('aria-current', 'page');
|
|
93
|
-
opt.setAttribute('aria-selected', 'true');
|
|
94
|
-
} else {
|
|
95
|
-
opt.removeAttribute('aria-current');
|
|
96
|
-
opt.removeAttribute('aria-selected');
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
this.#popover.showPopover();
|
|
101
|
-
|
|
102
|
-
this.#anchorCleanup?.();
|
|
103
|
-
this.#anchorCleanup = anchorPopover(this, this.#popover, {
|
|
104
|
-
placement: 'right', gap: 4,
|
|
105
|
-
});
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
disconnected() {
|
|
109
|
-
this.#anchorCleanup?.();
|
|
110
|
-
this.#anchorCleanup = null;
|
|
111
|
-
this.#popover?.hidePopover?.();
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
customElements.define('app-nav-group-ui', AdiaAppNavGroup);
|
|
115
|
-
|
|
116
|
-
export { AdiaAppNavGroup };
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
$schema: ../../../../scripts/schemas/component.yaml.schema.json
|
|
2
|
-
name: AdiaAppNavGroup
|
|
3
|
-
tag: app-nav-group-ui
|
|
4
|
-
component: AppNavGroup
|
|
5
|
-
category: nav
|
|
6
|
-
version: 1
|
|
7
|
-
description: |
|
|
8
|
-
Collapsible group inside app-nav-ui. Has icon, label, optional badge, and
|
|
9
|
-
a caret indicating open/closed. When the parent app-nav-ui is collapsed,
|
|
10
|
-
clicking the group opens a popover with its children instead of toggling
|
|
11
|
-
inline expansion.
|
|
12
|
-
|
|
13
|
-
props:
|
|
14
|
-
text:
|
|
15
|
-
type: string
|
|
16
|
-
default: ""
|
|
17
|
-
reflect: true
|
|
18
|
-
description: Group label text.
|
|
19
|
-
|
|
20
|
-
icon:
|
|
21
|
-
type: string
|
|
22
|
-
default: ""
|
|
23
|
-
reflect: true
|
|
24
|
-
description: Phosphor icon name rendered in the group header.
|
|
25
|
-
|
|
26
|
-
badge:
|
|
27
|
-
type: string
|
|
28
|
-
default: ""
|
|
29
|
-
reflect: true
|
|
30
|
-
description: Optional badge text (e.g. unread count).
|
|
31
|
-
|
|
32
|
-
open:
|
|
33
|
-
type: boolean
|
|
34
|
-
default: false
|
|
35
|
-
reflect: true
|
|
36
|
-
description: Expanded state. Toggled by header click; ignored when parent nav is collapsed (popover used instead).
|
|
37
|
-
|
|
38
|
-
events: {}
|
|
39
|
-
|
|
40
|
-
slots:
|
|
41
|
-
default:
|
|
42
|
-
description: app-nav-item-ui children rendered beneath the group header.
|
|
43
|
-
|
|
44
|
-
states:
|
|
45
|
-
- name: idle
|
|
46
|
-
description: Default, collapsed or open based on [open].
|
|
47
|
-
- name: open
|
|
48
|
-
attribute: open
|
|
49
|
-
description: Group is expanded; children visible.
|
|
50
|
-
|
|
51
|
-
traits: []
|
|
52
|
-
|
|
53
|
-
a2ui:
|
|
54
|
-
rules:
|
|
55
|
-
- Must be a direct child of app-nav-ui.
|
|
56
|
-
- Children must be app-nav-item-ui, not arbitrary components.
|
|
57
|
-
|
|
58
|
-
keywords: [app-nav-group, nav, group, menu-section]
|
|
59
|
-
related: [AppNav, AppNavItem]
|