@nonoun/native-ui 0.3.0 → 0.4.0
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-lean.css +20 -941
- package/dist/components.css +20 -948
- package/dist/components.js +66 -498
- package/dist/core.js +121 -38
- package/dist/custom-elements.json +4277 -7050
- package/dist/foundation.css +5 -6
- package/dist/index.d.ts +0 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/kernel.js +208 -208
- package/dist/native-ui-lean.css +25 -947
- package/dist/native-ui.css +25 -954
- package/dist/native-ui.js +4 -4
- package/dist/register-all.js +4 -4
- package/dist/traits/drag-controller.d.ts.map +1 -1
- package/dist/traits.js +3 -3
- package/dist/ui-icon.js +1 -1
- package/package.json +1 -1
- package/dist/components/ui-nav/index.d.ts +0 -6
- package/dist/components/ui-nav/index.d.ts.map +0 -1
- package/dist/components/ui-nav/ui-nav-element.d.ts +0 -20
- package/dist/components/ui-nav/ui-nav-element.d.ts.map +0 -1
- package/dist/components/ui-nav/ui-nav-group-element.d.ts +0 -24
- package/dist/components/ui-nav/ui-nav-group-element.d.ts.map +0 -1
- package/dist/components/ui-nav/ui-nav-group-header-element.d.ts +0 -7
- package/dist/components/ui-nav/ui-nav-group-header-element.d.ts.map +0 -1
- package/dist/components/ui-nav/ui-nav-item-element.d.ts +0 -23
- package/dist/components/ui-nav/ui-nav-item-element.d.ts.map +0 -1
- package/dist/components/ui-nav/ui-nav.d.ts +0 -2
- package/dist/components/ui-nav/ui-nav.d.ts.map +0 -1
- package/dist/containers/ui-layout-chat/index.d.ts +0 -3
- package/dist/containers/ui-layout-chat/index.d.ts.map +0 -1
- package/dist/containers/ui-layout-chat/ui-layout-chat-element.d.ts +0 -14
- package/dist/containers/ui-layout-chat/ui-layout-chat-element.d.ts.map +0 -1
- package/dist/containers/ui-layout-chat/ui-layout-chat.d.ts +0 -3
- package/dist/containers/ui-layout-chat/ui-layout-chat.d.ts.map +0 -1
- package/dist/containers/ui-layout-inspector/index.d.ts +0 -3
- package/dist/containers/ui-layout-inspector/index.d.ts.map +0 -1
- package/dist/containers/ui-layout-inspector/ui-layout-inspector-element.d.ts +0 -14
- package/dist/containers/ui-layout-inspector/ui-layout-inspector-element.d.ts.map +0 -1
- package/dist/containers/ui-layout-inspector/ui-layout-inspector.d.ts +0 -3
- package/dist/containers/ui-layout-inspector/ui-layout-inspector.d.ts.map +0 -1
- package/dist/containers/ui-layout-sidebar/index.d.ts +0 -4
- package/dist/containers/ui-layout-sidebar/index.d.ts.map +0 -1
- package/dist/containers/ui-layout-sidebar/ui-layout-sidebar-element.d.ts +0 -11
- package/dist/containers/ui-layout-sidebar/ui-layout-sidebar-element.d.ts.map +0 -1
- package/dist/containers/ui-layout-sidebar/ui-layout-sidebar-item-element.d.ts +0 -10
- package/dist/containers/ui-layout-sidebar/ui-layout-sidebar-item-element.d.ts.map +0 -1
- package/dist/containers/ui-layout-sidebar/ui-layout-sidebar-item.d.ts +0 -3
- package/dist/containers/ui-layout-sidebar/ui-layout-sidebar-item.d.ts.map +0 -1
- package/dist/containers/ui-layout-sidebar/ui-layout-sidebar.d.ts +0 -4
- package/dist/containers/ui-layout-sidebar/ui-layout-sidebar.d.ts.map +0 -1
package/dist/native-ui.css
CHANGED
|
@@ -1291,11 +1291,10 @@
|
|
|
1291
1291
|
ui-input,
|
|
1292
1292
|
ui-input-otp,
|
|
1293
1293
|
ui-kbd,
|
|
1294
|
-
ui-layout-chat,
|
|
1295
|
-
ui-layout-inspector,
|
|
1296
|
-
ui-layout-sidebar, ui-layout-sidebar-item,
|
|
1297
1294
|
ui-listbox,
|
|
1298
|
-
|
|
1295
|
+
nui-app-panel,
|
|
1296
|
+
nui-sidebar, nui-sidebar-item,
|
|
1297
|
+
nui-sidebar-nav, nui-sidebar-group, nui-sidebar-group-header, nui-sidebar-nav-item,
|
|
1299
1298
|
ui-option, ui-option-group, ui-option-group-header,
|
|
1300
1299
|
ui-pagination,
|
|
1301
1300
|
ui-radio, ui-radio-group,
|
|
@@ -1359,7 +1358,7 @@
|
|
|
1359
1358
|
ui-select, ui-combobox,
|
|
1360
1359
|
ui-segmented-control, ui-segment,
|
|
1361
1360
|
ui-tab, ui-accordion-item,
|
|
1362
|
-
ui-tree-item,
|
|
1361
|
+
ui-tree-item, nui-sidebar-nav-item,
|
|
1363
1362
|
ui-breadcrumb-item, ui-table-row,
|
|
1364
1363
|
ui-calendar, ui-range,
|
|
1365
1364
|
ui-card, ui-slideshow
|
|
@@ -1383,7 +1382,7 @@
|
|
|
1383
1382
|
ui-listbox, ui-command,
|
|
1384
1383
|
ui-segmented-control, ui-tabs,
|
|
1385
1384
|
ui-accordion, ui-tree,
|
|
1386
|
-
ui-calendar, ui-pagination,
|
|
1385
|
+
ui-calendar, ui-pagination, nui-sidebar-nav
|
|
1387
1386
|
)[aria-disabled="true"] {
|
|
1388
1387
|
color: var(--_ink-disabled);
|
|
1389
1388
|
pointer-events: none;
|
|
@@ -2107,6 +2106,15 @@
|
|
|
2107
2106
|
:where(ui-icon[size="lg"]) { --ui-icon-size: var(--ui-icon-lg); }
|
|
2108
2107
|
:where(ui-icon[size="xl"]) { --ui-icon-size: var(--ui-icon-xl); }
|
|
2109
2108
|
|
|
2109
|
+
/* ── Intent (declarative color) ── */
|
|
2110
|
+
|
|
2111
|
+
:where(ui-icon[intent="accent"]) { --ui-icon-color: var(--accent-ink); }
|
|
2112
|
+
:where(ui-icon[intent="success"]) { --ui-icon-color: var(--success-ink); }
|
|
2113
|
+
:where(ui-icon[intent="warning"]) { --ui-icon-color: var(--warning-ink); }
|
|
2114
|
+
:where(ui-icon[intent="danger"]) { --ui-icon-color: var(--danger-ink); }
|
|
2115
|
+
:where(ui-icon[intent="info"]) { --ui-icon-color: var(--info-ink); }
|
|
2116
|
+
:where(ui-icon[intent="muted"]) { --ui-icon-color: var(--neutral-ink-muted); }
|
|
2117
|
+
|
|
2110
2118
|
/* ── Forced Colors ── */
|
|
2111
2119
|
|
|
2112
2120
|
@media (forced-colors: active) {
|
|
@@ -2830,7 +2838,7 @@
|
|
|
2830
2838
|
/* ╭──────────────────────────────────────────────────────────╮
|
|
2831
2839
|
│ ui-chat │
|
|
2832
2840
|
│ Chat application shell with header / content / input / │
|
|
2833
|
-
│ footer sub-containers. Fills its parent (
|
|
2841
|
+
│ footer sub-containers. Fills its parent (nui-app-panel │
|
|
2834
2842
|
│ or any flex column). │
|
|
2835
2843
|
╰──────────────────────────────────────────────────────────╯ */
|
|
2836
2844
|
|
|
@@ -3388,6 +3396,16 @@
|
|
|
3388
3396
|
opacity: var(--ui-backdrop-opacity);
|
|
3389
3397
|
}
|
|
3390
3398
|
|
|
3399
|
+
/* ── Sizing API ──
|
|
3400
|
+
WHY: Host pages set width and box-shadow directly on ui-card inside ui-dialog.
|
|
3401
|
+
Expose custom properties so consumers can set these declaratively on ui-dialog
|
|
3402
|
+
without reaching into children. */
|
|
3403
|
+
|
|
3404
|
+
:where(ui-dialog) > :where(dialog) > :where(*) {
|
|
3405
|
+
width: var(--ui-dialog-width, auto);
|
|
3406
|
+
box-shadow: var(--ui-dialog-shadow, none);
|
|
3407
|
+
}
|
|
3408
|
+
|
|
3391
3409
|
}
|
|
3392
3410
|
|
|
3393
3411
|
@layer ui {
|
|
@@ -4043,370 +4061,6 @@
|
|
|
4043
4061
|
|
|
4044
4062
|
}
|
|
4045
4063
|
|
|
4046
|
-
@layer ui {
|
|
4047
|
-
|
|
4048
|
-
/* ╭──────────────────────────────────────────────────────────╮
|
|
4049
|
-
│ ui-nav │
|
|
4050
|
-
│ Navigation list with keyboard nav + selection. │
|
|
4051
|
-
│ Transparent wrapper — no visual surface. │
|
|
4052
|
-
│ Uses ui-nav-item / ui-nav-group for children. │
|
|
4053
|
-
╰──────────────────────────────────────────────────────────╯ */
|
|
4054
|
-
|
|
4055
|
-
/* WHY: ui-nav is a transparent flex wrapper — no inline padding.
|
|
4056
|
-
Inline padding is owned by leaf items (nav-item, summary).
|
|
4057
|
-
Block padding is owned by nav-group margins. */
|
|
4058
|
-
:where(ui-nav) {
|
|
4059
|
-
display: flex;
|
|
4060
|
-
flex-direction: column;
|
|
4061
|
-
gap: 0;
|
|
4062
|
-
padding: 0;
|
|
4063
|
-
outline: none;
|
|
4064
|
-
}
|
|
4065
|
-
|
|
4066
|
-
/* ── Nav Item ── */
|
|
4067
|
-
/* WHY: Nav items share the same visual pattern as options (ghost row,
|
|
4068
|
-
hover/active/selected states). */
|
|
4069
|
-
|
|
4070
|
-
:where(ui-nav-item) {
|
|
4071
|
-
--_font-weight: var(--ui-font-weight-text);
|
|
4072
|
-
--_line-height: var(--ui-line-height-control);
|
|
4073
|
-
|
|
4074
|
-
display: flex;
|
|
4075
|
-
align-items: center;
|
|
4076
|
-
gap: calc(var(--_space) * 2);
|
|
4077
|
-
padding-inline: calc(var(--_space-k) * var(--_space));
|
|
4078
|
-
|
|
4079
|
-
min-height: var(--_min-height);
|
|
4080
|
-
|
|
4081
|
-
font-size: var(--_font-size);
|
|
4082
|
-
letter-spacing: var(--_letter-spacing);
|
|
4083
|
-
line-height: var(--_line-height);
|
|
4084
|
-
font-weight: var(--_font-weight);
|
|
4085
|
-
|
|
4086
|
-
cursor: pointer;
|
|
4087
|
-
user-select: none;
|
|
4088
|
-
color: var(--_ink-muted);
|
|
4089
|
-
|
|
4090
|
-
transition:
|
|
4091
|
-
background var(--_duration) var(--_easing),
|
|
4092
|
-
color var(--_duration) var(--_easing),
|
|
4093
|
-
border-color var(--_duration) var(--_easing),
|
|
4094
|
-
opacity var(--_duration) var(--_easing),
|
|
4095
|
-
transform var(--_duration) var(--_easing);
|
|
4096
|
-
}
|
|
4097
|
-
|
|
4098
|
-
/* ── Nav Item States ── */
|
|
4099
|
-
|
|
4100
|
-
:where(ui-nav-item):hover,
|
|
4101
|
-
:where(ui-nav-item)[force-hover] {
|
|
4102
|
-
color: var(--_ink-hover);
|
|
4103
|
-
}
|
|
4104
|
-
|
|
4105
|
-
:where(ui-nav-item):active,
|
|
4106
|
-
:where(ui-nav-item)[force-active] {
|
|
4107
|
-
color: var(--_ink-active);
|
|
4108
|
-
}
|
|
4109
|
-
|
|
4110
|
-
:where(ui-nav-item)[aria-current="page"] {
|
|
4111
|
-
color: var(--_ink-strong);
|
|
4112
|
-
}
|
|
4113
|
-
|
|
4114
|
-
:where(ui-nav-item)[aria-disabled="true"] {
|
|
4115
|
-
color: var(--_ink-disabled);
|
|
4116
|
-
cursor: not-allowed;
|
|
4117
|
-
pointer-events: none;
|
|
4118
|
-
}
|
|
4119
|
-
|
|
4120
|
-
:where(ui-nav-item):focus-visible,
|
|
4121
|
-
:where(ui-nav-item)[force-focus-visible] {
|
|
4122
|
-
outline: 2px solid var(--ui-focus-ring);
|
|
4123
|
-
outline-offset: -2px;
|
|
4124
|
-
}
|
|
4125
|
-
|
|
4126
|
-
/* ── Nav Group ── */
|
|
4127
|
-
/* WHY: Groups stamp a native <details>/<summary> for collapsible behavior.
|
|
4128
|
-
DOM structure: ui-nav-group > details > summary > ui-nav-group-header
|
|
4129
|
-
> ui-nav-item* */
|
|
4130
|
-
|
|
4131
|
-
:where(ui-nav-group) {
|
|
4132
|
-
--_indicator-index: 0;
|
|
4133
|
-
|
|
4134
|
-
display: block;
|
|
4135
|
-
position: relative;
|
|
4136
|
-
}
|
|
4137
|
-
|
|
4138
|
-
:where(ui-nav-group) + :where(ui-nav-group) {
|
|
4139
|
-
margin-block-start: calc(var(--_space) * 2);
|
|
4140
|
-
}
|
|
4141
|
-
|
|
4142
|
-
/* ── Details (native disclosure with animated open/close) ── */
|
|
4143
|
-
/* WHY: ::details-content lets us animate the content area directly.
|
|
4144
|
-
interpolate-size allows height to transition between 0 and auto.
|
|
4145
|
-
content-visibility with allow-discrete keeps content visible during close. */
|
|
4146
|
-
|
|
4147
|
-
:where(ui-nav-group) > :where(details) {
|
|
4148
|
-
interpolate-size: allow-keywords;
|
|
4149
|
-
}
|
|
4150
|
-
|
|
4151
|
-
:where(ui-nav-group) > :where(details)::details-content {
|
|
4152
|
-
height: 0;
|
|
4153
|
-
overflow: clip;
|
|
4154
|
-
opacity: 0;
|
|
4155
|
-
|
|
4156
|
-
transition:
|
|
4157
|
-
height var(--_duration) var(--_easing),
|
|
4158
|
-
opacity var(--_duration) var(--_easing),
|
|
4159
|
-
content-visibility var(--_duration) var(--_easing) allow-discrete;
|
|
4160
|
-
}
|
|
4161
|
-
|
|
4162
|
-
:where(ui-nav-group) > :where(details[open])::details-content {
|
|
4163
|
-
height: auto;
|
|
4164
|
-
opacity: 1;
|
|
4165
|
-
}
|
|
4166
|
-
|
|
4167
|
-
/* ── Summary (clickable header row) ── */
|
|
4168
|
-
|
|
4169
|
-
:where(ui-nav-group) > :where(details) > :where(summary) {
|
|
4170
|
-
display: flex;
|
|
4171
|
-
align-items: center;
|
|
4172
|
-
gap: calc(var(--_space) * 2);
|
|
4173
|
-
padding-inline: calc(var(--_space-k) * var(--_space));
|
|
4174
|
-
cursor: pointer;
|
|
4175
|
-
user-select: none;
|
|
4176
|
-
list-style: none;
|
|
4177
|
-
outline: none;
|
|
4178
|
-
}
|
|
4179
|
-
|
|
4180
|
-
/* WHY: Remove default marker in WebKit */
|
|
4181
|
-
:where(ui-nav-group) > :where(details) > :where(summary)::-webkit-details-marker {
|
|
4182
|
-
display: none;
|
|
4183
|
-
}
|
|
4184
|
-
|
|
4185
|
-
:where(ui-nav-group) > :where(details) > :where(summary)::marker {
|
|
4186
|
-
display: none;
|
|
4187
|
-
content: '';
|
|
4188
|
-
}
|
|
4189
|
-
|
|
4190
|
-
/* ── Nav Group Header ── */
|
|
4191
|
-
/* WHY: Header sits inside <summary>. Bold text with optional icon. */
|
|
4192
|
-
|
|
4193
|
-
:where(ui-nav-group-header) {
|
|
4194
|
-
display: flex;
|
|
4195
|
-
align-items: center;
|
|
4196
|
-
flex: 1;
|
|
4197
|
-
gap: calc(var(--_space) * 2);
|
|
4198
|
-
min-height: var(--_min-height);
|
|
4199
|
-
font-size: var(--_font-size);
|
|
4200
|
-
font-weight: var(--ui-font-weight-button);
|
|
4201
|
-
letter-spacing: var(--_letter-spacing);
|
|
4202
|
-
line-height: var(--ui-line-height-control);
|
|
4203
|
-
color: var(--_ink);
|
|
4204
|
-
cursor: pointer;
|
|
4205
|
-
user-select: none;
|
|
4206
|
-
}
|
|
4207
|
-
|
|
4208
|
-
/* WHY: Fixed-size icon well — matches ui-layout-sidebar-item [slot="icon"].
|
|
4209
|
-
All sidebar icons align on the same 1.5rem column regardless of icon size.
|
|
4210
|
-
JS wraps the first <ui-icon> child in a .icon-well span during setup(). */
|
|
4211
|
-
:where(ui-nav-group-header) > :where(.icon-well) {
|
|
4212
|
-
display: inline-flex;
|
|
4213
|
-
align-items: center;
|
|
4214
|
-
justify-content: center;
|
|
4215
|
-
width: 1.5rem;
|
|
4216
|
-
height: 1.5rem;
|
|
4217
|
-
flex-shrink: 0;
|
|
4218
|
-
}
|
|
4219
|
-
|
|
4220
|
-
/* ── Chevron icon (right side of summary) ── */
|
|
4221
|
-
|
|
4222
|
-
:where(ui-nav-group) > :where(details) > :where(summary)::after {
|
|
4223
|
-
content: '';
|
|
4224
|
-
flex-shrink: 0;
|
|
4225
|
-
width: var(--_icon-size);
|
|
4226
|
-
height: var(--_icon-size);
|
|
4227
|
-
|
|
4228
|
-
mask-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M213.66,101.66l-80,80a8,8,0,0,1-11.32,0l-80-80A8,8,0,0,1,53.66,90.34L128,164.69l74.34-74.35a8,8,0,0,1,11.32,11.32Z' fill='currentColor'/%3E%3C/svg%3E");
|
|
4229
|
-
mask-size: contain;
|
|
4230
|
-
mask-repeat: no-repeat;
|
|
4231
|
-
mask-position: center;
|
|
4232
|
-
-webkit-mask-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M213.66,101.66l-80,80a8,8,0,0,1-11.32,0l-80-80A8,8,0,0,1,53.66,90.34L128,164.69l74.34-74.35a8,8,0,0,1,11.32,11.32Z' fill='currentColor'/%3E%3C/svg%3E");
|
|
4233
|
-
-webkit-mask-size: contain;
|
|
4234
|
-
-webkit-mask-repeat: no-repeat;
|
|
4235
|
-
-webkit-mask-position: center;
|
|
4236
|
-
|
|
4237
|
-
background: var(--_ink-muted);
|
|
4238
|
-
|
|
4239
|
-
transition:
|
|
4240
|
-
transform var(--_duration) var(--_easing);
|
|
4241
|
-
}
|
|
4242
|
-
|
|
4243
|
-
/* Chevron rotates when open */
|
|
4244
|
-
:where(ui-nav-group) > :where(details[open]) > :where(summary)::after {
|
|
4245
|
-
transform: rotate(180deg);
|
|
4246
|
-
}
|
|
4247
|
-
|
|
4248
|
-
/* ── Selected group — has a child with aria-current ── */
|
|
4249
|
-
|
|
4250
|
-
:where(ui-nav-group):state(has-selection) > :where(details) > :where(summary) :where(ui-nav-group-header) {
|
|
4251
|
-
color: var(--_ink-strong);
|
|
4252
|
-
}
|
|
4253
|
-
|
|
4254
|
-
/* ── Summary Hover ── */
|
|
4255
|
-
|
|
4256
|
-
:where(ui-nav-group) > :where(details) > :where(summary):hover :where(ui-nav-group-header),
|
|
4257
|
-
:where(ui-nav-group[force-hover]) > :where(details) > :where(summary) :where(ui-nav-group-header) {
|
|
4258
|
-
color: var(--_ink-strong);
|
|
4259
|
-
}
|
|
4260
|
-
|
|
4261
|
-
/* ── Summary Focus ── */
|
|
4262
|
-
|
|
4263
|
-
:where(ui-nav-group) > :where(details) > :where(summary):focus-visible,
|
|
4264
|
-
:where(ui-nav-group[force-focus-visible]) > :where(details) > :where(summary) {
|
|
4265
|
-
outline: 2px solid var(--ui-focus-ring);
|
|
4266
|
-
outline-offset: -2px;
|
|
4267
|
-
}
|
|
4268
|
-
|
|
4269
|
-
/* ── Vertical connector line (icon groups only) ── */
|
|
4270
|
-
/* WHY: Connector draws from below the header to the bottom of the group.
|
|
4271
|
-
Only shown when header contains an icon. Scoped via :has(). */
|
|
4272
|
-
|
|
4273
|
-
/* WHY: Insets account for the summary's padding-inline so the connector
|
|
4274
|
-
line passes through the icon center and child text aligns with header text. */
|
|
4275
|
-
:where(ui-nav-group):has(:where(ui-nav-group-header) :where(.icon-well)) {
|
|
4276
|
-
--_group-pad: calc(var(--_space-k) * var(--_space));
|
|
4277
|
-
--_group-icon-well: 1.5rem;
|
|
4278
|
-
--_group-line-inset: calc(var(--_group-pad) + var(--_group-icon-well) / 2);
|
|
4279
|
-
--_group-child-inset: calc(var(--_group-icon-well) + var(--_space) * 2);
|
|
4280
|
-
}
|
|
4281
|
-
|
|
4282
|
-
:where(ui-nav-group):has(:where(ui-nav-group-header) :where(.icon-well)):has(:where(details[open]))::after {
|
|
4283
|
-
content: '';
|
|
4284
|
-
position: absolute;
|
|
4285
|
-
inset-inline-start: var(--_group-line-inset);
|
|
4286
|
-
top: var(--_min-height);
|
|
4287
|
-
bottom: 0;
|
|
4288
|
-
width: 1px;
|
|
4289
|
-
background: var(--_border-muted);
|
|
4290
|
-
pointer-events: none;
|
|
4291
|
-
}
|
|
4292
|
-
|
|
4293
|
-
/* ── Sliding indicator (same pattern as vertical tabs) ── */
|
|
4294
|
-
/* WHY: A ::before pseudo on the group slides along the connector line.
|
|
4295
|
-
JS sets --_indicator-index; :state(has-selection) gates visibility. */
|
|
4296
|
-
|
|
4297
|
-
:where(ui-nav-group):has(:where(ui-nav-group-header) :where(.icon-well)):has(:where(details[open])):state(has-selection)::before {
|
|
4298
|
-
content: '';
|
|
4299
|
-
position: absolute;
|
|
4300
|
-
z-index: 1;
|
|
4301
|
-
inset-inline-start: calc(var(--_group-line-inset, 0px) - 0.5px);
|
|
4302
|
-
top: var(--_min-height);
|
|
4303
|
-
height: var(--_min-height);
|
|
4304
|
-
width: 2px;
|
|
4305
|
-
border-radius: 1px;
|
|
4306
|
-
background: var(--_surface);
|
|
4307
|
-
pointer-events: none;
|
|
4308
|
-
transform: translateY(calc(var(--_indicator-index) * var(--_min-height)));
|
|
4309
|
-
|
|
4310
|
-
transition:
|
|
4311
|
-
transform var(--_duration) var(--_easing),
|
|
4312
|
-
background var(--_duration) var(--_easing);
|
|
4313
|
-
}
|
|
4314
|
-
|
|
4315
|
-
/* ── Grouped Child Items ── */
|
|
4316
|
-
/* WHY: When header has an icon, margin-inline-start = icon-size + gap
|
|
4317
|
-
so item text aligns with header text past the icon.
|
|
4318
|
-
Items are inside <details> after the <summary>. */
|
|
4319
|
-
|
|
4320
|
-
:where(ui-nav-group) > :where(details) > :where(ui-nav-item) {
|
|
4321
|
-
margin-inline-start: var(--_group-child-inset, 0);
|
|
4322
|
-
}
|
|
4323
|
-
|
|
4324
|
-
/* ── Nav Group Flyout (collapsed sidebar) ── */
|
|
4325
|
-
/* WHY: In collapsed mode, summary click opens a ui-listbox popover to the right
|
|
4326
|
-
instead of expanding the <details>. Same pattern as sidebar-trigger menus. */
|
|
4327
|
-
|
|
4328
|
-
:where(ui-nav-group) > :where(ui-listbox.nav-group-flyout[popover]) {
|
|
4329
|
-
--_popover-origin: left center;
|
|
4330
|
-
--_popover-from: perspective(800px) scale(0.96) rotateY(20deg);
|
|
4331
|
-
|
|
4332
|
-
position: fixed;
|
|
4333
|
-
position-area: inline-end span-block-end;
|
|
4334
|
-
position-try-fallbacks: --nav-flyout-flip-up;
|
|
4335
|
-
margin-block: var(--ui-popover-viewport-margin);
|
|
4336
|
-
margin-inline: 0;
|
|
4337
|
-
margin-inline-start: var(--ui-popover-gap);
|
|
4338
|
-
min-width: 200px;
|
|
4339
|
-
max-height: var(--ui-popover-max-height);
|
|
4340
|
-
overflow-y: auto;
|
|
4341
|
-
}
|
|
4342
|
-
|
|
4343
|
-
@position-try --nav-flyout-flip-up {
|
|
4344
|
-
position-area: inline-end span-block-start;
|
|
4345
|
-
}
|
|
4346
|
-
|
|
4347
|
-
@position-try --nav-flyout-flip-down {
|
|
4348
|
-
position-area: inline-end span-block-end;
|
|
4349
|
-
}
|
|
4350
|
-
|
|
4351
|
-
/* ── Container Query: Collapsed Sidebar ── */
|
|
4352
|
-
/* WHY: Nav components own their own collapsed behavior via @container.
|
|
4353
|
-
The sidebar aside declares container-name: sidebar. When it shrinks
|
|
4354
|
-
to 48px (icon rail), nav responds to the width — not to [collapsed].
|
|
4355
|
-
Threshold 80px: collapsed = 48px, min expanded = 160px. */
|
|
4356
|
-
|
|
4357
|
-
@container sidebar (max-width: 80px) {
|
|
4358
|
-
|
|
4359
|
-
/* Nav items hide entirely — only group headers (with icons) remain. */
|
|
4360
|
-
:where(ui-nav-item) {
|
|
4361
|
-
display: none;
|
|
4362
|
-
}
|
|
4363
|
-
|
|
4364
|
-
/* Summary shrinks to icon-only. Reduced inline padding wraps tightly
|
|
4365
|
-
around the icon; parent align-items: center handles horizontal centering. */
|
|
4366
|
-
:where(ui-nav-group) > :where(details) > :where(summary) {
|
|
4367
|
-
padding-inline: var(--_space);
|
|
4368
|
-
border-radius: var(--_radius);
|
|
4369
|
-
}
|
|
4370
|
-
|
|
4371
|
-
/* Hide chevron — no expand/collapse in icon rail (flyout instead). */
|
|
4372
|
-
:where(ui-nav-group) > :where(details) > :where(summary)::after {
|
|
4373
|
-
display: none;
|
|
4374
|
-
}
|
|
4375
|
-
|
|
4376
|
-
/* Hide vertical connector line and sliding indicator. */
|
|
4377
|
-
:where(ui-nav-group)::after,
|
|
4378
|
-
:where(ui-nav-group)::before {
|
|
4379
|
-
display: none;
|
|
4380
|
-
}
|
|
4381
|
-
|
|
4382
|
-
/* Header collapses to icon-only. font-size: 0 hides text nodes
|
|
4383
|
-
(can't be targeted by CSS). Icon overrides back to normal below. */
|
|
4384
|
-
:where(ui-nav-group-header) {
|
|
4385
|
-
flex: 0 0 auto;
|
|
4386
|
-
font-size: 0;
|
|
4387
|
-
gap: 0;
|
|
4388
|
-
}
|
|
4389
|
-
|
|
4390
|
-
:where(ui-nav-group-header) :where(.icon-well) :where(ui-icon) {
|
|
4391
|
-
font-size: var(--_font-size, 1rem);
|
|
4392
|
-
}
|
|
4393
|
-
|
|
4394
|
-
/* WHY: In collapsed mode the group is a small icon — centering
|
|
4395
|
-
the flyout vertically with the anchor is more natural than top-aligning.
|
|
4396
|
-
Fallbacks handle viewport clipping (top/bottom edge). */
|
|
4397
|
-
:where(ui-nav-group) > :where(ui-listbox.nav-group-flyout[popover]) {
|
|
4398
|
-
position-area: inline-end;
|
|
4399
|
-
position-try-fallbacks: --nav-flyout-flip-up, --nav-flyout-flip-down;
|
|
4400
|
-
}
|
|
4401
|
-
|
|
4402
|
-
/* Collapse inter-group spacing in icon rail. */
|
|
4403
|
-
:where(ui-nav-group) + :where(ui-nav-group) {
|
|
4404
|
-
margin-block-start: 0;
|
|
4405
|
-
}
|
|
4406
|
-
}
|
|
4407
|
-
|
|
4408
|
-
}
|
|
4409
|
-
|
|
4410
4064
|
@layer ui {
|
|
4411
4065
|
|
|
4412
4066
|
/* ── Pagination Container ── */
|
|
@@ -6660,589 +6314,6 @@
|
|
|
6660
6314
|
|
|
6661
6315
|
}
|
|
6662
6316
|
|
|
6663
|
-
@layer ui {
|
|
6664
|
-
|
|
6665
|
-
/* ╭──────────────────────────────────────────────────────────╮
|
|
6666
|
-
│ ui-layout-body │
|
|
6667
|
-
│ Rounded, padded, scrollable content surface. │
|
|
6668
|
-
│ Fills remaining flex space inside ui-layout-canvas. │
|
|
6669
|
-
╰──────────────────────────────────────────────────────────╯ */
|
|
6670
|
-
|
|
6671
|
-
:where(ui-layout-body) {
|
|
6672
|
-
display: flex;
|
|
6673
|
-
flex: 1;
|
|
6674
|
-
min-width: 0;
|
|
6675
|
-
flex-direction: column;
|
|
6676
|
-
overflow-y: auto;
|
|
6677
|
-
scrollbar-width: none;
|
|
6678
|
-
background: var(--_ground, var(--_panel));
|
|
6679
|
-
border-radius: var(--_radius);
|
|
6680
|
-
padding: calc(var(--_space-k) * var(--_space));
|
|
6681
|
-
}
|
|
6682
|
-
|
|
6683
|
-
:where(ui-layout-body)[show-scrollbar] {
|
|
6684
|
-
scrollbar-width: thin;
|
|
6685
|
-
}
|
|
6686
|
-
|
|
6687
|
-
}
|
|
6688
|
-
|
|
6689
|
-
@layer ui {
|
|
6690
|
-
|
|
6691
|
-
/* ╭──────────────────────────────────────────────────────────╮
|
|
6692
|
-
│ ui-layout-breadcrumb │
|
|
6693
|
-
│ Grid bar with leading / label / trailing slots. │
|
|
6694
|
-
│ Same slot pattern as ui-header. │
|
|
6695
|
-
╰──────────────────────────────────────────────────────────╯ */
|
|
6696
|
-
|
|
6697
|
-
/* ── Base ── */
|
|
6698
|
-
|
|
6699
|
-
:where(ui-layout-breadcrumb) {
|
|
6700
|
-
display: grid;
|
|
6701
|
-
grid-template-columns: 1fr;
|
|
6702
|
-
align-items: center;
|
|
6703
|
-
min-height: var(--ui-layout-bar-height);
|
|
6704
|
-
gap: calc(var(--_space) * 2);
|
|
6705
|
-
padding-block: var(--_space);
|
|
6706
|
-
padding-inline: calc(var(--_space-k) * var(--_space));
|
|
6707
|
-
flex-shrink: 0;
|
|
6708
|
-
min-width: 0;
|
|
6709
|
-
}
|
|
6710
|
-
|
|
6711
|
-
/* ── Slots ── */
|
|
6712
|
-
|
|
6713
|
-
:where(ui-layout-breadcrumb):has(> [slot="leading"]):has(> [slot="trailing"]) {
|
|
6714
|
-
grid-template-columns: auto 1fr auto;
|
|
6715
|
-
}
|
|
6716
|
-
|
|
6717
|
-
:where(ui-layout-breadcrumb):has(> [slot="leading"]):not(:has(> [slot="trailing"])) {
|
|
6718
|
-
grid-template-columns: auto 1fr;
|
|
6719
|
-
}
|
|
6720
|
-
|
|
6721
|
-
:where(ui-layout-breadcrumb):not(:has(> [slot="leading"])):has(> [slot="trailing"]) {
|
|
6722
|
-
grid-template-columns: 1fr auto;
|
|
6723
|
-
}
|
|
6724
|
-
|
|
6725
|
-
:where(ui-layout-breadcrumb) > :where([slot="leading"]) {
|
|
6726
|
-
display: flex;
|
|
6727
|
-
align-items: center;
|
|
6728
|
-
gap: calc(var(--_space) * 2);
|
|
6729
|
-
}
|
|
6730
|
-
|
|
6731
|
-
:where(ui-layout-breadcrumb) > :where([slot="label"]),
|
|
6732
|
-
:where(ui-layout-breadcrumb) > :where(:not([slot])) {
|
|
6733
|
-
min-width: 0;
|
|
6734
|
-
}
|
|
6735
|
-
|
|
6736
|
-
:where(ui-layout-breadcrumb) > :where([slot="trailing"]) {
|
|
6737
|
-
display: flex;
|
|
6738
|
-
align-items: center;
|
|
6739
|
-
gap: calc(var(--_space) * 2);
|
|
6740
|
-
}
|
|
6741
|
-
|
|
6742
|
-
}
|
|
6743
|
-
|
|
6744
|
-
@layer ui {
|
|
6745
|
-
|
|
6746
|
-
/* ╭──────────────────────────────────────────────────────────╮
|
|
6747
|
-
│ ui-layout-canvas │
|
|
6748
|
-
│ Structural flex row for body + chat panels. │
|
|
6749
|
-
│ No background, no radius — purely layout. │
|
|
6750
|
-
╰──────────────────────────────────────────────────────────╯ */
|
|
6751
|
-
|
|
6752
|
-
:where(ui-layout-canvas) {
|
|
6753
|
-
display: flex;
|
|
6754
|
-
flex: 1;
|
|
6755
|
-
min-height: 0;
|
|
6756
|
-
padding: 0 calc(var(--_space-k) * var(--_space)) calc(var(--_space-k) * var(--_space));
|
|
6757
|
-
}
|
|
6758
|
-
|
|
6759
|
-
}
|
|
6760
|
-
|
|
6761
|
-
@layer ui {
|
|
6762
|
-
|
|
6763
|
-
/* ╭──────────────────────────────────────────────────────────╮
|
|
6764
|
-
│ ui-layout-chat │
|
|
6765
|
-
│ Rounded, padded, scrollable right panel. │
|
|
6766
|
-
│ Hidden by default — shown via [open] attribute. │
|
|
6767
|
-
╰──────────────────────────────────────────────────────────╯ */
|
|
6768
|
-
|
|
6769
|
-
:where(ui-layout-chat) {
|
|
6770
|
-
position: relative;
|
|
6771
|
-
display: flex;
|
|
6772
|
-
flex-direction: column;
|
|
6773
|
-
width: 0;
|
|
6774
|
-
min-width: 0;
|
|
6775
|
-
max-width: 480px;
|
|
6776
|
-
overflow: clip;
|
|
6777
|
-
scrollbar-width: none;
|
|
6778
|
-
background: var(--_ground, var(--_panel));
|
|
6779
|
-
border-radius: var(--_radius);
|
|
6780
|
-
padding: 0;
|
|
6781
|
-
transition:
|
|
6782
|
-
width var(--_duration) var(--_easing),
|
|
6783
|
-
min-width var(--_duration) var(--_easing),
|
|
6784
|
-
padding var(--_duration) var(--_easing),
|
|
6785
|
-
margin var(--_duration) var(--_easing);
|
|
6786
|
-
}
|
|
6787
|
-
|
|
6788
|
-
:where(ui-layout-chat[open]) {
|
|
6789
|
-
width: 360px;
|
|
6790
|
-
min-width: 280px;
|
|
6791
|
-
margin-inline-start: calc(var(--_space) * 2);
|
|
6792
|
-
overflow-y: auto;
|
|
6793
|
-
padding: calc(var(--_space-k) * var(--_space));
|
|
6794
|
-
}
|
|
6795
|
-
|
|
6796
|
-
/* WHY: When ui-chat manages its own sub-container padding and scroll,
|
|
6797
|
-
the layout container delegates — no own padding, no own scroll.
|
|
6798
|
-
overflow: visible lets CSS anchor-positioned popovers (ui-select etc.)
|
|
6799
|
-
resolve through to the top layer. */
|
|
6800
|
-
:where(ui-layout-chat[open]):has(> ui-chat) {
|
|
6801
|
-
padding: 0;
|
|
6802
|
-
overflow: visible;
|
|
6803
|
-
}
|
|
6804
|
-
|
|
6805
|
-
/* WHY: Disable width transition while dragging — it fights the pointer. */
|
|
6806
|
-
:where(ui-layout-chat[resizing]) {
|
|
6807
|
-
transition: none;
|
|
6808
|
-
}
|
|
6809
|
-
|
|
6810
|
-
:where(ui-layout-chat)[show-scrollbar] {
|
|
6811
|
-
scrollbar-width: thin;
|
|
6812
|
-
}
|
|
6813
|
-
|
|
6814
|
-
/* ── Resize Handle ── */
|
|
6815
|
-
|
|
6816
|
-
:where(ui-layout-chat) :where(.layout-resize-handle) {
|
|
6817
|
-
position: absolute;
|
|
6818
|
-
top: 0;
|
|
6819
|
-
left: 0;
|
|
6820
|
-
width: 4px;
|
|
6821
|
-
height: 100%;
|
|
6822
|
-
cursor: col-resize;
|
|
6823
|
-
z-index: 1;
|
|
6824
|
-
}
|
|
6825
|
-
|
|
6826
|
-
:where(ui-layout-chat) :where(.layout-resize-handle):hover,
|
|
6827
|
-
:where(ui-layout-chat[resizing]) :where(.layout-resize-handle) {
|
|
6828
|
-
background: var(--_border-muted);
|
|
6829
|
-
}
|
|
6830
|
-
|
|
6831
|
-
}
|
|
6832
|
-
|
|
6833
|
-
@layer ui {
|
|
6834
|
-
|
|
6835
|
-
/* ╭──────────────────────────────────────────────────────────╮
|
|
6836
|
-
│ ui-layout-inspector │
|
|
6837
|
-
│ Rounded, padded, scrollable right panel. │
|
|
6838
|
-
│ Hidden by default — shown via [open] attribute. │
|
|
6839
|
-
╰──────────────────────────────────────────────────────────╯ */
|
|
6840
|
-
|
|
6841
|
-
:where(ui-layout-inspector) {
|
|
6842
|
-
position: relative;
|
|
6843
|
-
display: flex;
|
|
6844
|
-
flex-direction: column;
|
|
6845
|
-
width: 0;
|
|
6846
|
-
min-width: 0;
|
|
6847
|
-
max-width: 480px;
|
|
6848
|
-
overflow: clip;
|
|
6849
|
-
scrollbar-width: none;
|
|
6850
|
-
background: var(--_ground, var(--_panel));
|
|
6851
|
-
border-radius: var(--_radius);
|
|
6852
|
-
padding: 0;
|
|
6853
|
-
transition:
|
|
6854
|
-
width var(--_duration) var(--_easing),
|
|
6855
|
-
min-width var(--_duration) var(--_easing),
|
|
6856
|
-
padding var(--_duration) var(--_easing),
|
|
6857
|
-
margin var(--_duration) var(--_easing);
|
|
6858
|
-
}
|
|
6859
|
-
|
|
6860
|
-
:where(ui-layout-inspector[open]) {
|
|
6861
|
-
width: 360px;
|
|
6862
|
-
min-width: 280px;
|
|
6863
|
-
margin-inline-start: calc(var(--_space) * 2);
|
|
6864
|
-
overflow-y: auto;
|
|
6865
|
-
padding: calc(var(--_space-k) * var(--_space));
|
|
6866
|
-
}
|
|
6867
|
-
|
|
6868
|
-
:where(ui-layout-inspector[resizing]) {
|
|
6869
|
-
transition: none;
|
|
6870
|
-
}
|
|
6871
|
-
|
|
6872
|
-
:where(ui-layout-inspector)[show-scrollbar] {
|
|
6873
|
-
scrollbar-width: thin;
|
|
6874
|
-
}
|
|
6875
|
-
|
|
6876
|
-
/* ── Resize Handle ── */
|
|
6877
|
-
|
|
6878
|
-
:where(ui-layout-inspector) :where(.layout-resize-handle) {
|
|
6879
|
-
position: absolute;
|
|
6880
|
-
top: 0;
|
|
6881
|
-
left: 0;
|
|
6882
|
-
width: 4px;
|
|
6883
|
-
height: 100%;
|
|
6884
|
-
cursor: col-resize;
|
|
6885
|
-
z-index: 1;
|
|
6886
|
-
}
|
|
6887
|
-
|
|
6888
|
-
:where(ui-layout-inspector) :where(.layout-resize-handle):hover,
|
|
6889
|
-
:where(ui-layout-inspector[resizing]) :where(.layout-resize-handle) {
|
|
6890
|
-
background: var(--_border-muted);
|
|
6891
|
-
}
|
|
6892
|
-
|
|
6893
|
-
}
|
|
6894
|
-
|
|
6895
|
-
@layer ui {
|
|
6896
|
-
|
|
6897
|
-
/* ╭──────────────────────────────────────────────────────────╮
|
|
6898
|
-
│ ui-layout-sidebar │
|
|
6899
|
-
│ Full-page layout: collapsible/resizable sidebar aside │
|
|
6900
|
-
│ + content column (breadcrumb, canvas, body, chat). │
|
|
6901
|
-
╰──────────────────────────────────────────────────────────╯ */
|
|
6902
|
-
|
|
6903
|
-
/* ── Outer Layout ── */
|
|
6904
|
-
|
|
6905
|
-
:where(ui-layout-sidebar) {
|
|
6906
|
-
display: flex;
|
|
6907
|
-
height: 100dvh;
|
|
6908
|
-
}
|
|
6909
|
-
|
|
6910
|
-
/* WHY: Reserve sidebar width before JS builds the DOM — prevents layout shift.
|
|
6911
|
-
Collapsed state is read synchronously in the constructor so CSS matches immediately.
|
|
6912
|
-
Replaced by the real aside once [data-ready] is set. */
|
|
6913
|
-
:where(ui-layout-sidebar):not([data-ready]):not([collapsed])::before {
|
|
6914
|
-
content: '';
|
|
6915
|
-
width: var(--ui-layout-sidebar-width);
|
|
6916
|
-
flex-shrink: 0;
|
|
6917
|
-
background: var(--_body);
|
|
6918
|
-
border-right: 1px solid var(--_border-muted);
|
|
6919
|
-
}
|
|
6920
|
-
|
|
6921
|
-
:where(ui-layout-sidebar):not([data-ready])[collapsed]::before {
|
|
6922
|
-
content: '';
|
|
6923
|
-
width: 48px;
|
|
6924
|
-
flex-shrink: 0;
|
|
6925
|
-
background: var(--_body);
|
|
6926
|
-
border-right: 1px solid var(--_border-muted);
|
|
6927
|
-
}
|
|
6928
|
-
|
|
6929
|
-
/* ── Content Column ── */
|
|
6930
|
-
/* WHY: Everything except the aside forms a flex column. */
|
|
6931
|
-
|
|
6932
|
-
:where(ui-layout-sidebar) > :where(:not([slot])) {
|
|
6933
|
-
flex: 1 1 0%;
|
|
6934
|
-
min-width: 0;
|
|
6935
|
-
min-height: 0;
|
|
6936
|
-
display: flex;
|
|
6937
|
-
flex-direction: column;
|
|
6938
|
-
padding: 0;
|
|
6939
|
-
}
|
|
6940
|
-
|
|
6941
|
-
/* ── Sidebar Aside ── */
|
|
6942
|
-
/* WHY: position: relative creates the containing block for absolute
|
|
6943
|
-
header/footer overlays. Content fills the full height and scrolls
|
|
6944
|
-
underneath the pinned header/footer. */
|
|
6945
|
-
|
|
6946
|
-
:where(ui-layout-sidebar) > :where([slot="sidebar"]) {
|
|
6947
|
-
--_sidebar-header-height: 0px;
|
|
6948
|
-
--_sidebar-footer-height: 0px;
|
|
6949
|
-
|
|
6950
|
-
container-name: sidebar;
|
|
6951
|
-
container-type: inline-size;
|
|
6952
|
-
position: sticky;
|
|
6953
|
-
top: 0;
|
|
6954
|
-
width: var(--ui-layout-sidebar-width);
|
|
6955
|
-
min-width: 160px;
|
|
6956
|
-
max-width: 400px;
|
|
6957
|
-
height: 100dvh;
|
|
6958
|
-
display: block;
|
|
6959
|
-
transition: width var(--_duration) var(--_easing), min-width var(--_duration) var(--_easing);
|
|
6960
|
-
overflow: hidden;
|
|
6961
|
-
z-index: 10;
|
|
6962
|
-
}
|
|
6963
|
-
|
|
6964
|
-
/* WHY: Disable width transition while dragging — it fights the pointer. */
|
|
6965
|
-
:where(ui-layout-sidebar) > :where([slot="sidebar"][resizing]) {
|
|
6966
|
-
transition: none;
|
|
6967
|
-
}
|
|
6968
|
-
|
|
6969
|
-
/* ── Collapsed Icon Rail ── */
|
|
6970
|
-
/* WHY: Collapsed = icon rail, not fully hidden. 48px fits icons (1rem) + padding.
|
|
6971
|
-
[collapsed] drives the aside to 48px which triggers @container sidebar queries
|
|
6972
|
-
in this file and in child component CSS (ui-nav.css, etc.). */
|
|
6973
|
-
|
|
6974
|
-
:where(ui-layout-sidebar)[collapsed] > :where([slot="sidebar"]) {
|
|
6975
|
-
width: 48px;
|
|
6976
|
-
min-width: 48px;
|
|
6977
|
-
}
|
|
6978
|
-
|
|
6979
|
-
/* ── Resize Handle ── */
|
|
6980
|
-
|
|
6981
|
-
:where(ui-layout-sidebar) :where(.layout-resize-handle) {
|
|
6982
|
-
position: absolute;
|
|
6983
|
-
top: 0;
|
|
6984
|
-
right: 0;
|
|
6985
|
-
width: 4px;
|
|
6986
|
-
height: 100%;
|
|
6987
|
-
cursor: col-resize;
|
|
6988
|
-
z-index: 1;
|
|
6989
|
-
}
|
|
6990
|
-
|
|
6991
|
-
:where(ui-layout-sidebar) :where(.layout-resize-handle):hover,
|
|
6992
|
-
:where(ui-layout-sidebar) > :where([slot="sidebar"][resizing]) :where(.layout-resize-handle) {
|
|
6993
|
-
background: var(--_border-muted);
|
|
6994
|
-
}
|
|
6995
|
-
|
|
6996
|
-
/* WHY: When collapsed to icon rail, the sidebar edge meets content — drop left padding. */
|
|
6997
|
-
|
|
6998
|
-
:where(ui-layout-sidebar)[collapsed] :where(ui-layout-canvas) {
|
|
6999
|
-
padding-inline-start: 0;
|
|
7000
|
-
}
|
|
7001
|
-
|
|
7002
|
-
:where(ui-layout-sidebar)[collapsed] :where(ui-layout-breadcrumb) {
|
|
7003
|
-
padding-inline-start: 0;
|
|
7004
|
-
}
|
|
7005
|
-
|
|
7006
|
-
/* ── Sidebar Header ── */
|
|
7007
|
-
/* WHY: Absolute-positioned overlay pinned to top of aside. Content scrolls
|
|
7008
|
-
underneath it. z-index: 2 sits above content (z-index: 0). */
|
|
7009
|
-
|
|
7010
|
-
:where(ui-layout-sidebar-header) {
|
|
7011
|
-
position: absolute;
|
|
7012
|
-
top: 0;
|
|
7013
|
-
left: 0;
|
|
7014
|
-
right: 0;
|
|
7015
|
-
z-index: 2;
|
|
7016
|
-
display: flex;
|
|
7017
|
-
flex-direction: column;
|
|
7018
|
-
}
|
|
7019
|
-
|
|
7020
|
-
/* ── Sidebar Content ── */
|
|
7021
|
-
/* WHY: Full height of the aside, scrollable. Padding-block offsets keep
|
|
7022
|
-
content from starting behind header / ending behind footer.
|
|
7023
|
-
Fade-out alpha mask dissolves content edges under the overlays. */
|
|
7024
|
-
|
|
7025
|
-
:where(ui-layout-sidebar-content) {
|
|
7026
|
-
display: flex;
|
|
7027
|
-
flex-direction: column;
|
|
7028
|
-
padding-block-start: var(--_sidebar-header-height);
|
|
7029
|
-
padding-block-end: var(--_sidebar-footer-height);
|
|
7030
|
-
width: 100%;
|
|
7031
|
-
height: 100%;
|
|
7032
|
-
overflow-y: auto;
|
|
7033
|
-
scrollbar-width: none;
|
|
7034
|
-
}
|
|
7035
|
-
|
|
7036
|
-
/* WHY: When header is present, fade top edge. Content dissolves as it
|
|
7037
|
-
scrolls under the header — transparent at top, fully visible by 1.25×
|
|
7038
|
-
the header height. No opaque header background needed. */
|
|
7039
|
-
:where(ui-layout-sidebar-content)[data-has-header] {
|
|
7040
|
-
mask-image: linear-gradient(
|
|
7041
|
-
to bottom,
|
|
7042
|
-
transparent 0,
|
|
7043
|
-
black calc(var(--_sidebar-header-height) * 1.25),
|
|
7044
|
-
black 100%
|
|
7045
|
-
);
|
|
7046
|
-
}
|
|
7047
|
-
|
|
7048
|
-
/* WHY: When footer is present, fade bottom edge. */
|
|
7049
|
-
:where(ui-layout-sidebar-content)[data-has-footer] {
|
|
7050
|
-
mask-image: linear-gradient(
|
|
7051
|
-
to bottom,
|
|
7052
|
-
black 0,
|
|
7053
|
-
black calc(100% - var(--_sidebar-footer-height) * 1.25),
|
|
7054
|
-
transparent 100%
|
|
7055
|
-
);
|
|
7056
|
-
}
|
|
7057
|
-
|
|
7058
|
-
/* WHY: When both header AND footer are present, fade both edges. */
|
|
7059
|
-
:where(ui-layout-sidebar-content)[data-has-header][data-has-footer] {
|
|
7060
|
-
mask-image: linear-gradient(
|
|
7061
|
-
to bottom,
|
|
7062
|
-
transparent 0,
|
|
7063
|
-
black calc(var(--_sidebar-header-height) * 1.25),
|
|
7064
|
-
black calc(100% - var(--_sidebar-footer-height) * 1.25),
|
|
7065
|
-
transparent 100%
|
|
7066
|
-
);
|
|
7067
|
-
}
|
|
7068
|
-
|
|
7069
|
-
/* ── Sidebar Footer ── */
|
|
7070
|
-
/* WHY: Absolute-positioned overlay pinned to bottom of aside. */
|
|
7071
|
-
|
|
7072
|
-
:where(ui-layout-sidebar-footer) {
|
|
7073
|
-
position: absolute;
|
|
7074
|
-
bottom: 0;
|
|
7075
|
-
left: 0;
|
|
7076
|
-
right: 0;
|
|
7077
|
-
z-index: 2;
|
|
7078
|
-
display: flex;
|
|
7079
|
-
flex-direction: column;
|
|
7080
|
-
}
|
|
7081
|
-
|
|
7082
|
-
/* ── Sidebar Item ── */
|
|
7083
|
-
/* WHY: Universal sidebar row element. Provides inline padding for any content
|
|
7084
|
-
(buttons, links, icons). When a child ui-listbox[popover] is present, JS
|
|
7085
|
-
wires PopoverController for click-to-toggle menu behavior.
|
|
7086
|
-
Absorbs the old ui-layout-sidebar-trigger role — one element for all rows. */
|
|
7087
|
-
|
|
7088
|
-
:where(ui-layout-sidebar-item) {
|
|
7089
|
-
display: flex;
|
|
7090
|
-
align-items: center;
|
|
7091
|
-
flex: 1;
|
|
7092
|
-
min-width: 0;
|
|
7093
|
-
gap: calc(var(--_space) * 2);
|
|
7094
|
-
min-height: var(--_min-height);
|
|
7095
|
-
font-size: var(--_font-size);
|
|
7096
|
-
font-weight: var(--ui-font-weight-button);
|
|
7097
|
-
letter-spacing: var(--_letter-spacing);
|
|
7098
|
-
line-height: var(--ui-line-height-control);
|
|
7099
|
-
color: var(--_ink);
|
|
7100
|
-
cursor: pointer;
|
|
7101
|
-
user-select: none;
|
|
7102
|
-
border: none;
|
|
7103
|
-
background: none;
|
|
7104
|
-
padding-block: var(--_space);
|
|
7105
|
-
padding-inline: calc(var(--_space-k) * var(--_space));
|
|
7106
|
-
border-radius: var(--_radius);
|
|
7107
|
-
transition: color var(--_duration) var(--_easing);
|
|
7108
|
-
}
|
|
7109
|
-
|
|
7110
|
-
/* WHY: Items in header/footer match the breadcrumb bar height so the
|
|
7111
|
-
first sidebar row aligns horizontally with the breadcrumb. */
|
|
7112
|
-
:where(ui-layout-sidebar-header) > :where(ui-layout-sidebar-item),
|
|
7113
|
-
:where(ui-layout-sidebar-footer) > :where(ui-layout-sidebar-item) {
|
|
7114
|
-
min-height: var(--ui-layout-bar-height);
|
|
7115
|
-
}
|
|
7116
|
-
|
|
7117
|
-
:where(ui-layout-sidebar-item):hover,
|
|
7118
|
-
:where(ui-layout-sidebar-item)[force-hover] {
|
|
7119
|
-
color: var(--_ink-strong);
|
|
7120
|
-
}
|
|
7121
|
-
|
|
7122
|
-
:where(ui-layout-sidebar-item):focus-visible,
|
|
7123
|
-
:where(ui-layout-sidebar-item)[force-focus-visible] {
|
|
7124
|
-
outline: 2px solid var(--ui-focus-ring);
|
|
7125
|
-
outline-offset: -2px;
|
|
7126
|
-
}
|
|
7127
|
-
|
|
7128
|
-
/* WHY: Fixed-size icon well so all sidebar icons (header logo, nav group icons,
|
|
7129
|
-
standalone icons) center-align on the same column width regardless of intrinsic
|
|
7130
|
-
icon size. 1.5rem matches the sidebar's visual rhythm at default density.
|
|
7131
|
-
Consumer wraps the icon: <span slot="icon"><ui-icon name="..."></ui-icon></span>
|
|
7132
|
-
The wrapper is the well; the icon keeps its own --ui-icon-size dimensions. */
|
|
7133
|
-
:where(ui-layout-sidebar-item) > :where([slot="icon"]) {
|
|
7134
|
-
display: inline-flex;
|
|
7135
|
-
align-items: center;
|
|
7136
|
-
justify-content: center;
|
|
7137
|
-
width: 1.5rem;
|
|
7138
|
-
height: 1.5rem;
|
|
7139
|
-
flex-shrink: 0;
|
|
7140
|
-
}
|
|
7141
|
-
|
|
7142
|
-
/* WHY: Trailing caret pushes to end — same pattern as button justify="spread". */
|
|
7143
|
-
:where(ui-layout-sidebar-item) > :where([slot="trailing"]) {
|
|
7144
|
-
margin-inline-start: auto;
|
|
7145
|
-
flex-shrink: 0;
|
|
7146
|
-
color: var(--_ink-muted);
|
|
7147
|
-
}
|
|
7148
|
-
|
|
7149
|
-
/* WHY: When the item wraps a sub-component (e.g. ui-button) that provides
|
|
7150
|
-
its own icon, hide [slot="icon"] in expanded mode — it only serves as the
|
|
7151
|
-
bare collapsed-rail representation. Items without sub-components (just
|
|
7152
|
-
icon + label + trailing) keep [slot="icon"] visible in both modes. */
|
|
7153
|
-
:where(ui-layout-sidebar-item:has(> ui-button)) > :where([slot="icon"]) {
|
|
7154
|
-
display: none;
|
|
7155
|
-
}
|
|
7156
|
-
|
|
7157
|
-
/* WHY: Title text truncates when sidebar narrows during resize. */
|
|
7158
|
-
:where(ui-layout-sidebar-item) > :where([slot="label"]) {
|
|
7159
|
-
flex: 1;
|
|
7160
|
-
min-width: 0;
|
|
7161
|
-
white-space: nowrap;
|
|
7162
|
-
overflow: hidden;
|
|
7163
|
-
text-overflow: ellipsis;
|
|
7164
|
-
}
|
|
7165
|
-
|
|
7166
|
-
/* ── Item Popover ── */
|
|
7167
|
-
/* WHY: Popover opens to the right of the sidebar item.
|
|
7168
|
-
Default: top-aligned, grows downward (span-block-end).
|
|
7169
|
-
Flip: bottom-aligned, grows upward (span-block-start). */
|
|
7170
|
-
|
|
7171
|
-
:where(ui-layout-sidebar-item) > :where(ui-listbox[popover]) {
|
|
7172
|
-
--_popover-origin: left center;
|
|
7173
|
-
--_popover-from: perspective(800px) scale(0.96) rotateY(20deg);
|
|
7174
|
-
|
|
7175
|
-
position: fixed;
|
|
7176
|
-
position-area: inline-end span-block-end;
|
|
7177
|
-
position-try-fallbacks: --sidebar-item-flip-up;
|
|
7178
|
-
margin-block: var(--ui-popover-viewport-margin);
|
|
7179
|
-
margin-inline: 0;
|
|
7180
|
-
margin-inline-start: var(--ui-popover-gap);
|
|
7181
|
-
min-width: 200px;
|
|
7182
|
-
max-height: var(--ui-popover-max-height);
|
|
7183
|
-
overflow-y: auto;
|
|
7184
|
-
}
|
|
7185
|
-
|
|
7186
|
-
@position-try --sidebar-item-flip-up {
|
|
7187
|
-
position-area: inline-end span-block-start;
|
|
7188
|
-
}
|
|
7189
|
-
|
|
7190
|
-
@position-try --sidebar-item-flip-down {
|
|
7191
|
-
position-area: inline-end span-block-end;
|
|
7192
|
-
}
|
|
7193
|
-
|
|
7194
|
-
/* ── Container Query: Collapsed Sidebar ── */
|
|
7195
|
-
/* WHY: Each component owns its own collapsed behavior via @container.
|
|
7196
|
-
The aside is the container (container-name: sidebar). When it shrinks
|
|
7197
|
-
to 48px (icon rail), components respond to the width, not to [collapsed].
|
|
7198
|
-
Threshold 80px: collapsed = 48px, min expanded = 160px. */
|
|
7199
|
-
|
|
7200
|
-
@container sidebar (max-width: 80px) {
|
|
7201
|
-
|
|
7202
|
-
/* Resize handle — no dragging in icon rail */
|
|
7203
|
-
:where(.layout-resize-handle) {
|
|
7204
|
-
display: none;
|
|
7205
|
-
}
|
|
7206
|
-
|
|
7207
|
-
/* Header/footer — center content horizontally */
|
|
7208
|
-
:where(ui-layout-sidebar-header),
|
|
7209
|
-
:where(ui-layout-sidebar-footer) {
|
|
7210
|
-
align-items: center;
|
|
7211
|
-
}
|
|
7212
|
-
|
|
7213
|
-
/* Content — center items in the 48px rail */
|
|
7214
|
-
:where(ui-layout-sidebar-content) {
|
|
7215
|
-
align-items: center;
|
|
7216
|
-
}
|
|
7217
|
-
|
|
7218
|
-
/* Item — shrink to icon-only. Show [slot="icon"], hide everything else.
|
|
7219
|
-
WHY: Sidebar items can contain complex children (buttons with slots,
|
|
7220
|
-
links, etc.). Rather than overriding sub-component styles, the item
|
|
7221
|
-
provides its own bare icon via [slot="icon"] for the collapsed rail. */
|
|
7222
|
-
:where(ui-layout-sidebar-item) {
|
|
7223
|
-
flex: 0 0 auto;
|
|
7224
|
-
padding-inline: var(--_space);
|
|
7225
|
-
}
|
|
7226
|
-
|
|
7227
|
-
:where(ui-layout-sidebar-item) > :where([slot="icon"]) {
|
|
7228
|
-
display: inline-flex;
|
|
7229
|
-
}
|
|
7230
|
-
|
|
7231
|
-
:where(ui-layout-sidebar-item) > :where(:not([slot="icon"]):not(ui-listbox[popover]):not(.nav-group-flyout)) {
|
|
7232
|
-
display: none;
|
|
7233
|
-
}
|
|
7234
|
-
|
|
7235
|
-
/* WHY: In collapsed mode the sidebar item is a small icon — centering
|
|
7236
|
-
the popover vertically with the anchor is more natural than top-aligning.
|
|
7237
|
-
Fallbacks handle viewport clipping (top/bottom edge). */
|
|
7238
|
-
:where(ui-layout-sidebar-item) > :where(ui-listbox[popover]) {
|
|
7239
|
-
position-area: inline-end;
|
|
7240
|
-
position-try-fallbacks: --sidebar-item-flip-up, --sidebar-item-flip-down;
|
|
7241
|
-
}
|
|
7242
|
-
}
|
|
7243
|
-
|
|
7244
|
-
}
|
|
7245
|
-
|
|
7246
6317
|
@layer ui {
|
|
7247
6318
|
|
|
7248
6319
|
/* ── Base ── */
|