@kerfjs/ui 5.0.0-beta.55 → 5.0.0-beta.56

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 (235) hide show
  1. package/README.md +12 -10
  2. package/ai/compile-time-contracts-v1.json +2 -2
  3. package/ai/component-catalog-v2.json +149 -39
  4. package/ai/component-catalog.json +202 -51
  5. package/ai/public-api-signatures-v1.md +439 -97
  6. package/ai/skill.md +43 -40
  7. package/ai/webawesome-jsx-signatures-v1.md +8 -2
  8. package/dist/app-tab.js +1 -1
  9. package/dist/badge.d.ts +35 -7
  10. package/dist/badge.js +1 -1
  11. package/dist/browser/content-item.js +3 -0
  12. package/dist/browser/select.js +1 -0
  13. package/dist/catalog-resources.d.ts +12 -1
  14. package/dist/catalog.d.ts +14 -3
  15. package/dist/catalog.js +52 -43
  16. package/dist/catalog.js.map +1 -1
  17. package/dist/{chunk-WZ2GLEY4.js → chunk-2G2ZJQYK.js} +2 -14
  18. package/dist/chunk-2G2ZJQYK.js.map +1 -0
  19. package/dist/{chunk-D7GWXIAS.js → chunk-5I7QGQVT.js} +1 -1
  20. package/dist/chunk-5I7QGQVT.js.map +1 -0
  21. package/dist/{chunk-RNRUVPJ3.js → chunk-63ZWBGE3.js} +3 -2
  22. package/dist/chunk-63ZWBGE3.js.map +1 -0
  23. package/dist/{chunk-44IG7PFV.js → chunk-6CINWX2E.js} +3 -3
  24. package/dist/{chunk-44IG7PFV.js.map → chunk-6CINWX2E.js.map} +1 -1
  25. package/dist/{chunk-C2FAYFDE.js → chunk-AGXQQFKZ.js} +2 -2
  26. package/dist/{chunk-C2FAYFDE.js.map → chunk-AGXQQFKZ.js.map} +1 -1
  27. package/dist/{chunk-ATHXW6RP.js → chunk-AHEG27M7.js} +2 -2
  28. package/dist/{chunk-ATHXW6RP.js.map → chunk-AHEG27M7.js.map} +1 -1
  29. package/dist/{chunk-7GUQYHKA.js → chunk-AK67F6QN.js} +4 -1
  30. package/dist/chunk-AK67F6QN.js.map +1 -0
  31. package/dist/chunk-BFPBS5Y4.js +250 -0
  32. package/dist/chunk-BFPBS5Y4.js.map +1 -0
  33. package/dist/{chunk-5OLVUEND.js → chunk-DG6G5EPF.js} +4 -6
  34. package/dist/chunk-DG6G5EPF.js.map +1 -0
  35. package/dist/{chunk-MTM43SJO.js → chunk-G33XC2NB.js} +1 -1
  36. package/dist/chunk-G33XC2NB.js.map +1 -0
  37. package/dist/{chunk-TZ5IHWB2.js → chunk-K6UNVKDK.js} +3 -3
  38. package/dist/{chunk-TZ5IHWB2.js.map → chunk-K6UNVKDK.js.map} +1 -1
  39. package/dist/{chunk-HMQ2ZDGG.js → chunk-KROD7KZK.js} +3 -2
  40. package/dist/chunk-KROD7KZK.js.map +1 -0
  41. package/dist/{chunk-5NDQABWK.js → chunk-M7QV3IHH.js} +3 -1
  42. package/dist/chunk-M7QV3IHH.js.map +1 -0
  43. package/dist/{chunk-RNZAKSME.js → chunk-MA6Z6EIM.js} +3 -3
  44. package/dist/{chunk-RNZAKSME.js.map → chunk-MA6Z6EIM.js.map} +1 -1
  45. package/dist/chunk-MA73TA6D.js +42 -0
  46. package/dist/chunk-MA73TA6D.js.map +1 -0
  47. package/dist/{chunk-ZMBU522F.js → chunk-MEY33VWB.js} +2 -2
  48. package/dist/{chunk-ZMBU522F.js.map → chunk-MEY33VWB.js.map} +1 -1
  49. package/dist/{chunk-T22EM4ET.js → chunk-MOBRFZH3.js} +81 -31
  50. package/dist/chunk-MOBRFZH3.js.map +1 -0
  51. package/dist/chunk-MP2GDBQZ.js +50 -0
  52. package/dist/chunk-MP2GDBQZ.js.map +1 -0
  53. package/dist/{chunk-3NBL3OUQ.js → chunk-NAPE7WUS.js} +2 -2
  54. package/dist/chunk-NAPE7WUS.js.map +1 -0
  55. package/dist/{chunk-BSKEH3UC.js → chunk-NBYTIVHS.js} +2 -2
  56. package/dist/{chunk-BSKEH3UC.js.map → chunk-NBYTIVHS.js.map} +1 -1
  57. package/dist/chunk-O3EXIBEZ.js +114 -0
  58. package/dist/chunk-O3EXIBEZ.js.map +1 -0
  59. package/dist/{chunk-R754MHXX.js → chunk-PK4N5QTO.js} +7 -6
  60. package/dist/chunk-PK4N5QTO.js.map +1 -0
  61. package/dist/{chunk-EAX2GSS4.js → chunk-QQOTQTDD.js} +51 -20
  62. package/dist/chunk-QQOTQTDD.js.map +1 -0
  63. package/dist/{chunk-LZXQVUGN.js → chunk-T4UZTNZ4.js} +4 -4
  64. package/dist/{chunk-LZXQVUGN.js.map → chunk-T4UZTNZ4.js.map} +1 -1
  65. package/dist/{chunk-N7FHFNT6.js → chunk-V65EOWNF.js} +33 -5
  66. package/dist/chunk-V65EOWNF.js.map +1 -0
  67. package/dist/{chunk-GUIHMIT2.js → chunk-VNPQDCQZ.js} +3 -3
  68. package/dist/{chunk-GUIHMIT2.js.map → chunk-VNPQDCQZ.js.map} +1 -1
  69. package/dist/{chunk-5I22LMCV.js → chunk-VZOFZPSO.js} +2 -2
  70. package/dist/chunk-VZOFZPSO.js.map +1 -0
  71. package/dist/{chunk-4BIMLITI.js → chunk-WLG6SSNT.js} +5 -3
  72. package/dist/chunk-WLG6SSNT.js.map +1 -0
  73. package/dist/{chunk-NE5JAOQS.js → chunk-WOUF7YXM.js} +3 -3
  74. package/dist/{chunk-NE5JAOQS.js.map → chunk-WOUF7YXM.js.map} +1 -1
  75. package/dist/collapsible-panel.d.ts +14 -3
  76. package/dist/collapsible-panel.js +13 -16
  77. package/dist/collapsible-panel.js.map +1 -1
  78. package/dist/content-item.d.ts +46 -0
  79. package/dist/content-item.js +4 -0
  80. package/dist/content-item.js.map +1 -0
  81. package/dist/css-values.d.ts +5 -11
  82. package/dist/css-values.js +1 -1
  83. package/dist/disclosure-arrow.d.ts +4 -1
  84. package/dist/disclosure-arrow.js +1 -1
  85. package/dist/floating-toolbar.d.ts +17 -6
  86. package/dist/floating-toolbar.js +1 -1
  87. package/dist/grid.js +1 -1
  88. package/dist/help-tags-register.d.ts +13 -0
  89. package/dist/help-tags-register.js +9 -0
  90. package/dist/help-tags-register.js.map +1 -0
  91. package/dist/index.d.ts +6 -5
  92. package/dist/index.js +27 -26
  93. package/dist/list-action-row.js +1 -1
  94. package/dist/list-header.d.ts +14 -1
  95. package/dist/list-header.js +1 -1
  96. package/dist/list-inset-control.d.ts +1 -1
  97. package/dist/list-inset-control.js +1 -1
  98. package/dist/list-inset-text.d.ts +3 -10
  99. package/dist/list-inset-text.js +1 -1
  100. package/dist/list-item.js +1 -1
  101. package/dist/list.d.ts +10 -3
  102. package/dist/list.js +1 -1
  103. package/dist/nav-stack.d.ts +38 -5
  104. package/dist/nav-stack.js +4 -1
  105. package/dist/pane.d.ts +20 -2
  106. package/dist/pane.js +1 -1
  107. package/dist/{panel-toolbar-BFQxFITu.d.ts → panel-toolbar-C8sF-YZC.d.ts} +12 -1
  108. package/dist/popup-menu-register.js +3 -2
  109. package/dist/popup-menu-register.js.map +1 -1
  110. package/dist/popup-menu.js +1 -1
  111. package/dist/row.d.ts +1 -1
  112. package/dist/row.js +1 -1
  113. package/dist/select-register.js +70 -3
  114. package/dist/select-register.js.map +1 -1
  115. package/dist/select.d.ts +46 -8
  116. package/dist/select.js +2 -1
  117. package/dist/{divider-sides-BzB6rphT.d.ts → sides-BPSWde0A.d.ts} +1 -3
  118. package/dist/skeleton.js +1 -1
  119. package/dist/spacer.js +1 -1
  120. package/dist/split-view.d.ts +31 -3
  121. package/dist/split-view.js +33 -5
  122. package/dist/split-view.js.map +1 -1
  123. package/dist/state-banner.js +1 -1
  124. package/dist/styles/badge.css +13 -0
  125. package/dist/styles/catalog/components/catalog-example.css +1 -1
  126. package/dist/styles/catalog/components/catalog-stage.css +1 -1
  127. package/dist/styles/collapsible-panel.css +192 -39
  128. package/dist/styles/content-item.css +30 -0
  129. package/dist/styles/floating-toolbar.css +5 -0
  130. package/dist/styles/foundation.css +28 -19
  131. package/dist/styles/layout.css +1 -21
  132. package/dist/styles/list-action-row.css +13 -1
  133. package/dist/styles/list-inset-text.css +1 -2
  134. package/dist/styles/list-item.css +14 -1
  135. package/dist/styles/list.css +1 -1
  136. package/dist/styles/nav-stack.css +29 -64
  137. package/dist/styles/pane.css +33 -1
  138. package/dist/styles/popup-menu.css +78 -0
  139. package/dist/styles/resizable-region.css +53 -10
  140. package/dist/styles/select.css +39 -12
  141. package/dist/styles/split-view.css +21 -25
  142. package/dist/styles/tab-scaffold.css +36 -14
  143. package/dist/styles/text.css +1 -1
  144. package/dist/styles/token-search-field.css +4 -4
  145. package/dist/styles/toolbar-control-group.css +31 -12
  146. package/dist/styles/toolbar.css +14 -5
  147. package/dist/styles/value-table.css +19 -2
  148. package/dist/styles/webawesome.css +3 -1
  149. package/dist/styles/workbench.css +134 -31
  150. package/dist/tab-scaffold.d.ts +35 -1
  151. package/dist/tab-scaffold.js +50 -16
  152. package/dist/tab-scaffold.js.map +1 -1
  153. package/dist/token-search-field.d.ts +4 -2
  154. package/dist/token-search-field.js +1 -1
  155. package/dist/toolbar-text.js +1 -1
  156. package/dist/toolbar.d.ts +12 -4
  157. package/dist/toolbar.js +1 -1
  158. package/dist/{types-D6vzj-VT.d.ts → types-DXAGogOS.d.ts} +39 -6
  159. package/dist/value-table.js +1 -1
  160. package/dist/webawesome.d.ts +7 -1
  161. package/dist/wire-catalog.d.ts +12 -1
  162. package/dist/wire-catalog.js +10 -2
  163. package/dist/wire-catalog.js.map +1 -1
  164. package/dist/wire-token-search-fields.js +1 -1
  165. package/dist/workbench.d.ts +59 -22
  166. package/dist/workbench.js +1 -1
  167. package/docs/accessibility.md +116 -7
  168. package/docs/app-layouts.md +9 -7
  169. package/docs/catalog.md +17 -3
  170. package/docs/collapsible-panel.md +26 -7
  171. package/docs/component-contract.md +36 -10
  172. package/docs/component-selection.md +41 -40
  173. package/docs/design/templates/empty-state/with-action-dark.svg +1 -1
  174. package/docs/design/templates/empty-state/with-action.svg +1 -1
  175. package/docs/design/templates/empty-state-dark.svg +1 -1
  176. package/docs/design/templates/empty-state.svg +1 -1
  177. package/docs/design/templates/list/compact-dark.svg +1 -1
  178. package/docs/design/templates/list/compact.svg +1 -1
  179. package/docs/design/templates/list/stack-dark.svg +1 -1
  180. package/docs/design/templates/list/stack.svg +1 -1
  181. package/docs/design/templates/list-action-row/default-dark.svg +1 -1
  182. package/docs/design/templates/list-action-row/default.svg +1 -1
  183. package/docs/design/templates/list-action-row/selected-dark.svg +1 -1
  184. package/docs/design/templates/list-action-row/selected.svg +1 -1
  185. package/docs/design/templates/list-action-row-dark.svg +1 -1
  186. package/docs/design/templates/list-action-row.svg +1 -1
  187. package/docs/design/templates/list-dark.svg +1 -1
  188. package/docs/design/templates/list-item/default-dark.svg +1 -1
  189. package/docs/design/templates/list-item/default.svg +1 -1
  190. package/docs/design/templates/list-item/selected-dark.svg +1 -1
  191. package/docs/design/templates/list-item/selected.svg +1 -1
  192. package/docs/design/templates/list-item/trailing-dark.svg +1 -1
  193. package/docs/design/templates/list-item/trailing.svg +1 -1
  194. package/docs/design/templates/list-item-dark.svg +1 -1
  195. package/docs/design/templates/list-item.svg +1 -1
  196. package/docs/design/templates/list.svg +1 -1
  197. package/docs/design/templates/value-table/details-dark.svg +1 -1
  198. package/docs/design/templates/value-table/details.svg +1 -1
  199. package/docs/design/templates/value-table-dark.svg +1 -1
  200. package/docs/design/templates/value-table.svg +1 -1
  201. package/docs/design-philosophy.md +1 -1
  202. package/docs/examples/command-palette-adapter.tsx +3 -2
  203. package/docs/layout.md +69 -29
  204. package/docs/nav-stack.md +45 -1
  205. package/docs/recipes.md +4 -3
  206. package/docs/split-view.md +46 -2
  207. package/docs/tab-scaffold.md +50 -1
  208. package/docs/type-contracts.md +17 -17
  209. package/docs/ux-demo.md +2 -2
  210. package/docs/webawesome-theme.md +1 -2
  211. package/docs/workbench.md +45 -9
  212. package/llms.txt +32 -4
  213. package/package.json +13 -2
  214. package/ux-demo/recipes/collapsible-sidebar.tsx +3 -2
  215. package/ux-demo/recipes/navigation-sidebar.tsx +3 -2
  216. package/ux-demo/recipes/navigation-stack.tsx +3 -2
  217. package/dist/chunk-3NBL3OUQ.js.map +0 -1
  218. package/dist/chunk-4BIMLITI.js.map +0 -1
  219. package/dist/chunk-5I22LMCV.js.map +0 -1
  220. package/dist/chunk-5NDQABWK.js.map +0 -1
  221. package/dist/chunk-5OLVUEND.js.map +0 -1
  222. package/dist/chunk-7GUQYHKA.js.map +0 -1
  223. package/dist/chunk-D7GWXIAS.js.map +0 -1
  224. package/dist/chunk-DQA5FMOX.js +0 -85
  225. package/dist/chunk-DQA5FMOX.js.map +0 -1
  226. package/dist/chunk-EAX2GSS4.js.map +0 -1
  227. package/dist/chunk-HMQ2ZDGG.js.map +0 -1
  228. package/dist/chunk-MTM43SJO.js.map +0 -1
  229. package/dist/chunk-N7FHFNT6.js.map +0 -1
  230. package/dist/chunk-R754MHXX.js.map +0 -1
  231. package/dist/chunk-RNRUVPJ3.js.map +0 -1
  232. package/dist/chunk-T22EM4ET.js.map +0 -1
  233. package/dist/chunk-WZ2GLEY4.js.map +0 -1
  234. package/dist/chunk-XD7DWYXG.js +0 -34
  235. package/dist/chunk-XD7DWYXG.js.map +0 -1
@@ -58,68 +58,35 @@
58
58
  opacity: 0;
59
59
  }
60
60
 
61
+ /* The chrome hosts the stack's real top Toolbar. It hands that toolbar the
62
+ edges the stack still touches through the edge context (never the bottom,
63
+ which the viewport owns); the toolbar pads for the sides it claims with
64
+ `safeAreaEdges` while its box paints through them. */
61
65
  .kui-nav-stack__chrome {
62
- display: flex;
63
- min-width: 0;
64
- min-height: calc(2px + 2.625rem + var(--_kui-nav-stack-safe-block-start));
65
- padding-block-start: var(--_kui-nav-stack-safe-block-start);
66
- padding-inline: calc(
67
- var(--kui-space-xs) + var(--_kui-nav-stack-safe-inline-start)
68
- )
69
- calc(var(--kui-space-xs) + var(--_kui-nav-stack-safe-inline-end));
70
- align-items: center;
71
- gap: var(--kui-space-xs);
66
+ --kui-edge-inset-block-start: var(--_kui-nav-stack-safe-block-start);
67
+ --kui-edge-inset-inline-start: var(--_kui-nav-stack-safe-inline-start);
68
+ --kui-edge-inset-inline-end: var(--_kui-nav-stack-safe-inline-end);
72
69
  background: var(--kui-color-surface);
73
70
  }
74
71
 
75
- .kui-nav-stack__lead {
76
- display: flex;
77
- flex: 1;
78
- min-width: 0;
79
- align-items: center;
80
- gap: var(--kui-space-2xs);
81
- }
82
-
83
- .kui-nav-stack__back {
84
- display: grid;
85
- width: 2.5rem;
86
- height: 2.5rem;
87
- padding: 0;
88
- border: 1px solid transparent;
89
- border-radius: var(--kui-layout-rounded-radius, calc(1px + 0.6875rem));
90
- color: inherit;
91
- background: transparent;
92
- cursor: pointer;
93
- place-items: center;
94
- }
95
-
96
- .kui-nav-stack__back:hover {
97
- border-color: var(--kui-color-border);
98
- background: var(--kui-color-neutral-fill-normal);
99
- }
100
-
101
- .kui-nav-stack__back:focus-visible {
102
- outline: var(--kui-focus-ring);
103
- outline-offset: 1px;
104
- }
105
-
106
- .kui-nav-stack__back-icon {
107
- display: block;
72
+ /* A navigation bar is one control band tall: the toolbar keeps its inline
73
+ padding and any claimed block inset, but drops the block gap so the bar is
74
+ the band height (44px) plus the unsafe inset it clears. */
75
+ .kui-nav-stack__chrome > .kui-nav-stack__toolbar {
76
+ min-height: calc(
77
+ var(--_kui-toolbar-band) + var(--_kui-toolbar-safe-block-start) +
78
+ var(--_kui-toolbar-safe-block-end)
79
+ );
80
+ padding-block: var(--_kui-toolbar-safe-block-start)
81
+ var(--_kui-toolbar-safe-block-end);
108
82
  }
109
83
 
110
- /* The title is ToolbarText (which owns its font, height, and ellipsis); it just
111
- needs to flex to fill the lead zone beside the back control. */
84
+ /* The title fills the leading zone beside the back control and truncates. */
112
85
  .kui-nav-stack__title {
113
86
  flex: 1 1 auto;
114
87
  min-width: 0;
115
88
  }
116
89
 
117
- .kui-nav-stack__actions {
118
- display: flex;
119
- align-items: center;
120
- gap: var(--kui-space-2xs);
121
- }
122
-
123
90
  .kui-nav-stack__viewport {
124
91
  --kui-edge-inset-block-start: var(--_kui-nav-stack-safe-block-start);
125
92
  --kui-edge-inset-block-end: var(--_kui-nav-stack-safe-block-end);
@@ -174,18 +141,16 @@
174
141
  var(--kui-edge-inset-block-end);
175
142
  }
176
143
 
177
- .kui-nav-stack__view:not(
178
- :has(
179
- > :is(
180
- [data-component="pane"],
181
- [data-component="nav-stack"],
182
- [data-component="split-view"],
183
- [data-component="workbench"],
184
- [data-component="tab-scaffold"]
185
- ):only-child
186
- )
187
- )
188
- > * {
144
+ .kui-nav-stack__view
145
+ > :not(
146
+ :is(
147
+ [data-component="pane"],
148
+ [data-component="nav-stack"],
149
+ [data-component="split-view"],
150
+ [data-component="workbench"],
151
+ [data-component="tab-scaffold"]
152
+ ):only-child
153
+ ) {
189
154
  --kui-edge-inset-block-start: 0px;
190
155
  --kui-edge-inset-block-end: 0px;
191
156
  --kui-edge-inset-inline-start: 0px;
@@ -214,7 +179,7 @@
214
179
  padding-block-end: var(--_kui-nav-stack-safe-block-end);
215
180
  padding-inline: var(--_kui-nav-stack-safe-inline-start)
216
181
  var(--_kui-nav-stack-safe-inline-end);
217
- border-block-start: 1px solid var(--kui-color-border);
182
+ border-block-start: 1px solid var(--kui-color-neutral-border-normal);
218
183
  background: var(--kui-color-surface);
219
184
  }
220
185
 
@@ -9,7 +9,8 @@
9
9
  min-height: 0;
10
10
  padding: 0;
11
11
  box-sizing: border-box;
12
- border: 0 solid var(--kui-pane-separator-color, var(--kui-color-border));
12
+ border: 0 solid
13
+ var(--kui-pane-separator-color, var(--kui-color-neutral-border-normal));
13
14
  border-block-start-width: var(--kui-pane-separator-block-start-width);
14
15
  border-block-end-width: var(--kui-pane-separator-block-end-width);
15
16
  border-inline-start-width: var(--kui-pane-separator-inline-start-width);
@@ -145,3 +146,34 @@
145
146
  flex-direction: column;
146
147
  grid-area: footer;
147
148
  }
149
+
150
+ /* `chromePlacement="auto"`: the header and footer stay pinned while the pane
151
+ is tall enough; below 480px of height (30rem, so it scales with the text
152
+ size) the whole pane scrolls as one column instead, so tall chrome can never
153
+ squeeze the content to nothing. The pane is its own size container and lays
154
+ its slots out as a column: while tall, the content fills the space between
155
+ the chrome and scrolls itself, and the pane never scrolls; while short, the
156
+ content takes its natural height and the pane scrolls. */
157
+ .kui-pane[data-chrome-placement="auto"] {
158
+ container: kui-pane / size;
159
+ display: flex;
160
+ overflow-y: auto;
161
+ flex-direction: column;
162
+ overscroll-behavior: contain;
163
+ }
164
+
165
+ .kui-pane[data-chrome-placement="auto"]
166
+ > :is(.kui-pane__header, .kui-pane__footer) {
167
+ flex: none;
168
+ }
169
+
170
+ .kui-pane[data-chrome-placement="auto"] > .kui-pane__content {
171
+ flex: 1 1 0;
172
+ }
173
+
174
+ @container kui-pane (max-height: 30rem) {
175
+ .kui-pane[data-chrome-placement="auto"] > .kui-pane__content {
176
+ flex: none;
177
+ overflow: visible;
178
+ }
179
+ }
@@ -10,3 +10,81 @@
10
10
  white-space: nowrap;
11
11
  clip-path: inset(50%);
12
12
  }
13
+
14
+ /* A PopupMenu draws exactly the Select's popup: the same caret motion, surface
15
+ inset, row geometry, reserved check column, current-row fill, and group
16
+ titles, all read from the private popup-choice contract in foundation.css
17
+ (select.css reads the same values). */
18
+
19
+ /* The trigger caret turns to face the open menu, like the Select's. */
20
+ .kui-popup-menu > wa-button::part(caret) {
21
+ rotate: 0deg;
22
+ transition: var(--_kui-popup-caret-transition);
23
+ }
24
+ .kui-popup-menu[open] > wa-button::part(caret) {
25
+ rotate: var(--_kui-popup-caret-open-rotation);
26
+ }
27
+
28
+ /* The Select's popup fades in place; Web Awesome's dropdown also scales from
29
+ 90%. Holding the scale leaves the shared fade. */
30
+ .kui-popup-menu::part(menu) {
31
+ padding: var(--_kui-popup-inset);
32
+ gap: var(--_kui-popup-row-gap);
33
+ scale: none !important;
34
+ }
35
+
36
+ .kui-popup-menu > wa-dropdown-item {
37
+ /* Leading inset plus the Select's check column, so item icons and labels
38
+ start where a Select option's do. */
39
+ padding: var(--_kui-popup-row-padding-block)
40
+ var(--_kui-popup-row-padding-inline-end) var(--_kui-popup-row-padding-block)
41
+ calc(
42
+ var(--_kui-popup-row-padding-inline-start) +
43
+ var(--_kui-popup-row-check-width)
44
+ );
45
+ }
46
+ .kui-popup-menu > wa-dropdown-item::part(label) {
47
+ padding-block: var(--_kui-popup-row-label-padding-block);
48
+ line-height: var(--_kui-popup-row-label-line-height);
49
+ }
50
+ /* A keyboard-focused item is the menu's current row: the Select's brand fill,
51
+ with no second focus ring inside the open popup. */
52
+ .kui-popup-menu > wa-dropdown-item:focus-visible {
53
+ outline: none;
54
+ color: var(--_kui-popup-row-current-color);
55
+ background-color: var(--_kui-popup-row-current-background);
56
+ }
57
+ .kui-popup-menu > wa-divider {
58
+ --spacing: 0.5em;
59
+ }
60
+
61
+ /* Center the icon on the label's line, like the Select's start slot. */
62
+ .kui-popup-menu > wa-dropdown-item::part(icon) {
63
+ display: flex;
64
+ align-self: center;
65
+ }
66
+ .kui-popup-menu__icon {
67
+ display: inline-flex;
68
+ width: var(--_kui-popup-row-icon-size);
69
+ height: var(--_kui-popup-row-icon-size);
70
+ flex: none;
71
+ /* Web Awesome spaces a slotted item icon 0.75em from its label (an
72
+ !important shadow rule). Sizing that em makes the gap the Select's. */
73
+ font-size: calc(var(--_kui-popup-row-icon-gap) / 0.75);
74
+ }
75
+ .kui-popup-menu__icon svg {
76
+ display: block;
77
+ width: 100%;
78
+ height: 100%;
79
+ }
80
+
81
+ /* A group title matches the Select's group title. It is a styled element
82
+ rather than a slotted heading, whose Web Awesome metrics are !important. */
83
+ .kui-popup-menu__heading {
84
+ padding: var(--_kui-popup-group-title-padding);
85
+ color: var(--kui-color-neutral-on-quiet);
86
+ font-size: var(--kui-font-2xs);
87
+ font-weight: var(--_kui-popup-group-title-font-weight);
88
+ letter-spacing: 0.04em;
89
+ text-transform: uppercase;
90
+ }
@@ -1,5 +1,7 @@
1
1
  .kui-resizable-region {
2
- --kui-resizable-region-separator-color: var(--kui-color-border);
2
+ --kui-resizable-region-separator-color: var(
3
+ --kui-color-neutral-border-normal
4
+ );
3
5
  --kui-resizable-region-handle-color: var(--kui-color-neutral-on-quiet);
4
6
  --kui-resizable-region-handle-active-color: var(--kui-color-text-link);
5
7
  /* Extra track a horizontal region adds when it reaches an unsafe screen edge,
@@ -211,6 +213,36 @@
211
213
  .kui-resizable-region[data-presentation="hidden"] {
212
214
  display: none;
213
215
  }
216
+ /* An open side overlay (a horizontal region) covers the work area beside it,
217
+ so that area's floating controls (a FloatingToolbar, a restore corner) are
218
+ hidden, not merely stacked beneath it: they never paint over the overlay
219
+ whatever stacking context an app puts them in, and hidden they leave the
220
+ tab order and the accessibility tree. They come back as the overlay
221
+ closes. The flag is read by FloatingToolbar and the layouts' restore
222
+ corners. It is set on the overlay's container and cleared again on the
223
+ overlay regions in it, so it reaches the overlay's siblings only. It is
224
+ never set by a universal selector below the :has() container (`:has(…) >
225
+ :not(…)`): Chromium then restyles every child of every ancestor of a DOM
226
+ change, which made each change in a long list about 30× slower. */
227
+ :where(
228
+ :has(
229
+ > .kui-resizable-region[data-presentation="overlay"][data-axis="horizontal"]:not(
230
+ [data-collapsed="true"]
231
+ )
232
+ )
233
+ ) {
234
+ --_kui-floating-covered: hidden;
235
+ }
236
+ :where(
237
+ :has(
238
+ > .kui-resizable-region[data-presentation="overlay"][data-axis="horizontal"]:not(
239
+ [data-collapsed="true"]
240
+ )
241
+ )
242
+ )
243
+ > .kui-resizable-region[data-presentation="overlay"] {
244
+ --_kui-floating-covered: initial;
245
+ }
214
246
 
215
247
  @container (max-width: 44rem) {
216
248
  .kui-resizable-region[data-responsive-fill-at="narrow"] {
@@ -256,18 +288,24 @@
256
288
  beside the collapsed one — a direct child of that container or of one of
257
289
  its direct children (the app's work-area column) — owns the container's
258
290
  bottom, so the corner floats above the drawer's top edge instead of over
259
- it. CollapsiblePanel drawers publish the same anchor. A drawer nested
260
- deeper, inside the work area's own content, belongs to another layout and
261
- is scoped out. Without anchor positioning the corner keeps the container's
262
- bottom edge. */
263
- .kui-resizable-region[data-axis="vertical"][data-edge="start"][data-presentation="inline"]:not(
291
+ it. The region publishes that edge as an anchor only there, beside a
292
+ CollapsiblePanel or ResizableRegion restore control (matched by their
293
+ restore attributes); CollapsiblePanel drawers publish the same anchor. A
294
+ drawer nested deeper, inside the work area's own content, belongs to
295
+ another layout and publishes nothing. The selector ends on the region, not
296
+ on a universal `> * > * > *` scope below the container: a universal
297
+ selector after a :has() container restyles every child of every ancestor
298
+ of a DOM change in Chromium. Without anchor positioning the corner keeps
299
+ the container's bottom edge. */
300
+ :where(
301
+ :has(> [data-panel-restore], > [data-region-restore]),
302
+ :has(> [data-panel-restore], > [data-region-restore]) > *
303
+ )
304
+ > .kui-resizable-region[data-axis="vertical"][data-edge="start"][data-presentation="inline"]:not(
264
305
  [data-collapsed="true"]
265
306
  ) {
266
307
  anchor-name: --kui-restore-drawer;
267
308
  }
268
- :where(:has(> .kui-resizable-region__restore)) > * > * > * {
269
- anchor-scope: --kui-restore-drawer;
270
- }
271
309
  .kui-resizable-region__restore {
272
310
  --_kui-resizable-region-restore-inset: var(
273
311
  --kui-resizable-region-restore-inset,
@@ -277,6 +315,8 @@
277
315
  from this point instead of adding its own inset on top. */
278
316
  --kui-floating-toolbar-inset: 0px;
279
317
  position: absolute;
318
+ /* Hidden while an open side overlay covers the content (see above). */
319
+ visibility: var(--_kui-floating-covered, inherit);
280
320
  z-index: var(
281
321
  --kui-resizable-region-restore-z,
282
322
  calc(var(--kui-resizable-region-overlay-z, 41) - 2)
@@ -379,7 +419,10 @@
379
419
  and the separator has less room past it than the handle's overhang, which
380
420
  puts it at the parent's edge. The handle then sits wholly inside the region
381
421
  and keeps its separator line on the region's edge, so a clipping ancestor
382
- never cuts off half of the hit target or its focus ring. */
422
+ never cuts off half of the hit target or its focus ring. The grip stays
423
+ centered in the handle there: the separator is the clipping edge, so a grip
424
+ centered on it would be cut in half. Everywhere else the grip is drawn on
425
+ the separator line. */
383
426
  .kui-resizable-region[data-handle-inset][data-axis="horizontal"][data-edge="end"]
384
427
  > .kui-resizable-region__handle {
385
428
  right: 0;
@@ -23,6 +23,11 @@
23
23
  text-overflow: ellipsis;
24
24
  white-space: nowrap;
25
25
  }
26
+ /* A multiple Select summarizes its choices in the display text (installed by
27
+ select/register) instead of drawing a removable tag per choice. */
28
+ .kui-select[multiple]::part(tags) {
29
+ display: none;
30
+ }
26
31
  .kui-select[data-size="compact"]::part(combobox) {
27
32
  min-height: 2rem;
28
33
  }
@@ -94,6 +99,13 @@
94
99
  .kui-select__icon[slot="start"] {
95
100
  margin-inline-end: 0 !important;
96
101
  }
102
+ /* A multiple icon-only trigger: its fixed icon, then a count badge while any
103
+ choice is chosen, 4px from the icon (the caret keeps its 12px after it).
104
+ The summary that ends its label (and accessible name) stays inline text, so
105
+ a visible label reads "Labels: Bug, Docs" in place of the hidden value. */
106
+ .kui-select__count {
107
+ margin-inline-start: 0.25rem;
108
+ }
97
109
  .kui-select::part(start),
98
110
  .kui-select::part(end),
99
111
  .kui-select::part(expand-icon) {
@@ -102,7 +114,21 @@
102
114
  .kui-select::part(expand-icon) {
103
115
  transform: scale(var(--kui-disclosure-icon-scale, 0.5));
104
116
  }
117
+ .kui-select::part(expand-icon) {
118
+ transition: var(--_kui-popup-caret-transition);
119
+ }
120
+ .kui-select[open]::part(expand-icon) {
121
+ rotate: var(--_kui-popup-caret-open-rotation);
122
+ }
123
+ /* The open listbox already shows where focus is (its current option), so the
124
+ trigger drops its focus ring while the popup is visible, as a PopupMenu
125
+ trigger does; the ring returns when the popup closes with focus still on
126
+ the control. */
127
+ .kui-select[open]::part(combobox) {
128
+ outline-color: transparent;
129
+ }
105
130
  .kui-select::part(listbox) {
131
+ padding: var(--_kui-popup-inset);
106
132
  width: max-content;
107
133
  min-width: 100%;
108
134
  max-width: min(20rem, calc(100vw - 1.25rem));
@@ -114,28 +140,29 @@
114
140
  align-items: center;
115
141
  }
116
142
  .kui-select wa-option {
117
- --wa-form-control-activated-color: var(--kui-color-brand-fill-normal);
118
- /* Current option text sits on the activated brand fill; use the darker on-fill
119
- accent so it clears WCAG AA (brand-on-quiet is 4.26:1 over that fill). */
120
- --current-text-color: var(--kui-color-brand-on-fill);
143
+ --wa-form-control-activated-color: var(--_kui-popup-row-current-background);
144
+ --current-text-color: var(--_kui-popup-row-current-color);
145
+ padding: var(--_kui-popup-row-padding-block)
146
+ var(--_kui-popup-row-padding-inline-end) var(--_kui-popup-row-padding-block)
147
+ var(--_kui-popup-row-padding-inline-start);
121
148
  }
122
149
  .kui-select wa-option::part(start) {
123
150
  align-self: center;
124
- margin-inline-end: 0.5rem;
151
+ margin-inline-end: var(--_kui-popup-row-icon-gap);
125
152
  margin-top: 0;
126
153
  }
127
154
  .kui-select wa-option::part(label) {
128
155
  min-width: 0;
129
- padding-block: 0.35rem;
130
- line-height: 1.25;
156
+ padding-block: var(--_kui-popup-row-label-padding-block);
157
+ line-height: var(--_kui-popup-row-label-line-height);
131
158
  overflow-wrap: normal;
132
159
  word-break: normal;
133
160
  white-space: normal;
134
161
  }
135
162
  .kui-select__icon {
136
163
  display: inline-flex;
137
- width: 1rem;
138
- height: 1rem;
164
+ width: var(--_kui-popup-row-icon-size);
165
+ height: var(--_kui-popup-row-icon-size);
139
166
  flex: none;
140
167
  }
141
168
  .kui-select > .kui-select__icon[slot="start"] {
@@ -173,10 +200,10 @@
173
200
  border-block-start: 1px solid var(--kui-color-neutral-border-quiet);
174
201
  }
175
202
  .kui-select__group-title {
176
- padding: 0.2rem 0.75rem 0.3rem;
203
+ padding: var(--_kui-popup-group-title-padding);
177
204
  color: var(--kui-color-neutral-on-quiet);
178
205
  font-size: var(--kui-font-2xs);
179
- font-weight: 750;
206
+ font-weight: var(--_kui-popup-group-title-font-weight);
180
207
  letter-spacing: 0.04em;
181
208
  text-transform: uppercase;
182
209
  }
@@ -208,7 +235,7 @@
208
235
  justify-content: space-between;
209
236
  gap: 0.5rem;
210
237
  padding-inline: var(--kui-layout-item-padding, 0.5rem);
211
- border: 1px solid var(--kui-color-border);
238
+ border: 1px solid var(--kui-color-neutral-border-normal);
212
239
  border-radius: var(--kui-layout-rounded-radius, calc(1px + 0.6875rem));
213
240
  background: var(--kui-color-surface);
214
241
  }
@@ -37,7 +37,7 @@
37
37
  var(--kui-split-view-list-width, 20rem) +
38
38
  var(--_kui-split-view-safe-inline-start)
39
39
  );
40
- border-inline-end: 1px solid var(--kui-color-border);
40
+ border-inline-end: 1px solid var(--kui-color-neutral-border-normal);
41
41
  }
42
42
 
43
43
  .kui-split-view__list[data-resizable="true"] {
@@ -104,30 +104,26 @@
104
104
  var(--kui-edge-inset-inline-end);
105
105
  }
106
106
 
107
- .kui-split-view__list:not(
108
- :has(
109
- > :is(
110
- [data-component="pane"],
111
- [data-component="nav-stack"],
112
- [data-component="split-view"],
113
- [data-component="workbench"],
114
- [data-component="tab-scaffold"]
115
- ):only-child
116
- )
117
- )
118
- > *,
119
- .kui-split-view__detail:not(
120
- :has(
121
- > :is(
122
- [data-component="pane"],
123
- [data-component="nav-stack"],
124
- [data-component="split-view"],
125
- [data-component="workbench"],
126
- [data-component="tab-scaffold"]
127
- ):only-child
128
- )
129
- )
130
- > * {
107
+ .kui-split-view__list
108
+ > :not(
109
+ :is(
110
+ [data-component="pane"],
111
+ [data-component="nav-stack"],
112
+ [data-component="split-view"],
113
+ [data-component="workbench"],
114
+ [data-component="tab-scaffold"]
115
+ ):only-child
116
+ ),
117
+ .kui-split-view__detail
118
+ > :not(
119
+ :is(
120
+ [data-component="pane"],
121
+ [data-component="nav-stack"],
122
+ [data-component="split-view"],
123
+ [data-component="workbench"],
124
+ [data-component="tab-scaffold"]
125
+ ):only-child
126
+ ) {
131
127
  --kui-edge-inset-block-start: 0px;
132
128
  --kui-edge-inset-block-end: 0px;
133
129
  --kui-edge-inset-inline-start: 0px;
@@ -66,18 +66,16 @@
66
66
  scroll-padding-block-start: var(--kui-edge-inset-block-start);
67
67
  }
68
68
 
69
- .kui-tab-scaffold__scene:not(
70
- :has(
71
- > :is(
72
- [data-component="pane"],
73
- [data-component="nav-stack"],
74
- [data-component="split-view"],
75
- [data-component="workbench"],
76
- [data-component="tab-scaffold"]
77
- ):only-child
78
- )
79
- )
80
- > * {
69
+ .kui-tab-scaffold__scene
70
+ > :not(
71
+ :is(
72
+ [data-component="pane"],
73
+ [data-component="nav-stack"],
74
+ [data-component="split-view"],
75
+ [data-component="workbench"],
76
+ [data-component="tab-scaffold"]
77
+ ):only-child
78
+ ) {
81
79
  --kui-edge-inset-block-start: 0px;
82
80
  --kui-edge-inset-block-end: 0px;
83
81
  --kui-edge-inset-inline-start: 0px;
@@ -98,7 +96,7 @@
98
96
  );
99
97
  padding-inline: var(--_kui-tab-scaffold-safe-inline-start)
100
98
  var(--_kui-tab-scaffold-safe-inline-end);
101
- border-block-start: 1px solid var(--kui-color-border);
99
+ border-block-start: 1px solid var(--kui-color-neutral-border-normal);
102
100
  background: var(--kui-color-surface);
103
101
  }
104
102
 
@@ -120,7 +118,7 @@
120
118
  }
121
119
 
122
120
  .kui-tab-scaffold__tab[aria-selected="true"] {
123
- color: var(--kui-color-accent-text);
121
+ color: var(--kui-color-brand-on-quiet);
124
122
  }
125
123
 
126
124
  .kui-tab-scaffold__tab:focus-visible {
@@ -129,10 +127,34 @@
129
127
  }
130
128
 
131
129
  .kui-tab-scaffold__tab-icon {
130
+ position: relative;
132
131
  display: grid;
133
132
  place-items: center;
134
133
  }
135
134
 
135
+ /* The iOS tab-bar badge: over the icon's top-trailing corner, its leading
136
+ edge just past the icon's center line so a longer count grows outward. The
137
+ Badge keeps its own geometry; only this anchor is positioned. Without an
138
+ icon the badge stays in flow above the label. */
139
+ .kui-tab-scaffold__tab-badge {
140
+ display: flex;
141
+ pointer-events: none;
142
+ }
143
+
144
+ .kui-tab-scaffold__tab-icon > .kui-tab-scaffold__tab-badge {
145
+ position: absolute;
146
+ inset-block-start: -0.4375rem;
147
+ inset-inline-start: calc(50% + 0.1875rem);
148
+ }
149
+
150
+ /* The text-free dot never grows, so it centers on the icon's top-trailing
151
+ corner instead: half over the glyph, half outside it. */
152
+ .kui-tab-scaffold__tab-icon
153
+ > .kui-tab-scaffold__tab-badge[data-badge-kind="dot"] {
154
+ inset-block-start: -0.125rem;
155
+ inset-inline-start: calc(100% - 0.3125rem);
156
+ }
157
+
136
158
  .kui-tab-scaffold__tab-icon svg {
137
159
  width: 1.375rem;
138
160
  height: 1.375rem;
@@ -10,7 +10,7 @@
10
10
  }
11
11
 
12
12
  .kui-text[data-tone="danger"] {
13
- color: var(--kui-color-danger-text);
13
+ color: var(--kui-color-danger-on-quiet);
14
14
  }
15
15
 
16
16
  .kui-text[data-size="compact"] {
@@ -1,8 +1,8 @@
1
1
  .kui-token-search {
2
2
  --kui-token-search-background: var(--kui-color-surface);
3
- --kui-token-search-border: var(--kui-color-border);
4
- --kui-token-search-token-background: var(--kui-color-accent);
5
- --kui-token-search-token-foreground: var(--kui-color-accent-text);
3
+ --kui-token-search-border: var(--kui-color-neutral-border-normal);
4
+ --kui-token-search-token-background: var(--kui-color-brand-fill-normal);
5
+ --kui-token-search-token-foreground: var(--kui-color-brand-on-quiet);
6
6
  --kui-token-search-line-size: 2.125rem;
7
7
 
8
8
  display: grid;
@@ -53,7 +53,7 @@
53
53
  padding-block: calc((var(--kui-token-search-line-size) - 1.35em) / 2) 0;
54
54
  box-sizing: border-box;
55
55
  outline: 0;
56
- caret-color: var(--kui-color-accent-text);
56
+ caret-color: var(--kui-color-brand-on-quiet);
57
57
  font-size: var(--kui-font-s);
58
58
  line-height: 1.35;
59
59
  white-space: pre-wrap;