@nonoun/native-ui 0.2.4 → 0.2.6
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/components/ui-kbd/index.d.ts +3 -0
- package/dist/components/ui-kbd/index.d.ts.map +1 -0
- package/dist/components/ui-kbd/ui-kbd-element.d.ts +5 -0
- package/dist/components/ui-kbd/ui-kbd-element.d.ts.map +1 -0
- package/dist/components/ui-kbd/ui-kbd.d.ts +3 -0
- package/dist/components/ui-kbd/ui-kbd.d.ts.map +1 -0
- package/dist/components/ui-nav/ui-nav-group-element.d.ts +8 -0
- package/dist/components/ui-nav/ui-nav-group-element.d.ts.map +1 -1
- package/dist/components/ui-nav/ui-nav-group-header-element.d.ts.map +1 -1
- package/dist/components-lean.css +319 -226
- package/dist/components.css +321 -233
- package/dist/containers/ui-layout-sidebar/index.d.ts +1 -1
- package/dist/containers/ui-layout-sidebar/index.d.ts.map +1 -1
- package/dist/containers/ui-layout-sidebar/ui-layout-sidebar-element.d.ts +4 -1
- package/dist/containers/ui-layout-sidebar/ui-layout-sidebar-element.d.ts.map +1 -1
- package/dist/containers/ui-layout-sidebar/ui-layout-sidebar-item-element.d.ts +10 -0
- package/dist/containers/ui-layout-sidebar/ui-layout-sidebar-item-element.d.ts.map +1 -0
- package/dist/containers/ui-layout-sidebar/ui-layout-sidebar-item.d.ts +3 -0
- package/dist/containers/ui-layout-sidebar/ui-layout-sidebar-item.d.ts.map +1 -0
- package/dist/containers/ui-layout-sidebar/ui-layout-sidebar.d.ts +1 -1
- package/dist/containers/ui-layout-sidebar/ui-layout-sidebar.d.ts.map +1 -1
- package/dist/custom-elements.json +2507 -2099
- package/dist/foundation.css +79 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/native-ui-lean.css +398 -227
- package/dist/native-ui.css +400 -234
- package/dist/native-ui.js +3 -6
- package/dist/register-all.js +1 -1
- package/dist/ui-icon-element.js +100 -7
- package/package.json +1 -1
- package/dist/containers/ui-layout-sidebar/ui-layout-sidebar-trigger-element.d.ts +0 -8
- package/dist/containers/ui-layout-sidebar/ui-layout-sidebar-trigger-element.d.ts.map +0 -1
- package/dist/containers/ui-layout-sidebar/ui-layout-sidebar-trigger.d.ts +0 -3
- package/dist/containers/ui-layout-sidebar/ui-layout-sidebar-trigger.d.ts.map +0 -1
package/dist/native-ui-lean.css
CHANGED
|
@@ -1267,6 +1267,54 @@
|
|
|
1267
1267
|
display: none;
|
|
1268
1268
|
}
|
|
1269
1269
|
|
|
1270
|
+
/* WHY: Custom elements render as unstyled inline text until define() runs.
|
|
1271
|
+
visibility:hidden preserves layout — no reflow when the element upgrades.
|
|
1272
|
+
Only targets elements that call define(); CSS-only containers are excluded
|
|
1273
|
+
(they never become :defined so would be permanently hidden). */
|
|
1274
|
+
:where(
|
|
1275
|
+
ui-accordion, ui-accordion-item,
|
|
1276
|
+
ui-avatar,
|
|
1277
|
+
ui-badge,
|
|
1278
|
+
ui-breadcrumb, ui-breadcrumb-item,
|
|
1279
|
+
ui-button,
|
|
1280
|
+
ui-calendar,
|
|
1281
|
+
ui-card,
|
|
1282
|
+
ui-chat-input,
|
|
1283
|
+
ui-checkbox,
|
|
1284
|
+
ui-combobox,
|
|
1285
|
+
ui-command, ui-command-empty, ui-command-group, ui-command-input, ui-command-item, ui-command-list,
|
|
1286
|
+
ui-controller,
|
|
1287
|
+
ui-dialog,
|
|
1288
|
+
ui-drawer,
|
|
1289
|
+
ui-field,
|
|
1290
|
+
ui-icon,
|
|
1291
|
+
ui-input,
|
|
1292
|
+
ui-input-otp,
|
|
1293
|
+
ui-kbd,
|
|
1294
|
+
ui-layout-chat,
|
|
1295
|
+
ui-layout-inspector,
|
|
1296
|
+
ui-layout-sidebar, ui-layout-sidebar-item,
|
|
1297
|
+
ui-listbox,
|
|
1298
|
+
ui-nav, ui-nav-group, ui-nav-group-header, ui-nav-item,
|
|
1299
|
+
ui-option, ui-option-group, ui-option-group-header,
|
|
1300
|
+
ui-pagination,
|
|
1301
|
+
ui-radio, ui-radio-group,
|
|
1302
|
+
ui-range,
|
|
1303
|
+
ui-section,
|
|
1304
|
+
ui-segment, ui-segmented-control,
|
|
1305
|
+
ui-select,
|
|
1306
|
+
ui-slide, ui-slideshow,
|
|
1307
|
+
ui-switch,
|
|
1308
|
+
ui-tab, ui-tab-panel, ui-tab-panels, ui-tabs,
|
|
1309
|
+
ui-table, ui-table-body, ui-table-cell, ui-table-head, ui-table-header, ui-table-row,
|
|
1310
|
+
ui-textarea,
|
|
1311
|
+
ui-toolbar,
|
|
1312
|
+
ui-tooltip,
|
|
1313
|
+
ui-tree, ui-tree-item
|
|
1314
|
+
):not(:defined) {
|
|
1315
|
+
visibility: hidden;
|
|
1316
|
+
}
|
|
1317
|
+
|
|
1270
1318
|
/* ── Document Defaults ── */
|
|
1271
1319
|
|
|
1272
1320
|
:where(:root) {
|
|
@@ -1460,7 +1508,7 @@
|
|
|
1460
1508
|
--ui-tooltip-max-width: 20rem;
|
|
1461
1509
|
|
|
1462
1510
|
/* Popover (select / combobox / command) */
|
|
1463
|
-
--ui-popover-max-height:
|
|
1511
|
+
--ui-popover-max-height: calc(100dvh - 2rem);
|
|
1464
1512
|
--ui-popover-gap: 0.25rem;
|
|
1465
1513
|
|
|
1466
1514
|
/* Drawer */
|
|
@@ -1493,6 +1541,18 @@
|
|
|
1493
1541
|
--ui-badge-size-xl: 1.375rem;
|
|
1494
1542
|
--ui-badge-dot: 0.5rem;
|
|
1495
1543
|
|
|
1544
|
+
/* Kbd */
|
|
1545
|
+
--ui-kbd-font-xs: 0.625rem;
|
|
1546
|
+
--ui-kbd-font-sm: 0.6875rem;
|
|
1547
|
+
--ui-kbd-font-md: 0.6875rem;
|
|
1548
|
+
--ui-kbd-font-lg: 0.75rem;
|
|
1549
|
+
--ui-kbd-font-xl: 0.8125rem;
|
|
1550
|
+
--ui-kbd-size-xs: 1rem;
|
|
1551
|
+
--ui-kbd-size-sm: 1.125rem;
|
|
1552
|
+
--ui-kbd-size-md: 1.25rem;
|
|
1553
|
+
--ui-kbd-size-lg: 1.375rem;
|
|
1554
|
+
--ui-kbd-size-xl: 1.5rem;
|
|
1555
|
+
|
|
1496
1556
|
/* Group header (option-group, table category) */
|
|
1497
1557
|
--ui-group-header-font: 0.625rem;
|
|
1498
1558
|
|
|
@@ -1606,6 +1666,8 @@
|
|
|
1606
1666
|
/* ── Intent (maps to color token families) ── */
|
|
1607
1667
|
|
|
1608
1668
|
:root {
|
|
1669
|
+
--_body: var(--neutral-body);
|
|
1670
|
+
|
|
1609
1671
|
--_card: var(--neutral-card);
|
|
1610
1672
|
--_card-hover: var(--neutral-card-hover);
|
|
1611
1673
|
|
|
@@ -1657,6 +1719,22 @@
|
|
|
1657
1719
|
--_ink-disabled: var(--neutral-ink-disabled);
|
|
1658
1720
|
}
|
|
1659
1721
|
|
|
1722
|
+
/* ── Toggle control defaults ── */
|
|
1723
|
+
/* WHY: Checkboxes, radios, switches, and range sliders use accent-colored
|
|
1724
|
+
surface fills for their checked/active states by default.
|
|
1725
|
+
[intent] selectors below override --_surface when an explicit intent is set. */
|
|
1726
|
+
|
|
1727
|
+
:where(ui-checkbox, ui-radio, ui-switch, ui-range) {
|
|
1728
|
+
--_surface: var(--accent-surface);
|
|
1729
|
+
--_surface-hover: var(--accent-surface-hover);
|
|
1730
|
+
--_surface-active: var(--accent-surface-active);
|
|
1731
|
+
--_surface-disabled: var(--accent-surface-disabled);
|
|
1732
|
+
--_surface-ink: var(--accent-surface-ink);
|
|
1733
|
+
--_surface-ink-hover: var(--accent-surface-ink-hover);
|
|
1734
|
+
--_surface-ink-active: var(--accent-surface-ink-active);
|
|
1735
|
+
--_surface-ink-disabled: var(--accent-surface-ink-disabled);
|
|
1736
|
+
}
|
|
1737
|
+
|
|
1660
1738
|
:where([intent="neutral"]) {
|
|
1661
1739
|
--_card: var(--neutral-card);
|
|
1662
1740
|
--_card-hover: var(--neutral-card-hover);
|
|
@@ -2365,7 +2443,7 @@
|
|
|
2365
2443
|
font-weight: var(--_font-weight);
|
|
2366
2444
|
|
|
2367
2445
|
border-radius: var(--_radius);
|
|
2368
|
-
border: 1px solid var(--_border-color, var(--
|
|
2446
|
+
border: 1px solid var(--_border-color, var(--_border-muted));
|
|
2369
2447
|
|
|
2370
2448
|
background: var(--_background, var(--_button));
|
|
2371
2449
|
color: var(--_color, var(--_ink));
|
|
@@ -2381,16 +2459,16 @@
|
|
|
2381
2459
|
/* ── States ── */
|
|
2382
2460
|
|
|
2383
2461
|
:where(ui-button):hover{
|
|
2384
|
-
background: var(--_background-hover, var(--
|
|
2462
|
+
background: var(--_background-hover, var(--_button-hover));
|
|
2385
2463
|
color: var(--_color-hover, var(--_ink-hover));
|
|
2386
|
-
border-color: var(--_border-color-hover, var(--
|
|
2464
|
+
border-color: var(--_border-color-hover, var(--_border-hover));
|
|
2387
2465
|
}
|
|
2388
2466
|
|
|
2389
2467
|
:where(ui-button):active,
|
|
2390
2468
|
:where(ui-button)[pressed]{
|
|
2391
|
-
background: var(--_background-active, var(--
|
|
2469
|
+
background: var(--_background-active, var(--_button-active));
|
|
2392
2470
|
color: var(--_color-active, var(--_ink-active));
|
|
2393
|
-
border-color: var(--_border-color-active, var(--
|
|
2471
|
+
border-color: var(--_border-color-active, var(--_border-active));
|
|
2394
2472
|
}
|
|
2395
2473
|
|
|
2396
2474
|
:where(ui-button):focus-visible{
|
|
@@ -2399,9 +2477,9 @@
|
|
|
2399
2477
|
}
|
|
2400
2478
|
|
|
2401
2479
|
:where(ui-button)[aria-disabled="true"] {
|
|
2402
|
-
background: var(--_background-disabled, var(--
|
|
2480
|
+
background: var(--_background-disabled, var(--_button-disabled));
|
|
2403
2481
|
color: var(--_color-disabled, var(--_ink-disabled));
|
|
2404
|
-
border-color: var(--_border-color-disabled, var(--
|
|
2482
|
+
border-color: var(--_border-color-disabled, var(--_border-muted));
|
|
2405
2483
|
cursor: not-allowed;
|
|
2406
2484
|
pointer-events: none;
|
|
2407
2485
|
}
|
|
@@ -2969,34 +3047,25 @@
|
|
|
2969
3047
|
}
|
|
2970
3048
|
|
|
2971
3049
|
/* ── Checked State ── */
|
|
2972
|
-
/* WHY: Default checked fill uses accent
|
|
2973
|
-
|
|
3050
|
+
/* WHY: Default checked fill uses --_surface (accent by default via
|
|
3051
|
+
intent="accent" being the implicit default for toggle controls).
|
|
2974
3052
|
When an explicit [intent] is set, the intent selector's --_surface wins. */
|
|
2975
3053
|
|
|
2976
3054
|
:where(ui-checkbox)[aria-checked="true"]::before {
|
|
2977
|
-
background: var(--accent-surface);
|
|
2978
|
-
border-color: var(--accent-surface);
|
|
2979
|
-
}
|
|
2980
|
-
|
|
2981
|
-
:where(ui-checkbox)[aria-checked="true"]::after {
|
|
2982
|
-
background: var(--accent-surface-ink);
|
|
2983
|
-
transform: translateY(-50%) scale(1);
|
|
2984
|
-
}
|
|
2985
|
-
|
|
2986
|
-
:where(ui-checkbox)[intent][aria-checked="true"]::before {
|
|
2987
3055
|
background: var(--_surface);
|
|
2988
3056
|
border-color: var(--_surface);
|
|
2989
3057
|
}
|
|
2990
3058
|
|
|
2991
|
-
:where(ui-checkbox)[
|
|
3059
|
+
:where(ui-checkbox)[aria-checked="true"]::after {
|
|
2992
3060
|
background: var(--_surface-ink);
|
|
3061
|
+
transform: translateY(-50%) scale(1);
|
|
2993
3062
|
}
|
|
2994
3063
|
|
|
2995
3064
|
/* ── Indeterminate State ── */
|
|
2996
3065
|
|
|
2997
3066
|
:where(ui-checkbox)[aria-checked="mixed"]::before {
|
|
2998
|
-
background: var(--
|
|
2999
|
-
border-color: var(--
|
|
3067
|
+
background: var(--_surface);
|
|
3068
|
+
border-color: var(--_surface);
|
|
3000
3069
|
}
|
|
3001
3070
|
|
|
3002
3071
|
:where(ui-checkbox)[aria-checked="mixed"]::after {
|
|
@@ -3004,17 +3073,8 @@
|
|
|
3004
3073
|
-webkit-mask-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' fill='currentColor' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M228,128a12,12,0,0,1-12,12H40a12,12,0,0,1,0-24H216A12,12,0,0,1,228,128Z'/%3E%3C/svg%3E");
|
|
3005
3074
|
mask-size: 75%;
|
|
3006
3075
|
-webkit-mask-size: 75%;
|
|
3007
|
-
background: var(--accent-surface-ink);
|
|
3008
|
-
transform: translateY(-50%) scale(1);
|
|
3009
|
-
}
|
|
3010
|
-
|
|
3011
|
-
:where(ui-checkbox)[intent][aria-checked="mixed"]::before {
|
|
3012
|
-
background: var(--_surface);
|
|
3013
|
-
border-color: var(--_surface);
|
|
3014
|
-
}
|
|
3015
|
-
|
|
3016
|
-
:where(ui-checkbox)[intent][aria-checked="mixed"]::after {
|
|
3017
3076
|
background: var(--_surface-ink);
|
|
3077
|
+
transform: translateY(-50%) scale(1);
|
|
3018
3078
|
}
|
|
3019
3079
|
|
|
3020
3080
|
/* ── Hover ── */
|
|
@@ -3031,13 +3091,6 @@
|
|
|
3031
3091
|
:where(ui-checkbox)[aria-checked="true"]:hover::before,
|
|
3032
3092
|
:where(ui-checkbox)[aria-checked="mixed"]:hover::before
|
|
3033
3093
|
:where(ui-checkbox)[aria-checked="mixed"][force-hover]::before {
|
|
3034
|
-
background: var(--accent-surface-hover);
|
|
3035
|
-
border-color: var(--accent-surface-hover);
|
|
3036
|
-
}
|
|
3037
|
-
|
|
3038
|
-
:where(ui-checkbox)[intent][aria-checked="true"]:hover::before,
|
|
3039
|
-
:where(ui-checkbox)[intent][aria-checked="mixed"]:hover::before
|
|
3040
|
-
:where(ui-checkbox)[intent][aria-checked="mixed"][force-hover]::before {
|
|
3041
3094
|
background: var(--_surface-hover);
|
|
3042
3095
|
border-color: var(--_surface-hover);
|
|
3043
3096
|
}
|
|
@@ -3051,12 +3104,6 @@
|
|
|
3051
3104
|
|
|
3052
3105
|
:where(ui-checkbox)[aria-checked="true"][pressed]::before,
|
|
3053
3106
|
:where(ui-checkbox)[aria-checked="mixed"][pressed]::before {
|
|
3054
|
-
background: var(--accent-surface-active);
|
|
3055
|
-
border-color: var(--accent-surface-active);
|
|
3056
|
-
}
|
|
3057
|
-
|
|
3058
|
-
:where(ui-checkbox)[intent][aria-checked="true"][pressed]::before,
|
|
3059
|
-
:where(ui-checkbox)[intent][aria-checked="mixed"][pressed]::before {
|
|
3060
3107
|
background: var(--_surface-active);
|
|
3061
3108
|
border-color: var(--_surface-active);
|
|
3062
3109
|
}
|
|
@@ -3703,6 +3750,45 @@
|
|
|
3703
3750
|
|
|
3704
3751
|
}
|
|
3705
3752
|
|
|
3753
|
+
@layer ui {
|
|
3754
|
+
|
|
3755
|
+
/* ╭──────────────────────────────────────────────────────────╮
|
|
3756
|
+
│ ui-kbd │
|
|
3757
|
+
│ Keyboard shortcut indicator. Own font/size scale │
|
|
3758
|
+
│ (like ui-badge) — zero-attribute = md. │
|
|
3759
|
+
╰──────────────────────────────────────────────────────────╯ */
|
|
3760
|
+
|
|
3761
|
+
:where(ui-kbd) {
|
|
3762
|
+
--_icon-size: 1.125em;
|
|
3763
|
+
|
|
3764
|
+
display: inline-flex;
|
|
3765
|
+
align-items: center;
|
|
3766
|
+
justify-content: center;
|
|
3767
|
+
font-family: ui-monospace, monospace;
|
|
3768
|
+
font-size: var(--ui-kbd-font-md);
|
|
3769
|
+
line-height: 1;
|
|
3770
|
+
min-height: var(--ui-kbd-size-md);
|
|
3771
|
+
padding-inline: 0.4em;
|
|
3772
|
+
border-radius: 0.5em;
|
|
3773
|
+
background: var(--_ground, var(--_body));
|
|
3774
|
+
border: 1px solid var(--_border-muted);
|
|
3775
|
+
color: var(--_ink-muted);
|
|
3776
|
+
white-space: nowrap;
|
|
3777
|
+
user-select: none;
|
|
3778
|
+
flex-shrink: 0;
|
|
3779
|
+
vertical-align: baseline;
|
|
3780
|
+
}
|
|
3781
|
+
|
|
3782
|
+
/* ── Sizes ── */
|
|
3783
|
+
|
|
3784
|
+
:where(ui-kbd[size="xs"]) { font-size: var(--ui-kbd-font-xs); min-height: var(--ui-kbd-size-xs); }
|
|
3785
|
+
:where(ui-kbd[size="sm"]) { font-size: var(--ui-kbd-font-sm); min-height: var(--ui-kbd-size-sm); }
|
|
3786
|
+
:where(ui-kbd[size="md"]) { font-size: var(--ui-kbd-font-md); min-height: var(--ui-kbd-size-md); }
|
|
3787
|
+
:where(ui-kbd[size="lg"]) { font-size: var(--ui-kbd-font-lg); min-height: var(--ui-kbd-size-lg); }
|
|
3788
|
+
:where(ui-kbd[size="xl"]) { font-size: var(--ui-kbd-font-xl); min-height: var(--ui-kbd-size-xl); }
|
|
3789
|
+
|
|
3790
|
+
}
|
|
3791
|
+
|
|
3706
3792
|
@layer ui {
|
|
3707
3793
|
|
|
3708
3794
|
/* ── Listbox Base ── */
|
|
@@ -3840,11 +3926,14 @@
|
|
|
3840
3926
|
│ Uses ui-nav-item / ui-nav-group for children. │
|
|
3841
3927
|
╰──────────────────────────────────────────────────────────╯ */
|
|
3842
3928
|
|
|
3929
|
+
/* WHY: ui-nav is a transparent flex wrapper — no inline padding.
|
|
3930
|
+
Inline padding is owned by leaf items (nav-item, summary).
|
|
3931
|
+
Block padding is owned by nav-group margins. */
|
|
3843
3932
|
:where(ui-nav) {
|
|
3844
3933
|
display: flex;
|
|
3845
3934
|
flex-direction: column;
|
|
3846
3935
|
gap: 0;
|
|
3847
|
-
padding:
|
|
3936
|
+
padding: 0;
|
|
3848
3937
|
outline: none;
|
|
3849
3938
|
}
|
|
3850
3939
|
|
|
@@ -3859,6 +3948,7 @@
|
|
|
3859
3948
|
display: flex;
|
|
3860
3949
|
align-items: center;
|
|
3861
3950
|
gap: calc(var(--_space) * 2);
|
|
3951
|
+
padding-inline: calc(var(--_space-k) * var(--_space));
|
|
3862
3952
|
|
|
3863
3953
|
min-height: var(--_min-height);
|
|
3864
3954
|
|
|
@@ -3955,6 +4045,7 @@
|
|
|
3955
4045
|
display: flex;
|
|
3956
4046
|
align-items: center;
|
|
3957
4047
|
gap: calc(var(--_space) * 2);
|
|
4048
|
+
padding-inline: calc(var(--_space-k) * var(--_space));
|
|
3958
4049
|
cursor: pointer;
|
|
3959
4050
|
user-select: none;
|
|
3960
4051
|
list-style: none;
|
|
@@ -3989,6 +4080,18 @@
|
|
|
3989
4080
|
user-select: none;
|
|
3990
4081
|
}
|
|
3991
4082
|
|
|
4083
|
+
/* WHY: Fixed-size icon well — matches ui-layout-sidebar-item [slot="icon"].
|
|
4084
|
+
All sidebar icons align on the same 1.5rem column regardless of icon size.
|
|
4085
|
+
JS wraps the first <ui-icon> child in a .icon-well span during setup(). */
|
|
4086
|
+
:where(ui-nav-group-header) > :where(.icon-well) {
|
|
4087
|
+
display: inline-flex;
|
|
4088
|
+
align-items: center;
|
|
4089
|
+
justify-content: center;
|
|
4090
|
+
width: 1.5rem;
|
|
4091
|
+
height: 1.5rem;
|
|
4092
|
+
flex-shrink: 0;
|
|
4093
|
+
}
|
|
4094
|
+
|
|
3992
4095
|
/* ── Chevron icon (right side of summary) ── */
|
|
3993
4096
|
|
|
3994
4097
|
:where(ui-nav-group) > :where(details) > :where(summary)::after {
|
|
@@ -4040,12 +4143,16 @@
|
|
|
4040
4143
|
/* WHY: Connector draws from below the header to the bottom of the group.
|
|
4041
4144
|
Only shown when header contains an icon. Scoped via :has(). */
|
|
4042
4145
|
|
|
4043
|
-
:
|
|
4044
|
-
|
|
4045
|
-
|
|
4146
|
+
/* WHY: Insets account for the summary's padding-inline so the connector
|
|
4147
|
+
line passes through the icon center and child text aligns with header text. */
|
|
4148
|
+
:where(ui-nav-group):has(:where(ui-nav-group-header) :where(.icon-well)) {
|
|
4149
|
+
--_group-pad: calc(var(--_space-k) * var(--_space));
|
|
4150
|
+
--_group-icon-well: 1.5rem;
|
|
4151
|
+
--_group-line-inset: calc(var(--_group-pad) + var(--_group-icon-well) / 2);
|
|
4152
|
+
--_group-child-inset: calc(var(--_group-icon-well) + var(--_space) * 2);
|
|
4046
4153
|
}
|
|
4047
4154
|
|
|
4048
|
-
:where(ui-nav-group):has(:where(ui-nav-group-header) :where(
|
|
4155
|
+
:where(ui-nav-group):has(:where(ui-nav-group-header) :where(.icon-well)):has(:where(details[open]))::after {
|
|
4049
4156
|
content: '';
|
|
4050
4157
|
position: absolute;
|
|
4051
4158
|
inset-inline-start: var(--_group-line-inset);
|
|
@@ -4060,7 +4167,7 @@
|
|
|
4060
4167
|
/* WHY: A ::before pseudo on the group slides along the connector line.
|
|
4061
4168
|
JS sets --_indicator-index; :state(has-selection) gates visibility. */
|
|
4062
4169
|
|
|
4063
|
-
:where(ui-nav-group):has(:where(ui-nav-group-header) :where(
|
|
4170
|
+
:where(ui-nav-group):has(:where(ui-nav-group-header) :where(.icon-well)):has(:where(details[open])):state(has-selection)::before {
|
|
4064
4171
|
content: '';
|
|
4065
4172
|
position: absolute;
|
|
4066
4173
|
z-index: 1;
|
|
@@ -4087,6 +4194,73 @@
|
|
|
4087
4194
|
margin-inline-start: var(--_group-child-inset, 0);
|
|
4088
4195
|
}
|
|
4089
4196
|
|
|
4197
|
+
/* ── Nav Group Flyout (collapsed sidebar) ── */
|
|
4198
|
+
/* WHY: In collapsed mode, summary click opens a ui-listbox popover to the right
|
|
4199
|
+
instead of expanding the <details>. Same pattern as sidebar-trigger menus. */
|
|
4200
|
+
|
|
4201
|
+
:where(ui-nav-group) > :where(ui-listbox.nav-group-flyout[popover]) {
|
|
4202
|
+
position: fixed;
|
|
4203
|
+
position-area: inline-end span-block-end;
|
|
4204
|
+
position-try-fallbacks: --nav-flyout-flip-up;
|
|
4205
|
+
margin: 0 0 0 var(--ui-popover-gap);
|
|
4206
|
+
min-width: 200px;
|
|
4207
|
+
max-height: var(--ui-popover-max-height);
|
|
4208
|
+
overflow-y: auto;
|
|
4209
|
+
}
|
|
4210
|
+
|
|
4211
|
+
@position-try --nav-flyout-flip-up {
|
|
4212
|
+
position-area: inline-end span-block-start;
|
|
4213
|
+
}
|
|
4214
|
+
|
|
4215
|
+
/* ── Container Query: Collapsed Sidebar ── */
|
|
4216
|
+
/* WHY: Nav components own their own collapsed behavior via @container.
|
|
4217
|
+
The sidebar aside declares container-name: sidebar. When it shrinks
|
|
4218
|
+
to 48px (icon rail), nav responds to the width — not to [collapsed].
|
|
4219
|
+
Threshold 80px: collapsed = 48px, min expanded = 160px. */
|
|
4220
|
+
|
|
4221
|
+
@container sidebar (max-width: 80px) {
|
|
4222
|
+
|
|
4223
|
+
/* Nav items hide entirely — only group headers (with icons) remain. */
|
|
4224
|
+
:where(ui-nav-item) {
|
|
4225
|
+
display: none;
|
|
4226
|
+
}
|
|
4227
|
+
|
|
4228
|
+
/* Summary shrinks to icon-only. Reduced inline padding wraps tightly
|
|
4229
|
+
around the icon; parent align-items: center handles horizontal centering. */
|
|
4230
|
+
:where(ui-nav-group) > :where(details) > :where(summary) {
|
|
4231
|
+
padding-inline: var(--_space);
|
|
4232
|
+
border-radius: var(--_radius);
|
|
4233
|
+
}
|
|
4234
|
+
|
|
4235
|
+
/* Hide chevron — no expand/collapse in icon rail (flyout instead). */
|
|
4236
|
+
:where(ui-nav-group) > :where(details) > :where(summary)::after {
|
|
4237
|
+
display: none;
|
|
4238
|
+
}
|
|
4239
|
+
|
|
4240
|
+
/* Hide vertical connector line and sliding indicator. */
|
|
4241
|
+
:where(ui-nav-group)::after,
|
|
4242
|
+
:where(ui-nav-group)::before {
|
|
4243
|
+
display: none;
|
|
4244
|
+
}
|
|
4245
|
+
|
|
4246
|
+
/* Header collapses to icon-only. font-size: 0 hides text nodes
|
|
4247
|
+
(can't be targeted by CSS). Icon overrides back to normal below. */
|
|
4248
|
+
:where(ui-nav-group-header) {
|
|
4249
|
+
flex: 0 0 auto;
|
|
4250
|
+
font-size: 0;
|
|
4251
|
+
gap: 0;
|
|
4252
|
+
}
|
|
4253
|
+
|
|
4254
|
+
:where(ui-nav-group-header) :where(.icon-well) :where(ui-icon) {
|
|
4255
|
+
font-size: var(--_font-size, 1rem);
|
|
4256
|
+
}
|
|
4257
|
+
|
|
4258
|
+
/* Collapse inter-group spacing in icon rail. */
|
|
4259
|
+
:where(ui-nav-group) + :where(ui-nav-group) {
|
|
4260
|
+
margin-block-start: 0;
|
|
4261
|
+
}
|
|
4262
|
+
}
|
|
4263
|
+
|
|
4090
4264
|
}
|
|
4091
4265
|
|
|
4092
4266
|
@layer ui {
|
|
@@ -4227,27 +4401,15 @@
|
|
|
4227
4401
|
}
|
|
4228
4402
|
|
|
4229
4403
|
/* ── Selected ── */
|
|
4230
|
-
/* WHY: Default selected fill uses accent so radio is visually distinct
|
|
4231
|
-
without needing intent="accent". Unchecked borders stay neutral.
|
|
4232
|
-
When an explicit [intent] is set, the intent selector's --_surface wins. */
|
|
4233
4404
|
|
|
4234
4405
|
:where(ui-radio)[aria-checked="true"]::before {
|
|
4235
|
-
background: var(--accent-surface);
|
|
4236
|
-
border-color: var(--accent-surface);
|
|
4237
|
-
}
|
|
4238
|
-
|
|
4239
|
-
:where(ui-radio)[aria-checked="true"]::after {
|
|
4240
|
-
background: var(--accent-surface-ink);
|
|
4241
|
-
transform: translateY(-50%) scale(1);
|
|
4242
|
-
}
|
|
4243
|
-
|
|
4244
|
-
:where(ui-radio-group)[intent] :where(ui-radio)[aria-checked="true"]::before {
|
|
4245
4406
|
background: var(--_surface);
|
|
4246
4407
|
border-color: var(--_surface);
|
|
4247
4408
|
}
|
|
4248
4409
|
|
|
4249
|
-
:where(ui-radio
|
|
4410
|
+
:where(ui-radio)[aria-checked="true"]::after {
|
|
4250
4411
|
background: var(--_surface-ink);
|
|
4412
|
+
transform: translateY(-50%) scale(1);
|
|
4251
4413
|
}
|
|
4252
4414
|
|
|
4253
4415
|
/* ── Hover ── */
|
|
@@ -4262,11 +4424,6 @@
|
|
|
4262
4424
|
}
|
|
4263
4425
|
|
|
4264
4426
|
:where(ui-radio)[aria-checked="true"]:hover::before{
|
|
4265
|
-
background: var(--accent-surface-hover);
|
|
4266
|
-
border-color: var(--accent-surface-hover);
|
|
4267
|
-
}
|
|
4268
|
-
|
|
4269
|
-
:where(ui-radio-group)[intent] :where(ui-radio)[aria-checked="true"]:hover::before{
|
|
4270
4427
|
background: var(--_surface-hover);
|
|
4271
4428
|
border-color: var(--_surface-hover);
|
|
4272
4429
|
}
|
|
@@ -4279,11 +4436,6 @@
|
|
|
4279
4436
|
}
|
|
4280
4437
|
|
|
4281
4438
|
:where(ui-radio)[aria-checked="true"][pressed]::before {
|
|
4282
|
-
background: var(--accent-surface-active);
|
|
4283
|
-
border-color: var(--accent-surface-active);
|
|
4284
|
-
}
|
|
4285
|
-
|
|
4286
|
-
:where(ui-radio-group)[intent] :where(ui-radio)[aria-checked="true"][pressed]::before {
|
|
4287
4439
|
background: var(--_surface-active);
|
|
4288
4440
|
border-color: var(--_surface-active);
|
|
4289
4441
|
}
|
|
@@ -4381,16 +4533,12 @@
|
|
|
4381
4533
|
/* 0% = track-height (circle), 100% = full width */
|
|
4382
4534
|
width: calc(var(--_track-height) + (100% - var(--_track-height)) * var(--_progress));
|
|
4383
4535
|
border-radius: calc(var(--_track-height) / 2);
|
|
4384
|
-
background: var(--
|
|
4536
|
+
background: var(--_surface);
|
|
4385
4537
|
|
|
4386
4538
|
transition:
|
|
4387
4539
|
background var(--_duration) var(--_easing);
|
|
4388
4540
|
}
|
|
4389
4541
|
|
|
4390
|
-
:where(ui-range)[intent]::after {
|
|
4391
|
-
background: var(--_surface);
|
|
4392
|
-
}
|
|
4393
|
-
|
|
4394
4542
|
/* ── Thumb ── */
|
|
4395
4543
|
|
|
4396
4544
|
:where(ui-range) > :where(.ui-range-thumb) {
|
|
@@ -4402,8 +4550,8 @@
|
|
|
4402
4550
|
width: var(--_thumb-size);
|
|
4403
4551
|
height: var(--_thumb-size);
|
|
4404
4552
|
border-radius: 50%;
|
|
4405
|
-
background: var(--
|
|
4406
|
-
border: 2px solid var(--
|
|
4553
|
+
background: var(--_surface-ink);
|
|
4554
|
+
border: 2px solid var(--_surface);
|
|
4407
4555
|
box-shadow: var(--ui-shadow-sm);
|
|
4408
4556
|
pointer-events: none;
|
|
4409
4557
|
|
|
@@ -4413,11 +4561,6 @@
|
|
|
4413
4561
|
border-color var(--_duration) var(--_easing);
|
|
4414
4562
|
}
|
|
4415
4563
|
|
|
4416
|
-
:where(ui-range)[intent] > :where(.ui-range-thumb) {
|
|
4417
|
-
background: var(--_surface-ink);
|
|
4418
|
-
border-color: var(--_surface);
|
|
4419
|
-
}
|
|
4420
|
-
|
|
4421
4564
|
/* ── Focus ── */
|
|
4422
4565
|
|
|
4423
4566
|
:where(ui-range):focus-visible > :where(.ui-range-thumb){
|
|
@@ -4428,19 +4571,10 @@
|
|
|
4428
4571
|
/* ── Hover ── */
|
|
4429
4572
|
|
|
4430
4573
|
:where(ui-range):hover::after{
|
|
4431
|
-
background: var(--accent-surface-hover);
|
|
4432
|
-
}
|
|
4433
|
-
|
|
4434
|
-
:where(ui-range)[intent]:hover::after{
|
|
4435
4574
|
background: var(--_surface-hover);
|
|
4436
4575
|
}
|
|
4437
4576
|
|
|
4438
4577
|
:where(ui-range):hover > :where(.ui-range-thumb){
|
|
4439
|
-
border-color: var(--accent-surface-hover);
|
|
4440
|
-
box-shadow: var(--ui-shadow-sm), 0 0 0 4px var(--accent-surface);
|
|
4441
|
-
}
|
|
4442
|
-
|
|
4443
|
-
:where(ui-range)[intent]:hover > :where(.ui-range-thumb){
|
|
4444
4578
|
border-color: var(--_surface-hover);
|
|
4445
4579
|
box-shadow: var(--ui-shadow-sm), 0 0 0 4px var(--_surface);
|
|
4446
4580
|
}
|
|
@@ -4448,19 +4582,10 @@
|
|
|
4448
4582
|
/* ── Active (dragging) ── */
|
|
4449
4583
|
|
|
4450
4584
|
:where(ui-range)[pressed]::after {
|
|
4451
|
-
background: var(--accent-surface-active);
|
|
4452
|
-
}
|
|
4453
|
-
|
|
4454
|
-
:where(ui-range)[intent][pressed]::after {
|
|
4455
4585
|
background: var(--_surface-active);
|
|
4456
4586
|
}
|
|
4457
4587
|
|
|
4458
4588
|
:where(ui-range)[pressed] > :where(.ui-range-thumb) {
|
|
4459
|
-
border-color: var(--accent-surface-active);
|
|
4460
|
-
box-shadow: var(--ui-shadow-sm), 0 0 0 6px var(--accent-surface);
|
|
4461
|
-
}
|
|
4462
|
-
|
|
4463
|
-
:where(ui-range)[intent][pressed] > :where(.ui-range-thumb) {
|
|
4464
4589
|
border-color: var(--_surface-active);
|
|
4465
4590
|
box-shadow: var(--ui-shadow-sm), 0 0 0 6px var(--_surface);
|
|
4466
4591
|
}
|
|
@@ -5007,22 +5132,13 @@
|
|
|
5007
5132
|
When an explicit [intent] is set, the intent selector's --_surface wins. */
|
|
5008
5133
|
|
|
5009
5134
|
:where(ui-switch)[aria-checked="true"]::before {
|
|
5010
|
-
background: var(--
|
|
5011
|
-
border-color: var(--
|
|
5135
|
+
background: var(--_surface);
|
|
5136
|
+
border-color: var(--_surface);
|
|
5012
5137
|
}
|
|
5013
5138
|
|
|
5014
5139
|
:where(ui-switch)[aria-checked="true"]::after {
|
|
5015
5140
|
/* Slide thumb to the right via translateX — GPU composited */
|
|
5016
5141
|
transform: translateY(-50%) translateX(calc(var(--_track-width) - var(--_thumb-size) - var(--_thumb-offset) * 2));
|
|
5017
|
-
background: var(--accent-surface-ink);
|
|
5018
|
-
}
|
|
5019
|
-
|
|
5020
|
-
:where(ui-switch)[intent][aria-checked="true"]::before {
|
|
5021
|
-
background: var(--_surface);
|
|
5022
|
-
border-color: var(--_surface);
|
|
5023
|
-
}
|
|
5024
|
-
|
|
5025
|
-
:where(ui-switch)[intent][aria-checked="true"]::after {
|
|
5026
5142
|
background: var(--_surface-ink);
|
|
5027
5143
|
}
|
|
5028
5144
|
|
|
@@ -5038,11 +5154,6 @@
|
|
|
5038
5154
|
}
|
|
5039
5155
|
|
|
5040
5156
|
:where(ui-switch)[aria-checked="true"]:hover::before{
|
|
5041
|
-
background: var(--accent-surface-hover);
|
|
5042
|
-
border-color: var(--accent-surface-hover);
|
|
5043
|
-
}
|
|
5044
|
-
|
|
5045
|
-
:where(ui-switch)[intent][aria-checked="true"]:hover::before{
|
|
5046
5157
|
background: var(--_surface-hover);
|
|
5047
5158
|
border-color: var(--_surface-hover);
|
|
5048
5159
|
}
|
|
@@ -5055,11 +5166,6 @@
|
|
|
5055
5166
|
}
|
|
5056
5167
|
|
|
5057
5168
|
:where(ui-switch)[aria-checked="true"][pressed]::before {
|
|
5058
|
-
background: var(--accent-surface-active);
|
|
5059
|
-
border-color: var(--accent-surface-active);
|
|
5060
|
-
}
|
|
5061
|
-
|
|
5062
|
-
:where(ui-switch)[intent][aria-checked="true"][pressed]::before {
|
|
5063
5169
|
background: var(--_surface-active);
|
|
5064
5170
|
border-color: var(--_surface-active);
|
|
5065
5171
|
}
|
|
@@ -6498,7 +6604,7 @@
|
|
|
6498
6604
|
|
|
6499
6605
|
:where(ui-layout-chat) :where(.layout-resize-handle):hover,
|
|
6500
6606
|
:where(ui-layout-chat[resizing]) :where(.layout-resize-handle) {
|
|
6501
|
-
background: var(--
|
|
6607
|
+
background: var(--_border-muted);
|
|
6502
6608
|
}
|
|
6503
6609
|
|
|
6504
6610
|
}
|
|
@@ -6560,7 +6666,7 @@
|
|
|
6560
6666
|
|
|
6561
6667
|
:where(ui-layout-inspector) :where(.layout-resize-handle):hover,
|
|
6562
6668
|
:where(ui-layout-inspector[resizing]) :where(.layout-resize-handle) {
|
|
6563
|
-
background: var(--
|
|
6669
|
+
background: var(--_border-muted);
|
|
6564
6670
|
}
|
|
6565
6671
|
|
|
6566
6672
|
}
|
|
@@ -6587,16 +6693,16 @@
|
|
|
6587
6693
|
content: '';
|
|
6588
6694
|
width: var(--ui-layout-sidebar-width);
|
|
6589
6695
|
flex-shrink: 0;
|
|
6590
|
-
background: var(--
|
|
6591
|
-
border-right: 1px solid var(--
|
|
6696
|
+
background: var(--_body);
|
|
6697
|
+
border-right: 1px solid var(--_border-muted);
|
|
6592
6698
|
}
|
|
6593
6699
|
|
|
6594
6700
|
:where(ui-layout-sidebar):not([data-ready])[collapsed]::before {
|
|
6595
6701
|
content: '';
|
|
6596
6702
|
width: 48px;
|
|
6597
6703
|
flex-shrink: 0;
|
|
6598
|
-
background: var(--
|
|
6599
|
-
border-right: 1px solid var(--
|
|
6704
|
+
background: var(--_body);
|
|
6705
|
+
border-right: 1px solid var(--_border-muted);
|
|
6600
6706
|
}
|
|
6601
6707
|
|
|
6602
6708
|
/* ── Content Column ── */
|
|
@@ -6612,16 +6718,23 @@
|
|
|
6612
6718
|
}
|
|
6613
6719
|
|
|
6614
6720
|
/* ── Sidebar Aside ── */
|
|
6721
|
+
/* WHY: position: relative creates the containing block for absolute
|
|
6722
|
+
header/footer overlays. Content fills the full height and scrolls
|
|
6723
|
+
underneath the pinned header/footer. */
|
|
6615
6724
|
|
|
6616
6725
|
:where(ui-layout-sidebar) > :where([slot="sidebar"]) {
|
|
6726
|
+
--_sidebar-header-height: 0px;
|
|
6727
|
+
--_sidebar-footer-height: 0px;
|
|
6728
|
+
|
|
6729
|
+
container-name: sidebar;
|
|
6730
|
+
container-type: inline-size;
|
|
6731
|
+
position: sticky;
|
|
6732
|
+
top: 0;
|
|
6617
6733
|
width: var(--ui-layout-sidebar-width);
|
|
6618
6734
|
min-width: 160px;
|
|
6619
6735
|
max-width: 400px;
|
|
6620
6736
|
height: 100dvh;
|
|
6621
|
-
|
|
6622
|
-
top: 0;
|
|
6623
|
-
display: flex;
|
|
6624
|
-
flex-direction: column;
|
|
6737
|
+
display: block;
|
|
6625
6738
|
transition: width var(--_duration) var(--_easing), min-width var(--_duration) var(--_easing);
|
|
6626
6739
|
overflow: hidden;
|
|
6627
6740
|
z-index: 10;
|
|
@@ -6633,7 +6746,9 @@
|
|
|
6633
6746
|
}
|
|
6634
6747
|
|
|
6635
6748
|
/* ── Collapsed Icon Rail ── */
|
|
6636
|
-
/* WHY: Collapsed = icon rail, not fully hidden. 48px fits icons (1rem) + padding.
|
|
6749
|
+
/* WHY: Collapsed = icon rail, not fully hidden. 48px fits icons (1rem) + padding.
|
|
6750
|
+
[collapsed] drives the aside to 48px which triggers @container sidebar queries
|
|
6751
|
+
in this file and in child component CSS (ui-nav.css, etc.). */
|
|
6637
6752
|
|
|
6638
6753
|
:where(ui-layout-sidebar)[collapsed] > :where([slot="sidebar"]) {
|
|
6639
6754
|
width: 48px;
|
|
@@ -6654,11 +6769,7 @@
|
|
|
6654
6769
|
|
|
6655
6770
|
:where(ui-layout-sidebar) :where(.layout-resize-handle):hover,
|
|
6656
6771
|
:where(ui-layout-sidebar) > :where([slot="sidebar"][resizing]) :where(.layout-resize-handle) {
|
|
6657
|
-
background: var(--
|
|
6658
|
-
}
|
|
6659
|
-
|
|
6660
|
-
:where(ui-layout-sidebar)[collapsed] > :where([slot="sidebar"]) :where(.layout-resize-handle) {
|
|
6661
|
-
display: none;
|
|
6772
|
+
background: var(--_border-muted);
|
|
6662
6773
|
}
|
|
6663
6774
|
|
|
6664
6775
|
/* WHY: When collapsed to icon rail, the sidebar edge meets content — drop left padding. */
|
|
@@ -6671,101 +6782,89 @@
|
|
|
6671
6782
|
padding-left: 0;
|
|
6672
6783
|
}
|
|
6673
6784
|
|
|
6674
|
-
/* ── Collapsed Icon-Rail Content ── */
|
|
6675
|
-
/* WHY: When collapsed, sidebar slot becomes a narrow icon rail.
|
|
6676
|
-
Text and trailing slots are hidden; only icons remain visible.
|
|
6677
|
-
Nav items hide entirely — only group headers (with icons) stay. */
|
|
6678
|
-
|
|
6679
|
-
:where(ui-layout-sidebar)[collapsed] :where([slot="sidebar"]) :where(ui-layout-sidebar-content) {
|
|
6680
|
-
align-items: center;
|
|
6681
|
-
padding: 0.5rem;
|
|
6682
|
-
}
|
|
6683
|
-
|
|
6684
|
-
:where(ui-layout-sidebar)[collapsed] :where([slot="sidebar"]) :where(ui-layout-sidebar-header),
|
|
6685
|
-
:where(ui-layout-sidebar)[collapsed] :where([slot="sidebar"]) :where(ui-layout-sidebar-footer) {
|
|
6686
|
-
justify-content: center;
|
|
6687
|
-
padding-inline: 0.5rem;
|
|
6688
|
-
}
|
|
6689
|
-
|
|
6690
|
-
:where(ui-layout-sidebar)[collapsed] :where([slot="sidebar"]) :where(ui-layout-sidebar-trigger) :where([slot="label"]),
|
|
6691
|
-
:where(ui-layout-sidebar)[collapsed] :where([slot="sidebar"]) :where(ui-layout-sidebar-trigger) :where([slot="trailing"]) {
|
|
6692
|
-
display: none;
|
|
6693
|
-
}
|
|
6694
|
-
|
|
6695
|
-
:where(ui-layout-sidebar)[collapsed] :where([slot="sidebar"]) :where(ui-nav-item) {
|
|
6696
|
-
display: none;
|
|
6697
|
-
}
|
|
6698
|
-
|
|
6699
|
-
:where(ui-layout-sidebar)[collapsed] :where([slot="sidebar"]) :where(ui-nav-group) > :where(details) > :where(summary) {
|
|
6700
|
-
justify-content: center;
|
|
6701
|
-
}
|
|
6702
|
-
|
|
6703
|
-
:where(ui-layout-sidebar)[collapsed] :where([slot="sidebar"]) :where(ui-nav-group) > :where(details) > :where(summary)::after {
|
|
6704
|
-
display: none;
|
|
6705
|
-
}
|
|
6706
|
-
|
|
6707
|
-
:where(ui-layout-sidebar)[collapsed] :where([slot="sidebar"]) :where(ui-nav-group)::after,
|
|
6708
|
-
:where(ui-layout-sidebar)[collapsed] :where([slot="sidebar"]) :where(ui-nav-group)::before {
|
|
6709
|
-
display: none;
|
|
6710
|
-
}
|
|
6711
|
-
|
|
6712
|
-
:where(ui-layout-sidebar)[collapsed] :where([slot="sidebar"]) :where(ui-nav-group-header) {
|
|
6713
|
-
justify-content: center;
|
|
6714
|
-
font-size: 0;
|
|
6715
|
-
gap: 0;
|
|
6716
|
-
}
|
|
6717
|
-
|
|
6718
|
-
/* WHY: Icon keeps its size even though parent font-size is 0. */
|
|
6719
|
-
:where(ui-layout-sidebar)[collapsed] :where([slot="sidebar"]) :where(ui-nav-group-header) :where(ui-icon) {
|
|
6720
|
-
font-size: var(--_font-size, 1rem);
|
|
6721
|
-
}
|
|
6722
|
-
|
|
6723
|
-
:where(ui-layout-sidebar)[collapsed] :where([slot="sidebar"]) :where(ui-nav-group) + :where(ui-nav-group) {
|
|
6724
|
-
margin-block-start: 0;
|
|
6725
|
-
}
|
|
6726
|
-
|
|
6727
6785
|
/* ── Sidebar Header ── */
|
|
6786
|
+
/* WHY: Absolute-positioned overlay pinned to top of aside. Content scrolls
|
|
6787
|
+
underneath it. z-index: 2 sits above content (z-index: 0). */
|
|
6728
6788
|
|
|
6729
6789
|
:where(ui-layout-sidebar-header) {
|
|
6790
|
+
position: absolute;
|
|
6791
|
+
top: 0;
|
|
6792
|
+
left: 0;
|
|
6793
|
+
right: 0;
|
|
6794
|
+
z-index: 2;
|
|
6730
6795
|
display: flex;
|
|
6731
|
-
|
|
6732
|
-
min-height: var(--ui-layout-bar-height);
|
|
6733
|
-
gap: calc(var(--_space) * 2);
|
|
6734
|
-
padding-block: var(--_space);
|
|
6735
|
-
padding-inline: calc(var(--_space-k) * var(--_space));
|
|
6736
|
-
flex-shrink: 0;
|
|
6796
|
+
flex-direction: column;
|
|
6737
6797
|
}
|
|
6738
6798
|
|
|
6739
6799
|
/* ── Sidebar Content ── */
|
|
6800
|
+
/* WHY: Full height of the aside, scrollable. Padding-block offsets keep
|
|
6801
|
+
content from starting behind header / ending behind footer.
|
|
6802
|
+
Fade-out alpha mask dissolves content edges under the overlays. */
|
|
6740
6803
|
|
|
6741
6804
|
:where(ui-layout-sidebar-content) {
|
|
6742
6805
|
display: flex;
|
|
6743
6806
|
flex-direction: column;
|
|
6744
|
-
|
|
6745
|
-
padding-block: var(--
|
|
6746
|
-
padding-inline: calc(var(--_space-k) * var(--_space));
|
|
6747
|
-
flex: 1;
|
|
6748
|
-
min-height: 0;
|
|
6807
|
+
padding-block-start: var(--_sidebar-header-height);
|
|
6808
|
+
padding-block-end: var(--_sidebar-footer-height);
|
|
6749
6809
|
width: 100%;
|
|
6810
|
+
height: 100%;
|
|
6811
|
+
overflow-y: auto;
|
|
6812
|
+
scrollbar-width: none;
|
|
6813
|
+
}
|
|
6814
|
+
|
|
6815
|
+
/* WHY: When header is present, fade top edge. Content dissolves as it
|
|
6816
|
+
scrolls under the header — transparent at top, fully visible by 1.25×
|
|
6817
|
+
the header height. No opaque header background needed. */
|
|
6818
|
+
:where(ui-layout-sidebar-content)[data-has-header] {
|
|
6819
|
+
mask-image: linear-gradient(
|
|
6820
|
+
to bottom,
|
|
6821
|
+
transparent 0,
|
|
6822
|
+
black calc(var(--_sidebar-header-height) * 1.25),
|
|
6823
|
+
black 100%
|
|
6824
|
+
);
|
|
6825
|
+
}
|
|
6826
|
+
|
|
6827
|
+
/* WHY: When footer is present, fade bottom edge. */
|
|
6828
|
+
:where(ui-layout-sidebar-content)[data-has-footer] {
|
|
6829
|
+
mask-image: linear-gradient(
|
|
6830
|
+
to bottom,
|
|
6831
|
+
black 0,
|
|
6832
|
+
black calc(100% - var(--_sidebar-footer-height) * 1.25),
|
|
6833
|
+
transparent 100%
|
|
6834
|
+
);
|
|
6835
|
+
}
|
|
6836
|
+
|
|
6837
|
+
/* WHY: When both header AND footer are present, fade both edges. */
|
|
6838
|
+
:where(ui-layout-sidebar-content)[data-has-header][data-has-footer] {
|
|
6839
|
+
mask-image: linear-gradient(
|
|
6840
|
+
to bottom,
|
|
6841
|
+
transparent 0,
|
|
6842
|
+
black calc(var(--_sidebar-header-height) * 1.25),
|
|
6843
|
+
black calc(100% - var(--_sidebar-footer-height) * 1.25),
|
|
6844
|
+
transparent 100%
|
|
6845
|
+
);
|
|
6750
6846
|
}
|
|
6751
6847
|
|
|
6752
6848
|
/* ── Sidebar Footer ── */
|
|
6849
|
+
/* WHY: Absolute-positioned overlay pinned to bottom of aside. */
|
|
6753
6850
|
|
|
6754
6851
|
:where(ui-layout-sidebar-footer) {
|
|
6852
|
+
position: absolute;
|
|
6853
|
+
bottom: 0;
|
|
6854
|
+
left: 0;
|
|
6855
|
+
right: 0;
|
|
6856
|
+
z-index: 2;
|
|
6755
6857
|
display: flex;
|
|
6756
|
-
|
|
6757
|
-
min-height: var(--ui-layout-bar-height);
|
|
6758
|
-
gap: calc(var(--_space) * 2);
|
|
6759
|
-
padding-block: var(--_space);
|
|
6760
|
-
padding-inline: calc(var(--_space-k) * var(--_space));
|
|
6761
|
-
flex-shrink: 0;
|
|
6858
|
+
flex-direction: column;
|
|
6762
6859
|
}
|
|
6763
6860
|
|
|
6764
|
-
/* ── Sidebar
|
|
6765
|
-
/* WHY:
|
|
6766
|
-
|
|
6861
|
+
/* ── Sidebar Item ── */
|
|
6862
|
+
/* WHY: Universal sidebar row element. Provides inline padding for any content
|
|
6863
|
+
(buttons, links, icons). When a child ui-listbox[popover] is present, JS
|
|
6864
|
+
wires PopoverController for click-to-toggle menu behavior.
|
|
6865
|
+
Absorbs the old ui-layout-sidebar-trigger role — one element for all rows. */
|
|
6767
6866
|
|
|
6768
|
-
:where(ui-layout-sidebar-
|
|
6867
|
+
:where(ui-layout-sidebar-item) {
|
|
6769
6868
|
display: flex;
|
|
6770
6869
|
align-items: center;
|
|
6771
6870
|
flex: 1;
|
|
@@ -6781,29 +6880,59 @@
|
|
|
6781
6880
|
user-select: none;
|
|
6782
6881
|
border: none;
|
|
6783
6882
|
background: none;
|
|
6784
|
-
padding: var(--_space);
|
|
6883
|
+
padding-block: var(--_space);
|
|
6884
|
+
padding-inline: calc(var(--_space-k) * var(--_space));
|
|
6785
6885
|
border-radius: var(--_radius);
|
|
6786
6886
|
transition: color var(--_duration) var(--_easing);
|
|
6787
6887
|
}
|
|
6788
6888
|
|
|
6789
|
-
:
|
|
6889
|
+
/* WHY: Items in header/footer match the breadcrumb bar height so the
|
|
6890
|
+
first sidebar row aligns horizontally with the breadcrumb. */
|
|
6891
|
+
:where(ui-layout-sidebar-header) > :where(ui-layout-sidebar-item),
|
|
6892
|
+
:where(ui-layout-sidebar-footer) > :where(ui-layout-sidebar-item) {
|
|
6893
|
+
min-height: var(--ui-layout-bar-height);
|
|
6894
|
+
}
|
|
6895
|
+
|
|
6896
|
+
:where(ui-layout-sidebar-item):hover{
|
|
6790
6897
|
color: var(--_ink-strong);
|
|
6791
6898
|
}
|
|
6792
6899
|
|
|
6793
|
-
:where(ui-layout-sidebar-
|
|
6900
|
+
:where(ui-layout-sidebar-item):focus-visible{
|
|
6794
6901
|
outline: 2px solid var(--ui-focus-ring);
|
|
6795
6902
|
outline-offset: -2px;
|
|
6796
6903
|
}
|
|
6797
6904
|
|
|
6905
|
+
/* WHY: Fixed-size icon well so all sidebar icons (header logo, nav group icons,
|
|
6906
|
+
standalone icons) center-align on the same column width regardless of intrinsic
|
|
6907
|
+
icon size. 1.5rem matches the sidebar's visual rhythm at default density.
|
|
6908
|
+
Consumer wraps the icon: <span slot="icon"><ui-icon name="..."></ui-icon></span>
|
|
6909
|
+
The wrapper is the well; the icon keeps its own --ui-icon-size dimensions. */
|
|
6910
|
+
:where(ui-layout-sidebar-item) > :where([slot="icon"]) {
|
|
6911
|
+
display: inline-flex;
|
|
6912
|
+
align-items: center;
|
|
6913
|
+
justify-content: center;
|
|
6914
|
+
width: 1.5rem;
|
|
6915
|
+
height: 1.5rem;
|
|
6916
|
+
flex-shrink: 0;
|
|
6917
|
+
}
|
|
6918
|
+
|
|
6798
6919
|
/* WHY: Trailing caret pushes to end — same pattern as button justify="spread". */
|
|
6799
|
-
:where(ui-layout-sidebar-
|
|
6920
|
+
:where(ui-layout-sidebar-item) > :where([slot="trailing"]) {
|
|
6800
6921
|
margin-inline-start: auto;
|
|
6801
6922
|
flex-shrink: 0;
|
|
6802
6923
|
color: var(--_ink-muted);
|
|
6803
6924
|
}
|
|
6804
6925
|
|
|
6926
|
+
/* WHY: When the item wraps a sub-component (e.g. ui-button) that provides
|
|
6927
|
+
its own icon, hide [slot="icon"] in expanded mode — it only serves as the
|
|
6928
|
+
bare collapsed-rail representation. Items without sub-components (just
|
|
6929
|
+
icon + label + trailing) keep [slot="icon"] visible in both modes. */
|
|
6930
|
+
:where(ui-layout-sidebar-item:has(> ui-button)) > :where([slot="icon"]) {
|
|
6931
|
+
display: none;
|
|
6932
|
+
}
|
|
6933
|
+
|
|
6805
6934
|
/* WHY: Title text truncates when sidebar narrows during resize. */
|
|
6806
|
-
:where(ui-layout-sidebar-
|
|
6935
|
+
:where(ui-layout-sidebar-item) > :where([slot="label"]) {
|
|
6807
6936
|
flex: 1;
|
|
6808
6937
|
min-width: 0;
|
|
6809
6938
|
white-space: nowrap;
|
|
@@ -6811,25 +6940,67 @@
|
|
|
6811
6940
|
text-overflow: ellipsis;
|
|
6812
6941
|
}
|
|
6813
6942
|
|
|
6814
|
-
/* ──
|
|
6815
|
-
/* WHY: Popover opens to the right of the sidebar
|
|
6943
|
+
/* ── Item Popover ── */
|
|
6944
|
+
/* WHY: Popover opens to the right of the sidebar item.
|
|
6816
6945
|
Default: top-aligned, grows downward (span-block-end).
|
|
6817
6946
|
Flip: bottom-aligned, grows upward (span-block-start). */
|
|
6818
6947
|
|
|
6819
|
-
:where(ui-layout-sidebar-
|
|
6948
|
+
:where(ui-layout-sidebar-item) > :where(ui-listbox[popover]) {
|
|
6820
6949
|
position: fixed;
|
|
6821
6950
|
position-area: inline-end span-block-end;
|
|
6822
|
-
position-try-fallbacks: --flip-up;
|
|
6951
|
+
position-try-fallbacks: --sidebar-item-flip-up;
|
|
6823
6952
|
margin: 0 0 0 var(--ui-popover-gap);
|
|
6824
6953
|
min-width: 200px;
|
|
6825
6954
|
max-height: var(--ui-popover-max-height);
|
|
6826
6955
|
overflow-y: auto;
|
|
6827
6956
|
}
|
|
6828
6957
|
|
|
6829
|
-
@position-try --flip-up {
|
|
6958
|
+
@position-try --sidebar-item-flip-up {
|
|
6830
6959
|
position-area: inline-end span-block-start;
|
|
6831
6960
|
}
|
|
6832
6961
|
|
|
6962
|
+
/* ── Container Query: Collapsed Sidebar ── */
|
|
6963
|
+
/* WHY: Each component owns its own collapsed behavior via @container.
|
|
6964
|
+
The aside is the container (container-name: sidebar). When it shrinks
|
|
6965
|
+
to 48px (icon rail), components respond to the width, not to [collapsed].
|
|
6966
|
+
Threshold 80px: collapsed = 48px, min expanded = 160px. */
|
|
6967
|
+
|
|
6968
|
+
@container sidebar (max-width: 80px) {
|
|
6969
|
+
|
|
6970
|
+
/* Resize handle — no dragging in icon rail */
|
|
6971
|
+
:where(.layout-resize-handle) {
|
|
6972
|
+
display: none;
|
|
6973
|
+
}
|
|
6974
|
+
|
|
6975
|
+
/* Header/footer — center content horizontally */
|
|
6976
|
+
:where(ui-layout-sidebar-header),
|
|
6977
|
+
:where(ui-layout-sidebar-footer) {
|
|
6978
|
+
align-items: center;
|
|
6979
|
+
}
|
|
6980
|
+
|
|
6981
|
+
/* Content — center items in the 48px rail */
|
|
6982
|
+
:where(ui-layout-sidebar-content) {
|
|
6983
|
+
align-items: center;
|
|
6984
|
+
}
|
|
6985
|
+
|
|
6986
|
+
/* Item — shrink to icon-only. Show [slot="icon"], hide everything else.
|
|
6987
|
+
WHY: Sidebar items can contain complex children (buttons with slots,
|
|
6988
|
+
links, etc.). Rather than overriding sub-component styles, the item
|
|
6989
|
+
provides its own bare icon via [slot="icon"] for the collapsed rail. */
|
|
6990
|
+
:where(ui-layout-sidebar-item) {
|
|
6991
|
+
flex: 0 0 auto;
|
|
6992
|
+
padding-inline: var(--_space);
|
|
6993
|
+
}
|
|
6994
|
+
|
|
6995
|
+
:where(ui-layout-sidebar-item) > :where([slot="icon"]) {
|
|
6996
|
+
display: inline-flex;
|
|
6997
|
+
}
|
|
6998
|
+
|
|
6999
|
+
:where(ui-layout-sidebar-item) > :where(:not([slot="icon"]):not(ui-listbox[popover]):not(.nav-group-flyout)) {
|
|
7000
|
+
display: none;
|
|
7001
|
+
}
|
|
7002
|
+
}
|
|
7003
|
+
|
|
6833
7004
|
}
|
|
6834
7005
|
|
|
6835
7006
|
@layer ui {
|