@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/components.css
CHANGED
|
@@ -365,7 +365,7 @@
|
|
|
365
365
|
font-weight: var(--_font-weight);
|
|
366
366
|
|
|
367
367
|
border-radius: var(--_radius);
|
|
368
|
-
border: 1px solid var(--_border-color, var(--
|
|
368
|
+
border: 1px solid var(--_border-color, var(--_border-muted));
|
|
369
369
|
|
|
370
370
|
background: var(--_background, var(--_button));
|
|
371
371
|
color: var(--_color, var(--_ink));
|
|
@@ -382,17 +382,17 @@
|
|
|
382
382
|
|
|
383
383
|
:where(ui-button):hover,
|
|
384
384
|
:where(ui-button)[force-hover] {
|
|
385
|
-
background: var(--_background-hover, var(--
|
|
385
|
+
background: var(--_background-hover, var(--_button-hover));
|
|
386
386
|
color: var(--_color-hover, var(--_ink-hover));
|
|
387
|
-
border-color: var(--_border-color-hover, var(--
|
|
387
|
+
border-color: var(--_border-color-hover, var(--_border-hover));
|
|
388
388
|
}
|
|
389
389
|
|
|
390
390
|
:where(ui-button):active,
|
|
391
391
|
:where(ui-button)[pressed],
|
|
392
392
|
:where(ui-button)[force-active] {
|
|
393
|
-
background: var(--_background-active, var(--
|
|
393
|
+
background: var(--_background-active, var(--_button-active));
|
|
394
394
|
color: var(--_color-active, var(--_ink-active));
|
|
395
|
-
border-color: var(--_border-color-active, var(--
|
|
395
|
+
border-color: var(--_border-color-active, var(--_border-active));
|
|
396
396
|
}
|
|
397
397
|
|
|
398
398
|
:where(ui-button):focus-visible,
|
|
@@ -402,9 +402,9 @@
|
|
|
402
402
|
}
|
|
403
403
|
|
|
404
404
|
:where(ui-button)[aria-disabled="true"] {
|
|
405
|
-
background: var(--_background-disabled, var(--
|
|
405
|
+
background: var(--_background-disabled, var(--_button-disabled));
|
|
406
406
|
color: var(--_color-disabled, var(--_ink-disabled));
|
|
407
|
-
border-color: var(--_border-color-disabled, var(--
|
|
407
|
+
border-color: var(--_border-color-disabled, var(--_border-muted));
|
|
408
408
|
cursor: not-allowed;
|
|
409
409
|
pointer-events: none;
|
|
410
410
|
}
|
|
@@ -977,34 +977,25 @@
|
|
|
977
977
|
}
|
|
978
978
|
|
|
979
979
|
/* ── Checked State ── */
|
|
980
|
-
/* WHY: Default checked fill uses accent
|
|
981
|
-
|
|
980
|
+
/* WHY: Default checked fill uses --_surface (accent by default via
|
|
981
|
+
intent="accent" being the implicit default for toggle controls).
|
|
982
982
|
When an explicit [intent] is set, the intent selector's --_surface wins. */
|
|
983
983
|
|
|
984
984
|
:where(ui-checkbox)[aria-checked="true"]::before {
|
|
985
|
-
background: var(--accent-surface);
|
|
986
|
-
border-color: var(--accent-surface);
|
|
987
|
-
}
|
|
988
|
-
|
|
989
|
-
:where(ui-checkbox)[aria-checked="true"]::after {
|
|
990
|
-
background: var(--accent-surface-ink);
|
|
991
|
-
transform: translateY(-50%) scale(1);
|
|
992
|
-
}
|
|
993
|
-
|
|
994
|
-
:where(ui-checkbox)[intent][aria-checked="true"]::before {
|
|
995
985
|
background: var(--_surface);
|
|
996
986
|
border-color: var(--_surface);
|
|
997
987
|
}
|
|
998
988
|
|
|
999
|
-
:where(ui-checkbox)[
|
|
989
|
+
:where(ui-checkbox)[aria-checked="true"]::after {
|
|
1000
990
|
background: var(--_surface-ink);
|
|
991
|
+
transform: translateY(-50%) scale(1);
|
|
1001
992
|
}
|
|
1002
993
|
|
|
1003
994
|
/* ── Indeterminate State ── */
|
|
1004
995
|
|
|
1005
996
|
:where(ui-checkbox)[aria-checked="mixed"]::before {
|
|
1006
|
-
background: var(--
|
|
1007
|
-
border-color: var(--
|
|
997
|
+
background: var(--_surface);
|
|
998
|
+
border-color: var(--_surface);
|
|
1008
999
|
}
|
|
1009
1000
|
|
|
1010
1001
|
:where(ui-checkbox)[aria-checked="mixed"]::after {
|
|
@@ -1012,17 +1003,8 @@
|
|
|
1012
1003
|
-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");
|
|
1013
1004
|
mask-size: 75%;
|
|
1014
1005
|
-webkit-mask-size: 75%;
|
|
1015
|
-
background: var(--accent-surface-ink);
|
|
1016
|
-
transform: translateY(-50%) scale(1);
|
|
1017
|
-
}
|
|
1018
|
-
|
|
1019
|
-
:where(ui-checkbox)[intent][aria-checked="mixed"]::before {
|
|
1020
|
-
background: var(--_surface);
|
|
1021
|
-
border-color: var(--_surface);
|
|
1022
|
-
}
|
|
1023
|
-
|
|
1024
|
-
:where(ui-checkbox)[intent][aria-checked="mixed"]::after {
|
|
1025
1006
|
background: var(--_surface-ink);
|
|
1007
|
+
transform: translateY(-50%) scale(1);
|
|
1026
1008
|
}
|
|
1027
1009
|
|
|
1028
1010
|
/* ── Hover ── */
|
|
@@ -1042,14 +1024,6 @@
|
|
|
1042
1024
|
:where(ui-checkbox)[aria-checked="mixed"]:hover::before,
|
|
1043
1025
|
:where(ui-checkbox)[aria-checked="true"][force-hover]::before,
|
|
1044
1026
|
:where(ui-checkbox)[aria-checked="mixed"][force-hover]::before {
|
|
1045
|
-
background: var(--accent-surface-hover);
|
|
1046
|
-
border-color: var(--accent-surface-hover);
|
|
1047
|
-
}
|
|
1048
|
-
|
|
1049
|
-
:where(ui-checkbox)[intent][aria-checked="true"]:hover::before,
|
|
1050
|
-
:where(ui-checkbox)[intent][aria-checked="mixed"]:hover::before,
|
|
1051
|
-
:where(ui-checkbox)[intent][aria-checked="true"][force-hover]::before,
|
|
1052
|
-
:where(ui-checkbox)[intent][aria-checked="mixed"][force-hover]::before {
|
|
1053
1027
|
background: var(--_surface-hover);
|
|
1054
1028
|
border-color: var(--_surface-hover);
|
|
1055
1029
|
}
|
|
@@ -1063,12 +1037,6 @@
|
|
|
1063
1037
|
|
|
1064
1038
|
:where(ui-checkbox)[aria-checked="true"][pressed]::before,
|
|
1065
1039
|
:where(ui-checkbox)[aria-checked="mixed"][pressed]::before {
|
|
1066
|
-
background: var(--accent-surface-active);
|
|
1067
|
-
border-color: var(--accent-surface-active);
|
|
1068
|
-
}
|
|
1069
|
-
|
|
1070
|
-
:where(ui-checkbox)[intent][aria-checked="true"][pressed]::before,
|
|
1071
|
-
:where(ui-checkbox)[intent][aria-checked="mixed"][pressed]::before {
|
|
1072
1040
|
background: var(--_surface-active);
|
|
1073
1041
|
border-color: var(--_surface-active);
|
|
1074
1042
|
}
|
|
@@ -1722,6 +1690,45 @@
|
|
|
1722
1690
|
|
|
1723
1691
|
}
|
|
1724
1692
|
|
|
1693
|
+
@layer ui {
|
|
1694
|
+
|
|
1695
|
+
/* ╭──────────────────────────────────────────────────────────╮
|
|
1696
|
+
│ ui-kbd │
|
|
1697
|
+
│ Keyboard shortcut indicator. Own font/size scale │
|
|
1698
|
+
│ (like ui-badge) — zero-attribute = md. │
|
|
1699
|
+
╰──────────────────────────────────────────────────────────╯ */
|
|
1700
|
+
|
|
1701
|
+
:where(ui-kbd) {
|
|
1702
|
+
--_icon-size: 1.125em;
|
|
1703
|
+
|
|
1704
|
+
display: inline-flex;
|
|
1705
|
+
align-items: center;
|
|
1706
|
+
justify-content: center;
|
|
1707
|
+
font-family: ui-monospace, monospace;
|
|
1708
|
+
font-size: var(--ui-kbd-font-md);
|
|
1709
|
+
line-height: 1;
|
|
1710
|
+
min-height: var(--ui-kbd-size-md);
|
|
1711
|
+
padding-inline: 0.4em;
|
|
1712
|
+
border-radius: 0.5em;
|
|
1713
|
+
background: var(--_ground, var(--_body));
|
|
1714
|
+
border: 1px solid var(--_border-muted);
|
|
1715
|
+
color: var(--_ink-muted);
|
|
1716
|
+
white-space: nowrap;
|
|
1717
|
+
user-select: none;
|
|
1718
|
+
flex-shrink: 0;
|
|
1719
|
+
vertical-align: baseline;
|
|
1720
|
+
}
|
|
1721
|
+
|
|
1722
|
+
/* ── Sizes ── */
|
|
1723
|
+
|
|
1724
|
+
:where(ui-kbd[size="xs"]) { font-size: var(--ui-kbd-font-xs); min-height: var(--ui-kbd-size-xs); }
|
|
1725
|
+
:where(ui-kbd[size="sm"]) { font-size: var(--ui-kbd-font-sm); min-height: var(--ui-kbd-size-sm); }
|
|
1726
|
+
:where(ui-kbd[size="md"]) { font-size: var(--ui-kbd-font-md); min-height: var(--ui-kbd-size-md); }
|
|
1727
|
+
:where(ui-kbd[size="lg"]) { font-size: var(--ui-kbd-font-lg); min-height: var(--ui-kbd-size-lg); }
|
|
1728
|
+
:where(ui-kbd[size="xl"]) { font-size: var(--ui-kbd-font-xl); min-height: var(--ui-kbd-size-xl); }
|
|
1729
|
+
|
|
1730
|
+
}
|
|
1731
|
+
|
|
1725
1732
|
@layer ui {
|
|
1726
1733
|
|
|
1727
1734
|
/* ── Listbox Base ── */
|
|
@@ -1862,11 +1869,14 @@
|
|
|
1862
1869
|
│ Uses ui-nav-item / ui-nav-group for children. │
|
|
1863
1870
|
╰──────────────────────────────────────────────────────────╯ */
|
|
1864
1871
|
|
|
1872
|
+
/* WHY: ui-nav is a transparent flex wrapper — no inline padding.
|
|
1873
|
+
Inline padding is owned by leaf items (nav-item, summary).
|
|
1874
|
+
Block padding is owned by nav-group margins. */
|
|
1865
1875
|
:where(ui-nav) {
|
|
1866
1876
|
display: flex;
|
|
1867
1877
|
flex-direction: column;
|
|
1868
1878
|
gap: 0;
|
|
1869
|
-
padding:
|
|
1879
|
+
padding: 0;
|
|
1870
1880
|
outline: none;
|
|
1871
1881
|
}
|
|
1872
1882
|
|
|
@@ -1881,6 +1891,7 @@
|
|
|
1881
1891
|
display: flex;
|
|
1882
1892
|
align-items: center;
|
|
1883
1893
|
gap: calc(var(--_space) * 2);
|
|
1894
|
+
padding-inline: calc(var(--_space-k) * var(--_space));
|
|
1884
1895
|
|
|
1885
1896
|
min-height: var(--_min-height);
|
|
1886
1897
|
|
|
@@ -1980,6 +1991,7 @@
|
|
|
1980
1991
|
display: flex;
|
|
1981
1992
|
align-items: center;
|
|
1982
1993
|
gap: calc(var(--_space) * 2);
|
|
1994
|
+
padding-inline: calc(var(--_space-k) * var(--_space));
|
|
1983
1995
|
cursor: pointer;
|
|
1984
1996
|
user-select: none;
|
|
1985
1997
|
list-style: none;
|
|
@@ -2014,6 +2026,18 @@
|
|
|
2014
2026
|
user-select: none;
|
|
2015
2027
|
}
|
|
2016
2028
|
|
|
2029
|
+
/* WHY: Fixed-size icon well — matches ui-layout-sidebar-item [slot="icon"].
|
|
2030
|
+
All sidebar icons align on the same 1.5rem column regardless of icon size.
|
|
2031
|
+
JS wraps the first <ui-icon> child in a .icon-well span during setup(). */
|
|
2032
|
+
:where(ui-nav-group-header) > :where(.icon-well) {
|
|
2033
|
+
display: inline-flex;
|
|
2034
|
+
align-items: center;
|
|
2035
|
+
justify-content: center;
|
|
2036
|
+
width: 1.5rem;
|
|
2037
|
+
height: 1.5rem;
|
|
2038
|
+
flex-shrink: 0;
|
|
2039
|
+
}
|
|
2040
|
+
|
|
2017
2041
|
/* ── Chevron icon (right side of summary) ── */
|
|
2018
2042
|
|
|
2019
2043
|
:where(ui-nav-group) > :where(details) > :where(summary)::after {
|
|
@@ -2067,12 +2091,16 @@
|
|
|
2067
2091
|
/* WHY: Connector draws from below the header to the bottom of the group.
|
|
2068
2092
|
Only shown when header contains an icon. Scoped via :has(). */
|
|
2069
2093
|
|
|
2070
|
-
:
|
|
2071
|
-
|
|
2072
|
-
|
|
2094
|
+
/* WHY: Insets account for the summary's padding-inline so the connector
|
|
2095
|
+
line passes through the icon center and child text aligns with header text. */
|
|
2096
|
+
:where(ui-nav-group):has(:where(ui-nav-group-header) :where(.icon-well)) {
|
|
2097
|
+
--_group-pad: calc(var(--_space-k) * var(--_space));
|
|
2098
|
+
--_group-icon-well: 1.5rem;
|
|
2099
|
+
--_group-line-inset: calc(var(--_group-pad) + var(--_group-icon-well) / 2);
|
|
2100
|
+
--_group-child-inset: calc(var(--_group-icon-well) + var(--_space) * 2);
|
|
2073
2101
|
}
|
|
2074
2102
|
|
|
2075
|
-
:where(ui-nav-group):has(:where(ui-nav-group-header) :where(
|
|
2103
|
+
:where(ui-nav-group):has(:where(ui-nav-group-header) :where(.icon-well)):has(:where(details[open]))::after {
|
|
2076
2104
|
content: '';
|
|
2077
2105
|
position: absolute;
|
|
2078
2106
|
inset-inline-start: var(--_group-line-inset);
|
|
@@ -2087,7 +2115,7 @@
|
|
|
2087
2115
|
/* WHY: A ::before pseudo on the group slides along the connector line.
|
|
2088
2116
|
JS sets --_indicator-index; :state(has-selection) gates visibility. */
|
|
2089
2117
|
|
|
2090
|
-
:where(ui-nav-group):has(:where(ui-nav-group-header) :where(
|
|
2118
|
+
:where(ui-nav-group):has(:where(ui-nav-group-header) :where(.icon-well)):has(:where(details[open])):state(has-selection)::before {
|
|
2091
2119
|
content: '';
|
|
2092
2120
|
position: absolute;
|
|
2093
2121
|
z-index: 1;
|
|
@@ -2114,6 +2142,73 @@
|
|
|
2114
2142
|
margin-inline-start: var(--_group-child-inset, 0);
|
|
2115
2143
|
}
|
|
2116
2144
|
|
|
2145
|
+
/* ── Nav Group Flyout (collapsed sidebar) ── */
|
|
2146
|
+
/* WHY: In collapsed mode, summary click opens a ui-listbox popover to the right
|
|
2147
|
+
instead of expanding the <details>. Same pattern as sidebar-trigger menus. */
|
|
2148
|
+
|
|
2149
|
+
:where(ui-nav-group) > :where(ui-listbox.nav-group-flyout[popover]) {
|
|
2150
|
+
position: fixed;
|
|
2151
|
+
position-area: inline-end span-block-end;
|
|
2152
|
+
position-try-fallbacks: --nav-flyout-flip-up;
|
|
2153
|
+
margin: 0 0 0 var(--ui-popover-gap);
|
|
2154
|
+
min-width: 200px;
|
|
2155
|
+
max-height: var(--ui-popover-max-height);
|
|
2156
|
+
overflow-y: auto;
|
|
2157
|
+
}
|
|
2158
|
+
|
|
2159
|
+
@position-try --nav-flyout-flip-up {
|
|
2160
|
+
position-area: inline-end span-block-start;
|
|
2161
|
+
}
|
|
2162
|
+
|
|
2163
|
+
/* ── Container Query: Collapsed Sidebar ── */
|
|
2164
|
+
/* WHY: Nav components own their own collapsed behavior via @container.
|
|
2165
|
+
The sidebar aside declares container-name: sidebar. When it shrinks
|
|
2166
|
+
to 48px (icon rail), nav responds to the width — not to [collapsed].
|
|
2167
|
+
Threshold 80px: collapsed = 48px, min expanded = 160px. */
|
|
2168
|
+
|
|
2169
|
+
@container sidebar (max-width: 80px) {
|
|
2170
|
+
|
|
2171
|
+
/* Nav items hide entirely — only group headers (with icons) remain. */
|
|
2172
|
+
:where(ui-nav-item) {
|
|
2173
|
+
display: none;
|
|
2174
|
+
}
|
|
2175
|
+
|
|
2176
|
+
/* Summary shrinks to icon-only. Reduced inline padding wraps tightly
|
|
2177
|
+
around the icon; parent align-items: center handles horizontal centering. */
|
|
2178
|
+
:where(ui-nav-group) > :where(details) > :where(summary) {
|
|
2179
|
+
padding-inline: var(--_space);
|
|
2180
|
+
border-radius: var(--_radius);
|
|
2181
|
+
}
|
|
2182
|
+
|
|
2183
|
+
/* Hide chevron — no expand/collapse in icon rail (flyout instead). */
|
|
2184
|
+
:where(ui-nav-group) > :where(details) > :where(summary)::after {
|
|
2185
|
+
display: none;
|
|
2186
|
+
}
|
|
2187
|
+
|
|
2188
|
+
/* Hide vertical connector line and sliding indicator. */
|
|
2189
|
+
:where(ui-nav-group)::after,
|
|
2190
|
+
:where(ui-nav-group)::before {
|
|
2191
|
+
display: none;
|
|
2192
|
+
}
|
|
2193
|
+
|
|
2194
|
+
/* Header collapses to icon-only. font-size: 0 hides text nodes
|
|
2195
|
+
(can't be targeted by CSS). Icon overrides back to normal below. */
|
|
2196
|
+
:where(ui-nav-group-header) {
|
|
2197
|
+
flex: 0 0 auto;
|
|
2198
|
+
font-size: 0;
|
|
2199
|
+
gap: 0;
|
|
2200
|
+
}
|
|
2201
|
+
|
|
2202
|
+
:where(ui-nav-group-header) :where(.icon-well) :where(ui-icon) {
|
|
2203
|
+
font-size: var(--_font-size, 1rem);
|
|
2204
|
+
}
|
|
2205
|
+
|
|
2206
|
+
/* Collapse inter-group spacing in icon rail. */
|
|
2207
|
+
:where(ui-nav-group) + :where(ui-nav-group) {
|
|
2208
|
+
margin-block-start: 0;
|
|
2209
|
+
}
|
|
2210
|
+
}
|
|
2211
|
+
|
|
2117
2212
|
}
|
|
2118
2213
|
|
|
2119
2214
|
@layer ui {
|
|
@@ -2254,27 +2349,15 @@
|
|
|
2254
2349
|
}
|
|
2255
2350
|
|
|
2256
2351
|
/* ── Selected ── */
|
|
2257
|
-
/* WHY: Default selected fill uses accent so radio is visually distinct
|
|
2258
|
-
without needing intent="accent". Unchecked borders stay neutral.
|
|
2259
|
-
When an explicit [intent] is set, the intent selector's --_surface wins. */
|
|
2260
2352
|
|
|
2261
2353
|
:where(ui-radio)[aria-checked="true"]::before {
|
|
2262
|
-
background: var(--accent-surface);
|
|
2263
|
-
border-color: var(--accent-surface);
|
|
2264
|
-
}
|
|
2265
|
-
|
|
2266
|
-
:where(ui-radio)[aria-checked="true"]::after {
|
|
2267
|
-
background: var(--accent-surface-ink);
|
|
2268
|
-
transform: translateY(-50%) scale(1);
|
|
2269
|
-
}
|
|
2270
|
-
|
|
2271
|
-
:where(ui-radio-group)[intent] :where(ui-radio)[aria-checked="true"]::before {
|
|
2272
2354
|
background: var(--_surface);
|
|
2273
2355
|
border-color: var(--_surface);
|
|
2274
2356
|
}
|
|
2275
2357
|
|
|
2276
|
-
:where(ui-radio
|
|
2358
|
+
:where(ui-radio)[aria-checked="true"]::after {
|
|
2277
2359
|
background: var(--_surface-ink);
|
|
2360
|
+
transform: translateY(-50%) scale(1);
|
|
2278
2361
|
}
|
|
2279
2362
|
|
|
2280
2363
|
/* ── Hover ── */
|
|
@@ -2292,12 +2375,6 @@
|
|
|
2292
2375
|
|
|
2293
2376
|
:where(ui-radio)[aria-checked="true"]:hover::before,
|
|
2294
2377
|
:where(ui-radio)[aria-checked="true"][force-hover]::before {
|
|
2295
|
-
background: var(--accent-surface-hover);
|
|
2296
|
-
border-color: var(--accent-surface-hover);
|
|
2297
|
-
}
|
|
2298
|
-
|
|
2299
|
-
:where(ui-radio-group)[intent] :where(ui-radio)[aria-checked="true"]:hover::before,
|
|
2300
|
-
:where(ui-radio-group)[intent] :where(ui-radio)[aria-checked="true"][force-hover]::before {
|
|
2301
2378
|
background: var(--_surface-hover);
|
|
2302
2379
|
border-color: var(--_surface-hover);
|
|
2303
2380
|
}
|
|
@@ -2310,11 +2387,6 @@
|
|
|
2310
2387
|
}
|
|
2311
2388
|
|
|
2312
2389
|
:where(ui-radio)[aria-checked="true"][pressed]::before {
|
|
2313
|
-
background: var(--accent-surface-active);
|
|
2314
|
-
border-color: var(--accent-surface-active);
|
|
2315
|
-
}
|
|
2316
|
-
|
|
2317
|
-
:where(ui-radio-group)[intent] :where(ui-radio)[aria-checked="true"][pressed]::before {
|
|
2318
2390
|
background: var(--_surface-active);
|
|
2319
2391
|
border-color: var(--_surface-active);
|
|
2320
2392
|
}
|
|
@@ -2413,16 +2485,12 @@
|
|
|
2413
2485
|
/* 0% = track-height (circle), 100% = full width */
|
|
2414
2486
|
width: calc(var(--_track-height) + (100% - var(--_track-height)) * var(--_progress));
|
|
2415
2487
|
border-radius: calc(var(--_track-height) / 2);
|
|
2416
|
-
background: var(--
|
|
2488
|
+
background: var(--_surface);
|
|
2417
2489
|
|
|
2418
2490
|
transition:
|
|
2419
2491
|
background var(--_duration) var(--_easing);
|
|
2420
2492
|
}
|
|
2421
2493
|
|
|
2422
|
-
:where(ui-range)[intent]::after {
|
|
2423
|
-
background: var(--_surface);
|
|
2424
|
-
}
|
|
2425
|
-
|
|
2426
2494
|
/* ── Thumb ── */
|
|
2427
2495
|
|
|
2428
2496
|
:where(ui-range) > :where(.ui-range-thumb) {
|
|
@@ -2434,8 +2502,8 @@
|
|
|
2434
2502
|
width: var(--_thumb-size);
|
|
2435
2503
|
height: var(--_thumb-size);
|
|
2436
2504
|
border-radius: 50%;
|
|
2437
|
-
background: var(--
|
|
2438
|
-
border: 2px solid var(--
|
|
2505
|
+
background: var(--_surface-ink);
|
|
2506
|
+
border: 2px solid var(--_surface);
|
|
2439
2507
|
box-shadow: var(--ui-shadow-sm);
|
|
2440
2508
|
pointer-events: none;
|
|
2441
2509
|
|
|
@@ -2445,11 +2513,6 @@
|
|
|
2445
2513
|
border-color var(--_duration) var(--_easing);
|
|
2446
2514
|
}
|
|
2447
2515
|
|
|
2448
|
-
:where(ui-range)[intent] > :where(.ui-range-thumb) {
|
|
2449
|
-
background: var(--_surface-ink);
|
|
2450
|
-
border-color: var(--_surface);
|
|
2451
|
-
}
|
|
2452
|
-
|
|
2453
2516
|
/* ── Focus ── */
|
|
2454
2517
|
|
|
2455
2518
|
:where(ui-range):focus-visible > :where(.ui-range-thumb),
|
|
@@ -2462,22 +2525,11 @@
|
|
|
2462
2525
|
|
|
2463
2526
|
:where(ui-range):hover::after,
|
|
2464
2527
|
:where(ui-range)[force-hover]::after {
|
|
2465
|
-
background: var(--accent-surface-hover);
|
|
2466
|
-
}
|
|
2467
|
-
|
|
2468
|
-
:where(ui-range)[intent]:hover::after,
|
|
2469
|
-
:where(ui-range)[intent][force-hover]::after {
|
|
2470
2528
|
background: var(--_surface-hover);
|
|
2471
2529
|
}
|
|
2472
2530
|
|
|
2473
2531
|
:where(ui-range):hover > :where(.ui-range-thumb),
|
|
2474
2532
|
:where(ui-range)[force-hover] > :where(.ui-range-thumb) {
|
|
2475
|
-
border-color: var(--accent-surface-hover);
|
|
2476
|
-
box-shadow: var(--ui-shadow-sm), 0 0 0 4px var(--accent-surface);
|
|
2477
|
-
}
|
|
2478
|
-
|
|
2479
|
-
:where(ui-range)[intent]:hover > :where(.ui-range-thumb),
|
|
2480
|
-
:where(ui-range)[intent][force-hover] > :where(.ui-range-thumb) {
|
|
2481
2533
|
border-color: var(--_surface-hover);
|
|
2482
2534
|
box-shadow: var(--ui-shadow-sm), 0 0 0 4px var(--_surface);
|
|
2483
2535
|
}
|
|
@@ -2485,19 +2537,10 @@
|
|
|
2485
2537
|
/* ── Active (dragging) ── */
|
|
2486
2538
|
|
|
2487
2539
|
:where(ui-range)[pressed]::after {
|
|
2488
|
-
background: var(--accent-surface-active);
|
|
2489
|
-
}
|
|
2490
|
-
|
|
2491
|
-
:where(ui-range)[intent][pressed]::after {
|
|
2492
2540
|
background: var(--_surface-active);
|
|
2493
2541
|
}
|
|
2494
2542
|
|
|
2495
2543
|
:where(ui-range)[pressed] > :where(.ui-range-thumb) {
|
|
2496
|
-
border-color: var(--accent-surface-active);
|
|
2497
|
-
box-shadow: var(--ui-shadow-sm), 0 0 0 6px var(--accent-surface);
|
|
2498
|
-
}
|
|
2499
|
-
|
|
2500
|
-
:where(ui-range)[intent][pressed] > :where(.ui-range-thumb) {
|
|
2501
2544
|
border-color: var(--_surface-active);
|
|
2502
2545
|
box-shadow: var(--ui-shadow-sm), 0 0 0 6px var(--_surface);
|
|
2503
2546
|
}
|
|
@@ -3052,22 +3095,13 @@
|
|
|
3052
3095
|
When an explicit [intent] is set, the intent selector's --_surface wins. */
|
|
3053
3096
|
|
|
3054
3097
|
:where(ui-switch)[aria-checked="true"]::before {
|
|
3055
|
-
background: var(--
|
|
3056
|
-
border-color: var(--
|
|
3098
|
+
background: var(--_surface);
|
|
3099
|
+
border-color: var(--_surface);
|
|
3057
3100
|
}
|
|
3058
3101
|
|
|
3059
3102
|
:where(ui-switch)[aria-checked="true"]::after {
|
|
3060
3103
|
/* Slide thumb to the right via translateX — GPU composited */
|
|
3061
3104
|
transform: translateY(-50%) translateX(calc(var(--_track-width) - var(--_thumb-size) - var(--_thumb-offset) * 2));
|
|
3062
|
-
background: var(--accent-surface-ink);
|
|
3063
|
-
}
|
|
3064
|
-
|
|
3065
|
-
:where(ui-switch)[intent][aria-checked="true"]::before {
|
|
3066
|
-
background: var(--_surface);
|
|
3067
|
-
border-color: var(--_surface);
|
|
3068
|
-
}
|
|
3069
|
-
|
|
3070
|
-
:where(ui-switch)[intent][aria-checked="true"]::after {
|
|
3071
3105
|
background: var(--_surface-ink);
|
|
3072
3106
|
}
|
|
3073
3107
|
|
|
@@ -3086,12 +3120,6 @@
|
|
|
3086
3120
|
|
|
3087
3121
|
:where(ui-switch)[aria-checked="true"]:hover::before,
|
|
3088
3122
|
:where(ui-switch)[aria-checked="true"][force-hover]::before {
|
|
3089
|
-
background: var(--accent-surface-hover);
|
|
3090
|
-
border-color: var(--accent-surface-hover);
|
|
3091
|
-
}
|
|
3092
|
-
|
|
3093
|
-
:where(ui-switch)[intent][aria-checked="true"]:hover::before,
|
|
3094
|
-
:where(ui-switch)[intent][aria-checked="true"][force-hover]::before {
|
|
3095
3123
|
background: var(--_surface-hover);
|
|
3096
3124
|
border-color: var(--_surface-hover);
|
|
3097
3125
|
}
|
|
@@ -3104,11 +3132,6 @@
|
|
|
3104
3132
|
}
|
|
3105
3133
|
|
|
3106
3134
|
:where(ui-switch)[aria-checked="true"][pressed]::before {
|
|
3107
|
-
background: var(--accent-surface-active);
|
|
3108
|
-
border-color: var(--accent-surface-active);
|
|
3109
|
-
}
|
|
3110
|
-
|
|
3111
|
-
:where(ui-switch)[intent][aria-checked="true"][pressed]::before {
|
|
3112
3135
|
background: var(--_surface-active);
|
|
3113
3136
|
border-color: var(--_surface-active);
|
|
3114
3137
|
}
|
|
@@ -4568,7 +4591,7 @@
|
|
|
4568
4591
|
|
|
4569
4592
|
:where(ui-layout-chat) :where(.layout-resize-handle):hover,
|
|
4570
4593
|
:where(ui-layout-chat[resizing]) :where(.layout-resize-handle) {
|
|
4571
|
-
background: var(--
|
|
4594
|
+
background: var(--_border-muted);
|
|
4572
4595
|
}
|
|
4573
4596
|
|
|
4574
4597
|
}
|
|
@@ -4630,7 +4653,7 @@
|
|
|
4630
4653
|
|
|
4631
4654
|
:where(ui-layout-inspector) :where(.layout-resize-handle):hover,
|
|
4632
4655
|
:where(ui-layout-inspector[resizing]) :where(.layout-resize-handle) {
|
|
4633
|
-
background: var(--
|
|
4656
|
+
background: var(--_border-muted);
|
|
4634
4657
|
}
|
|
4635
4658
|
|
|
4636
4659
|
}
|
|
@@ -4657,16 +4680,16 @@
|
|
|
4657
4680
|
content: '';
|
|
4658
4681
|
width: var(--ui-layout-sidebar-width);
|
|
4659
4682
|
flex-shrink: 0;
|
|
4660
|
-
background: var(--
|
|
4661
|
-
border-right: 1px solid var(--
|
|
4683
|
+
background: var(--_body);
|
|
4684
|
+
border-right: 1px solid var(--_border-muted);
|
|
4662
4685
|
}
|
|
4663
4686
|
|
|
4664
4687
|
:where(ui-layout-sidebar):not([data-ready])[collapsed]::before {
|
|
4665
4688
|
content: '';
|
|
4666
4689
|
width: 48px;
|
|
4667
4690
|
flex-shrink: 0;
|
|
4668
|
-
background: var(--
|
|
4669
|
-
border-right: 1px solid var(--
|
|
4691
|
+
background: var(--_body);
|
|
4692
|
+
border-right: 1px solid var(--_border-muted);
|
|
4670
4693
|
}
|
|
4671
4694
|
|
|
4672
4695
|
/* ── Content Column ── */
|
|
@@ -4682,16 +4705,23 @@
|
|
|
4682
4705
|
}
|
|
4683
4706
|
|
|
4684
4707
|
/* ── Sidebar Aside ── */
|
|
4708
|
+
/* WHY: position: relative creates the containing block for absolute
|
|
4709
|
+
header/footer overlays. Content fills the full height and scrolls
|
|
4710
|
+
underneath the pinned header/footer. */
|
|
4685
4711
|
|
|
4686
4712
|
:where(ui-layout-sidebar) > :where([slot="sidebar"]) {
|
|
4713
|
+
--_sidebar-header-height: 0px;
|
|
4714
|
+
--_sidebar-footer-height: 0px;
|
|
4715
|
+
|
|
4716
|
+
container-name: sidebar;
|
|
4717
|
+
container-type: inline-size;
|
|
4718
|
+
position: sticky;
|
|
4719
|
+
top: 0;
|
|
4687
4720
|
width: var(--ui-layout-sidebar-width);
|
|
4688
4721
|
min-width: 160px;
|
|
4689
4722
|
max-width: 400px;
|
|
4690
4723
|
height: 100dvh;
|
|
4691
|
-
|
|
4692
|
-
top: 0;
|
|
4693
|
-
display: flex;
|
|
4694
|
-
flex-direction: column;
|
|
4724
|
+
display: block;
|
|
4695
4725
|
transition: width var(--_duration) var(--_easing), min-width var(--_duration) var(--_easing);
|
|
4696
4726
|
overflow: hidden;
|
|
4697
4727
|
z-index: 10;
|
|
@@ -4703,7 +4733,9 @@
|
|
|
4703
4733
|
}
|
|
4704
4734
|
|
|
4705
4735
|
/* ── Collapsed Icon Rail ── */
|
|
4706
|
-
/* WHY: Collapsed = icon rail, not fully hidden. 48px fits icons (1rem) + padding.
|
|
4736
|
+
/* WHY: Collapsed = icon rail, not fully hidden. 48px fits icons (1rem) + padding.
|
|
4737
|
+
[collapsed] drives the aside to 48px which triggers @container sidebar queries
|
|
4738
|
+
in this file and in child component CSS (ui-nav.css, etc.). */
|
|
4707
4739
|
|
|
4708
4740
|
:where(ui-layout-sidebar)[collapsed] > :where([slot="sidebar"]) {
|
|
4709
4741
|
width: 48px;
|
|
@@ -4724,11 +4756,7 @@
|
|
|
4724
4756
|
|
|
4725
4757
|
:where(ui-layout-sidebar) :where(.layout-resize-handle):hover,
|
|
4726
4758
|
:where(ui-layout-sidebar) > :where([slot="sidebar"][resizing]) :where(.layout-resize-handle) {
|
|
4727
|
-
background: var(--
|
|
4728
|
-
}
|
|
4729
|
-
|
|
4730
|
-
:where(ui-layout-sidebar)[collapsed] > :where([slot="sidebar"]) :where(.layout-resize-handle) {
|
|
4731
|
-
display: none;
|
|
4759
|
+
background: var(--_border-muted);
|
|
4732
4760
|
}
|
|
4733
4761
|
|
|
4734
4762
|
/* WHY: When collapsed to icon rail, the sidebar edge meets content — drop left padding. */
|
|
@@ -4741,101 +4769,89 @@
|
|
|
4741
4769
|
padding-left: 0;
|
|
4742
4770
|
}
|
|
4743
4771
|
|
|
4744
|
-
/* ── Collapsed Icon-Rail Content ── */
|
|
4745
|
-
/* WHY: When collapsed, sidebar slot becomes a narrow icon rail.
|
|
4746
|
-
Text and trailing slots are hidden; only icons remain visible.
|
|
4747
|
-
Nav items hide entirely — only group headers (with icons) stay. */
|
|
4748
|
-
|
|
4749
|
-
:where(ui-layout-sidebar)[collapsed] :where([slot="sidebar"]) :where(ui-layout-sidebar-content) {
|
|
4750
|
-
align-items: center;
|
|
4751
|
-
padding: 0.5rem;
|
|
4752
|
-
}
|
|
4753
|
-
|
|
4754
|
-
:where(ui-layout-sidebar)[collapsed] :where([slot="sidebar"]) :where(ui-layout-sidebar-header),
|
|
4755
|
-
:where(ui-layout-sidebar)[collapsed] :where([slot="sidebar"]) :where(ui-layout-sidebar-footer) {
|
|
4756
|
-
justify-content: center;
|
|
4757
|
-
padding-inline: 0.5rem;
|
|
4758
|
-
}
|
|
4759
|
-
|
|
4760
|
-
:where(ui-layout-sidebar)[collapsed] :where([slot="sidebar"]) :where(ui-layout-sidebar-trigger) :where([slot="label"]),
|
|
4761
|
-
:where(ui-layout-sidebar)[collapsed] :where([slot="sidebar"]) :where(ui-layout-sidebar-trigger) :where([slot="trailing"]) {
|
|
4762
|
-
display: none;
|
|
4763
|
-
}
|
|
4764
|
-
|
|
4765
|
-
:where(ui-layout-sidebar)[collapsed] :where([slot="sidebar"]) :where(ui-nav-item) {
|
|
4766
|
-
display: none;
|
|
4767
|
-
}
|
|
4768
|
-
|
|
4769
|
-
:where(ui-layout-sidebar)[collapsed] :where([slot="sidebar"]) :where(ui-nav-group) > :where(details) > :where(summary) {
|
|
4770
|
-
justify-content: center;
|
|
4771
|
-
}
|
|
4772
|
-
|
|
4773
|
-
:where(ui-layout-sidebar)[collapsed] :where([slot="sidebar"]) :where(ui-nav-group) > :where(details) > :where(summary)::after {
|
|
4774
|
-
display: none;
|
|
4775
|
-
}
|
|
4776
|
-
|
|
4777
|
-
:where(ui-layout-sidebar)[collapsed] :where([slot="sidebar"]) :where(ui-nav-group)::after,
|
|
4778
|
-
:where(ui-layout-sidebar)[collapsed] :where([slot="sidebar"]) :where(ui-nav-group)::before {
|
|
4779
|
-
display: none;
|
|
4780
|
-
}
|
|
4781
|
-
|
|
4782
|
-
:where(ui-layout-sidebar)[collapsed] :where([slot="sidebar"]) :where(ui-nav-group-header) {
|
|
4783
|
-
justify-content: center;
|
|
4784
|
-
font-size: 0;
|
|
4785
|
-
gap: 0;
|
|
4786
|
-
}
|
|
4787
|
-
|
|
4788
|
-
/* WHY: Icon keeps its size even though parent font-size is 0. */
|
|
4789
|
-
:where(ui-layout-sidebar)[collapsed] :where([slot="sidebar"]) :where(ui-nav-group-header) :where(ui-icon) {
|
|
4790
|
-
font-size: var(--_font-size, 1rem);
|
|
4791
|
-
}
|
|
4792
|
-
|
|
4793
|
-
:where(ui-layout-sidebar)[collapsed] :where([slot="sidebar"]) :where(ui-nav-group) + :where(ui-nav-group) {
|
|
4794
|
-
margin-block-start: 0;
|
|
4795
|
-
}
|
|
4796
|
-
|
|
4797
4772
|
/* ── Sidebar Header ── */
|
|
4773
|
+
/* WHY: Absolute-positioned overlay pinned to top of aside. Content scrolls
|
|
4774
|
+
underneath it. z-index: 2 sits above content (z-index: 0). */
|
|
4798
4775
|
|
|
4799
4776
|
:where(ui-layout-sidebar-header) {
|
|
4777
|
+
position: absolute;
|
|
4778
|
+
top: 0;
|
|
4779
|
+
left: 0;
|
|
4780
|
+
right: 0;
|
|
4781
|
+
z-index: 2;
|
|
4800
4782
|
display: flex;
|
|
4801
|
-
|
|
4802
|
-
min-height: var(--ui-layout-bar-height);
|
|
4803
|
-
gap: calc(var(--_space) * 2);
|
|
4804
|
-
padding-block: var(--_space);
|
|
4805
|
-
padding-inline: calc(var(--_space-k) * var(--_space));
|
|
4806
|
-
flex-shrink: 0;
|
|
4783
|
+
flex-direction: column;
|
|
4807
4784
|
}
|
|
4808
4785
|
|
|
4809
4786
|
/* ── Sidebar Content ── */
|
|
4787
|
+
/* WHY: Full height of the aside, scrollable. Padding-block offsets keep
|
|
4788
|
+
content from starting behind header / ending behind footer.
|
|
4789
|
+
Fade-out alpha mask dissolves content edges under the overlays. */
|
|
4810
4790
|
|
|
4811
4791
|
:where(ui-layout-sidebar-content) {
|
|
4812
4792
|
display: flex;
|
|
4813
4793
|
flex-direction: column;
|
|
4814
|
-
|
|
4815
|
-
padding-block: var(--
|
|
4816
|
-
padding-inline: calc(var(--_space-k) * var(--_space));
|
|
4817
|
-
flex: 1;
|
|
4818
|
-
min-height: 0;
|
|
4794
|
+
padding-block-start: var(--_sidebar-header-height);
|
|
4795
|
+
padding-block-end: var(--_sidebar-footer-height);
|
|
4819
4796
|
width: 100%;
|
|
4797
|
+
height: 100%;
|
|
4798
|
+
overflow-y: auto;
|
|
4799
|
+
scrollbar-width: none;
|
|
4800
|
+
}
|
|
4801
|
+
|
|
4802
|
+
/* WHY: When header is present, fade top edge. Content dissolves as it
|
|
4803
|
+
scrolls under the header — transparent at top, fully visible by 1.25×
|
|
4804
|
+
the header height. No opaque header background needed. */
|
|
4805
|
+
:where(ui-layout-sidebar-content)[data-has-header] {
|
|
4806
|
+
mask-image: linear-gradient(
|
|
4807
|
+
to bottom,
|
|
4808
|
+
transparent 0,
|
|
4809
|
+
black calc(var(--_sidebar-header-height) * 1.25),
|
|
4810
|
+
black 100%
|
|
4811
|
+
);
|
|
4812
|
+
}
|
|
4813
|
+
|
|
4814
|
+
/* WHY: When footer is present, fade bottom edge. */
|
|
4815
|
+
:where(ui-layout-sidebar-content)[data-has-footer] {
|
|
4816
|
+
mask-image: linear-gradient(
|
|
4817
|
+
to bottom,
|
|
4818
|
+
black 0,
|
|
4819
|
+
black calc(100% - var(--_sidebar-footer-height) * 1.25),
|
|
4820
|
+
transparent 100%
|
|
4821
|
+
);
|
|
4822
|
+
}
|
|
4823
|
+
|
|
4824
|
+
/* WHY: When both header AND footer are present, fade both edges. */
|
|
4825
|
+
:where(ui-layout-sidebar-content)[data-has-header][data-has-footer] {
|
|
4826
|
+
mask-image: linear-gradient(
|
|
4827
|
+
to bottom,
|
|
4828
|
+
transparent 0,
|
|
4829
|
+
black calc(var(--_sidebar-header-height) * 1.25),
|
|
4830
|
+
black calc(100% - var(--_sidebar-footer-height) * 1.25),
|
|
4831
|
+
transparent 100%
|
|
4832
|
+
);
|
|
4820
4833
|
}
|
|
4821
4834
|
|
|
4822
4835
|
/* ── Sidebar Footer ── */
|
|
4836
|
+
/* WHY: Absolute-positioned overlay pinned to bottom of aside. */
|
|
4823
4837
|
|
|
4824
4838
|
:where(ui-layout-sidebar-footer) {
|
|
4839
|
+
position: absolute;
|
|
4840
|
+
bottom: 0;
|
|
4841
|
+
left: 0;
|
|
4842
|
+
right: 0;
|
|
4843
|
+
z-index: 2;
|
|
4825
4844
|
display: flex;
|
|
4826
|
-
|
|
4827
|
-
min-height: var(--ui-layout-bar-height);
|
|
4828
|
-
gap: calc(var(--_space) * 2);
|
|
4829
|
-
padding-block: var(--_space);
|
|
4830
|
-
padding-inline: calc(var(--_space-k) * var(--_space));
|
|
4831
|
-
flex-shrink: 0;
|
|
4845
|
+
flex-direction: column;
|
|
4832
4846
|
}
|
|
4833
4847
|
|
|
4834
|
-
/* ── Sidebar
|
|
4835
|
-
/* WHY:
|
|
4836
|
-
|
|
4848
|
+
/* ── Sidebar Item ── */
|
|
4849
|
+
/* WHY: Universal sidebar row element. Provides inline padding for any content
|
|
4850
|
+
(buttons, links, icons). When a child ui-listbox[popover] is present, JS
|
|
4851
|
+
wires PopoverController for click-to-toggle menu behavior.
|
|
4852
|
+
Absorbs the old ui-layout-sidebar-trigger role — one element for all rows. */
|
|
4837
4853
|
|
|
4838
|
-
:where(ui-layout-sidebar-
|
|
4854
|
+
:where(ui-layout-sidebar-item) {
|
|
4839
4855
|
display: flex;
|
|
4840
4856
|
align-items: center;
|
|
4841
4857
|
flex: 1;
|
|
@@ -4851,31 +4867,61 @@
|
|
|
4851
4867
|
user-select: none;
|
|
4852
4868
|
border: none;
|
|
4853
4869
|
background: none;
|
|
4854
|
-
padding: var(--_space);
|
|
4870
|
+
padding-block: var(--_space);
|
|
4871
|
+
padding-inline: calc(var(--_space-k) * var(--_space));
|
|
4855
4872
|
border-radius: var(--_radius);
|
|
4856
4873
|
transition: color var(--_duration) var(--_easing);
|
|
4857
4874
|
}
|
|
4858
4875
|
|
|
4859
|
-
:
|
|
4860
|
-
|
|
4876
|
+
/* WHY: Items in header/footer match the breadcrumb bar height so the
|
|
4877
|
+
first sidebar row aligns horizontally with the breadcrumb. */
|
|
4878
|
+
:where(ui-layout-sidebar-header) > :where(ui-layout-sidebar-item),
|
|
4879
|
+
:where(ui-layout-sidebar-footer) > :where(ui-layout-sidebar-item) {
|
|
4880
|
+
min-height: var(--ui-layout-bar-height);
|
|
4881
|
+
}
|
|
4882
|
+
|
|
4883
|
+
:where(ui-layout-sidebar-item):hover,
|
|
4884
|
+
:where(ui-layout-sidebar-item)[force-hover] {
|
|
4861
4885
|
color: var(--_ink-strong);
|
|
4862
4886
|
}
|
|
4863
4887
|
|
|
4864
|
-
:where(ui-layout-sidebar-
|
|
4865
|
-
:where(ui-layout-sidebar-
|
|
4888
|
+
:where(ui-layout-sidebar-item):focus-visible,
|
|
4889
|
+
:where(ui-layout-sidebar-item)[force-focus-visible] {
|
|
4866
4890
|
outline: 2px solid var(--ui-focus-ring);
|
|
4867
4891
|
outline-offset: -2px;
|
|
4868
4892
|
}
|
|
4869
4893
|
|
|
4894
|
+
/* WHY: Fixed-size icon well so all sidebar icons (header logo, nav group icons,
|
|
4895
|
+
standalone icons) center-align on the same column width regardless of intrinsic
|
|
4896
|
+
icon size. 1.5rem matches the sidebar's visual rhythm at default density.
|
|
4897
|
+
Consumer wraps the icon: <span slot="icon"><ui-icon name="..."></ui-icon></span>
|
|
4898
|
+
The wrapper is the well; the icon keeps its own --ui-icon-size dimensions. */
|
|
4899
|
+
:where(ui-layout-sidebar-item) > :where([slot="icon"]) {
|
|
4900
|
+
display: inline-flex;
|
|
4901
|
+
align-items: center;
|
|
4902
|
+
justify-content: center;
|
|
4903
|
+
width: 1.5rem;
|
|
4904
|
+
height: 1.5rem;
|
|
4905
|
+
flex-shrink: 0;
|
|
4906
|
+
}
|
|
4907
|
+
|
|
4870
4908
|
/* WHY: Trailing caret pushes to end — same pattern as button justify="spread". */
|
|
4871
|
-
:where(ui-layout-sidebar-
|
|
4909
|
+
:where(ui-layout-sidebar-item) > :where([slot="trailing"]) {
|
|
4872
4910
|
margin-inline-start: auto;
|
|
4873
4911
|
flex-shrink: 0;
|
|
4874
4912
|
color: var(--_ink-muted);
|
|
4875
4913
|
}
|
|
4876
4914
|
|
|
4915
|
+
/* WHY: When the item wraps a sub-component (e.g. ui-button) that provides
|
|
4916
|
+
its own icon, hide [slot="icon"] in expanded mode — it only serves as the
|
|
4917
|
+
bare collapsed-rail representation. Items without sub-components (just
|
|
4918
|
+
icon + label + trailing) keep [slot="icon"] visible in both modes. */
|
|
4919
|
+
:where(ui-layout-sidebar-item:has(> ui-button)) > :where([slot="icon"]) {
|
|
4920
|
+
display: none;
|
|
4921
|
+
}
|
|
4922
|
+
|
|
4877
4923
|
/* WHY: Title text truncates when sidebar narrows during resize. */
|
|
4878
|
-
:where(ui-layout-sidebar-
|
|
4924
|
+
:where(ui-layout-sidebar-item) > :where([slot="label"]) {
|
|
4879
4925
|
flex: 1;
|
|
4880
4926
|
min-width: 0;
|
|
4881
4927
|
white-space: nowrap;
|
|
@@ -4883,25 +4929,67 @@
|
|
|
4883
4929
|
text-overflow: ellipsis;
|
|
4884
4930
|
}
|
|
4885
4931
|
|
|
4886
|
-
/* ──
|
|
4887
|
-
/* WHY: Popover opens to the right of the sidebar
|
|
4932
|
+
/* ── Item Popover ── */
|
|
4933
|
+
/* WHY: Popover opens to the right of the sidebar item.
|
|
4888
4934
|
Default: top-aligned, grows downward (span-block-end).
|
|
4889
4935
|
Flip: bottom-aligned, grows upward (span-block-start). */
|
|
4890
4936
|
|
|
4891
|
-
:where(ui-layout-sidebar-
|
|
4937
|
+
:where(ui-layout-sidebar-item) > :where(ui-listbox[popover]) {
|
|
4892
4938
|
position: fixed;
|
|
4893
4939
|
position-area: inline-end span-block-end;
|
|
4894
|
-
position-try-fallbacks: --flip-up;
|
|
4940
|
+
position-try-fallbacks: --sidebar-item-flip-up;
|
|
4895
4941
|
margin: 0 0 0 var(--ui-popover-gap);
|
|
4896
4942
|
min-width: 200px;
|
|
4897
4943
|
max-height: var(--ui-popover-max-height);
|
|
4898
4944
|
overflow-y: auto;
|
|
4899
4945
|
}
|
|
4900
4946
|
|
|
4901
|
-
@position-try --flip-up {
|
|
4947
|
+
@position-try --sidebar-item-flip-up {
|
|
4902
4948
|
position-area: inline-end span-block-start;
|
|
4903
4949
|
}
|
|
4904
4950
|
|
|
4951
|
+
/* ── Container Query: Collapsed Sidebar ── */
|
|
4952
|
+
/* WHY: Each component owns its own collapsed behavior via @container.
|
|
4953
|
+
The aside is the container (container-name: sidebar). When it shrinks
|
|
4954
|
+
to 48px (icon rail), components respond to the width, not to [collapsed].
|
|
4955
|
+
Threshold 80px: collapsed = 48px, min expanded = 160px. */
|
|
4956
|
+
|
|
4957
|
+
@container sidebar (max-width: 80px) {
|
|
4958
|
+
|
|
4959
|
+
/* Resize handle — no dragging in icon rail */
|
|
4960
|
+
:where(.layout-resize-handle) {
|
|
4961
|
+
display: none;
|
|
4962
|
+
}
|
|
4963
|
+
|
|
4964
|
+
/* Header/footer — center content horizontally */
|
|
4965
|
+
:where(ui-layout-sidebar-header),
|
|
4966
|
+
:where(ui-layout-sidebar-footer) {
|
|
4967
|
+
align-items: center;
|
|
4968
|
+
}
|
|
4969
|
+
|
|
4970
|
+
/* Content — center items in the 48px rail */
|
|
4971
|
+
:where(ui-layout-sidebar-content) {
|
|
4972
|
+
align-items: center;
|
|
4973
|
+
}
|
|
4974
|
+
|
|
4975
|
+
/* Item — shrink to icon-only. Show [slot="icon"], hide everything else.
|
|
4976
|
+
WHY: Sidebar items can contain complex children (buttons with slots,
|
|
4977
|
+
links, etc.). Rather than overriding sub-component styles, the item
|
|
4978
|
+
provides its own bare icon via [slot="icon"] for the collapsed rail. */
|
|
4979
|
+
:where(ui-layout-sidebar-item) {
|
|
4980
|
+
flex: 0 0 auto;
|
|
4981
|
+
padding-inline: var(--_space);
|
|
4982
|
+
}
|
|
4983
|
+
|
|
4984
|
+
:where(ui-layout-sidebar-item) > :where([slot="icon"]) {
|
|
4985
|
+
display: inline-flex;
|
|
4986
|
+
}
|
|
4987
|
+
|
|
4988
|
+
:where(ui-layout-sidebar-item) > :where(:not([slot="icon"]):not(ui-listbox[popover]):not(.nav-group-flyout)) {
|
|
4989
|
+
display: none;
|
|
4990
|
+
}
|
|
4991
|
+
}
|
|
4992
|
+
|
|
4905
4993
|
}
|
|
4906
4994
|
|
|
4907
4995
|
@layer ui {
|