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