@nonoun/native-app 0.2.0 → 0.2.2
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/dist/{nui-app-panel/nui-app-panel-element.d.ts → app-panel/app-panel-element.d.ts} +3 -3
- package/dist/app-panel/app-panel-element.d.ts.map +1 -0
- package/dist/custom-elements.json +75 -75
- package/dist/index.d.ts +8 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/{nui-app.css → native-app.css} +168 -133
- package/dist/{nui-app.js → native-app.js} +32 -32
- package/dist/{nui-sidebar/nui-sidebar-element.d.ts → sidebar/sidebar-element.d.ts} +3 -3
- package/dist/sidebar/sidebar-element.d.ts.map +1 -0
- package/dist/{nui-sidebar/nui-sidebar-group-element.d.ts → sidebar/sidebar-group-element.d.ts} +4 -4
- package/dist/sidebar/sidebar-group-element.d.ts.map +1 -0
- package/dist/sidebar/sidebar-group-header-element.d.ts +7 -0
- package/dist/sidebar/sidebar-group-header-element.d.ts.map +1 -0
- package/dist/sidebar/sidebar-item-element.d.ts +10 -0
- package/dist/sidebar/sidebar-item-element.d.ts.map +1 -0
- package/dist/{nui-sidebar/nui-sidebar-nav-element.d.ts → sidebar/sidebar-nav-element.d.ts} +4 -4
- package/dist/sidebar/sidebar-nav-element.d.ts.map +1 -0
- package/dist/{nui-sidebar/nui-sidebar-nav-item-element.d.ts → sidebar/sidebar-nav-item-element.d.ts} +4 -4
- package/dist/sidebar/sidebar-nav-item-element.d.ts.map +1 -0
- package/package.json +1 -1
- package/dist/nui-app-panel/nui-app-panel-element.d.ts.map +0 -1
- package/dist/nui-sidebar/nui-sidebar-element.d.ts.map +0 -1
- package/dist/nui-sidebar/nui-sidebar-group-element.d.ts.map +0 -1
- package/dist/nui-sidebar/nui-sidebar-group-header-element.d.ts +0 -7
- package/dist/nui-sidebar/nui-sidebar-group-header-element.d.ts.map +0 -1
- package/dist/nui-sidebar/nui-sidebar-item-element.d.ts +0 -10
- package/dist/nui-sidebar/nui-sidebar-item-element.d.ts.map +0 -1
- package/dist/nui-sidebar/nui-sidebar-nav-element.d.ts.map +0 -1
- package/dist/nui-sidebar/nui-sidebar-nav-item-element.d.ts.map +0 -1
|
@@ -1,14 +1,21 @@
|
|
|
1
1
|
@layer ui {
|
|
2
2
|
|
|
3
|
+
:where(n-sidebar):not(:defined),
|
|
4
|
+
:where(n-sidebar-item):not(:defined),
|
|
5
|
+
:where(n-sidebar-nav):not(:defined),
|
|
6
|
+
:where(n-sidebar-group):not(:defined),
|
|
7
|
+
:where(n-sidebar-group-header):not(:defined),
|
|
8
|
+
:where(n-sidebar-nav-item):not(:defined) { visibility: hidden; }
|
|
9
|
+
|
|
3
10
|
/* ╭──────────────────────────────────────────────────────────╮
|
|
4
|
-
│
|
|
11
|
+
│ n-sidebar │
|
|
5
12
|
│ Full-page layout: collapsible/resizable sidebar aside │
|
|
6
13
|
│ + content column (breadcrumb, canvas, body, chat). │
|
|
7
14
|
╰──────────────────────────────────────────────────────────╯ */
|
|
8
15
|
|
|
9
16
|
/* ── Outer Layout ── */
|
|
10
17
|
|
|
11
|
-
:where(
|
|
18
|
+
:where(n-sidebar) {
|
|
12
19
|
display: flex;
|
|
13
20
|
height: 100dvh;
|
|
14
21
|
}
|
|
@@ -16,15 +23,15 @@
|
|
|
16
23
|
/* WHY: Reserve sidebar width before JS builds the DOM — prevents layout shift.
|
|
17
24
|
Collapsed state is read synchronously in the constructor so CSS matches immediately.
|
|
18
25
|
Replaced by the real aside once [data-ready] is set. */
|
|
19
|
-
:where(
|
|
26
|
+
:where(n-sidebar):not([data-ready]):not([collapsed])::before {
|
|
20
27
|
content: '';
|
|
21
|
-
width: var(--
|
|
28
|
+
width: var(--n-sidebar-width);
|
|
22
29
|
flex-shrink: 0;
|
|
23
30
|
background: var(--n-body);
|
|
24
31
|
border-right: 1px solid var(--n-border-muted);
|
|
25
32
|
}
|
|
26
33
|
|
|
27
|
-
:where(
|
|
34
|
+
:where(n-sidebar):not([data-ready])[collapsed]::before {
|
|
28
35
|
content: '';
|
|
29
36
|
width: 48px;
|
|
30
37
|
flex-shrink: 0;
|
|
@@ -35,7 +42,7 @@
|
|
|
35
42
|
/* ── Content Column ── */
|
|
36
43
|
/* WHY: Everything except the aside forms a flex column. */
|
|
37
44
|
|
|
38
|
-
:where(
|
|
45
|
+
:where(n-sidebar) > :where(:not([slot])) {
|
|
39
46
|
flex: 1 1 0%;
|
|
40
47
|
min-width: 0;
|
|
41
48
|
min-height: 0;
|
|
@@ -49,7 +56,7 @@
|
|
|
49
56
|
header/footer overlays. Content fills the full height and scrolls
|
|
50
57
|
underneath the pinned header/footer. */
|
|
51
58
|
|
|
52
|
-
:where(
|
|
59
|
+
:where(n-sidebar) > :where([slot="sidebar"]) {
|
|
53
60
|
--n-sidebar-header-height: 0px;
|
|
54
61
|
--n-sidebar-footer-height: 0px;
|
|
55
62
|
|
|
@@ -57,7 +64,7 @@
|
|
|
57
64
|
container-type: inline-size;
|
|
58
65
|
position: sticky;
|
|
59
66
|
top: 0;
|
|
60
|
-
width: var(--
|
|
67
|
+
width: var(--n-sidebar-width);
|
|
61
68
|
min-width: 160px;
|
|
62
69
|
max-width: 400px;
|
|
63
70
|
height: 100dvh;
|
|
@@ -68,7 +75,7 @@
|
|
|
68
75
|
}
|
|
69
76
|
|
|
70
77
|
/* WHY: Disable width transition while dragging — it fights the pointer. */
|
|
71
|
-
:where(
|
|
78
|
+
:where(n-sidebar) > :where([slot="sidebar"][resizing]) {
|
|
72
79
|
transition: none;
|
|
73
80
|
}
|
|
74
81
|
|
|
@@ -77,14 +84,14 @@
|
|
|
77
84
|
[collapsed] drives the aside to 48px which triggers @container sidebar queries
|
|
78
85
|
in this file and in child component CSS. */
|
|
79
86
|
|
|
80
|
-
:where(
|
|
87
|
+
:where(n-sidebar)[collapsed] > :where([slot="sidebar"]) {
|
|
81
88
|
width: 48px;
|
|
82
89
|
min-width: 48px;
|
|
83
90
|
}
|
|
84
91
|
|
|
85
92
|
/* ── Resize Handle ── */
|
|
86
93
|
|
|
87
|
-
:where(
|
|
94
|
+
:where(n-sidebar) :where(.layout-resize-handle) {
|
|
88
95
|
position: absolute;
|
|
89
96
|
top: 0;
|
|
90
97
|
right: 0;
|
|
@@ -94,18 +101,18 @@
|
|
|
94
101
|
z-index: 1;
|
|
95
102
|
}
|
|
96
103
|
|
|
97
|
-
:where(
|
|
98
|
-
:where(
|
|
104
|
+
:where(n-sidebar) :where(.layout-resize-handle):hover,
|
|
105
|
+
:where(n-sidebar) > :where([slot="sidebar"][resizing]) :where(.layout-resize-handle) {
|
|
99
106
|
background: var(--n-border-muted);
|
|
100
107
|
}
|
|
101
108
|
|
|
102
109
|
/* WHY: When collapsed to icon rail, the sidebar edge meets content — drop left padding. */
|
|
103
110
|
|
|
104
|
-
:where(
|
|
111
|
+
:where(n-sidebar)[collapsed] :where(n-app-canvas) {
|
|
105
112
|
padding-inline-start: 0;
|
|
106
113
|
}
|
|
107
114
|
|
|
108
|
-
:where(
|
|
115
|
+
:where(n-sidebar)[collapsed] :where(n-app-breadcrumb) {
|
|
109
116
|
padding-inline-start: 0;
|
|
110
117
|
}
|
|
111
118
|
|
|
@@ -113,7 +120,7 @@
|
|
|
113
120
|
/* WHY: Absolute-positioned overlay pinned to top of aside. Content scrolls
|
|
114
121
|
underneath it. z-index: 2 sits above content (z-index: 0). */
|
|
115
122
|
|
|
116
|
-
:where(
|
|
123
|
+
:where(n-sidebar-header) {
|
|
117
124
|
position: absolute;
|
|
118
125
|
top: 0;
|
|
119
126
|
left: 0;
|
|
@@ -128,7 +135,7 @@
|
|
|
128
135
|
content from starting behind header / ending behind footer.
|
|
129
136
|
Fade-out alpha mask dissolves content edges under the overlays. */
|
|
130
137
|
|
|
131
|
-
:where(
|
|
138
|
+
:where(n-sidebar-content) {
|
|
132
139
|
display: flex;
|
|
133
140
|
flex-direction: column;
|
|
134
141
|
padding-block-start: var(--n-sidebar-header-height);
|
|
@@ -142,7 +149,7 @@
|
|
|
142
149
|
/* WHY: When header is present, fade top edge. Content dissolves as it
|
|
143
150
|
scrolls under the header — transparent at top, fully visible by 1.25×
|
|
144
151
|
the header height. No opaque header background needed. */
|
|
145
|
-
:where(
|
|
152
|
+
:where(n-sidebar-content)[data-has-header] {
|
|
146
153
|
mask-image: linear-gradient(
|
|
147
154
|
to bottom,
|
|
148
155
|
transparent 0,
|
|
@@ -152,7 +159,7 @@
|
|
|
152
159
|
}
|
|
153
160
|
|
|
154
161
|
/* WHY: When footer is present, fade bottom edge. */
|
|
155
|
-
:where(
|
|
162
|
+
:where(n-sidebar-content)[data-has-footer] {
|
|
156
163
|
mask-image: linear-gradient(
|
|
157
164
|
to bottom,
|
|
158
165
|
black 0,
|
|
@@ -162,7 +169,7 @@
|
|
|
162
169
|
}
|
|
163
170
|
|
|
164
171
|
/* WHY: When both header AND footer are present, fade both edges. */
|
|
165
|
-
:where(
|
|
172
|
+
:where(n-sidebar-content)[data-has-header][data-has-footer] {
|
|
166
173
|
mask-image: linear-gradient(
|
|
167
174
|
to bottom,
|
|
168
175
|
transparent 0,
|
|
@@ -175,7 +182,7 @@
|
|
|
175
182
|
/* ── Sidebar Footer ── */
|
|
176
183
|
/* WHY: Absolute-positioned overlay pinned to bottom of aside. */
|
|
177
184
|
|
|
178
|
-
:where(
|
|
185
|
+
:where(n-sidebar-footer) {
|
|
179
186
|
position: absolute;
|
|
180
187
|
bottom: 0;
|
|
181
188
|
left: 0;
|
|
@@ -187,10 +194,10 @@
|
|
|
187
194
|
|
|
188
195
|
/* ── Sidebar Item ── */
|
|
189
196
|
/* WHY: Universal sidebar row element. Provides inline padding for any content
|
|
190
|
-
(buttons, links, icons). When a child
|
|
197
|
+
(buttons, links, icons). When a child n-listbox[popover] is present, JS
|
|
191
198
|
wires PopoverController for click-to-toggle menu behavior. */
|
|
192
199
|
|
|
193
|
-
:where(
|
|
200
|
+
:where(n-sidebar-item) {
|
|
194
201
|
display: flex;
|
|
195
202
|
align-items: center;
|
|
196
203
|
flex: 1;
|
|
@@ -198,9 +205,9 @@
|
|
|
198
205
|
gap: calc(var(--n-space) * 2);
|
|
199
206
|
min-height: var(--n-size);
|
|
200
207
|
font-size: var(--n-font-size);
|
|
201
|
-
font-weight: var(--
|
|
208
|
+
font-weight: var(--n-button-font-weight);
|
|
202
209
|
letter-spacing: var(--n-letter-spacing);
|
|
203
|
-
line-height: var(--
|
|
210
|
+
line-height: var(--n-control-line-height);
|
|
204
211
|
color: var(--n-ink);
|
|
205
212
|
cursor: pointer;
|
|
206
213
|
user-select: none;
|
|
@@ -214,26 +221,26 @@
|
|
|
214
221
|
|
|
215
222
|
/* WHY: Items in header/footer match the breadcrumb bar height so the
|
|
216
223
|
first sidebar row aligns horizontally with the breadcrumb. */
|
|
217
|
-
:where(
|
|
218
|
-
:where(
|
|
219
|
-
min-height: var(--
|
|
224
|
+
:where(n-sidebar-header) > :where(n-sidebar-item),
|
|
225
|
+
:where(n-sidebar-footer) > :where(n-sidebar-item) {
|
|
226
|
+
min-height: var(--n-sidebar-item-height);
|
|
220
227
|
}
|
|
221
228
|
|
|
222
|
-
:where(
|
|
223
|
-
:where(
|
|
229
|
+
:where(n-sidebar-item):hover,
|
|
230
|
+
:where(n-sidebar-item)[force-hover] {
|
|
224
231
|
color: var(--n-ink-strong);
|
|
225
232
|
}
|
|
226
233
|
|
|
227
|
-
:where(
|
|
228
|
-
:where(
|
|
229
|
-
outline: 2px solid var(--
|
|
234
|
+
:where(n-sidebar-item):focus-visible,
|
|
235
|
+
:where(n-sidebar-item)[force-focus-visible] {
|
|
236
|
+
outline: 2px solid var(--n-focus-ring);
|
|
230
237
|
outline-offset: -2px;
|
|
231
238
|
}
|
|
232
239
|
|
|
233
240
|
/* WHY: Fixed-size icon well so all sidebar icons center-align on the same
|
|
234
241
|
column width regardless of intrinsic icon size. 1.5rem matches the sidebar's
|
|
235
242
|
visual rhythm at default density. */
|
|
236
|
-
:where(
|
|
243
|
+
:where(n-sidebar-item) > :where([slot="icon"]) {
|
|
237
244
|
display: inline-flex;
|
|
238
245
|
align-items: center;
|
|
239
246
|
justify-content: center;
|
|
@@ -243,21 +250,21 @@
|
|
|
243
250
|
}
|
|
244
251
|
|
|
245
252
|
/* WHY: Trailing caret pushes to end — same pattern as button justify="spread". */
|
|
246
|
-
:where(
|
|
253
|
+
:where(n-sidebar-item) > :where([slot="trailing"]) {
|
|
247
254
|
margin-inline-start: auto;
|
|
248
255
|
flex-shrink: 0;
|
|
249
256
|
color: var(--n-ink-muted);
|
|
250
257
|
}
|
|
251
258
|
|
|
252
|
-
/* WHY: When the item wraps a sub-component (e.g.
|
|
259
|
+
/* WHY: When the item wraps a sub-component (e.g. n-button) that provides
|
|
253
260
|
its own icon, hide [slot="icon"] in expanded mode — it only serves as the
|
|
254
261
|
bare collapsed-rail representation. */
|
|
255
|
-
:where(
|
|
262
|
+
:where(n-sidebar-item:has(> n-button)) > :where([slot="icon"]) {
|
|
256
263
|
display: none;
|
|
257
264
|
}
|
|
258
265
|
|
|
259
266
|
/* WHY: Title text truncates when sidebar narrows during resize. */
|
|
260
|
-
:where(
|
|
267
|
+
:where(n-sidebar-item) > :where([slot="label"]) {
|
|
261
268
|
flex: 1;
|
|
262
269
|
min-width: 0;
|
|
263
270
|
white-space: nowrap;
|
|
@@ -270,18 +277,18 @@
|
|
|
270
277
|
Default: top-aligned, grows downward (span-block-end).
|
|
271
278
|
Flip: bottom-aligned, grows upward (span-block-start). */
|
|
272
279
|
|
|
273
|
-
:where(
|
|
280
|
+
:where(n-sidebar-item) > :where(n-listbox[popover]) {
|
|
274
281
|
--n-popover-origin: left center;
|
|
275
282
|
--n-popover-from: perspective(800px) scale(0.96) rotateY(20deg);
|
|
276
283
|
|
|
277
284
|
position: fixed;
|
|
278
285
|
position-area: inline-end span-block-end;
|
|
279
286
|
position-try-fallbacks: --sidebar-item-flip-up;
|
|
280
|
-
margin-block: var(--
|
|
287
|
+
margin-block: var(--n-popover-viewport-margin);
|
|
281
288
|
margin-inline: 0;
|
|
282
|
-
margin-inline-start: var(--
|
|
289
|
+
margin-inline-start: var(--n-popover-gap);
|
|
283
290
|
min-width: 200px;
|
|
284
|
-
max-height: var(--
|
|
291
|
+
max-height: var(--n-popover-max-height);
|
|
285
292
|
overflow-y: auto;
|
|
286
293
|
}
|
|
287
294
|
|
|
@@ -307,33 +314,33 @@
|
|
|
307
314
|
}
|
|
308
315
|
|
|
309
316
|
/* Header/footer — center content horizontally */
|
|
310
|
-
:where(
|
|
311
|
-
:where(
|
|
317
|
+
:where(n-sidebar-header),
|
|
318
|
+
:where(n-sidebar-footer) {
|
|
312
319
|
align-items: center;
|
|
313
320
|
}
|
|
314
321
|
|
|
315
322
|
/* Content — center items in the 48px rail */
|
|
316
|
-
:where(
|
|
323
|
+
:where(n-sidebar-content) {
|
|
317
324
|
align-items: center;
|
|
318
325
|
}
|
|
319
326
|
|
|
320
327
|
/* Item — shrink to icon-only. */
|
|
321
|
-
:where(
|
|
328
|
+
:where(n-sidebar-item) {
|
|
322
329
|
flex: 0 0 auto;
|
|
323
330
|
padding-inline: var(--n-space);
|
|
324
331
|
}
|
|
325
332
|
|
|
326
|
-
:where(
|
|
333
|
+
:where(n-sidebar-item) > :where([slot="icon"]) {
|
|
327
334
|
display: inline-flex;
|
|
328
335
|
}
|
|
329
336
|
|
|
330
|
-
:where(
|
|
337
|
+
:where(n-sidebar-item) > :where(:not([slot="icon"]):not(n-listbox[popover]):not(.nav-group-flyout)) {
|
|
331
338
|
display: none;
|
|
332
339
|
}
|
|
333
340
|
|
|
334
341
|
/* WHY: In collapsed mode the sidebar item is a small icon — centering
|
|
335
342
|
the popover vertically with the anchor is more natural than top-aligning. */
|
|
336
|
-
:where(
|
|
343
|
+
:where(n-sidebar-item) > :where(n-listbox[popover]) {
|
|
337
344
|
position-area: inline-end;
|
|
338
345
|
position-try-fallbacks: --sidebar-item-flip-up, --sidebar-item-flip-down;
|
|
339
346
|
}
|
|
@@ -341,30 +348,36 @@
|
|
|
341
348
|
|
|
342
349
|
|
|
343
350
|
/* ╭──────────────────────────────────────────────────────────╮
|
|
344
|
-
│
|
|
351
|
+
│ n-sidebar-nav │
|
|
345
352
|
│ Navigation list with keyboard nav + selection. │
|
|
346
353
|
│ Transparent wrapper — no visual surface. │
|
|
347
|
-
│ Uses
|
|
354
|
+
│ Uses n-sidebar-nav-item / n-sidebar-group. │
|
|
348
355
|
╰──────────────────────────────────────────────────────────╯ */
|
|
349
356
|
|
|
350
|
-
/* WHY:
|
|
357
|
+
/* WHY: n-sidebar-nav is a transparent flex wrapper — no inline padding.
|
|
351
358
|
Inline padding is owned by leaf items (nav-item, summary).
|
|
352
359
|
Block padding is owned by nav-group margins. */
|
|
353
|
-
:where(
|
|
360
|
+
:where(n-sidebar-nav) {
|
|
354
361
|
display: flex;
|
|
355
362
|
flex-direction: column;
|
|
356
363
|
gap: 0;
|
|
357
364
|
padding: 0;
|
|
358
365
|
outline: none;
|
|
366
|
+
user-select: none;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
:where(n-sidebar-nav)[aria-disabled="true"] {
|
|
370
|
+
color: var(--n-ink-disabled);
|
|
371
|
+
pointer-events: none;
|
|
359
372
|
}
|
|
360
373
|
|
|
361
374
|
/* ── Nav Item ── */
|
|
362
375
|
/* WHY: Nav items share the same visual pattern as options (ghost row,
|
|
363
376
|
hover/active/selected states). */
|
|
364
377
|
|
|
365
|
-
:where(
|
|
366
|
-
--n-font-weight: var(--
|
|
367
|
-
--n-line-height: var(--
|
|
378
|
+
:where(n-sidebar-nav-item) {
|
|
379
|
+
--n-font-weight: var(--n-text-font-weight);
|
|
380
|
+
--n-line-height: var(--n-control-line-height-dense);
|
|
368
381
|
|
|
369
382
|
display: flex;
|
|
370
383
|
align-items: center;
|
|
@@ -392,55 +405,56 @@
|
|
|
392
405
|
|
|
393
406
|
/* ── Nav Item States ── */
|
|
394
407
|
|
|
395
|
-
:where(
|
|
396
|
-
:where(
|
|
408
|
+
:where(n-sidebar-nav-item):hover,
|
|
409
|
+
:where(n-sidebar-nav-item)[force-hover] {
|
|
397
410
|
color: var(--n-ink-hover);
|
|
398
411
|
}
|
|
399
412
|
|
|
400
|
-
:where(
|
|
401
|
-
:where(
|
|
413
|
+
:where(n-sidebar-nav-item):active,
|
|
414
|
+
:where(n-sidebar-nav-item)[force-active] {
|
|
402
415
|
color: var(--n-ink-active);
|
|
403
416
|
}
|
|
404
417
|
|
|
405
|
-
:where(
|
|
418
|
+
:where(n-sidebar-nav-item)[aria-current="page"] {
|
|
406
419
|
color: var(--n-ink-strong);
|
|
407
420
|
}
|
|
408
421
|
|
|
409
|
-
:where(
|
|
422
|
+
:where(n-sidebar-nav-item)[aria-disabled="true"] {
|
|
410
423
|
color: var(--n-ink-disabled);
|
|
411
424
|
cursor: not-allowed;
|
|
412
425
|
pointer-events: none;
|
|
413
426
|
}
|
|
414
427
|
|
|
415
|
-
:where(
|
|
416
|
-
:where(
|
|
417
|
-
outline: 2px solid var(--
|
|
428
|
+
:where(n-sidebar-nav-item):focus-visible,
|
|
429
|
+
:where(n-sidebar-nav-item)[force-focus-visible] {
|
|
430
|
+
outline: 2px solid var(--n-focus-ring);
|
|
418
431
|
outline-offset: -2px;
|
|
419
432
|
}
|
|
420
433
|
|
|
421
434
|
/* ── Nav Group ── */
|
|
422
435
|
/* WHY: Groups stamp a native <details>/<summary> for collapsible behavior.
|
|
423
|
-
DOM structure:
|
|
424
|
-
>
|
|
436
|
+
DOM structure: n-sidebar-group > details > summary > n-sidebar-group-header
|
|
437
|
+
> n-sidebar-nav-item* */
|
|
425
438
|
|
|
426
|
-
:where(
|
|
439
|
+
:where(n-sidebar-group) {
|
|
427
440
|
--n-indicator-index: 0;
|
|
428
441
|
|
|
429
442
|
display: block;
|
|
430
443
|
position: relative;
|
|
444
|
+
user-select: none;
|
|
431
445
|
}
|
|
432
446
|
|
|
433
|
-
:where(
|
|
447
|
+
:where(n-sidebar-group) + :where(n-sidebar-group) {
|
|
434
448
|
margin-block-start: calc(var(--n-space) * 2);
|
|
435
449
|
}
|
|
436
450
|
|
|
437
451
|
/* ── Details (native disclosure with animated open/close) ── */
|
|
438
452
|
|
|
439
|
-
:where(
|
|
453
|
+
:where(n-sidebar-group) > :where(details) {
|
|
440
454
|
interpolate-size: allow-keywords;
|
|
441
455
|
}
|
|
442
456
|
|
|
443
|
-
:where(
|
|
457
|
+
:where(n-sidebar-group) > :where(details)::details-content {
|
|
444
458
|
height: 0;
|
|
445
459
|
overflow: clip;
|
|
446
460
|
opacity: 0;
|
|
@@ -451,14 +465,14 @@
|
|
|
451
465
|
content-visibility var(--n-duration) var(--n-easing) allow-discrete;
|
|
452
466
|
}
|
|
453
467
|
|
|
454
|
-
:where(
|
|
468
|
+
:where(n-sidebar-group) > :where(details[open])::details-content {
|
|
455
469
|
height: auto;
|
|
456
470
|
opacity: 1;
|
|
457
471
|
}
|
|
458
472
|
|
|
459
473
|
/* ── Summary (clickable header row) ── */
|
|
460
474
|
|
|
461
|
-
:where(
|
|
475
|
+
:where(n-sidebar-group) > :where(details) > :where(summary) {
|
|
462
476
|
display: flex;
|
|
463
477
|
align-items: center;
|
|
464
478
|
gap: calc(var(--n-space) * 2);
|
|
@@ -470,11 +484,11 @@
|
|
|
470
484
|
}
|
|
471
485
|
|
|
472
486
|
/* WHY: Remove default marker in WebKit */
|
|
473
|
-
:where(
|
|
487
|
+
:where(n-sidebar-group) > :where(details) > :where(summary)::-webkit-details-marker {
|
|
474
488
|
display: none;
|
|
475
489
|
}
|
|
476
490
|
|
|
477
|
-
:where(
|
|
491
|
+
:where(n-sidebar-group) > :where(details) > :where(summary)::marker {
|
|
478
492
|
display: none;
|
|
479
493
|
content: '';
|
|
480
494
|
}
|
|
@@ -482,25 +496,25 @@
|
|
|
482
496
|
/* ── Nav Group Header ── */
|
|
483
497
|
/* WHY: Header sits inside <summary>. Bold text with optional icon. */
|
|
484
498
|
|
|
485
|
-
:where(
|
|
499
|
+
:where(n-sidebar-group-header) {
|
|
486
500
|
display: flex;
|
|
487
501
|
align-items: center;
|
|
488
502
|
flex: 1;
|
|
489
503
|
gap: calc(var(--n-space) * 2);
|
|
490
504
|
min-height: var(--n-size);
|
|
491
505
|
font-size: var(--n-font-size);
|
|
492
|
-
font-weight: var(--
|
|
506
|
+
font-weight: var(--n-button-font-weight);
|
|
493
507
|
letter-spacing: var(--n-letter-spacing);
|
|
494
|
-
line-height: var(--
|
|
508
|
+
line-height: var(--n-control-line-height);
|
|
495
509
|
color: var(--n-ink);
|
|
496
510
|
cursor: pointer;
|
|
497
511
|
user-select: none;
|
|
498
512
|
}
|
|
499
513
|
|
|
500
|
-
/* WHY: Fixed-size icon well — matches
|
|
514
|
+
/* WHY: Fixed-size icon well — matches n-sidebar-item [slot="icon"].
|
|
501
515
|
All sidebar icons align on the same 1.5rem column regardless of icon size.
|
|
502
|
-
JS wraps the first <
|
|
503
|
-
:where(
|
|
516
|
+
JS wraps the first <n-icon> child in a .icon-well span during setup(). */
|
|
517
|
+
:where(n-sidebar-group-header) > :where(.icon-well) {
|
|
504
518
|
display: inline-flex;
|
|
505
519
|
align-items: center;
|
|
506
520
|
justify-content: center;
|
|
@@ -511,7 +525,7 @@
|
|
|
511
525
|
|
|
512
526
|
/* ── Chevron icon (right side of summary) ── */
|
|
513
527
|
|
|
514
|
-
:where(
|
|
528
|
+
:where(n-sidebar-group) > :where(details) > :where(summary)::after {
|
|
515
529
|
content: '';
|
|
516
530
|
flex-shrink: 0;
|
|
517
531
|
width: var(--n-icon-size);
|
|
@@ -533,41 +547,41 @@
|
|
|
533
547
|
}
|
|
534
548
|
|
|
535
549
|
/* Chevron rotates when open */
|
|
536
|
-
:where(
|
|
550
|
+
:where(n-sidebar-group) > :where(details[open]) > :where(summary)::after {
|
|
537
551
|
transform: rotate(180deg);
|
|
538
552
|
}
|
|
539
553
|
|
|
540
554
|
/* ── Selected group — has a child with aria-current ── */
|
|
541
555
|
|
|
542
|
-
:where(
|
|
556
|
+
:where(n-sidebar-group):state(has-selection) > :where(details) > :where(summary) :where(n-sidebar-group-header) {
|
|
543
557
|
color: var(--n-ink-strong);
|
|
544
558
|
}
|
|
545
559
|
|
|
546
560
|
/* ── Summary Hover ── */
|
|
547
561
|
|
|
548
|
-
:where(
|
|
549
|
-
:where(
|
|
562
|
+
:where(n-sidebar-group) > :where(details) > :where(summary):hover :where(n-sidebar-group-header),
|
|
563
|
+
:where(n-sidebar-group[force-hover]) > :where(details) > :where(summary) :where(n-sidebar-group-header) {
|
|
550
564
|
color: var(--n-ink-strong);
|
|
551
565
|
}
|
|
552
566
|
|
|
553
567
|
/* ── Summary Focus ── */
|
|
554
568
|
|
|
555
|
-
:where(
|
|
556
|
-
:where(
|
|
557
|
-
outline: 2px solid var(--
|
|
569
|
+
:where(n-sidebar-group) > :where(details) > :where(summary):focus-visible,
|
|
570
|
+
:where(n-sidebar-group[force-focus-visible]) > :where(details) > :where(summary) {
|
|
571
|
+
outline: 2px solid var(--n-focus-ring);
|
|
558
572
|
outline-offset: -2px;
|
|
559
573
|
}
|
|
560
574
|
|
|
561
575
|
/* ── Vertical connector line (icon groups only) ── */
|
|
562
576
|
|
|
563
|
-
:where(
|
|
577
|
+
:where(n-sidebar-group):has(:where(n-sidebar-group-header) :where(.icon-well)) {
|
|
564
578
|
--n-group-pad: calc(var(--n-space-k) * var(--n-space));
|
|
565
579
|
--n-group-icon-well: 1.5rem;
|
|
566
580
|
--n-group-line-inset: calc(var(--n-group-pad) + var(--n-group-icon-well) / 2);
|
|
567
581
|
--n-group-child-inset: calc(var(--n-group-icon-well) + var(--n-space) * 2);
|
|
568
582
|
}
|
|
569
583
|
|
|
570
|
-
:where(
|
|
584
|
+
:where(n-sidebar-group):has(:where(n-sidebar-group-header) :where(.icon-well)):has(:where(details[open]))::after {
|
|
571
585
|
content: '';
|
|
572
586
|
position: absolute;
|
|
573
587
|
inset-inline-start: var(--n-group-line-inset);
|
|
@@ -580,7 +594,7 @@
|
|
|
580
594
|
|
|
581
595
|
/* ── Sliding indicator ── */
|
|
582
596
|
|
|
583
|
-
:where(
|
|
597
|
+
:where(n-sidebar-group):has(:where(n-sidebar-group-header) :where(.icon-well)):has(:where(details[open])):state(has-selection)::before {
|
|
584
598
|
content: '';
|
|
585
599
|
position: absolute;
|
|
586
600
|
z-index: 1;
|
|
@@ -600,24 +614,24 @@
|
|
|
600
614
|
|
|
601
615
|
/* ── Grouped Child Items ── */
|
|
602
616
|
|
|
603
|
-
:where(
|
|
617
|
+
:where(n-sidebar-group) > :where(details) > :where(n-sidebar-nav-item) {
|
|
604
618
|
margin-inline-start: var(--n-group-child-inset, 0);
|
|
605
619
|
}
|
|
606
620
|
|
|
607
621
|
/* ── Nav Group Flyout (collapsed sidebar) ── */
|
|
608
622
|
|
|
609
|
-
:where(
|
|
623
|
+
:where(n-sidebar-group) > :where(n-listbox.nav-group-flyout[popover]) {
|
|
610
624
|
--n-popover-origin: left center;
|
|
611
625
|
--n-popover-from: perspective(800px) scale(0.96) rotateY(20deg);
|
|
612
626
|
|
|
613
627
|
position: fixed;
|
|
614
628
|
position-area: inline-end span-block-end;
|
|
615
629
|
position-try-fallbacks: --nav-flyout-flip-up;
|
|
616
|
-
margin-block: var(--
|
|
630
|
+
margin-block: var(--n-popover-viewport-margin);
|
|
617
631
|
margin-inline: 0;
|
|
618
|
-
margin-inline-start: var(--
|
|
632
|
+
margin-inline-start: var(--n-popover-gap);
|
|
619
633
|
min-width: 200px;
|
|
620
|
-
max-height: var(--
|
|
634
|
+
max-height: var(--n-popover-max-height);
|
|
621
635
|
overflow-y: auto;
|
|
622
636
|
}
|
|
623
637
|
|
|
@@ -634,47 +648,47 @@
|
|
|
634
648
|
@container sidebar (max-width: 80px) {
|
|
635
649
|
|
|
636
650
|
/* Nav items hide entirely — only group headers (with icons) remain. */
|
|
637
|
-
:where(
|
|
651
|
+
:where(n-sidebar-nav-item) {
|
|
638
652
|
display: none;
|
|
639
653
|
}
|
|
640
654
|
|
|
641
655
|
/* Summary shrinks to icon-only. */
|
|
642
|
-
:where(
|
|
656
|
+
:where(n-sidebar-group) > :where(details) > :where(summary) {
|
|
643
657
|
padding-inline: var(--n-space);
|
|
644
658
|
border-radius: var(--n-radius);
|
|
645
659
|
}
|
|
646
660
|
|
|
647
661
|
/* Hide chevron — no expand/collapse in icon rail (flyout instead). */
|
|
648
|
-
:where(
|
|
662
|
+
:where(n-sidebar-group) > :where(details) > :where(summary)::after {
|
|
649
663
|
display: none;
|
|
650
664
|
}
|
|
651
665
|
|
|
652
666
|
/* Hide vertical connector line and sliding indicator. */
|
|
653
|
-
:where(
|
|
654
|
-
:where(
|
|
667
|
+
:where(n-sidebar-group)::after,
|
|
668
|
+
:where(n-sidebar-group)::before {
|
|
655
669
|
display: none;
|
|
656
670
|
}
|
|
657
671
|
|
|
658
672
|
/* Header collapses to icon-only. */
|
|
659
|
-
:where(
|
|
673
|
+
:where(n-sidebar-group-header) {
|
|
660
674
|
flex: 0 0 auto;
|
|
661
675
|
font-size: 0;
|
|
662
676
|
gap: 0;
|
|
663
677
|
}
|
|
664
678
|
|
|
665
|
-
:where(
|
|
679
|
+
:where(n-sidebar-group-header) :where(.icon-well) :where(n-icon) {
|
|
666
680
|
font-size: var(--n-font-size, 1rem);
|
|
667
681
|
}
|
|
668
682
|
|
|
669
683
|
/* WHY: In collapsed mode the group is a small icon — centering
|
|
670
684
|
the flyout vertically with the anchor is more natural. */
|
|
671
|
-
:where(
|
|
685
|
+
:where(n-sidebar-group) > :where(n-listbox.nav-group-flyout[popover]) {
|
|
672
686
|
position-area: inline-end;
|
|
673
687
|
position-try-fallbacks: --nav-flyout-flip-up, --nav-flyout-flip-down;
|
|
674
688
|
}
|
|
675
689
|
|
|
676
690
|
/* Collapse inter-group spacing in icon rail. */
|
|
677
|
-
:where(
|
|
691
|
+
:where(n-sidebar-group) + :where(n-sidebar-group) {
|
|
678
692
|
margin-block-start: 0;
|
|
679
693
|
}
|
|
680
694
|
}
|
|
@@ -684,18 +698,18 @@
|
|
|
684
698
|
@layer ui {
|
|
685
699
|
|
|
686
700
|
/* ╭──────────────────────────────────────────────────────────╮
|
|
687
|
-
│
|
|
701
|
+
│ n-app-breadcrumb │
|
|
688
702
|
│ Grid bar with leading / label / trailing slots. │
|
|
689
|
-
│ Same slot pattern as
|
|
703
|
+
│ Same slot pattern as n-card-header. │
|
|
690
704
|
╰──────────────────────────────────────────────────────────╯ */
|
|
691
705
|
|
|
692
706
|
/* ── Base ── */
|
|
693
707
|
|
|
694
|
-
:where(
|
|
708
|
+
:where(n-app-breadcrumb) {
|
|
695
709
|
display: grid;
|
|
696
710
|
grid-template-columns: 1fr;
|
|
697
711
|
align-items: center;
|
|
698
|
-
min-height: var(--
|
|
712
|
+
min-height: var(--n-sidebar-item-height);
|
|
699
713
|
gap: calc(var(--n-space) * 2);
|
|
700
714
|
padding-block: var(--n-space);
|
|
701
715
|
padding-inline: calc(var(--n-space-k) * var(--n-space));
|
|
@@ -705,30 +719,30 @@
|
|
|
705
719
|
|
|
706
720
|
/* ── Slots ── */
|
|
707
721
|
|
|
708
|
-
:where(
|
|
722
|
+
:where(n-app-breadcrumb):has(> [slot="leading"]):has(> [slot="trailing"]) {
|
|
709
723
|
grid-template-columns: auto 1fr auto;
|
|
710
724
|
}
|
|
711
725
|
|
|
712
|
-
:where(
|
|
726
|
+
:where(n-app-breadcrumb):has(> [slot="leading"]):not(:has(> [slot="trailing"])) {
|
|
713
727
|
grid-template-columns: auto 1fr;
|
|
714
728
|
}
|
|
715
729
|
|
|
716
|
-
:where(
|
|
730
|
+
:where(n-app-breadcrumb):not(:has(> [slot="leading"])):has(> [slot="trailing"]) {
|
|
717
731
|
grid-template-columns: 1fr auto;
|
|
718
732
|
}
|
|
719
733
|
|
|
720
|
-
:where(
|
|
734
|
+
:where(n-app-breadcrumb) > :where([slot="leading"]) {
|
|
721
735
|
display: flex;
|
|
722
736
|
align-items: center;
|
|
723
737
|
gap: calc(var(--n-space) * 2);
|
|
724
738
|
}
|
|
725
739
|
|
|
726
|
-
:where(
|
|
727
|
-
:where(
|
|
740
|
+
:where(n-app-breadcrumb) > :where([slot="label"]),
|
|
741
|
+
:where(n-app-breadcrumb) > :where(:not([slot])) {
|
|
728
742
|
min-width: 0;
|
|
729
743
|
}
|
|
730
744
|
|
|
731
|
-
:where(
|
|
745
|
+
:where(n-app-breadcrumb) > :where([slot="trailing"]) {
|
|
732
746
|
display: flex;
|
|
733
747
|
align-items: center;
|
|
734
748
|
gap: calc(var(--n-space) * 2);
|
|
@@ -739,12 +753,12 @@
|
|
|
739
753
|
@layer ui {
|
|
740
754
|
|
|
741
755
|
/* ╭──────────────────────────────────────────────────────────╮
|
|
742
|
-
│
|
|
756
|
+
│ n-app-canvas │
|
|
743
757
|
│ Structural flex row for body + chat panels. │
|
|
744
758
|
│ No background, no radius — purely layout. │
|
|
745
759
|
╰──────────────────────────────────────────────────────────╯ */
|
|
746
760
|
|
|
747
|
-
:where(
|
|
761
|
+
:where(n-app-canvas) {
|
|
748
762
|
display: flex;
|
|
749
763
|
flex: 1;
|
|
750
764
|
min-height: 0;
|
|
@@ -755,8 +769,10 @@
|
|
|
755
769
|
|
|
756
770
|
@layer ui {
|
|
757
771
|
|
|
772
|
+
:where(n-app-panel):not(:defined) { visibility: hidden; }
|
|
773
|
+
|
|
758
774
|
/* ╭──────────────────────────────────────────────────────────╮
|
|
759
|
-
│
|
|
775
|
+
│ n-app-panel │
|
|
760
776
|
│ Layout panel — main content surface or collapsible │
|
|
761
777
|
│ aside. Default: flex-1 scrollable body. [aside]: │
|
|
762
778
|
│ fixed-width side panel with open/close + resize. │
|
|
@@ -764,21 +780,23 @@
|
|
|
764
780
|
|
|
765
781
|
/* ── Base (shared) ── */
|
|
766
782
|
|
|
767
|
-
:where(
|
|
783
|
+
:where(n-app-panel) {
|
|
784
|
+
--n-ground: var(--n-panel);
|
|
785
|
+
|
|
768
786
|
display: flex;
|
|
769
787
|
flex-direction: column;
|
|
770
788
|
scrollbar-width: none;
|
|
771
|
-
background: var(--n-ground
|
|
789
|
+
background: var(--n-ground);
|
|
772
790
|
border-radius: var(--n-radius);
|
|
773
791
|
}
|
|
774
792
|
|
|
775
|
-
:where(
|
|
793
|
+
:where(n-app-panel)[show-scrollbar] {
|
|
776
794
|
scrollbar-width: thin;
|
|
777
795
|
}
|
|
778
796
|
|
|
779
797
|
/* ── Main mode (default) ── */
|
|
780
798
|
|
|
781
|
-
:where(
|
|
799
|
+
:where(n-app-panel):not([aside]) {
|
|
782
800
|
flex: 1;
|
|
783
801
|
min-width: 0;
|
|
784
802
|
overflow-y: auto;
|
|
@@ -787,7 +805,7 @@
|
|
|
787
805
|
|
|
788
806
|
/* ── Aside mode ── */
|
|
789
807
|
|
|
790
|
-
:where(
|
|
808
|
+
:where(n-app-panel)[aside] {
|
|
791
809
|
position: relative;
|
|
792
810
|
width: 0;
|
|
793
811
|
min-width: 0;
|
|
@@ -801,7 +819,7 @@
|
|
|
801
819
|
margin var(--n-duration) var(--n-easing);
|
|
802
820
|
}
|
|
803
821
|
|
|
804
|
-
:where(
|
|
822
|
+
:where(n-app-panel)[aside][open] {
|
|
805
823
|
width: 360px;
|
|
806
824
|
min-width: 280px;
|
|
807
825
|
margin-inline-start: calc(var(--n-space) * 2);
|
|
@@ -809,23 +827,23 @@
|
|
|
809
827
|
padding: calc(var(--n-space-k) * var(--n-space));
|
|
810
828
|
}
|
|
811
829
|
|
|
812
|
-
/* WHY: When
|
|
830
|
+
/* WHY: When n-chat manages its own sub-container padding and scroll,
|
|
813
831
|
the layout container delegates — no own padding, no own scroll.
|
|
814
|
-
overflow: visible lets CSS anchor-positioned popovers (
|
|
832
|
+
overflow: visible lets CSS anchor-positioned popovers (n-select etc.)
|
|
815
833
|
resolve through to the top layer. */
|
|
816
|
-
:where(
|
|
834
|
+
:where(n-app-panel)[aside][open]:has(> n-chat) {
|
|
817
835
|
padding: 0;
|
|
818
836
|
overflow: visible;
|
|
819
837
|
}
|
|
820
838
|
|
|
821
839
|
/* WHY: Disable width transition while dragging — it fights the pointer. */
|
|
822
|
-
:where(
|
|
840
|
+
:where(n-app-panel)[aside][resizing] {
|
|
823
841
|
transition: none;
|
|
824
842
|
}
|
|
825
843
|
|
|
826
844
|
/* ── Resize Handle ── */
|
|
827
845
|
|
|
828
|
-
:where(
|
|
846
|
+
:where(n-app-panel)[aside] :where(.layout-resize-handle) {
|
|
829
847
|
position: absolute;
|
|
830
848
|
top: 0;
|
|
831
849
|
left: 0;
|
|
@@ -835,9 +853,26 @@
|
|
|
835
853
|
z-index: 1;
|
|
836
854
|
}
|
|
837
855
|
|
|
838
|
-
:where(
|
|
839
|
-
:where(
|
|
856
|
+
:where(n-app-panel)[aside] :where(.layout-resize-handle):hover,
|
|
857
|
+
:where(n-app-panel)[aside][resizing] :where(.layout-resize-handle) {
|
|
840
858
|
background: var(--n-border-muted);
|
|
841
859
|
}
|
|
842
860
|
|
|
861
|
+
/* ── Panel sub-container integration ── */
|
|
862
|
+
/* WHY: When n-panel-body is present, delegate overflow to it so
|
|
863
|
+
header/footer stay fixed while body scrolls. */
|
|
864
|
+
|
|
865
|
+
:where(n-app-panel):has(> n-panel-body) {
|
|
866
|
+
overflow: hidden;
|
|
867
|
+
padding: 0;
|
|
868
|
+
}
|
|
869
|
+
|
|
870
|
+
:where(n-app-panel) > :where(n-panel-header) {
|
|
871
|
+
border-bottom: 1px solid var(--n-border-muted);
|
|
872
|
+
}
|
|
873
|
+
|
|
874
|
+
:where(n-app-panel) > :where(n-panel-footer) {
|
|
875
|
+
border-top: 1px solid var(--n-border-muted);
|
|
876
|
+
}
|
|
877
|
+
|
|
843
878
|
}
|