@aquera/nile-elements 2.0.9 → 2.0.11
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 +11 -0
- package/demo/app-shell.html +852 -0
- package/demo/nxtgen-classes.css +5 -5
- package/demo/nxtgen-dark.css +25 -25
- package/demo/nxtgen-properties.css +2 -2
- package/demo/nxtgen-utilities.css +5 -5
- package/demo/nxtgen.css +5 -5
- package/demo/utilities.css +2 -2
- package/demo/variables.css +2 -2
- package/dist/index.cjs.js +1 -1
- package/dist/index.esm.js +1 -1
- package/dist/index.js +594 -308
- package/dist/internal/app-shell-utility-control-styles.cjs.js +2 -0
- package/dist/internal/app-shell-utility-control-styles.cjs.js.map +1 -0
- package/dist/internal/app-shell-utility-control-styles.esm.js +16 -0
- package/dist/nile-app-shell/index.cjs.js +1 -1
- package/dist/nile-app-shell/index.esm.js +1 -1
- package/dist/nile-app-shell/nile-app-shell.cjs.js +1 -1
- package/dist/nile-app-shell/nile-app-shell.cjs.js.map +1 -1
- package/dist/nile-app-shell/nile-app-shell.css.cjs.js +1 -1
- package/dist/nile-app-shell/nile-app-shell.css.cjs.js.map +1 -1
- package/dist/nile-app-shell/nile-app-shell.css.esm.js +270 -92
- package/dist/nile-app-shell/nile-app-shell.esm.js +61 -10
- package/dist/nile-app-shell/shell-controller.cjs.js.map +1 -1
- package/dist/nile-app-shell-main/nile-app-shell-main.cjs.js.map +1 -1
- package/dist/nile-app-shell-nav-toggle/index.cjs.js +1 -1
- package/dist/nile-app-shell-nav-toggle/index.esm.js +1 -1
- package/dist/nile-app-shell-nav-toggle/nile-app-shell-nav-toggle.cjs.js +1 -1
- package/dist/nile-app-shell-nav-toggle/nile-app-shell-nav-toggle.cjs.js.map +1 -1
- package/dist/nile-app-shell-nav-toggle/nile-app-shell-nav-toggle.css.cjs.js +1 -1
- package/dist/nile-app-shell-nav-toggle/nile-app-shell-nav-toggle.css.cjs.js.map +1 -1
- package/dist/nile-app-shell-nav-toggle/nile-app-shell-nav-toggle.css.esm.js +7 -3
- package/dist/nile-app-shell-nav-toggle/nile-app-shell-nav-toggle.esm.js +3 -3
- package/dist/nile-app-shell-panel/index.cjs.js +1 -1
- package/dist/nile-app-shell-panel/index.esm.js +1 -1
- package/dist/nile-app-shell-panel/nile-app-shell-panel.cjs.js +1 -1
- package/dist/nile-app-shell-panel/nile-app-shell-panel.cjs.js.map +1 -1
- package/dist/nile-app-shell-panel/nile-app-shell-panel.css.cjs.js +1 -1
- package/dist/nile-app-shell-panel/nile-app-shell-panel.css.cjs.js.map +1 -1
- package/dist/nile-app-shell-panel/nile-app-shell-panel.css.esm.js +29 -7
- package/dist/nile-app-shell-panel/nile-app-shell-panel.esm.js +18 -5
- package/dist/nile-app-shell-side-nav/nile-app-shell-side-nav.cjs.js.map +1 -1
- package/dist/nile-app-shell-side-nav/nile-app-shell-side-nav.css.cjs.js.map +1 -1
- package/dist/nile-badge/nile-badge.css.cjs.js +1 -1
- package/dist/nile-badge/nile-badge.css.cjs.js.map +1 -1
- package/dist/nile-badge/nile-badge.css.esm.js +2 -2
- package/dist/nile-button-toggle/nile-button-toggle.css.cjs.js +1 -1
- package/dist/nile-button-toggle/nile-button-toggle.css.cjs.js.map +1 -1
- package/dist/nile-button-toggle/nile-button-toggle.css.esm.js +2 -2
- package/dist/nile-code-editor/nile-code-editor.cjs.js +1 -1
- package/dist/nile-code-editor/nile-code-editor.cjs.js.map +1 -1
- package/dist/nile-code-editor/nile-code-editor.esm.js +1 -1
- package/dist/nile-menu-item/nile-menu-item.css.cjs.js +1 -1
- package/dist/nile-menu-item/nile-menu-item.css.cjs.js.map +1 -1
- package/dist/nile-menu-item/nile-menu-item.css.esm.js +1 -1
- package/dist/nile-rich-text-editor/nile-rich-text-editor.css.cjs.js +1 -1
- package/dist/nile-rich-text-editor/nile-rich-text-editor.css.cjs.js.map +1 -1
- package/dist/nile-rich-text-editor/nile-rich-text-editor.css.esm.js +5 -2
- package/dist/nile-toast/nile-toast.css.cjs.js +1 -1
- package/dist/nile-toast/nile-toast.css.cjs.js.map +1 -1
- package/dist/nile-toast/nile-toast.css.esm.js +5 -5
- package/dist/src/internal/app-shell-utility-control-styles.d.ts +12 -0
- package/dist/src/internal/app-shell-utility-control-styles.js +29 -0
- package/dist/src/internal/app-shell-utility-control-styles.js.map +1 -0
- package/dist/src/nile-app-shell/nile-app-shell-regions.test.d.ts +3 -0
- package/dist/src/nile-app-shell/nile-app-shell-regions.test.js +206 -0
- package/dist/src/nile-app-shell/nile-app-shell-regions.test.js.map +1 -1
- package/dist/src/nile-app-shell/nile-app-shell.css.d.ts +1 -9
- package/dist/src/nile-app-shell/nile-app-shell.css.js +270 -99
- package/dist/src/nile-app-shell/nile-app-shell.css.js.map +1 -1
- package/dist/src/nile-app-shell/nile-app-shell.d.ts +90 -122
- package/dist/src/nile-app-shell/nile-app-shell.js +224 -143
- package/dist/src/nile-app-shell/nile-app-shell.js.map +1 -1
- package/dist/src/nile-app-shell/nile-app-shell.test.d.ts +3 -0
- package/dist/src/nile-app-shell/nile-app-shell.test.js +898 -29
- package/dist/src/nile-app-shell/nile-app-shell.test.js.map +1 -1
- package/dist/src/nile-app-shell/shell-controller.d.ts +1 -8
- package/dist/src/nile-app-shell/shell-controller.js +2 -14
- package/dist/src/nile-app-shell/shell-controller.js.map +1 -1
- package/dist/src/nile-app-shell-main/nile-app-shell-main.d.ts +2 -6
- package/dist/src/nile-app-shell-main/nile-app-shell-main.js +2 -6
- package/dist/src/nile-app-shell-main/nile-app-shell-main.js.map +1 -1
- package/dist/src/nile-app-shell-nav-toggle/nile-app-shell-nav-toggle.css.d.ts +1 -4
- package/dist/src/nile-app-shell-nav-toggle/nile-app-shell-nav-toggle.css.js +7 -5
- package/dist/src/nile-app-shell-nav-toggle/nile-app-shell-nav-toggle.css.js.map +1 -1
- package/dist/src/nile-app-shell-nav-toggle/nile-app-shell-nav-toggle.d.ts +4 -8
- package/dist/src/nile-app-shell-nav-toggle/nile-app-shell-nav-toggle.js +5 -6
- package/dist/src/nile-app-shell-nav-toggle/nile-app-shell-nav-toggle.js.map +1 -1
- package/dist/src/nile-app-shell-panel/nile-app-shell-panel.css.js +28 -5
- package/dist/src/nile-app-shell-panel/nile-app-shell-panel.css.js.map +1 -1
- package/dist/src/nile-app-shell-panel/nile-app-shell-panel.d.ts +18 -13
- package/dist/src/nile-app-shell-panel/nile-app-shell-panel.js +45 -16
- package/dist/src/nile-app-shell-panel/nile-app-shell-panel.js.map +1 -1
- package/dist/src/nile-app-shell-side-nav/nile-app-shell-side-nav.css.d.ts +1 -4
- package/dist/src/nile-app-shell-side-nav/nile-app-shell-side-nav.css.js +1 -4
- package/dist/src/nile-app-shell-side-nav/nile-app-shell-side-nav.css.js.map +1 -1
- package/dist/src/nile-app-shell-side-nav/nile-app-shell-side-nav.d.ts +4 -12
- package/dist/src/nile-app-shell-side-nav/nile-app-shell-side-nav.js +4 -12
- package/dist/src/nile-app-shell-side-nav/nile-app-shell-side-nav.js.map +1 -1
- package/dist/src/nile-badge/nile-badge.css.js +2 -2
- package/dist/src/nile-badge/nile-badge.css.js.map +1 -1
- package/dist/src/nile-button-toggle/nile-button-toggle.css.js +2 -2
- package/dist/src/nile-button-toggle/nile-button-toggle.css.js.map +1 -1
- package/dist/src/nile-code-editor/nile-code-editor.d.ts +1 -1
- package/dist/src/nile-code-editor/nile-code-editor.js +2 -2
- package/dist/src/nile-code-editor/nile-code-editor.js.map +1 -1
- package/dist/src/nile-menu-item/nile-menu-item.css.js +1 -1
- package/dist/src/nile-menu-item/nile-menu-item.css.js.map +1 -1
- package/dist/src/nile-rich-text-editor/nile-rich-text-editor.css.js +5 -2
- package/dist/src/nile-rich-text-editor/nile-rich-text-editor.css.js.map +1 -1
- package/dist/src/nile-toast/nile-toast.css.js +5 -5
- package/dist/src/nile-toast/nile-toast.css.js.map +1 -1
- package/dist/src/version.js +1 -1
- package/dist/src/version.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/version.cjs.js +1 -1
- package/dist/version.cjs.js.map +1 -1
- package/dist/version.esm.js +1 -1
- package/package.json +1 -1
- package/plop-templates/lit/lit.test.ts.hbs +22 -0
- package/plop-templates/lit/lit.ts.hbs +10 -5
- package/plopfile.js +12 -0
- package/src/internal/app-shell-utility-control-styles.ts +30 -0
- package/src/nile-app-shell/nile-app-shell-regions.test.ts +248 -0
- package/src/nile-app-shell/nile-app-shell.css.ts +270 -99
- package/src/nile-app-shell/nile-app-shell.test.ts +1120 -29
- package/src/nile-app-shell/nile-app-shell.ts +241 -148
- package/src/nile-app-shell/shell-controller.ts +2 -14
- package/src/nile-app-shell-main/nile-app-shell-main.ts +2 -6
- package/src/nile-app-shell-nav-toggle/nile-app-shell-nav-toggle.css.ts +7 -5
- package/src/nile-app-shell-nav-toggle/nile-app-shell-nav-toggle.ts +7 -11
- package/src/nile-app-shell-panel/nile-app-shell-panel.css.ts +28 -5
- package/src/nile-app-shell-panel/nile-app-shell-panel.ts +44 -16
- package/src/nile-app-shell-side-nav/nile-app-shell-side-nav.css.ts +1 -4
- package/src/nile-app-shell-side-nav/nile-app-shell-side-nav.ts +4 -12
- package/src/nile-badge/nile-badge.css.ts +2 -2
- package/src/nile-button-toggle/nile-button-toggle.css.ts +2 -2
- package/src/nile-code-editor/nile-code-editor.ts +2 -2
- package/src/nile-menu-item/nile-menu-item.css.ts +1 -1
- package/src/nile-rich-text-editor/nile-rich-text-editor.css.ts +5 -2
- package/src/nile-toast/nile-toast.css.ts +5 -5
- package/vscode-html-custom-data.json +114 -37
|
@@ -0,0 +1,852 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en-GB">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8" />
|
|
5
|
+
<title>App shell demo</title>
|
|
6
|
+
<link rel="stylesheet" href="" id="stylesheet" />
|
|
7
|
+
<script>
|
|
8
|
+
// nxtgen is the theme the design system ships; it is the only sheet that
|
|
9
|
+
// defines the --ng-* tokens this page's own CSS is written against.
|
|
10
|
+
// ?style=variables.css still loads the legacy --nile-* sheet.
|
|
11
|
+
const params = new URLSearchParams(window.location.search);
|
|
12
|
+
const style = params.get('style') || 'nxtgen.css';
|
|
13
|
+
document.getElementById('stylesheet').href = style;
|
|
14
|
+
</script>
|
|
15
|
+
|
|
16
|
+
<!-- <link rel="stylesheet" href="variables.css" id="stylesheet" /> -->
|
|
17
|
+
<link rel="stylesheet" href="index.css" />
|
|
18
|
+
|
|
19
|
+
<style>
|
|
20
|
+
/* index.css centres a small demo in a flex body; the shell IS the page. */
|
|
21
|
+
body {
|
|
22
|
+
display: block;
|
|
23
|
+
height: 100%;
|
|
24
|
+
margin: 0;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
html,
|
|
28
|
+
body {
|
|
29
|
+
height: 100%;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/*
|
|
33
|
+
* The view swap below drives `hidden`, and an explicit `display` in a
|
|
34
|
+
* class or inline style outranks the UA's `[hidden] { display: none }`.
|
|
35
|
+
*/
|
|
36
|
+
[hidden] {
|
|
37
|
+
display: none !important;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/*
|
|
41
|
+
* A control slotted into the panel's `actions` lives in this page's tree,
|
|
42
|
+
* not the panel's shadow tree, so the panel cannot reach its `base` part.
|
|
43
|
+
* This is the recipe that matches it to the panel's own 32px controls.
|
|
44
|
+
*/
|
|
45
|
+
nile-app-shell-panel [slot='actions']::part(base) {
|
|
46
|
+
width: 32px;
|
|
47
|
+
height: 32px;
|
|
48
|
+
padding: 0;
|
|
49
|
+
background: transparent;
|
|
50
|
+
border-color: transparent;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
nile-app-shell-panel [slot='actions']:hover::part(base) {
|
|
54
|
+
background: var(--ng-colors-bg-primary-hover);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.demo-nav {
|
|
58
|
+
display: flex;
|
|
59
|
+
flex-direction: column;
|
|
60
|
+
gap: 4px;
|
|
61
|
+
padding: 8px 12px;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.demo-nav a {
|
|
65
|
+
display: flex;
|
|
66
|
+
align-items: center;
|
|
67
|
+
gap: 10px;
|
|
68
|
+
height: 40px;
|
|
69
|
+
padding-inline: 10px;
|
|
70
|
+
border-radius: 8px;
|
|
71
|
+
color: var(--ng-colors-text-tertiary-600);
|
|
72
|
+
text-decoration: none;
|
|
73
|
+
font-size: 14px;
|
|
74
|
+
white-space: nowrap;
|
|
75
|
+
overflow: hidden;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.demo-nav a[aria-current='page'] {
|
|
79
|
+
background: var(--ng-colors-bg-primary);
|
|
80
|
+
color: var(--ng-colors-text-primary-900);
|
|
81
|
+
font-weight: 600;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/*
|
|
85
|
+
* The rail, from page CSS with no subscription: the side-nav mirrors the
|
|
86
|
+
* shell's effective rail onto its own `collapsed` attribute.
|
|
87
|
+
*/
|
|
88
|
+
nile-app-shell-side-nav[collapsed] .demo-label,
|
|
89
|
+
nile-app-shell-side-nav[collapsed] .demo-brand-name {
|
|
90
|
+
display: none;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
nile-app-shell-side-nav[collapsed] .demo-nav a {
|
|
94
|
+
justify-content: center;
|
|
95
|
+
padding-inline: 0;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
.demo-brand {
|
|
99
|
+
display: flex;
|
|
100
|
+
align-items: center;
|
|
101
|
+
gap: 10px;
|
|
102
|
+
height: 40px;
|
|
103
|
+
padding: 0 10px;
|
|
104
|
+
margin: 8px 12px 0;
|
|
105
|
+
font-weight: 600;
|
|
106
|
+
font-size: 15px;
|
|
107
|
+
white-space: nowrap;
|
|
108
|
+
overflow: hidden;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
nile-app-shell-side-nav[collapsed] .demo-brand {
|
|
112
|
+
justify-content: center;
|
|
113
|
+
padding: 0;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
.demo-thread {
|
|
117
|
+
display: flex;
|
|
118
|
+
flex-direction: column;
|
|
119
|
+
gap: 12px;
|
|
120
|
+
font-size: 14px;
|
|
121
|
+
color: var(--ng-colors-text-tertiary-600);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
.demo-chat-row {
|
|
125
|
+
display: flex;
|
|
126
|
+
flex-direction: column;
|
|
127
|
+
gap: 2px;
|
|
128
|
+
padding: 10px 12px;
|
|
129
|
+
border: 1px solid var(--ng-colors-border-secondary);
|
|
130
|
+
border-radius: 10px;
|
|
131
|
+
background: none;
|
|
132
|
+
text-align: start;
|
|
133
|
+
cursor: pointer;
|
|
134
|
+
font: inherit;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
.demo-chat-row:hover {
|
|
138
|
+
background: var(--ng-colors-bg-primary-hover);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
.demo-chat-row b {
|
|
142
|
+
font-size: 14px;
|
|
143
|
+
color: var(--ng-colors-text-primary-900);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
.demo-chat-row span {
|
|
147
|
+
font-size: 12px;
|
|
148
|
+
color: var(--ng-colors-text-tertiary-600);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
.demo-group-label {
|
|
152
|
+
font-size: 12px;
|
|
153
|
+
font-weight: 600;
|
|
154
|
+
letter-spacing: 0.04em;
|
|
155
|
+
text-transform: uppercase;
|
|
156
|
+
color: var(--ng-colors-text-tertiary-600);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/* ----------------------------------------------- header variant gallery
|
|
160
|
+
*
|
|
161
|
+
* The AC-7 comparison surface: the header's three Figma axes crossed out
|
|
162
|
+
* in full, twelve cards that differ ONLY by those axes, grouped under
|
|
163
|
+
* the height each pair of axes is meant to produce. Everything here is
|
|
164
|
+
* prefixed vg- so it cannot collide with the reference demo above.
|
|
165
|
+
*/
|
|
166
|
+
.vg {
|
|
167
|
+
box-sizing: border-box;
|
|
168
|
+
padding: 24px 24px 96px;
|
|
169
|
+
font-family: var(--ng-font-family-body);
|
|
170
|
+
color: var(--ng-colors-text-primary-900);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
.vg-intro {
|
|
174
|
+
max-width: 78ch;
|
|
175
|
+
margin: 0 0 24px;
|
|
176
|
+
font-size: 14px;
|
|
177
|
+
line-height: 20px;
|
|
178
|
+
color: var(--ng-colors-text-tertiary-600);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
.vg-intro h1 {
|
|
182
|
+
margin: 0 0 8px;
|
|
183
|
+
font-size: 20px;
|
|
184
|
+
line-height: 28px;
|
|
185
|
+
color: var(--ng-colors-text-primary-900);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
.vg-intro code {
|
|
189
|
+
font-size: 13px;
|
|
190
|
+
color: var(--ng-colors-text-primary-900);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
.vg-section {
|
|
194
|
+
margin: 0 0 32px;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
.vg-section-head {
|
|
198
|
+
display: flex;
|
|
199
|
+
align-items: baseline;
|
|
200
|
+
gap: 12px;
|
|
201
|
+
margin: 0 0 12px;
|
|
202
|
+
padding-bottom: 8px;
|
|
203
|
+
border-bottom: 1px solid var(--ng-colors-border-secondary);
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
.vg-section-head h2 {
|
|
207
|
+
margin: 0;
|
|
208
|
+
font-size: 15px;
|
|
209
|
+
line-height: 22px;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
.vg-section-head span {
|
|
213
|
+
font-size: 13px;
|
|
214
|
+
color: var(--ng-colors-text-tertiary-600);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
.vg-card {
|
|
218
|
+
margin: 0 0 16px;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
.vg-caption {
|
|
222
|
+
display: flex;
|
|
223
|
+
align-items: center;
|
|
224
|
+
flex-wrap: wrap;
|
|
225
|
+
gap: 8px;
|
|
226
|
+
margin: 0 0 6px;
|
|
227
|
+
font-size: 13px;
|
|
228
|
+
line-height: 18px;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
.vg-id {
|
|
232
|
+
font-weight: 600;
|
|
233
|
+
font-variant-numeric: tabular-nums;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
.vg-axes {
|
|
237
|
+
color: var(--ng-colors-text-tertiary-600);
|
|
238
|
+
font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
|
|
239
|
+
font-size: 12px;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/* A measurement, not decoration: green only when the card's own header
|
|
243
|
+
block measures the height its axes are specified to produce. */
|
|
244
|
+
.vg-chip {
|
|
245
|
+
display: inline-flex;
|
|
246
|
+
align-items: center;
|
|
247
|
+
gap: 6px;
|
|
248
|
+
padding: 1px 8px;
|
|
249
|
+
border: 1px solid var(--ng-colors-border-secondary);
|
|
250
|
+
border-radius: 999px;
|
|
251
|
+
font-size: 12px;
|
|
252
|
+
font-variant-numeric: tabular-nums;
|
|
253
|
+
white-space: nowrap;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
.vg-chip[data-state='ok'] {
|
|
257
|
+
border-color: #75b389;
|
|
258
|
+
background: #eef7f1;
|
|
259
|
+
color: #1f5c38;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
.vg-chip[data-state='off'] {
|
|
263
|
+
border-color: #d08a8a;
|
|
264
|
+
background: #fbeeee;
|
|
265
|
+
color: #7d2020;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
.vg-chip[data-state='note'] {
|
|
269
|
+
border-color: #d8b268;
|
|
270
|
+
background: #fdf6e7;
|
|
271
|
+
color: #6b4c12;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/* The card frame gives each shell the height it needs to lay out: the
|
|
275
|
+
shell sizes to its parent unless it is full-height. */
|
|
276
|
+
.vg-frame {
|
|
277
|
+
height: 220px;
|
|
278
|
+
border: 1px solid var(--ng-colors-border-secondary);
|
|
279
|
+
border-radius: 12px;
|
|
280
|
+
overflow: hidden;
|
|
281
|
+
background: var(--ng-colors-bg-primary);
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
.vg-nav {
|
|
285
|
+
display: flex;
|
|
286
|
+
flex-direction: column;
|
|
287
|
+
gap: 4px;
|
|
288
|
+
padding: 12px;
|
|
289
|
+
font-size: 14px;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
.vg-nav span {
|
|
293
|
+
display: flex;
|
|
294
|
+
align-items: center;
|
|
295
|
+
height: 36px;
|
|
296
|
+
padding-inline: 10px;
|
|
297
|
+
border-radius: 8px;
|
|
298
|
+
color: var(--ng-colors-text-tertiary-600);
|
|
299
|
+
white-space: nowrap;
|
|
300
|
+
overflow: hidden;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
.vg-nav span:first-child {
|
|
304
|
+
background: var(--ng-colors-bg-primary);
|
|
305
|
+
color: var(--ng-colors-text-primary-900);
|
|
306
|
+
font-weight: 600;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
.vg-body {
|
|
310
|
+
font-size: 13px;
|
|
311
|
+
line-height: 18px;
|
|
312
|
+
color: var(--ng-colors-text-tertiary-600);
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
/* Bottom-right so it never sits over a header being compared. */
|
|
316
|
+
.vg-switch {
|
|
317
|
+
position: fixed;
|
|
318
|
+
right: 16px;
|
|
319
|
+
bottom: 16px;
|
|
320
|
+
z-index: 10;
|
|
321
|
+
padding: 8px 14px;
|
|
322
|
+
border: 1px solid var(--ng-colors-border-secondary);
|
|
323
|
+
border-radius: 999px;
|
|
324
|
+
background: var(--ng-colors-bg-primary);
|
|
325
|
+
box-shadow: 0 2px 8px rgb(0 0 0 / 12%);
|
|
326
|
+
font: inherit;
|
|
327
|
+
font-size: 13px;
|
|
328
|
+
cursor: pointer;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
.vg-switch:hover {
|
|
332
|
+
background: var(--ng-colors-bg-primary-hover);
|
|
333
|
+
}
|
|
334
|
+
</style>
|
|
335
|
+
<script type="module" src="index.js"></script>
|
|
336
|
+
<!-- nile-elements renders nile-glyph but does not register it. -->
|
|
337
|
+
<script type="module">
|
|
338
|
+
import '@aquera/nile-glyph';
|
|
339
|
+
</script>
|
|
340
|
+
</head>
|
|
341
|
+
<body>
|
|
342
|
+
<!--
|
|
343
|
+
Two views, switched by ?view= and the pill bottom-right:
|
|
344
|
+
(default) the reference shell, one realistic page
|
|
345
|
+
?view=variants the AC-7 comparison surface, all 12 header variants
|
|
346
|
+
-->
|
|
347
|
+
<div id="vgShellView" style="height: 100%">
|
|
348
|
+
<nile-app-shell id="shell" full-height persist-key="demo-shell">
|
|
349
|
+
<nile-app-shell-side-nav>
|
|
350
|
+
<div slot="header" class="demo-brand">
|
|
351
|
+
<nile-glyph
|
|
352
|
+
name="ng-layers-2"
|
|
353
|
+
size="20"
|
|
354
|
+
method="stroke"
|
|
355
|
+
color="currentColor"
|
|
356
|
+
></nile-glyph>
|
|
357
|
+
<span class="demo-brand-name">Aquera</span>
|
|
358
|
+
</div>
|
|
359
|
+
<nav class="demo-nav">
|
|
360
|
+
<a href="#" aria-current="page">
|
|
361
|
+
<nile-glyph
|
|
362
|
+
name="ng-home-line"
|
|
363
|
+
size="20"
|
|
364
|
+
method="stroke"
|
|
365
|
+
color="currentColor"
|
|
366
|
+
></nile-glyph>
|
|
367
|
+
<span class="demo-label">Workforce overview</span>
|
|
368
|
+
</a>
|
|
369
|
+
<a href="#">
|
|
370
|
+
<nile-glyph
|
|
371
|
+
name="ng-plug"
|
|
372
|
+
size="20"
|
|
373
|
+
method="stroke"
|
|
374
|
+
color="currentColor"
|
|
375
|
+
></nile-glyph>
|
|
376
|
+
<span class="demo-label">Integrations</span>
|
|
377
|
+
</a>
|
|
378
|
+
<a href="#">
|
|
379
|
+
<nile-glyph
|
|
380
|
+
name="ng-inbox"
|
|
381
|
+
size="20"
|
|
382
|
+
method="stroke"
|
|
383
|
+
color="currentColor"
|
|
384
|
+
></nile-glyph>
|
|
385
|
+
<span class="demo-label">Requests</span>
|
|
386
|
+
</a>
|
|
387
|
+
<a href="#">
|
|
388
|
+
<nile-glyph
|
|
389
|
+
name="ng-settings-01"
|
|
390
|
+
size="20"
|
|
391
|
+
method="stroke"
|
|
392
|
+
color="currentColor"
|
|
393
|
+
></nile-glyph>
|
|
394
|
+
<span class="demo-label">Settings</span>
|
|
395
|
+
</a>
|
|
396
|
+
</nav>
|
|
397
|
+
</nile-app-shell-side-nav>
|
|
398
|
+
|
|
399
|
+
<h1 slot="top-bar" style="margin: 0; font-size: 16px">
|
|
400
|
+
Workforce overview
|
|
401
|
+
</h1>
|
|
402
|
+
|
|
403
|
+
<nile-button
|
|
404
|
+
slot="top-bar-actions"
|
|
405
|
+
variant="tertiary"
|
|
406
|
+
id="tabs-toggle"
|
|
407
|
+
>
|
|
408
|
+
Hide tabs
|
|
409
|
+
</nile-button>
|
|
410
|
+
|
|
411
|
+
<!--
|
|
412
|
+
The module's second level: a nile-nav-tab-group in the shell's `tabs`
|
|
413
|
+
slot, hoisted out of the page scroller so it never scrolls away. Toggle
|
|
414
|
+
the shell's `noTabs` to switch the whole strip off.
|
|
415
|
+
-->
|
|
416
|
+
<nile-nav-tab-group slot="tabs" id="views">
|
|
417
|
+
<nile-nav-tab slot="nav" panel="apps" active>
|
|
418
|
+
Connected applications
|
|
419
|
+
<nile-badge slot="suffix" variant="gray">94</nile-badge>
|
|
420
|
+
</nile-nav-tab>
|
|
421
|
+
<nile-nav-tab slot="nav" panel="approvals">
|
|
422
|
+
Approvals
|
|
423
|
+
<nile-badge slot="suffix" variant="gray">3</nile-badge>
|
|
424
|
+
</nile-nav-tab>
|
|
425
|
+
</nile-nav-tab-group>
|
|
426
|
+
|
|
427
|
+
<nile-app-shell-main>
|
|
428
|
+
<div id="panel-apps">
|
|
429
|
+
<p style="color: var(--ng-colors-text-tertiary-600)">
|
|
430
|
+
Page body for <b>Connected applications</b>. Press the Ask button in
|
|
431
|
+
the top bar, then the clock in the panel header to open chat
|
|
432
|
+
history — the back control takes the brand mark's place, and
|
|
433
|
+
pressing it emits <code>nile-back</code>.
|
|
434
|
+
</p>
|
|
435
|
+
</div>
|
|
436
|
+
<div id="panel-approvals" hidden>
|
|
437
|
+
<p style="color: var(--ng-colors-text-tertiary-600)">
|
|
438
|
+
Page body for <b>Approvals</b>. The tab strip lives in the shell's
|
|
439
|
+
<code>tabs</code> slot, so switching views never moves the chrome.
|
|
440
|
+
</p>
|
|
441
|
+
</div>
|
|
442
|
+
</nile-app-shell-main>
|
|
443
|
+
|
|
444
|
+
<nile-app-shell-panel id="ask" label="Ask Aquera">
|
|
445
|
+
<div id="thread" class="demo-thread">
|
|
446
|
+
<p>How many contractors roll off this quarter?</p>
|
|
447
|
+
</div>
|
|
448
|
+
|
|
449
|
+
<div id="historyView" hidden style="display: contents">
|
|
450
|
+
<span class="demo-group-label">Today</span>
|
|
451
|
+
<button class="demo-chat-row" type="button">
|
|
452
|
+
<b>Contractor roll-off, Q3</b>
|
|
453
|
+
<span>4 messages</span>
|
|
454
|
+
</button>
|
|
455
|
+
<button class="demo-chat-row" type="button">
|
|
456
|
+
<b>Okta group drift</b>
|
|
457
|
+
<span>11 messages</span>
|
|
458
|
+
</button>
|
|
459
|
+
<span class="demo-group-label">Yesterday</span>
|
|
460
|
+
<button class="demo-chat-row" type="button">
|
|
461
|
+
<b>Right-size Zoom licences</b>
|
|
462
|
+
<span>6 messages</span>
|
|
463
|
+
</button>
|
|
464
|
+
</div>
|
|
465
|
+
|
|
466
|
+
<nile-button
|
|
467
|
+
slot="actions"
|
|
468
|
+
variant="ghost"
|
|
469
|
+
circle
|
|
470
|
+
id="history-toggle"
|
|
471
|
+
title="Chat history"
|
|
472
|
+
aria-label="Chat history"
|
|
473
|
+
>
|
|
474
|
+
<nile-glyph
|
|
475
|
+
name="ng-clock-refresh"
|
|
476
|
+
size="20"
|
|
477
|
+
method="stroke"
|
|
478
|
+
color="currentColor"
|
|
479
|
+
></nile-glyph>
|
|
480
|
+
</nile-button>
|
|
481
|
+
|
|
482
|
+
<div slot="footer">
|
|
483
|
+
<nile-input placeholder="Ask about this page…"></nile-input>
|
|
484
|
+
</div>
|
|
485
|
+
</nile-app-shell-panel>
|
|
486
|
+
</nile-app-shell>
|
|
487
|
+
</div>
|
|
488
|
+
|
|
489
|
+
<!--
|
|
490
|
+
The header variant gallery. The cards are generated from the axis matrix
|
|
491
|
+
rather than written out twelve times, so the only thing that can differ
|
|
492
|
+
between them is the axes themselves — which is the whole point of a
|
|
493
|
+
parity comparison.
|
|
494
|
+
-->
|
|
495
|
+
<div id="vgVariantsView" class="vg" hidden>
|
|
496
|
+
<div class="vg-intro">
|
|
497
|
+
<h1>App Shell header — 12 variants</h1>
|
|
498
|
+
<p>
|
|
499
|
+
The three Figma axes crossed out in full:
|
|
500
|
+
<code>Tabs</code> × <code>Description</code> ×
|
|
501
|
+
<code>Leading</code>. Cards are grouped by the height their axes are
|
|
502
|
+
specified to produce, so each section heading is one of the four
|
|
503
|
+
heights in SPEC-app-shell-header D-2. The chip on each card is its
|
|
504
|
+
<em>measured</em> header block — bar top to strip bottom — so a
|
|
505
|
+
variant that does not land on its number says so here rather than in
|
|
506
|
+
devtools.
|
|
507
|
+
</p>
|
|
508
|
+
<p>
|
|
509
|
+
<code>pageTitle</code> and <code>badge</code> are on every card:
|
|
510
|
+
neither is one of the three axes, so holding them constant is what
|
|
511
|
+
makes the axes comparable. Tabbed cards carry a second chip for the
|
|
512
|
+
inner tab row (32px) and the strip that holds it (33px) — two
|
|
513
|
+
separate numbers, both confirmed against the Figma nodes. See AC-6.
|
|
514
|
+
</p>
|
|
515
|
+
<p>
|
|
516
|
+
Heights below 600px of viewport height are compressed by design
|
|
517
|
+
(<code>@media (max-height: 600px)</code> in
|
|
518
|
+
<code>nile-app-shell.css.ts</code>), so compare in a window taller
|
|
519
|
+
than that. The chips say when the window is too short.
|
|
520
|
+
</p>
|
|
521
|
+
<button class="vg-switch" type="button" id="vgRemeasure" style="right: 200px">
|
|
522
|
+
Re-measure
|
|
523
|
+
</button>
|
|
524
|
+
</div>
|
|
525
|
+
<div id="vgGrid"></div>
|
|
526
|
+
</div>
|
|
527
|
+
|
|
528
|
+
<button class="vg-switch" type="button" id="vgSwitch"></button>
|
|
529
|
+
|
|
530
|
+
<script type="module">
|
|
531
|
+
/*
|
|
532
|
+
* The panel owns the chrome, the page owns the view stack: `back` draws
|
|
533
|
+
* the control, `nile-back` says it was pressed, and this decides what
|
|
534
|
+
* going back means.
|
|
535
|
+
*/
|
|
536
|
+
const shell = document.getElementById('shell');
|
|
537
|
+
const ask = document.getElementById('ask');
|
|
538
|
+
const thread = document.getElementById('thread');
|
|
539
|
+
const historyView = document.getElementById('historyView');
|
|
540
|
+
const views = document.getElementById('views');
|
|
541
|
+
|
|
542
|
+
document.getElementById('history-toggle').addEventListener('click', () => {
|
|
543
|
+
ask.label = 'Chat history';
|
|
544
|
+
ask.back = true;
|
|
545
|
+
thread.hidden = true;
|
|
546
|
+
historyView.hidden = false;
|
|
547
|
+
});
|
|
548
|
+
|
|
549
|
+
ask.addEventListener('nile-back', () => {
|
|
550
|
+
ask.label = 'Ask Aquera';
|
|
551
|
+
ask.back = false;
|
|
552
|
+
historyView.hidden = true;
|
|
553
|
+
thread.hidden = false;
|
|
554
|
+
});
|
|
555
|
+
|
|
556
|
+
/*
|
|
557
|
+
* The strip is the module's second level; the page owns which view it
|
|
558
|
+
* shows. `detail.value` is the tab's `panel`.
|
|
559
|
+
*/
|
|
560
|
+
views.addEventListener('nile-tab-change', event => {
|
|
561
|
+
const active = event.detail.value;
|
|
562
|
+
document.getElementById('panel-apps').hidden = active !== 'apps';
|
|
563
|
+
document.getElementById('panel-approvals').hidden = active !== 'approvals';
|
|
564
|
+
});
|
|
565
|
+
|
|
566
|
+
// `noTabs` hides the strip without emptying the slot.
|
|
567
|
+
const tabsToggle = document.getElementById('tabs-toggle');
|
|
568
|
+
tabsToggle.addEventListener('click', () => {
|
|
569
|
+
shell.noTabs = !shell.noTabs;
|
|
570
|
+
tabsToggle.textContent = shell.noTabs ? 'Show tabs' : 'Hide tabs';
|
|
571
|
+
});
|
|
572
|
+
|
|
573
|
+
// Opening a thread replaces the transcript and returns to the chat view.
|
|
574
|
+
historyView.addEventListener('click', event => {
|
|
575
|
+
const row = event.target.closest('.demo-chat-row');
|
|
576
|
+
if (!row) return;
|
|
577
|
+
ask.label = row.querySelector('b').textContent;
|
|
578
|
+
ask.back = false;
|
|
579
|
+
historyView.hidden = true;
|
|
580
|
+
thread.hidden = false;
|
|
581
|
+
});
|
|
582
|
+
</script>
|
|
583
|
+
|
|
584
|
+
<!--
|
|
585
|
+
The header variant gallery: view switching, card generation and the
|
|
586
|
+
measurement readout. SPEC-app-shell-header AC-5 / AC-6 / AC-7.
|
|
587
|
+
-->
|
|
588
|
+
<script type="module">
|
|
589
|
+
const params = new URLSearchParams(window.location.search);
|
|
590
|
+
const showVariants = params.get('view') === 'variants';
|
|
591
|
+
|
|
592
|
+
const vgShellView = document.getElementById('vgShellView');
|
|
593
|
+
const vgVariantsView = document.getElementById('vgVariantsView');
|
|
594
|
+
const vgSwitch = document.getElementById('vgSwitch');
|
|
595
|
+
const vgGrid = document.getElementById('vgGrid');
|
|
596
|
+
const vgRemeasure = document.getElementById('vgRemeasure');
|
|
597
|
+
|
|
598
|
+
vgShellView.hidden = showVariants;
|
|
599
|
+
vgVariantsView.hidden = !showVariants;
|
|
600
|
+
vgSwitch.textContent = showVariants
|
|
601
|
+
? 'Reference shell demo'
|
|
602
|
+
: 'Header variants (12)';
|
|
603
|
+
vgSwitch.addEventListener('click', () => {
|
|
604
|
+
// Keeps ?style= so a variant sweep can be repeated on either theme.
|
|
605
|
+
params.set('view', showVariants ? 'shell' : 'variants');
|
|
606
|
+
window.location.search = params.toString();
|
|
607
|
+
});
|
|
608
|
+
|
|
609
|
+
/*
|
|
610
|
+
* The axis matrix, in the order the four heights come in. Tabs and
|
|
611
|
+
* Description each buy height; Leading buys none — which is the claim
|
|
612
|
+
* the three cards inside each section are there to show.
|
|
613
|
+
*/
|
|
614
|
+
const SECTIONS = [
|
|
615
|
+
{ tabs: false, description: false, height: 68 },
|
|
616
|
+
{ tabs: false, description: true, height: 76 },
|
|
617
|
+
{ tabs: true, description: false, height: 101 },
|
|
618
|
+
{ tabs: true, description: true, height: 109 },
|
|
619
|
+
];
|
|
620
|
+
|
|
621
|
+
const LEADINGS = [
|
|
622
|
+
{ value: 'none', label: 'Leading=None' },
|
|
623
|
+
{ value: 'back', label: 'Leading=Back' },
|
|
624
|
+
{ value: 'app-icon', label: 'Leading=AppIcon' },
|
|
625
|
+
];
|
|
626
|
+
|
|
627
|
+
const DESCRIPTION = 'Manage the applications connected to this tenant';
|
|
628
|
+
|
|
629
|
+
/*
|
|
630
|
+
* Both numbers are confirmed against the Figma nodes (2026-09-22). The
|
|
631
|
+
* strip is 33px — the variant frames are 101px with tabs and 68px
|
|
632
|
+
* without. The row inside it is 32px, composed by the tab node's own
|
|
633
|
+
* 0 / 4 / 12 / 4 padding around a 20px label line box: 0 + 20 + 12.
|
|
634
|
+
*/
|
|
635
|
+
const STRIP_HEIGHT = 33;
|
|
636
|
+
const ROW_HEIGHT = 32;
|
|
637
|
+
|
|
638
|
+
const card = (n, section, leading) => {
|
|
639
|
+
const axes = `tabs=${section.tabs ? 'on' : 'off'} · description=${
|
|
640
|
+
section.description ? 'on' : 'off'
|
|
641
|
+
} · leading=${leading.value}`;
|
|
642
|
+
|
|
643
|
+
return `
|
|
644
|
+
<div class="vg-card">
|
|
645
|
+
<p class="vg-caption">
|
|
646
|
+
<span class="vg-id">${String(n).padStart(2, '0')}</span>
|
|
647
|
+
<span>${leading.label}</span>
|
|
648
|
+
<span class="vg-axes">${axes}</span>
|
|
649
|
+
<span class="vg-chip" data-role="block">measuring…</span>
|
|
650
|
+
${
|
|
651
|
+
section.tabs
|
|
652
|
+
? '<span class="vg-chip" data-role="row">measuring…</span>'
|
|
653
|
+
: ''
|
|
654
|
+
}
|
|
655
|
+
${
|
|
656
|
+
leading.value === 'none'
|
|
657
|
+
? ''
|
|
658
|
+
: '<span class="vg-chip" data-role="lead">measuring…</span>'
|
|
659
|
+
}
|
|
660
|
+
</p>
|
|
661
|
+
<div class="vg-frame">
|
|
662
|
+
<nile-app-shell
|
|
663
|
+
pageTitle="Connected applications"
|
|
664
|
+
badge="94 apps"
|
|
665
|
+
leading="${leading.value}"
|
|
666
|
+
${section.description ? `description="${DESCRIPTION}"` : ''}
|
|
667
|
+
${leading.value === 'back' ? 'backLabel="Integrations"' : ''}
|
|
668
|
+
no-panel-shortcut
|
|
669
|
+
>
|
|
670
|
+
<nav slot="side-nav" class="vg-nav">
|
|
671
|
+
<span>Integrations</span>
|
|
672
|
+
<span>Requests</span>
|
|
673
|
+
</nav>
|
|
674
|
+
${
|
|
675
|
+
leading.value === 'app-icon'
|
|
676
|
+
? `<nile-glyph
|
|
677
|
+
slot="app-icon"
|
|
678
|
+
name="ng-layers-2"
|
|
679
|
+
size="20"
|
|
680
|
+
method="stroke"
|
|
681
|
+
color="currentColor"
|
|
682
|
+
></nile-glyph>`
|
|
683
|
+
: ''
|
|
684
|
+
}
|
|
685
|
+
${
|
|
686
|
+
section.tabs
|
|
687
|
+
? `<nile-nav-tab-group slot="tabs">
|
|
688
|
+
<nile-nav-tab slot="nav" panel="apps" active>
|
|
689
|
+
Connected applications
|
|
690
|
+
</nile-nav-tab>
|
|
691
|
+
<nile-nav-tab slot="nav" panel="approvals">
|
|
692
|
+
Approvals
|
|
693
|
+
</nile-nav-tab>
|
|
694
|
+
</nile-nav-tab-group>`
|
|
695
|
+
: ''
|
|
696
|
+
}
|
|
697
|
+
<nile-button slot="top-bar-actions" variant="tertiary">
|
|
698
|
+
Add application
|
|
699
|
+
</nile-button>
|
|
700
|
+
<div class="vg-body">
|
|
701
|
+
Page body. The header above is the whole subject of this
|
|
702
|
+
card; the axes are named in the caption.
|
|
703
|
+
</div>
|
|
704
|
+
<div slot="panel">
|
|
705
|
+
Assistant panel, slotted so the header draws its Ask control.
|
|
706
|
+
</div>
|
|
707
|
+
</nile-app-shell>
|
|
708
|
+
</div>
|
|
709
|
+
</div>`;
|
|
710
|
+
};
|
|
711
|
+
|
|
712
|
+
/** Every card, with the height its axes are specified to produce. */
|
|
713
|
+
const cards = [];
|
|
714
|
+
|
|
715
|
+
const build = () => {
|
|
716
|
+
let n = 0;
|
|
717
|
+
vgGrid.innerHTML = SECTIONS.map(section => {
|
|
718
|
+
const body = LEADINGS.map(leading => card(++n, section, leading)).join(
|
|
719
|
+
''
|
|
720
|
+
);
|
|
721
|
+
return `
|
|
722
|
+
<section class="vg-section">
|
|
723
|
+
<div class="vg-section-head">
|
|
724
|
+
<h2>
|
|
725
|
+
Tabs ${section.tabs ? 'On' : 'Off'} · Description
|
|
726
|
+
${section.description ? 'On' : 'Off'}
|
|
727
|
+
</h2>
|
|
728
|
+
<span>specified header block: ${section.height}px</span>
|
|
729
|
+
</div>
|
|
730
|
+
${body}
|
|
731
|
+
</section>`;
|
|
732
|
+
}).join('');
|
|
733
|
+
|
|
734
|
+
vgGrid.querySelectorAll('.vg-card').forEach((el, i) => {
|
|
735
|
+
const section = SECTIONS[Math.floor(i / LEADINGS.length)];
|
|
736
|
+
cards.push({
|
|
737
|
+
shell: el.querySelector('nile-app-shell'),
|
|
738
|
+
expected: section.height,
|
|
739
|
+
tabs: section.tabs,
|
|
740
|
+
blockChip: el.querySelector('[data-role="block"]'),
|
|
741
|
+
rowChip: el.querySelector('[data-role="row"]'),
|
|
742
|
+
leadChip: el.querySelector('[data-role="lead"]'),
|
|
743
|
+
});
|
|
744
|
+
});
|
|
745
|
+
};
|
|
746
|
+
|
|
747
|
+
const px = value => `${Math.round(value * 10) / 10}px`;
|
|
748
|
+
|
|
749
|
+
const measure = () => {
|
|
750
|
+
// The bar compresses under 600px of viewport height, by design.
|
|
751
|
+
const short = window.innerHeight <= 600;
|
|
752
|
+
|
|
753
|
+
cards.forEach(entry => {
|
|
754
|
+
const root = entry.shell.shadowRoot;
|
|
755
|
+
if (!root) return;
|
|
756
|
+
|
|
757
|
+
const bar = root.querySelector('.container > .top-bar');
|
|
758
|
+
const strip = root.querySelector('.tabs');
|
|
759
|
+
const barBox = bar.getBoundingClientRect();
|
|
760
|
+
const block = entry.shell.tabsVisible
|
|
761
|
+
? strip.getBoundingClientRect().bottom - barBox.top
|
|
762
|
+
: barBox.height;
|
|
763
|
+
|
|
764
|
+
if (short) {
|
|
765
|
+
entry.blockChip.dataset.state = 'note';
|
|
766
|
+
entry.blockChip.textContent = `${px(
|
|
767
|
+
block
|
|
768
|
+
)} — window under 600px tall, heights compress by design`;
|
|
769
|
+
} else {
|
|
770
|
+
const ok = Math.abs(block - entry.expected) < 0.5;
|
|
771
|
+
entry.blockChip.dataset.state = ok ? 'ok' : 'off';
|
|
772
|
+
entry.blockChip.textContent = ok
|
|
773
|
+
? `header block ${px(block)}`
|
|
774
|
+
: `header block ${px(block)} — expected ${entry.expected}px`;
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
/*
|
|
778
|
+
* The leading element belongs to the title's row, so it sits 2px
|
|
779
|
+
* below the title's top edge — (24px line box - 20px control) / 2 —
|
|
780
|
+
* whether or not there is a description under it. The app icon is
|
|
781
|
+
* 20px, its own size rather than the 32px utility control box.
|
|
782
|
+
*/
|
|
783
|
+
if (entry.leadChip) {
|
|
784
|
+
const title = root
|
|
785
|
+
.querySelector('[part~="page-title"]')
|
|
786
|
+
.getBoundingClientRect();
|
|
787
|
+
const icon = root.querySelector('[part~="app-icon"]');
|
|
788
|
+
/*
|
|
789
|
+
* For leading=back the 20px element is the ARROW, not the control:
|
|
790
|
+
* the control is the title's own 24px line box, so its label sits
|
|
791
|
+
* level with the page title (+0) while the arrow centres in it
|
|
792
|
+
* (+2). Measuring the control box would report +0 and look wrong.
|
|
793
|
+
*/
|
|
794
|
+
const measured = icon
|
|
795
|
+
? icon
|
|
796
|
+
: root.querySelector('[part~="back"]').querySelector('nile-glyph');
|
|
797
|
+
const box = measured.getBoundingClientRect();
|
|
798
|
+
const offset = Math.round(box.top - title.top);
|
|
799
|
+
const sized = Math.round(box.width);
|
|
800
|
+
const ok = offset === 2 && sized === 20;
|
|
801
|
+
|
|
802
|
+
entry.leadChip.dataset.state = ok ? 'ok' : 'off';
|
|
803
|
+
entry.leadChip.textContent =
|
|
804
|
+
`${icon ? 'app icon' : 'back arrow'} ${sized}×${Math.round(
|
|
805
|
+
box.height
|
|
806
|
+
)}` +
|
|
807
|
+
` · ${offset >= 0 ? '+' : ''}${offset}px from title top` +
|
|
808
|
+
(ok ? '' : ' — expected 20px at +2px');
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
if (!entry.tabs || !entry.rowChip) return;
|
|
812
|
+
|
|
813
|
+
/*
|
|
814
|
+
* Two different numbers, and AC-6 asks for both. The strip is a
|
|
815
|
+
* min-height floor, so it reads 33px whenever the row fits inside
|
|
816
|
+
* it — which is exactly why the row is measured and reported
|
|
817
|
+
* separately rather than inferred from the strip.
|
|
818
|
+
*/
|
|
819
|
+
const stripBox = strip.getBoundingClientRect();
|
|
820
|
+
const group = entry.shell.querySelector('nile-nav-tab-group');
|
|
821
|
+
const rowBox = group.getBoundingClientRect();
|
|
822
|
+
const slack = rowBox.top - stripBox.top;
|
|
823
|
+
const stripOk = Math.abs(stripBox.height - STRIP_HEIGHT) < 0.5;
|
|
824
|
+
const rowOk = Math.abs(rowBox.height - ROW_HEIGHT) < 0.5;
|
|
825
|
+
|
|
826
|
+
entry.rowChip.dataset.state = stripOk && rowOk ? 'ok' : 'off';
|
|
827
|
+
entry.rowChip.textContent =
|
|
828
|
+
`strip ${px(stripBox.height)} · row ${px(rowBox.height)}` +
|
|
829
|
+
(rowOk ? '' : ` — expected ${ROW_HEIGHT}px`) +
|
|
830
|
+
` · slack above ${px(slack)}`;
|
|
831
|
+
});
|
|
832
|
+
};
|
|
833
|
+
|
|
834
|
+
if (showVariants) {
|
|
835
|
+
build();
|
|
836
|
+
// The shells have to be upgraded and laid out before a box means
|
|
837
|
+
// anything, and the nav track animates up from 0 on first paint.
|
|
838
|
+
await customElements.whenDefined('nile-app-shell');
|
|
839
|
+
await Promise.all(cards.map(entry => entry.shell.updateComplete));
|
|
840
|
+
requestAnimationFrame(() => requestAnimationFrame(measure));
|
|
841
|
+
|
|
842
|
+
vgRemeasure.addEventListener('click', measure);
|
|
843
|
+
|
|
844
|
+
let pending;
|
|
845
|
+
window.addEventListener('resize', () => {
|
|
846
|
+
window.clearTimeout(pending);
|
|
847
|
+
pending = window.setTimeout(measure, 150);
|
|
848
|
+
});
|
|
849
|
+
}
|
|
850
|
+
</script>
|
|
851
|
+
</body>
|
|
852
|
+
</html>
|