@kerfjs/ui 5.0.0-beta.60 → 5.0.0-beta.62

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.
Files changed (142) hide show
  1. package/README.md +1 -0
  2. package/ai/component-catalog.json +141 -24
  3. package/ai/component-composition-rules.json +8 -0
  4. package/ai/component-composition.d.ts +10 -0
  5. package/ai/component-composition.json +117 -8
  6. package/ai/component-composition.schema.json +21 -0
  7. package/ai/components/README.md +5 -4
  8. package/ai/components/chip.md +72 -0
  9. package/ai/components/grid.md +10 -7
  10. package/ai/components/list-item.md +10 -7
  11. package/ai/components/pane.md +3 -2
  12. package/ai/components/select.md +6 -2
  13. package/ai/components/tabs.md +8 -4
  14. package/ai/components/toolbar-text.md +2 -1
  15. package/ai/components/toolbar.md +3 -2
  16. package/ai/public-api-signatures-v1.md +116 -24
  17. package/ai/skill.md +24 -4
  18. package/ai/webawesome-jsx-signatures-v1.md +1 -1
  19. package/dist/app-tab.d.ts +12 -2
  20. package/dist/app-tab.js +1 -1
  21. package/dist/browser/chip.js +3 -0
  22. package/dist/catalog.js +8 -8
  23. package/dist/chip.d.ts +29 -0
  24. package/dist/chip.js +3 -0
  25. package/dist/chip.js.map +1 -0
  26. package/dist/{chunk-WPLIO5WJ.js → chunk-4MG3KXJM.js} +40 -5
  27. package/dist/chunk-4MG3KXJM.js.map +1 -0
  28. package/dist/{chunk-F7F7KRO2.js → chunk-4SQK27MR.js} +33 -18
  29. package/dist/chunk-4SQK27MR.js.map +1 -0
  30. package/dist/chunk-EAC4CDY7.js +57 -0
  31. package/dist/chunk-EAC4CDY7.js.map +1 -0
  32. package/dist/{chunk-T57AXDFM.js → chunk-ENGVYQPG.js} +4 -3
  33. package/dist/chunk-ENGVYQPG.js.map +1 -0
  34. package/dist/{chunk-5PESG2VP.js → chunk-KYDDCJXU.js} +4 -3
  35. package/dist/chunk-KYDDCJXU.js.map +1 -0
  36. package/dist/{chunk-MERWRTBG.js → chunk-N2DRU35S.js} +1 -1
  37. package/dist/chunk-N2DRU35S.js.map +1 -0
  38. package/dist/{chunk-EZVNC4J6.js → chunk-OD2VXAPL.js} +4 -1
  39. package/dist/chunk-OD2VXAPL.js.map +1 -0
  40. package/dist/{chunk-T66UNBXL.js → chunk-Q6YU3BT7.js} +11 -2
  41. package/dist/chunk-Q6YU3BT7.js.map +1 -0
  42. package/dist/{chunk-N3GKMPDW.js → chunk-RKTTF3L4.js} +3 -1
  43. package/dist/chunk-RKTTF3L4.js.map +1 -0
  44. package/dist/chunk-SWVW56CV.js +188 -0
  45. package/dist/chunk-SWVW56CV.js.map +1 -0
  46. package/dist/{chunk-46263QLK.js → chunk-UA6JW52D.js} +53 -7
  47. package/dist/chunk-UA6JW52D.js.map +1 -0
  48. package/dist/{chunk-AGXQQFKZ.js → chunk-UCKKT6KO.js} +13 -4
  49. package/dist/chunk-UCKKT6KO.js.map +1 -0
  50. package/dist/{chunk-3SXMEK3B.js → chunk-V3DX3K65.js} +1 -1
  51. package/dist/chunk-V3DX3K65.js.map +1 -0
  52. package/dist/{chunk-UWONG4QE.js → chunk-VCBTX62E.js} +11 -3
  53. package/dist/chunk-VCBTX62E.js.map +1 -0
  54. package/dist/{chunk-2OXQHM7I.js → chunk-X6ADHJNI.js} +45 -20
  55. package/dist/chunk-X6ADHJNI.js.map +1 -0
  56. package/dist/collapsible-panel.js +2 -2
  57. package/dist/grid.d.ts +13 -5
  58. package/dist/grid.js +1 -1
  59. package/dist/index.d.ts +5 -4
  60. package/dist/index.js +17 -16
  61. package/dist/list-item.d.ts +11 -1
  62. package/dist/list-item.js +1 -1
  63. package/dist/nav-stack.d.ts +3 -1
  64. package/dist/nav-stack.js +1 -1
  65. package/dist/pane.d.ts +8 -3
  66. package/dist/pane.js +1 -1
  67. package/dist/popup-menu.d.ts +2 -2
  68. package/dist/popup-menu.js +1 -1
  69. package/dist/select-register.js +46 -0
  70. package/dist/select-register.js.map +1 -1
  71. package/dist/select.d.ts +16 -0
  72. package/dist/select.js +1 -1
  73. package/dist/split-view.d.ts +1 -1
  74. package/dist/split-view.js +1 -1
  75. package/dist/styles/app-tab.css +119 -0
  76. package/dist/styles/chip.css +118 -0
  77. package/dist/styles/grid.css +7 -0
  78. package/dist/styles/list-item.css +14 -9
  79. package/dist/styles/nav-stack.css +13 -0
  80. package/dist/styles/pane.css +33 -0
  81. package/dist/styles/popup-menu.css +2 -1
  82. package/dist/styles/resizable-region.css +9 -0
  83. package/dist/styles/segmented-control.css +2 -1
  84. package/dist/styles/select.css +45 -0
  85. package/dist/styles/split-view.css +6 -0
  86. package/dist/styles/styles.css +1 -0
  87. package/dist/styles/tab-bar.css +3 -0
  88. package/dist/styles/tab-scaffold.css +13 -0
  89. package/dist/styles/toolbar-text.css +15 -6
  90. package/dist/styles/toolbar.css +15 -5
  91. package/dist/styles/workbench.css +117 -93
  92. package/dist/tab-bar.d.ts +6 -2
  93. package/dist/tab-bar.js +1 -1
  94. package/dist/tab-scaffold.d.ts +3 -0
  95. package/dist/tab-scaffold.js +1 -0
  96. package/dist/tab-scaffold.js.map +1 -1
  97. package/dist/{token-search-field-CCke1yvQ.d.ts → token-search-field-DvgFLhLL.d.ts} +6 -2
  98. package/dist/token-search-field.d.ts +1 -1
  99. package/dist/token-search-model.d.ts +1 -1
  100. package/dist/token-search-model.js +1 -1
  101. package/dist/toolbar-text.d.ts +1 -1
  102. package/dist/toolbar-text.js +1 -1
  103. package/dist/toolbar.d.ts +2 -2
  104. package/dist/toolbar.js +1 -1
  105. package/dist/wire-catalog.js +1 -1
  106. package/dist/wire-tab-bars.js +1 -1
  107. package/dist/wire-token-search-fields.d.ts +1 -1
  108. package/dist/workbench.js +1 -1
  109. package/docs/accessibility.md +29 -3
  110. package/docs/collapsible-panel.md +4 -3
  111. package/docs/component-contract.md +5 -0
  112. package/docs/component-selection.md +92 -11
  113. package/docs/design/templates/segmented-control/equal-dark.svg +1 -1
  114. package/docs/design/templates/segmented-control/equal.svg +1 -1
  115. package/docs/design/templates/segmented-control/pill-small-dark.svg +1 -1
  116. package/docs/design/templates/segmented-control/pill-small.svg +1 -1
  117. package/docs/design/templates/segmented-control-dark.svg +1 -1
  118. package/docs/design/templates/segmented-control.svg +1 -1
  119. package/docs/layout.md +51 -9
  120. package/docs/nav-stack.md +5 -0
  121. package/docs/split-view.md +5 -0
  122. package/docs/sunken-panel.md +12 -0
  123. package/docs/tab-scaffold.md +5 -0
  124. package/docs/webawesome-theme.md +62 -0
  125. package/docs/workbench.md +22 -10
  126. package/llms.txt +40 -8
  127. package/package.json +7 -1
  128. package/dist/chunk-2OXQHM7I.js.map +0 -1
  129. package/dist/chunk-3SXMEK3B.js.map +0 -1
  130. package/dist/chunk-46263QLK.js.map +0 -1
  131. package/dist/chunk-5I7OHCIP.js +0 -96
  132. package/dist/chunk-5I7OHCIP.js.map +0 -1
  133. package/dist/chunk-5PESG2VP.js.map +0 -1
  134. package/dist/chunk-AGXQQFKZ.js.map +0 -1
  135. package/dist/chunk-EZVNC4J6.js.map +0 -1
  136. package/dist/chunk-F7F7KRO2.js.map +0 -1
  137. package/dist/chunk-MERWRTBG.js.map +0 -1
  138. package/dist/chunk-N3GKMPDW.js.map +0 -1
  139. package/dist/chunk-T57AXDFM.js.map +0 -1
  140. package/dist/chunk-T66UNBXL.js.map +0 -1
  141. package/dist/chunk-UWONG4QE.js.map +0 -1
  142. package/dist/chunk-WPLIO5WJ.js.map +0 -1
@@ -54,7 +54,8 @@
54
54
  color: var(--_kui-popup-row-current-color);
55
55
  background-color: var(--_kui-popup-row-current-background);
56
56
  }
57
- .kui-popup-menu > wa-divider {
57
+ .kui-popup-menu > wa-divider,
58
+ .kui-popup-menu wa-divider[slot="submenu"] {
58
59
  --spacing: 0.5em;
59
60
  }
60
61
 
@@ -73,6 +73,15 @@
73
73
  > .kui-resizable-region__content {
74
74
  overflow: visible;
75
75
  }
76
+ /* An open Web Awesome dropdown (including PopupMenu) releases both clipping
77
+ ancestors without rerendering the region during the dropdown lifecycle. */
78
+ .kui-resizable-region:has(wa-dropdown[open]) {
79
+ z-index: var(--kui-resizable-region-popup-z, 5);
80
+ overflow: visible;
81
+ }
82
+ .kui-resizable-region:has(wa-dropdown[open]) > .kui-resizable-region__content {
83
+ overflow: visible;
84
+ }
76
85
  .kui-resizable-region[data-separator="hidden"] {
77
86
  --kui-resizable-region-separator-color: transparent;
78
87
  }
@@ -1,7 +1,7 @@
1
1
  .kui-segmented-control {
2
2
  --kui-segmented-background: var(--kui-color-neutral-fill-normal);
3
3
  --kui-segmented-border: transparent;
4
- --kui-segmented-foreground: var(--kui-color-neutral-on-quiet);
4
+ --kui-segmented-foreground: var(--kui-color-neutral-on-normal);
5
5
  --kui-segmented-hover-background: var(--kui-color-surface);
6
6
  --kui-segmented-hover-border: var(--kui-color-neutral-border-normal);
7
7
  --kui-segmented-selected-background: var(--kui-color-surface);
@@ -38,6 +38,7 @@
38
38
  .kui-segmented-control[data-appearance="outlined"] {
39
39
  --kui-segmented-border: var(--kui-color-neutral-border-normal);
40
40
  --kui-segmented-background: var(--kui-color-surface);
41
+ --kui-segmented-foreground: var(--kui-color-neutral-on-quiet);
41
42
  }
42
43
 
43
44
  .kui-segmented-control[data-appearance="toolbar"] {
@@ -108,6 +108,21 @@
108
108
  margin-inline-start: 0.75rem;
109
109
  transform: scale(0.875);
110
110
  }
111
+ .kui-select[data-caret="false"]::part(expand-icon) {
112
+ display: none;
113
+ }
114
+ .kui-select[data-selected-presentation="icon-only"][data-caret="false"]::part(
115
+ combobox
116
+ ) {
117
+ width: var(
118
+ --_kui-toolbar-control-group-slot-height,
119
+ var(--_kui-select-height)
120
+ );
121
+ justify-content: center;
122
+ }
123
+ .kui-select[data-caret="false"] .kui-select__placeholder-chevron {
124
+ display: none;
125
+ }
111
126
  .kui-select[data-selected-presentation="icon-only"]::part(display-input) {
112
127
  position: absolute;
113
128
  width: 1px;
@@ -233,6 +248,36 @@
233
248
  text-transform: uppercase;
234
249
  }
235
250
 
251
+ .kui-select__actions {
252
+ display: flex;
253
+ gap: 0.25rem;
254
+ margin-block-start: 0.25rem;
255
+ padding-block-start: 0.5rem;
256
+ border-block-start: 1px solid var(--kui-color-neutral-border-quiet);
257
+ }
258
+
259
+ .kui-select__action {
260
+ flex: 1 1 auto;
261
+ min-width: 0;
262
+ min-height: 2.25rem;
263
+ padding-inline: 0.5rem;
264
+ border: 0;
265
+ border-radius: var(--kui-radius-s);
266
+ color: var(--kui-color-neutral-on-quiet);
267
+ background: transparent;
268
+ font: inherit;
269
+ cursor: pointer;
270
+ }
271
+
272
+ .kui-select__action:hover {
273
+ background: var(--kui-color-neutral-fill-quiet);
274
+ }
275
+
276
+ .kui-select__action:focus-visible {
277
+ outline: var(--kui-focus-ring);
278
+ outline-offset: -2px;
279
+ }
280
+
236
281
  /* Loading placeholder: a static box that mirrors the closed combobox (label
237
282
  above, a value skeleton and a dormant chevron inside a 44px control box).
238
283
  Rendered instead of the interactive wa-select, so it needs no registration. */
@@ -137,4 +137,10 @@
137
137
  :is([data-workbench-main], [data-workbench-panel-content])
138
138
  > [data-component="split-view"]:only-child {
139
139
  height: 100%;
140
+ --kui-edge-inset-block-start: var(--_kui-workbench-content-edge-block-start);
141
+ --kui-edge-inset-block-end: var(--_kui-workbench-content-edge-block-end);
142
+ --kui-edge-inset-inline-start: var(
143
+ --_kui-workbench-content-edge-inline-start
144
+ );
145
+ --kui-edge-inset-inline-end: var(--_kui-workbench-content-edge-inline-end);
140
146
  }
@@ -1,6 +1,7 @@
1
1
  @import "./foundation.css";
2
2
  @import "./layout.css";
3
3
  @import "./badge.css";
4
+ @import "./chip.css";
4
5
  @import "./lucide-icon.css";
5
6
  @import "./disclosure-arrow.css";
6
7
  @import "./toolbar.css";
@@ -45,6 +45,9 @@
45
45
  scroll-padding-inline: var(--kui-tab-bar-strip-scroll-padding-inline, 0);
46
46
  overscroll-behavior-inline: contain;
47
47
  }
48
+ .kui-tab-bar[data-icon-only-at] .kui-tab-bar__tabs {
49
+ container: kui-tab-bar-tabs / inline-size;
50
+ }
48
51
  .kui-tab-bar[data-presentation="segmented"],
49
52
  .kui-tab-bar[data-presentation="inspector"] {
50
53
  --kui-tab-bar-background: var(--kui-color-neutral-fill-quiet);
@@ -46,6 +46,13 @@
46
46
  inset: 0;
47
47
  }
48
48
 
49
+ .kui-tab-scaffold__scene[data-appearance="sunken"] {
50
+ background: var(
51
+ --kui-sunken-panel-background,
52
+ var(--kui-color-surface-lowered)
53
+ );
54
+ }
55
+
49
56
  /* A scene is its region's scroll owner, so its top inset is padding inside
50
57
  the scroller. A scene whose only child is a Pane or layout (usually a
51
58
  NavStack) lets that child own the insets instead. */
@@ -191,4 +198,10 @@
191
198
  :is([data-workbench-main], [data-workbench-panel-content])
192
199
  > [data-component="tab-scaffold"]:only-child {
193
200
  height: 100%;
201
+ --kui-edge-inset-block-start: var(--_kui-workbench-content-edge-block-start);
202
+ --kui-edge-inset-block-end: var(--_kui-workbench-content-edge-block-end);
203
+ --kui-edge-inset-inline-start: var(
204
+ --_kui-workbench-content-edge-inline-start
205
+ );
206
+ --kui-edge-inset-inline-end: var(--_kui-workbench-content-edge-inline-end);
194
207
  }
@@ -47,17 +47,23 @@
47
47
  text-overflow: ellipsis;
48
48
  }
49
49
 
50
- .kui-toolbar-text[data-size="xlarge"] {
51
- /* Matches page/panel titles: the same responsive clamp so a heading toolbar
52
- title reads at the page-title scale without a bespoke override. Height grows
53
- to the larger text (the fixed 40px would clip its ascenders). */
50
+ .kui-toolbar-text:is([data-size="xlarge"], [data-size="xlarge-fixed"]) {
51
+ /* Both title sizes keep page/panel title color and geometry. Height grows to
52
+ their text instead of clipping ascenders in the default 40px box. */
54
53
  height: auto;
55
54
  min-height: 2.75rem;
56
55
  color: var(--kui-color-text);
57
- font-size: clamp(var(--kui-font-l), 2.3vw, var(--kui-font-2xl));
58
56
  letter-spacing: -0.025em;
59
57
  }
60
58
 
59
+ .kui-toolbar-text[data-size="xlarge"] {
60
+ font-size: clamp(var(--kui-font-l), 2.3vw, var(--kui-font-2xl));
61
+ }
62
+
63
+ .kui-toolbar-text[data-size="xlarge-fixed"] {
64
+ font-size: var(--kui-font-l);
65
+ }
66
+
61
67
  .kui-toolbar-text[data-size="large"] {
62
68
  font-size: var(--kui-font-m);
63
69
  letter-spacing: -0.015em;
@@ -93,7 +99,10 @@
93
99
  min-height: 2.5rem;
94
100
  }
95
101
 
96
- .kui-toolbar-text[data-size="xlarge"][data-wrap="true"] {
102
+ .kui-toolbar-text:is(
103
+ [data-size="xlarge"],
104
+ [data-size="xlarge-fixed"]
105
+ )[data-wrap="true"] {
97
106
  min-height: 2.75rem;
98
107
  }
99
108
 
@@ -35,21 +35,24 @@
35
35
  column shrinks still keeps a whole control row clear of the unsafe area. */
36
36
  min-height: calc(
37
37
  var(--kui-toolbar-group-size, calc(2px + 2.625rem)) +
38
- (2 * var(--kui-toolbar-gap, 0.5rem)) +
38
+ (2 * var(--kui-toolbar-inset, var(--kui-toolbar-gap, 0.5rem))) +
39
39
  var(--_kui-toolbar-safe-block-start) + var(--_kui-toolbar-safe-block-end)
40
40
  );
41
41
  padding-block: calc(
42
- var(--kui-toolbar-gap, 0.5rem) + var(--_kui-toolbar-safe-block-start)
42
+ var(--kui-toolbar-inset, var(--kui-toolbar-gap, 0.5rem)) +
43
+ var(--_kui-toolbar-safe-block-start)
43
44
  )
44
45
  calc(
45
- var(--kui-toolbar-gap, 0.5rem) + var(--_kui-toolbar-safe-block-end)
46
+ var(--kui-toolbar-inset, var(--kui-toolbar-gap, 0.5rem)) +
47
+ var(--_kui-toolbar-safe-block-end)
46
48
  );
47
49
  padding-inline: calc(
48
- var(--kui-toolbar-gap, 0.5rem) +
50
+ var(--kui-toolbar-inset, var(--kui-toolbar-gap, 0.5rem)) +
49
51
  var(--_kui-toolbar-safe-inline-start)
50
52
  )
51
53
  calc(
52
- var(--kui-toolbar-gap, 0.5rem) + var(--_kui-toolbar-safe-inline-end)
54
+ var(--kui-toolbar-inset, var(--kui-toolbar-gap, 0.5rem)) +
55
+ var(--_kui-toolbar-safe-inline-end)
53
56
  );
54
57
  }
55
58
 
@@ -92,6 +95,13 @@
92
95
  grid-template-columns: minmax(0, 1fr) auto;
93
96
  }
94
97
 
98
+ /* Equal side tracks center the middle zone on the toolbar's content box even
99
+ when one side has no controls. Side content still shrinks or wraps within
100
+ its own track, and responsive policies below may move a zone to a new row. */
101
+ .kui-toolbar[data-center-align="balanced"][data-has-center="true"] {
102
+ grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
103
+ }
104
+
95
105
  .kui-toolbar[data-responsive="trailing-priority"][data-has-center="false"]:has(
96
106
  > .kui-toolbar__trailing [data-expanded="true"]
97
107
  ) {
@@ -91,21 +91,11 @@
91
91
  flex-direction: column;
92
92
  }
93
93
 
94
- .kui-workbench:has(
95
- > .kui-workbench__rail--left[data-presentation="inline"]:not(
96
- [data-collapsed="true"]
97
- )
98
- )
99
- > .kui-workbench__center {
94
+ .kui-workbench[data-left-inline-expanded="true"] > .kui-workbench__center {
100
95
  --kui-edge-inset-inline-start: 0px;
101
96
  }
102
97
 
103
- .kui-workbench:has(
104
- > .kui-workbench__rail--right[data-presentation="inline"]:not(
105
- [data-collapsed="true"]
106
- )
107
- )
108
- > .kui-workbench__center {
98
+ .kui-workbench[data-right-inline-expanded="true"] > .kui-workbench__center {
109
99
  --kui-edge-inset-inline-end: 0px;
110
100
  }
111
101
 
@@ -115,18 +105,64 @@
115
105
  overflow: auto;
116
106
  }
117
107
 
118
- .kui-workbench__main:has(
119
- ~ .kui-workbench__drawer[data-presentation="inline"]:not(
120
- [data-collapsed="true"]
121
- )
122
- ) {
123
- --kui-edge-inset-block-end: 0px;
108
+ /* When no Pane chrome is composed, the Workbench region owns its scroll.
109
+ A resizable auto-overflow panel instead scrolls its content box so its
110
+ separator handle remains fixed. Paint only that owner. */
111
+ .kui-workbench__main[data-appearance="sunken"],
112
+ :is(.kui-workbench__rail, .kui-workbench__drawer)[data-appearance="sunken"] {
113
+ background: var(
114
+ --kui-sunken-panel-background,
115
+ var(--kui-color-surface-lowered)
116
+ );
117
+ }
118
+
119
+ :is(
120
+ .kui-workbench__rail,
121
+ .kui-workbench__drawer
122
+ )[data-appearance="sunken"][data-resizable="true"][data-content-overflow="auto"] {
123
+ background: transparent;
124
+ }
125
+
126
+ :is(
127
+ .kui-workbench__rail,
128
+ .kui-workbench__drawer
129
+ )[data-appearance="sunken"][data-resizable="true"][data-content-overflow="auto"]
130
+ > .kui-workbench__panel-content {
131
+ background: var(
132
+ --kui-sunken-panel-background,
133
+ var(--kui-color-surface-lowered)
134
+ );
135
+ }
136
+
137
+ .kui-workbench__main[data-drawer-inline-expanded="true"] {
138
+ --_kui-workbench-content-edge-block-end: 0px;
124
139
  }
125
140
 
126
141
  /* The main area and each panel's content are the consumers: they pad for the
127
142
  edges their region still touches, the main area inside its scroller so
128
143
  content scrolls under an unsafe edge but can always be scrolled clear. A
129
144
  region whose only child is a Pane or layout lets that child own the insets. */
145
+ .kui-workbench__center,
146
+ .kui-workbench__rail,
147
+ .kui-workbench__drawer {
148
+ --_kui-workbench-content-edge-block-start: var(--kui-edge-inset-block-start);
149
+ --_kui-workbench-content-edge-block-end: var(--kui-edge-inset-block-end);
150
+ --_kui-workbench-content-edge-inline-start: var(
151
+ --kui-edge-inset-inline-start
152
+ );
153
+ --_kui-workbench-content-edge-inline-end: var(--kui-edge-inset-inline-end);
154
+ }
155
+
156
+ .kui-workbench__main,
157
+ .kui-workbench__panel-content {
158
+ /* Clear the public context at the region, so arbitrary app children inherit
159
+ zero without a selector whose subject is every child in the document. */
160
+ --kui-edge-inset-block-start: 0px;
161
+ --kui-edge-inset-block-end: 0px;
162
+ --kui-edge-inset-inline-start: 0px;
163
+ --kui-edge-inset-inline-end: 0px;
164
+ }
165
+
130
166
  .kui-workbench__main:not(
131
167
  :has(
132
168
  > :is(
@@ -149,44 +185,24 @@
149
185
  ):only-child
150
186
  )
151
187
  ) {
152
- padding-block: var(--kui-edge-inset-block-start)
153
- var(--kui-edge-inset-block-end);
154
- padding-inline: var(--kui-edge-inset-inline-start)
155
- var(--kui-edge-inset-inline-end);
156
- scroll-padding-block: var(--kui-edge-inset-block-start)
157
- var(--kui-edge-inset-block-end);
158
- }
159
-
160
- /* Every other child sees a cleared context. The exemption is tested on the
161
- child itself, never as `region:not(:has(…)) > *`: a `:has()` before a
162
- universal child makes each child of the region re-check the region's
163
- `:has()` on every DOM change (~46ms per restyle for 1000 rows in Chromium).
164
- SplitView, NavStack, TabScaffold, and CollapsiblePanel content use the same
165
- shape. */
166
- .kui-workbench__main
167
- > :not(
168
- :is(
169
- [data-component="pane"],
170
- [data-component="nav-stack"],
171
- [data-component="split-view"],
172
- [data-component="workbench"],
173
- [data-component="tab-scaffold"]
174
- ):only-child
175
- ),
176
- .kui-workbench__panel-content
177
- > :not(
178
- :is(
179
- [data-component="pane"],
180
- [data-component="nav-stack"],
181
- [data-component="split-view"],
182
- [data-component="workbench"],
183
- [data-component="tab-scaffold"]
184
- ):only-child
185
- ) {
186
- --kui-edge-inset-block-start: 0px;
187
- --kui-edge-inset-block-end: 0px;
188
- --kui-edge-inset-inline-start: 0px;
189
- --kui-edge-inset-inline-end: 0px;
188
+ padding-block: var(--_kui-workbench-content-edge-block-start)
189
+ var(--_kui-workbench-content-edge-block-end);
190
+ padding-inline: var(--_kui-workbench-content-edge-inline-start)
191
+ var(--_kui-workbench-content-edge-inline-end);
192
+ scroll-padding-block: var(--_kui-workbench-content-edge-block-start)
193
+ var(--_kui-workbench-content-edge-block-end);
194
+ }
195
+
196
+ /* A nested Workbench owns its safe-area insets. Other sole layout children
197
+ restore this context from their own stylesheets. */
198
+ :is(.kui-workbench__main, .kui-workbench__panel-content)
199
+ > [data-component="workbench"]:only-child {
200
+ --kui-edge-inset-block-start: var(--_kui-workbench-content-edge-block-start);
201
+ --kui-edge-inset-block-end: var(--_kui-workbench-content-edge-block-end);
202
+ --kui-edge-inset-inline-start: var(
203
+ --_kui-workbench-content-edge-inline-start
204
+ );
205
+ --kui-edge-inset-inline-end: var(--_kui-workbench-content-edge-inline-end);
190
206
  }
191
207
 
192
208
  /* A region whose only child is a Pane or layout lets it fill the region, so a
@@ -231,6 +247,11 @@
231
247
  overflow: visible;
232
248
  }
233
249
 
250
+ .kui-workbench__rail:has(wa-dropdown[open]),
251
+ .kui-workbench__drawer:has(wa-dropdown[open]) {
252
+ z-index: var(--kui-workbench-popup-z, 5);
253
+ }
254
+
234
255
  /* The fixed-size sliding content. The rail/drawer keeps a definite size on its
235
256
  content so the transform reads as a slide, not a squeeze. */
236
257
  .kui-workbench__rail .kui-workbench__panel-content {
@@ -254,6 +275,11 @@
254
275
  transition: none;
255
276
  }
256
277
 
278
+ :is(.kui-workbench__rail, .kui-workbench__drawer)[data-resizing="true"]
279
+ > .kui-workbench__panel-content {
280
+ transition: none;
281
+ }
282
+
257
283
  .kui-workbench__rail[data-collapse-motion="fade-slide"][data-collapsed="true"]
258
284
  .kui-workbench__panel-content,
259
285
  .kui-workbench__drawer[data-collapse-motion="fade-slide"][data-collapsed="true"]
@@ -579,10 +605,7 @@
579
605
  `responsiveFillAt`), and inline above it. The Workbench becomes a named
580
606
  inline-size container only when a panel opts in. The work area keeps its
581
607
  safe-area inset under an overlay panel. */
582
- .kui-workbench:has(
583
- > .kui-workbench__rail[data-responsive-overlay-at],
584
- > .kui-workbench__center > .kui-workbench__drawer[data-responsive-overlay-at]
585
- ) {
608
+ .kui-workbench[data-responsive-overlay="true"] {
586
609
  container: kui-workbench / inline-size;
587
610
  }
588
611
 
@@ -622,16 +645,12 @@
622
645
  display: none;
623
646
  }
624
647
 
625
- .kui-workbench:has(
626
- > .kui-workbench__rail--left[data-responsive-overlay-at="narrow"][data-presentation="inline"]
627
- )
648
+ .kui-workbench[data-left-responsive-inline="narrow"]
628
649
  > .kui-workbench__center {
629
650
  --kui-edge-inset-inline-start: var(--_kui-workbench-safe-inline-start);
630
651
  }
631
652
 
632
- .kui-workbench:has(
633
- > .kui-workbench__rail--right[data-responsive-overlay-at="narrow"][data-presentation="inline"]
634
- )
653
+ .kui-workbench[data-right-responsive-inline="narrow"]
635
654
  > .kui-workbench__center {
636
655
  --kui-edge-inset-inline-end: var(--_kui-workbench-safe-inline-end);
637
656
  }
@@ -665,10 +684,10 @@
665
684
  display: none;
666
685
  }
667
686
 
668
- .kui-workbench__main:has(
669
- ~ .kui-workbench__drawer[data-responsive-overlay-at="narrow"][data-presentation="inline"]
670
- ) {
671
- --kui-edge-inset-block-end: var(--_kui-workbench-safe-block-end);
687
+ .kui-workbench__main[data-drawer-responsive-inline="narrow"] {
688
+ --_kui-workbench-content-edge-block-end: var(
689
+ --_kui-workbench-safe-block-end
690
+ );
672
691
  }
673
692
  }
674
693
 
@@ -708,16 +727,12 @@
708
727
  display: none;
709
728
  }
710
729
 
711
- .kui-workbench:has(
712
- > .kui-workbench__rail--left[data-responsive-overlay-at="compact"][data-presentation="inline"]
713
- )
730
+ .kui-workbench[data-left-responsive-inline="compact"]
714
731
  > .kui-workbench__center {
715
732
  --kui-edge-inset-inline-start: var(--_kui-workbench-safe-inline-start);
716
733
  }
717
734
 
718
- .kui-workbench:has(
719
- > .kui-workbench__rail--right[data-responsive-overlay-at="compact"][data-presentation="inline"]
720
- )
735
+ .kui-workbench[data-right-responsive-inline="compact"]
721
736
  > .kui-workbench__center {
722
737
  --kui-edge-inset-inline-end: var(--_kui-workbench-safe-inline-end);
723
738
  }
@@ -751,13 +766,28 @@
751
766
  display: none;
752
767
  }
753
768
 
754
- .kui-workbench__main:has(
755
- ~ .kui-workbench__drawer[data-responsive-overlay-at="compact"][data-presentation="inline"]
756
- ) {
757
- --kui-edge-inset-block-end: var(--_kui-workbench-safe-block-end);
769
+ .kui-workbench__main[data-drawer-responsive-inline="compact"] {
770
+ --_kui-workbench-content-edge-block-end: var(
771
+ --_kui-workbench-safe-block-end
772
+ );
758
773
  }
759
774
  }
760
775
 
776
+ /* Release the panel and its sliding/scrolling content while a PopupMenu or
777
+ Web Awesome dropdown is open. This comes after resize clipping and keeps
778
+ the popup in place through wa-show/wa-after-hide without a prop change. */
779
+ .kui-workbench__rail:not([data-collapsed="true"]):has(wa-dropdown[open]),
780
+ .kui-workbench__drawer:not([data-collapsed="true"]):has(wa-dropdown[open]) {
781
+ overflow: visible;
782
+ clip-path: none;
783
+ }
784
+ .kui-workbench__rail:not([data-collapsed="true"]):has(wa-dropdown[open])
785
+ > .kui-workbench__panel-content,
786
+ .kui-workbench__drawer:not([data-collapsed="true"]):has(wa-dropdown[open])
787
+ > .kui-workbench__panel-content {
788
+ overflow: visible;
789
+ }
790
+
761
791
  /* A collapsed panel's restore control floats in a corner of the Workbench
762
792
  itself, never of the viewport, so an embedded Workbench cannot float it over
763
793
  page chrome outside it. It is inset from the corner plus the unsafe area of
@@ -860,20 +890,15 @@
860
890
  the open rail), so the overlay's own floating controls stay; FloatingToolbar
861
891
  and the layouts' restore corners read it. A direct child
862
892
  resolves the Workbench's own container query, never a nested one's. */
863
- .kui-workbench:has(
864
- > .kui-workbench__rail[data-presentation="overlay"]:not(
865
- [data-collapsed="true"]
866
- )
867
- )
893
+ .kui-workbench[data-rail-overlay-expanded="true"]
868
894
  > :is(.kui-workbench__center, .kui-workbench__restore) {
869
895
  --_kui-workbench-covered: hidden;
870
896
  }
871
897
 
872
898
  @container kui-workbench (max-width: 44rem) {
873
- .kui-workbench:has(
874
- > .kui-workbench__rail[data-responsive-overlay-at="narrow"][data-presentation="inline"]:not(
875
- [data-collapsed="true"]
876
- )
899
+ .kui-workbench:is(
900
+ [data-left-responsive-expanded="narrow"],
901
+ [data-right-responsive-expanded="narrow"]
877
902
  )
878
903
  > :is(.kui-workbench__center, .kui-workbench__restore) {
879
904
  --_kui-workbench-covered: hidden;
@@ -881,10 +906,9 @@
881
906
  }
882
907
 
883
908
  @container kui-workbench (max-width: 28rem) {
884
- .kui-workbench:has(
885
- > .kui-workbench__rail[data-responsive-overlay-at="compact"][data-presentation="inline"]:not(
886
- [data-collapsed="true"]
887
- )
909
+ .kui-workbench:is(
910
+ [data-left-responsive-expanded="compact"],
911
+ [data-right-responsive-expanded="compact"]
888
912
  )
889
913
  > :is(.kui-workbench__center, .kui-workbench__restore) {
890
914
  --_kui-workbench-covered: hidden;
package/dist/tab-bar.d.ts CHANGED
@@ -5,6 +5,8 @@ type TabActivation = 'automatic' | 'manual';
5
5
  type TabBarAllocation = 'intrinsic' | 'fill';
6
6
  type TabBarPresentation = 'rail' | 'segmented' | 'inspector';
7
7
  type TabBarTrailingPlacement = 'separate' | 'adjacent';
8
+ /** Tablist width where segmented AppTabs switch to icon-only. */
9
+ type TabBarIconOnlyAt = 'wide' | 'narrow' | 'compact';
8
10
  interface TabBarProps {
9
11
  id: string;
10
12
  label: string;
@@ -28,12 +30,14 @@ interface TabBarProps {
28
30
  allocation?: TabBarAllocation;
29
31
  /** Named strip chrome for application rails, segmented tabs, or inspectors. */
30
32
  presentation?: TabBarPresentation;
33
+ /** Switch segmented AppTabs to icon-only at tablist widths of 832, 704, or 448px. Each tab needs a leading icon. */
34
+ iconOnlyAt?: TabBarIconOnlyAt;
31
35
  /** Keep a trailing action beside the final tab or at the far edge of the bar. */
32
36
  trailingPlacement?: TabBarTrailingPlacement;
33
37
  /** Native named-slot assignment when composed inside a web component. */
34
38
  slot?: string;
35
39
  }
36
40
  /** Render a controlled tab strip. The application owns selection, order, and persistence. */
37
- declare function TabBar({ id, label, children, leading, trailing, end, className, activation, allocation, presentation, trailingPlacement, slot, }: TabBarProps): kerfjs.SafeHtml;
41
+ declare function TabBar({ id, label, children, leading, trailing, end, className, activation, allocation, presentation, iconOnlyAt, trailingPlacement, slot, }: TabBarProps): kerfjs.SafeHtml;
38
42
 
39
- export { type TabActivation, TabBar, type TabBarAllocation, type TabBarPresentation, type TabBarProps, type TabBarTrailingPlacement };
43
+ export { type TabActivation, TabBar, type TabBarAllocation, type TabBarIconOnlyAt, type TabBarPresentation, type TabBarProps, type TabBarTrailingPlacement };
package/dist/tab-bar.js CHANGED
@@ -1,3 +1,3 @@
1
- export { TabBar } from './chunk-N3GKMPDW.js';
1
+ export { TabBar } from './chunk-RKTTF3L4.js';
2
2
 
3
3
  //# sourceMappingURL=tab-bar.js.map
@@ -1,4 +1,5 @@
1
1
  import { SafeHtml } from 'kerfjs';
2
+ import { PaneAppearance } from './pane.js';
2
3
  import { K as KerfUiContent } from './semantic-content-BbzjvSu9.js';
3
4
 
4
5
  interface TabScaffoldTabBase<Id extends string> {
@@ -8,6 +9,8 @@ interface TabScaffoldTabBase<Id extends string> {
8
9
  icon?: SafeHtml;
9
10
  /** The tab's content — typically a `NavStack` so each tab keeps its own stack. */
10
11
  content: KerfUiContent;
12
+ /** Background of this scene's scrolling work surface. */
13
+ appearance?: PaneAppearance;
11
14
  }
12
15
  /** A tab with an optional count or short-status badge. */
13
16
  interface TabScaffoldTabCountBadge {
@@ -26,6 +26,7 @@ function TabScaffold({
26
26
  class: "kui-tab-scaffold__scene",
27
27
  "data-tab-scaffold-scene": tab.id,
28
28
  "data-active": String(tab.id === active),
29
+ "data-appearance": tab.appearance === "sunken" ? "sunken" : void 0,
29
30
  "aria-hidden": String(tab.id !== active),
30
31
  children: tab.content
31
32
  }