@kerfjs/ui 5.0.0-beta.49 → 5.0.0-beta.51

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 (319) hide show
  1. package/README.md +69 -15
  2. package/ai/catalog-authoring.json +12 -1
  3. package/ai/catalog-authoring.schema.json +49 -1
  4. package/ai/compile-time-contracts-v1.json +19 -2
  5. package/ai/compile-time-contracts-v1.schema.json +1 -0
  6. package/ai/component-catalog-v2-overrides.json +7 -0
  7. package/ai/component-catalog-v2.d.ts +19 -1
  8. package/ai/component-catalog-v2.json +920 -149
  9. package/ai/component-catalog-v2.schema.json +33 -1
  10. package/ai/component-catalog.json +689 -153
  11. package/ai/component-catalog.schema.json +21 -1
  12. package/ai/public-api-signatures-v1.md +404 -184
  13. package/ai/skill.md +31 -14
  14. package/ai/webawesome-jsx-signatures-v1.md +1 -1
  15. package/analyzer/index.mjs +105 -35
  16. package/dist/app-tab.d.ts +3 -1
  17. package/dist/app-tab.js +1 -1
  18. package/dist/badge.d.ts +24 -0
  19. package/dist/badge.js +3 -0
  20. package/dist/badge.js.map +1 -0
  21. package/dist/browser/badge.js +3 -0
  22. package/dist/browser/list-header.js +1 -0
  23. package/dist/browser/state-banner.js +1 -0
  24. package/dist/catalog-resources.d.ts +2 -2
  25. package/dist/catalog.d.ts +47 -125
  26. package/dist/catalog.js +429 -262
  27. package/dist/catalog.js.map +1 -1
  28. package/dist/{chunk-W2FK7ZNY.js → chunk-4R777DUZ.js} +10 -2
  29. package/dist/chunk-4R777DUZ.js.map +1 -0
  30. package/dist/{chunk-OMSRSL3B.js → chunk-5FZZMIMD.js} +6 -4
  31. package/dist/chunk-5FZZMIMD.js.map +1 -0
  32. package/dist/{chunk-AQFWBG23.js → chunk-5PMGQDG7.js} +5 -3
  33. package/dist/chunk-5PMGQDG7.js.map +1 -0
  34. package/dist/{chunk-SOK5EUF7.js → chunk-6ZXOQEAN.js} +4 -2
  35. package/dist/chunk-6ZXOQEAN.js.map +1 -0
  36. package/dist/{chunk-I4V3UDSA.js → chunk-7GUQYHKA.js} +25 -6
  37. package/dist/chunk-7GUQYHKA.js.map +1 -0
  38. package/dist/{chunk-XKFRMGMW.js → chunk-7IUSV4XG.js} +3 -1
  39. package/dist/chunk-7IUSV4XG.js.map +1 -0
  40. package/dist/{chunk-IU4QUY5I.js → chunk-AEPXGCNF.js} +20 -3
  41. package/dist/chunk-AEPXGCNF.js.map +1 -0
  42. package/dist/{chunk-VDUJZF5G.js → chunk-CMUIXJZM.js} +2 -2
  43. package/dist/{chunk-VDUJZF5G.js.map → chunk-CMUIXJZM.js.map} +1 -1
  44. package/dist/{chunk-DAO2VFTT.js → chunk-D547PH4L.js} +7 -5
  45. package/dist/chunk-D547PH4L.js.map +1 -0
  46. package/dist/{chunk-2TYUFZUC.js → chunk-D7GWXIAS.js} +4 -2
  47. package/dist/chunk-D7GWXIAS.js.map +1 -0
  48. package/dist/{chunk-E34TE2ZI.js → chunk-DVZCMMB3.js} +6 -4
  49. package/dist/chunk-DVZCMMB3.js.map +1 -0
  50. package/dist/{chunk-6NDBE2OK.js → chunk-E36EVCKG.js} +5 -3
  51. package/dist/chunk-E36EVCKG.js.map +1 -0
  52. package/dist/chunk-EKYZCRCX.js +256 -0
  53. package/dist/chunk-EKYZCRCX.js.map +1 -0
  54. package/dist/{chunk-TIGSG6BX.js → chunk-HJKRCKDR.js} +7 -3
  55. package/dist/chunk-HJKRCKDR.js.map +1 -0
  56. package/dist/{chunk-Y6LYKFXY.js → chunk-HMQ2ZDGG.js} +5 -3
  57. package/dist/chunk-HMQ2ZDGG.js.map +1 -0
  58. package/dist/{chunk-UDHHKZWO.js → chunk-JM53SMVF.js} +9 -5
  59. package/dist/chunk-JM53SMVF.js.map +1 -0
  60. package/dist/{chunk-OGTJNHRG.js → chunk-JMGKM7RK.js} +6 -4
  61. package/dist/chunk-JMGKM7RK.js.map +1 -0
  62. package/dist/{chunk-GYGM363P.js → chunk-KX7DP2GO.js} +17 -7
  63. package/dist/chunk-KX7DP2GO.js.map +1 -0
  64. package/dist/{chunk-OL4TC3U2.js → chunk-MO56ZZLG.js} +6 -2
  65. package/dist/chunk-MO56ZZLG.js.map +1 -0
  66. package/dist/{chunk-VXFGMDA7.js → chunk-MTM43SJO.js} +16 -2
  67. package/dist/chunk-MTM43SJO.js.map +1 -0
  68. package/dist/{chunk-ZPWZIVI6.js → chunk-N3GKMPDW.js} +7 -3
  69. package/dist/chunk-N3GKMPDW.js.map +1 -0
  70. package/dist/{chunk-DYBPI5O2.js → chunk-NDUGJ4TU.js} +4 -2
  71. package/dist/chunk-NDUGJ4TU.js.map +1 -0
  72. package/dist/{chunk-I45QO2IZ.js → chunk-NMGTHYW3.js} +7 -5
  73. package/dist/chunk-NMGTHYW3.js.map +1 -0
  74. package/dist/{chunk-WSXUPSID.js → chunk-NN6GYOA2.js} +7 -3
  75. package/dist/chunk-NN6GYOA2.js.map +1 -0
  76. package/dist/{chunk-OGNE3OFT.js → chunk-NZXWU4R5.js} +24 -3
  77. package/dist/chunk-NZXWU4R5.js.map +1 -0
  78. package/dist/{chunk-V6GQKOX2.js → chunk-O3RCCSQJ.js} +6 -4
  79. package/dist/chunk-O3RCCSQJ.js.map +1 -0
  80. package/dist/{chunk-WVLMZ5SG.js → chunk-S4QRSBFI.js} +25 -3
  81. package/dist/chunk-S4QRSBFI.js.map +1 -0
  82. package/dist/{chunk-CK6P5AUK.js → chunk-UBH743HV.js} +10 -7
  83. package/dist/chunk-UBH743HV.js.map +1 -0
  84. package/dist/{chunk-T7DOWS6T.js → chunk-ULCDZTWL.js} +7 -4
  85. package/dist/chunk-ULCDZTWL.js.map +1 -0
  86. package/dist/{chunk-V6HCTCVD.js → chunk-UPZ6EEJN.js} +9 -5
  87. package/dist/chunk-UPZ6EEJN.js.map +1 -0
  88. package/dist/{chunk-CAB6NQ2T.js → chunk-VOCPXGQN.js} +3 -1
  89. package/dist/chunk-VOCPXGQN.js.map +1 -0
  90. package/dist/chunk-XD7DWYXG.js +34 -0
  91. package/dist/chunk-XD7DWYXG.js.map +1 -0
  92. package/dist/{chunk-B6JYRX3P.js → chunk-ZIYOJFZD.js} +43 -4
  93. package/dist/chunk-ZIYOJFZD.js.map +1 -0
  94. package/dist/{chunk-EYALJQQD.js → chunk-ZK5EGVFP.js} +4 -2
  95. package/dist/chunk-ZK5EGVFP.js.map +1 -0
  96. package/dist/{chunk-6WTETUZ6.js → chunk-ZLWQZUGF.js} +8 -2
  97. package/dist/chunk-ZLWQZUGF.js.map +1 -0
  98. package/dist/collapsible-panel.d.ts +4 -2
  99. package/dist/collapsible-panel.js +4 -2
  100. package/dist/collapsible-panel.js.map +1 -1
  101. package/dist/css-values.d.ts +39 -3
  102. package/dist/css-values.js +1 -1
  103. package/dist/disclosure-arrow.d.ts +3 -1
  104. package/dist/disclosure-arrow.js +1 -1
  105. package/dist/empty-state.d.ts +3 -1
  106. package/dist/empty-state.js +1 -1
  107. package/dist/floating-toolbar.d.ts +3 -1
  108. package/dist/floating-toolbar.js +1 -1
  109. package/dist/grid.d.ts +17 -1
  110. package/dist/grid.js +2 -1
  111. package/dist/index.d.ts +4 -3
  112. package/dist/index.js +34 -33
  113. package/dist/list-action-row.d.ts +3 -1
  114. package/dist/list-action-row.js +1 -1
  115. package/dist/list-header.d.ts +6 -1
  116. package/dist/list-header.js +2 -1
  117. package/dist/list-inset-control.d.ts +3 -1
  118. package/dist/list-inset-control.js +1 -1
  119. package/dist/list-inset-text.d.ts +3 -1
  120. package/dist/list-inset-text.js +1 -1
  121. package/dist/list-item.d.ts +3 -1
  122. package/dist/list-item.js +1 -1
  123. package/dist/list.d.ts +23 -2
  124. package/dist/list.js +2 -1
  125. package/dist/loading-spinner.d.ts +3 -1
  126. package/dist/loading-spinner.js +1 -1
  127. package/dist/lucide-icon.d.ts +3 -1
  128. package/dist/lucide-icon.js +1 -1
  129. package/dist/nav-stack.d.ts +3 -1
  130. package/dist/nav-stack.js +1 -1
  131. package/dist/pane.d.ts +19 -2
  132. package/dist/pane.js +1 -1
  133. package/dist/resizable-region.d.ts +5 -2
  134. package/dist/resizable-region.js +1 -1
  135. package/dist/row.d.ts +21 -1
  136. package/dist/row.js +2 -1
  137. package/dist/segmented-control.d.ts +3 -1
  138. package/dist/segmented-control.js +1 -1
  139. package/dist/select.d.ts +16 -4
  140. package/dist/select.js +1 -1
  141. package/dist/skeleton.d.ts +3 -1
  142. package/dist/skeleton.js +1 -1
  143. package/dist/spacer.d.ts +3 -1
  144. package/dist/spacer.js +1 -1
  145. package/dist/split-view.d.ts +3 -1
  146. package/dist/split-view.js +24 -5
  147. package/dist/split-view.js.map +1 -1
  148. package/dist/state-banner.d.ts +3 -1
  149. package/dist/state-banner.js +2 -1
  150. package/dist/styles/badge.css +86 -0
  151. package/dist/styles/catalog/components/catalog-detail.css +35 -0
  152. package/dist/styles/catalog/components/catalog-example-stack.css +9 -0
  153. package/dist/styles/catalog/components/catalog-example.css +180 -0
  154. package/dist/styles/catalog/components/catalog-resource-footer.css +37 -0
  155. package/dist/styles/catalog/components/catalog-secondary-sections.css +38 -0
  156. package/dist/styles/catalog/components/catalog-section-list.css +22 -0
  157. package/dist/styles/catalog/components/catalog-sidebar.css +82 -0
  158. package/dist/styles/catalog/components/catalog-stage.css +60 -0
  159. package/dist/styles/catalog/components/catalog.css +22 -0
  160. package/dist/styles/catalog.css +10 -587
  161. package/dist/styles/collapsible-panel.css +132 -4
  162. package/dist/styles/document.css +23 -0
  163. package/dist/styles/foundation.css +21 -7
  164. package/dist/styles/grid.css +10 -0
  165. package/dist/styles/list-header.css +49 -60
  166. package/dist/styles/list-inset-control.css +8 -1
  167. package/dist/styles/list-item.css +6 -0
  168. package/dist/styles/list.css +11 -0
  169. package/dist/styles/nav-stack.css +89 -2
  170. package/dist/styles/pane.css +86 -1
  171. package/dist/styles/resizable-region.css +117 -5
  172. package/dist/styles/row.css +10 -0
  173. package/dist/styles/select.css +39 -7
  174. package/dist/styles/split-view.css +108 -2
  175. package/dist/styles/state-banner.css +0 -27
  176. package/dist/styles/styles.css +1 -0
  177. package/dist/styles/tab-bar.css +6 -1
  178. package/dist/styles/tab-scaffold.css +64 -1
  179. package/dist/styles/text.css +10 -0
  180. package/dist/styles/token-search-field.css +5 -40
  181. package/dist/styles/toolbar-control-group.css +198 -25
  182. package/dist/styles/toolbar-text.css +8 -1
  183. package/dist/styles/toolbar.css +169 -5
  184. package/dist/styles/webawesome.css +70 -9
  185. package/dist/styles/workbench.css +136 -4
  186. package/dist/sunken-panel.d.ts +3 -1
  187. package/dist/sunken-panel.js +1 -1
  188. package/dist/surface-scaffold.d.ts +6 -2
  189. package/dist/surface-scaffold.js +1 -1
  190. package/dist/tab-bar.d.ts +8 -1
  191. package/dist/tab-bar.js +1 -1
  192. package/dist/tab-scaffold.d.ts +3 -1
  193. package/dist/tab-scaffold.js +3 -1
  194. package/dist/tab-scaffold.js.map +1 -1
  195. package/dist/text.d.ts +9 -5
  196. package/dist/text.js +1 -1
  197. package/dist/token-search-field.d.ts +5 -1
  198. package/dist/token-search-field.js +1 -1
  199. package/dist/toolbar-control-group.d.ts +33 -3
  200. package/dist/toolbar-control-group.js +1 -1
  201. package/dist/toolbar-text.d.ts +3 -1
  202. package/dist/toolbar-text.js +1 -1
  203. package/dist/toolbar.d.ts +30 -1
  204. package/dist/toolbar.js +1 -1
  205. package/dist/types-CEsieBZi.d.ts +69 -0
  206. package/dist/value-table.d.ts +6 -2
  207. package/dist/value-table.js +1 -1
  208. package/dist/wire-resizable-regions.js +1 -1
  209. package/dist/wire-sidebar.d.ts +18 -3
  210. package/dist/wire-sidebar.js +95 -14
  211. package/dist/wire-sidebar.js.map +1 -1
  212. package/dist/wire-token-search-fields.js +1 -1
  213. package/dist/workbench.d.ts +3 -1
  214. package/dist/workbench.js +3 -1
  215. package/dist/workbench.js.map +1 -1
  216. package/docs/accessibility.md +56 -9
  217. package/docs/app-layouts.md +73 -0
  218. package/docs/catalog.md +48 -9
  219. package/docs/collapsible-panel.md +81 -8
  220. package/docs/component-contract.md +96 -28
  221. package/docs/component-integration.md +9 -4
  222. package/docs/component-selection.md +36 -15
  223. package/docs/design/templates/list/stack-dark.svg +1 -1
  224. package/docs/design/templates/list/stack.svg +1 -1
  225. package/docs/design/templates/list-dark.svg +1 -1
  226. package/docs/design/templates/list-header/action-dark.svg +1 -1
  227. package/docs/design/templates/list-header/action.svg +1 -1
  228. package/docs/design/templates/list-header/count-dark.svg +1 -1
  229. package/docs/design/templates/list-header/count.svg +1 -1
  230. package/docs/design/templates/list-header/inline-action-dark.svg +1 -1
  231. package/docs/design/templates/list-header/inline-action.svg +1 -1
  232. package/docs/design/templates/list-header/toggle-expanded-dark.svg +1 -1
  233. package/docs/design/templates/list-header/toggle-expanded.svg +1 -1
  234. package/docs/design/templates/list-header-dark.svg +1 -1
  235. package/docs/design/templates/list-header.svg +1 -1
  236. package/docs/design/templates/list.svg +1 -1
  237. package/docs/design/templates/state-banner/info-badge-dark.svg +1 -1
  238. package/docs/design/templates/state-banner/info-badge.svg +1 -1
  239. package/docs/design/templates/state-banner-dark.svg +1 -1
  240. package/docs/design/templates/state-banner.svg +1 -1
  241. package/docs/design/templates/toolbar/title-and-actions-dark.svg +1 -1
  242. package/docs/design/templates/toolbar/title-and-actions.svg +1 -1
  243. package/docs/design/templates/toolbar-control-group/with-text-dark.svg +1 -1
  244. package/docs/design/templates/toolbar-control-group/with-text.svg +1 -1
  245. package/docs/design/templates/toolbar-control-group-dark.svg +1 -1
  246. package/docs/design/templates/toolbar-control-group.svg +1 -1
  247. package/docs/design/templates/toolbar-dark.svg +1 -1
  248. package/docs/design/templates/toolbar-text/default-dark.svg +1 -1
  249. package/docs/design/templates/toolbar-text/default.svg +1 -1
  250. package/docs/design/templates/toolbar-text/large-dark.svg +1 -1
  251. package/docs/design/templates/toolbar-text/large.svg +1 -1
  252. package/docs/design/templates/toolbar-text/small-dark.svg +1 -1
  253. package/docs/design/templates/toolbar-text/small.svg +1 -1
  254. package/docs/design/templates/toolbar-text-dark.svg +1 -1
  255. package/docs/design/templates/toolbar-text.svg +1 -1
  256. package/docs/design/templates/toolbar.svg +1 -1
  257. package/docs/design-philosophy.md +6 -5
  258. package/docs/document-baseline.md +31 -0
  259. package/docs/layout.md +86 -21
  260. package/docs/nav-stack.md +8 -0
  261. package/docs/recipes.md +78 -43
  262. package/docs/split-view.md +8 -0
  263. package/docs/tab-scaffold.md +4 -2
  264. package/docs/type-contracts.md +21 -16
  265. package/docs/ui-analyzer.md +19 -0
  266. package/docs/ui-evaluator.md +17 -0
  267. package/docs/ux-demo.md +8 -8
  268. package/docs/webawesome-theme.md +25 -6
  269. package/docs/workbench.md +20 -1
  270. package/evaluator/index.mjs +73 -8
  271. package/llms.txt +61 -23
  272. package/package.json +12 -3
  273. package/ux-demo/recipes/app-shell.tsx +244 -184
  274. package/ux-demo/recipes/collapsible-sidebar.tsx +175 -116
  275. package/ux-demo/recipes/compact-toolbar.tsx +119 -102
  276. package/ux-demo/recipes/composer-form.tsx +79 -69
  277. package/ux-demo/recipes/list-detail-dialog.tsx +120 -136
  278. package/ux-demo/recipes/list-workspace-states.tsx +85 -79
  279. package/ux-demo/recipes/loaders.ts +5 -2
  280. package/ux-demo/recipes/loading-inspector.tsx +151 -134
  281. package/ux-demo/recipes/navigation-sidebar.tsx +93 -80
  282. package/ux-demo/recipes/navigation-stack.tsx +33 -22
  283. package/ux-demo/recipes/types.ts +14 -0
  284. package/ux-demo/recipes/workspace-header.tsx +73 -57
  285. package/dist/chunk-2TYUFZUC.js.map +0 -1
  286. package/dist/chunk-6NDBE2OK.js.map +0 -1
  287. package/dist/chunk-6WTETUZ6.js.map +0 -1
  288. package/dist/chunk-AQFWBG23.js.map +0 -1
  289. package/dist/chunk-B6JYRX3P.js.map +0 -1
  290. package/dist/chunk-CAB6NQ2T.js.map +0 -1
  291. package/dist/chunk-CK6P5AUK.js.map +0 -1
  292. package/dist/chunk-DAO2VFTT.js.map +0 -1
  293. package/dist/chunk-DYBPI5O2.js.map +0 -1
  294. package/dist/chunk-E34TE2ZI.js.map +0 -1
  295. package/dist/chunk-EYALJQQD.js.map +0 -1
  296. package/dist/chunk-GYGM363P.js.map +0 -1
  297. package/dist/chunk-I45QO2IZ.js.map +0 -1
  298. package/dist/chunk-I4V3UDSA.js.map +0 -1
  299. package/dist/chunk-IU4QUY5I.js.map +0 -1
  300. package/dist/chunk-OGNE3OFT.js.map +0 -1
  301. package/dist/chunk-OGTJNHRG.js.map +0 -1
  302. package/dist/chunk-OL4TC3U2.js.map +0 -1
  303. package/dist/chunk-OMSRSL3B.js.map +0 -1
  304. package/dist/chunk-SOK5EUF7.js.map +0 -1
  305. package/dist/chunk-T7DOWS6T.js.map +0 -1
  306. package/dist/chunk-TIGSG6BX.js.map +0 -1
  307. package/dist/chunk-UDHHKZWO.js.map +0 -1
  308. package/dist/chunk-V6GQKOX2.js.map +0 -1
  309. package/dist/chunk-V6HCTCVD.js.map +0 -1
  310. package/dist/chunk-VXFGMDA7.js.map +0 -1
  311. package/dist/chunk-W2FK7ZNY.js.map +0 -1
  312. package/dist/chunk-WN52USHV.js +0 -115
  313. package/dist/chunk-WN52USHV.js.map +0 -1
  314. package/dist/chunk-WSXUPSID.js.map +0 -1
  315. package/dist/chunk-WVLMZ5SG.js.map +0 -1
  316. package/dist/chunk-XKFRMGMW.js.map +0 -1
  317. package/dist/chunk-Y6LYKFXY.js.map +0 -1
  318. package/dist/chunk-ZPWZIVI6.js.map +0 -1
  319. package/ux-demo/recipes/recipes.css +0 -453
@@ -213,30 +213,7 @@
213
213
  margin-inline-start: 0.375rem;
214
214
  }
215
215
 
216
- .kui-toolbar-control-group:has(> .kui-token-search[data-collapsible="true"]) {
217
- width: min(var(--kui-token-search-expanded-width, 30rem), 100%);
218
- max-width: 100%;
219
- height: auto;
220
- min-width: 0;
221
- overflow: hidden;
222
- /* Same reason as the field above (KF-EPEM88): drive the inline size through
223
- `width`, not `flex-basis`, so a group placed in a flex column is not
224
- stretched to the expanded width in its cross axis. */
225
- flex: 0 1 auto;
226
- transition:
227
- width 0.25s ease,
228
- background-color 0.2s ease,
229
- border-color 0.2s ease;
230
- }
231
-
232
- .kui-toolbar-control-group[data-expanded="false"]:has(
233
- > .kui-token-search[data-collapsible="true"]
234
- ) {
235
- width: var(--kui-toolbar-group-size, calc(2px + 2.625rem));
236
- flex: 0 0 auto;
237
- }
238
-
239
- .kui-toolbar-control-group > .kui-token-search[data-collapsible="true"] {
216
+ .kui-token-search[data-presentation="toolbar-group"][data-collapsible="true"] {
240
217
  --kui-token-search-line-size: 2rem;
241
218
 
242
219
  min-height: 2.5rem;
@@ -250,14 +227,12 @@
250
227
  box-shadow: none;
251
228
  }
252
229
 
253
- .kui-toolbar-control-group
254
- > .kui-token-search[data-collapsible="true"]:focus-within {
230
+ .kui-token-search[data-presentation="toolbar-group"][data-collapsible="true"]:focus-within {
255
231
  border-color: var(--kui-color-focus);
256
232
  background: var(--kui-token-search-background);
257
233
  }
258
234
 
259
- .kui-toolbar-control-group
260
- > .kui-token-search[data-collapsible="true"][data-expanded="false"] {
235
+ .kui-token-search[data-presentation="toolbar-group"][data-collapsible="true"][data-expanded="false"] {
261
236
  width: 2.5rem;
262
237
  min-width: 2.5rem;
263
238
  height: 2.5rem;
@@ -265,23 +240,13 @@
265
240
  padding: 0;
266
241
  }
267
242
 
268
- .kui-toolbar-control-group
269
- > .kui-token-search[data-collapsible="true"][data-expanded="false"]
243
+ .kui-token-search[data-presentation="toolbar-group"][data-collapsible="true"][data-expanded="false"]
270
244
  .kui-token-search__expand {
271
245
  padding-inline: 0;
272
246
  }
273
247
 
274
- .kui-toolbar-control-group:has(
275
- > .kui-token-search[data-collapsible="true"]
276
- ):focus-within {
277
- border-color: var(--kui-color-text-link);
278
- box-shadow: 0 0 0 3px
279
- color-mix(in srgb, var(--kui-color-text-link) 22%, transparent);
280
- }
281
-
282
248
  @media (prefers-reduced-motion: reduce) {
283
- .kui-token-search[data-collapsible="true"],
284
- .kui-toolbar-control-group:has(> .kui-token-search[data-collapsible="true"]) {
249
+ .kui-token-search[data-collapsible="true"] {
285
250
  transition-duration: 0s;
286
251
  }
287
252
  }
@@ -21,6 +21,15 @@
21
21
  )
22
22
  );
23
23
  --kui-toolbar-item-radius: var(--kui-control-highlight-radius);
24
+ /* Internal group-to-child contract: the control slot a composed child (an
25
+ icon-only Select) fills so it is inset evenly on every side and the
26
+ group-owned focus ring stays concentric with the visible control. The
27
+ group sizes to the child's width. A default slot is 40px tall inside the
28
+ 2px inset; a compact slot is the full 32px padding box, and a lone
29
+ compact child also overlaps the 1px inline padding. */
30
+ --_kui-toolbar-slot-height: 2.5rem;
31
+ --_kui-toolbar-slot-overlap: 0px;
32
+ --_kui-toolbar-slot-radius: var(--kui-toolbar-item-radius);
24
33
  display: inline-flex;
25
34
  height: var(--kui-toolbar-group-size, calc(2px + 2.625rem));
26
35
  min-width: var(--kui-toolbar-group-size, calc(2px + 2.625rem));
@@ -35,6 +44,16 @@
35
44
  gap: 0;
36
45
  }
37
46
 
47
+ .kui-toolbar-control-group[data-visibility="compact-only"] {
48
+ display: none;
49
+ }
50
+
51
+ @container kui-toolbar (max-width: 44rem) {
52
+ .kui-toolbar-control-group[data-visibility="compact-only"] {
53
+ display: inline-flex;
54
+ }
55
+ }
56
+
38
57
  /* `shape="rounded"` swaps the default pill radius for the design system's softer
39
58
  rounded rectangle. The shared highlight contract derives every inner hover or
40
59
  selected surface from this outer radius and the group's full inset. */
@@ -61,18 +80,59 @@
61
80
  }
62
81
  .kui-toolbar-control-group[data-size="compact"] {
63
82
  --kui-toolbar-group-size: 2.125rem;
83
+ --_kui-toolbar-slot-height: 2rem;
84
+ --_kui-toolbar-slot-overlap: 1px;
85
+ --_kui-toolbar-slot-radius: max(
86
+ 0px,
87
+ calc(var(--kui-toolbar-group-radius) - 1px)
88
+ );
89
+ gap: 4px; /* Compensating for -2px margins */
64
90
  }
65
91
  .kui-toolbar-control-group[data-density="tight"] {
66
92
  --kui-layout-item-padding: 0.3125rem;
67
93
  }
68
- .kui-toolbar-control-group[data-content="text"] > :is(button, wa-button),
69
- .kui-toolbar-control-group[data-content="mixed"] > :is(button, wa-button) {
94
+ .kui-toolbar-control-group[data-overflow="scroll"] {
95
+ max-width: 100%;
96
+ overflow-x: auto;
97
+ }
98
+ .kui-toolbar-control-group[data-content="search"] {
99
+ width: min(var(--kui-token-search-expanded-width, 30rem), 100%);
100
+ max-width: 100%;
101
+ height: auto;
102
+ min-width: 0;
103
+ overflow: hidden;
104
+ flex: 0 1 auto;
105
+ transition:
106
+ width 0.25s ease,
107
+ background-color 0.2s ease,
108
+ border-color 0.2s ease;
109
+ }
110
+ .kui-toolbar-control-group[data-content="search"][data-expanded="false"] {
111
+ width: var(--kui-toolbar-group-size, calc(2px + 2.625rem));
112
+ flex: 0 0 auto;
113
+ }
114
+ .kui-toolbar-control-group[data-content="text"]
115
+ > :is(button, wa-button, .kui-toolbar-action-link),
116
+ .kui-toolbar-control-group[data-content="mixed"]
117
+ > :is(button, wa-button, .kui-toolbar-action-link) {
70
118
  min-width: max-content;
71
119
  }
72
120
  .kui-toolbar-control-group[data-content="mixed"] > button {
73
121
  display: flex;
74
122
  gap: var(--kui-space-xs);
75
123
  }
124
+ .kui-toolbar-control-group[data-content="mixed"] wa-button {
125
+ line-height: normal;
126
+ }
127
+ /* Toolbar controls never wrap. Web Awesome's label part is a plain block, so a
128
+ slotted icon (a block SVG) and its text would otherwise stack vertically —
129
+ lay them out on one row the way native mixed buttons already are. */
130
+ .kui-toolbar-control-group wa-button::part(label) {
131
+ display: inline-flex;
132
+ align-items: center;
133
+ gap: var(--kui-space-xs);
134
+ white-space: nowrap;
135
+ }
76
136
  .kui-toolbar-control-group[data-content="avatar"][data-scrim="true"] {
77
137
  --kui-toolbar-control-background: color-mix(
78
138
  in srgb,
@@ -123,7 +183,8 @@
123
183
  background: transparent;
124
184
  }
125
185
 
126
- .kui-toolbar-control-group > :is(button, wa-button, wa-dropdown) {
186
+ .kui-toolbar-control-group
187
+ > :is(button, wa-button, wa-dropdown, .kui-toolbar-action-link) {
127
188
  flex: 0 0 auto;
128
189
  }
129
190
  .kui-toolbar-control-group > wa-dropdown {
@@ -154,13 +215,62 @@
154
215
  background: var(--kui-toolbar-control-hover-background);
155
216
  }
156
217
 
218
+ .kui-toolbar-control-group > .kui-toolbar-action-link {
219
+ position: relative;
220
+ display: inline-flex;
221
+ min-width: 2.5rem;
222
+ height: 2.5rem;
223
+ padding-inline: var(--kui-layout-item-padding, 0.5rem);
224
+ box-sizing: border-box;
225
+ border: 1px solid transparent;
226
+ border-radius: var(
227
+ --kui-toolbar-item-radius,
228
+ var(--kui-layout-pill-radius, calc(1px + 1.3125rem))
229
+ );
230
+ color: inherit;
231
+ background: transparent;
232
+ align-items: center;
233
+ justify-content: center;
234
+ gap: var(--kui-space-2xs);
235
+ text-decoration: none;
236
+ white-space: nowrap;
237
+ }
238
+
239
+ .kui-toolbar-control-group > .kui-toolbar-action-link:hover {
240
+ border-color: var(--kui-toolbar-control-border);
241
+ background: var(--kui-toolbar-control-hover-background);
242
+ }
243
+
244
+ .kui-toolbar-action-link code {
245
+ position: absolute;
246
+ inset-block-start: 0;
247
+ inset-inline-start: 0;
248
+ width: 1px;
249
+ height: 1px;
250
+ padding: 0;
251
+ overflow: hidden;
252
+ border: 0;
253
+ clip-path: inset(50%);
254
+ white-space: nowrap;
255
+ }
256
+
157
257
  .kui-toolbar-control-group > button svg,
158
- .kui-toolbar-control-group wa-button > svg {
258
+ .kui-toolbar-control-group wa-button > svg,
259
+ .kui-toolbar-control-group > .kui-toolbar-action-link svg {
159
260
  display: block;
160
261
  width: 1rem;
161
262
  height: 1rem;
162
263
  }
163
264
 
265
+ /* Nested Web Awesome buttons take the group's control height, not the theme's
266
+ 44px standalone control height. */
267
+ .kui-toolbar-control-group wa-button {
268
+ --wa-form-control-height: 2.5rem;
269
+ }
270
+ .kui-toolbar-control-group[data-size="compact"] wa-button {
271
+ --wa-form-control-height: 2rem;
272
+ }
273
+
164
274
  .kui-toolbar-control-group > wa-button,
165
275
  .kui-toolbar-control-group > wa-dropdown,
166
276
  .kui-toolbar-control-group > wa-dropdown > wa-button,
@@ -169,6 +279,7 @@
169
279
  height: 2.5rem;
170
280
  }
171
281
  .kui-toolbar-control-group[data-size="compact"] > button,
282
+ .kui-toolbar-control-group[data-size="compact"] > .kui-toolbar-action-link,
172
283
  .kui-toolbar-control-group[data-size="compact"] > wa-button,
173
284
  .kui-toolbar-control-group[data-size="compact"] > wa-dropdown,
174
285
  .kui-toolbar-control-group[data-size="compact"] > wa-dropdown > wa-button,
@@ -186,6 +297,24 @@
186
297
  min-height: 2rem;
187
298
  }
188
299
 
300
+ /* A compact icon button is a 32px circle like its compact wa-button and
301
+ Select siblings; the default 8px inline padding around a 16px icon made its
302
+ selected highlight a 34x32 oval. */
303
+ .kui-toolbar-control-group[data-size="compact"][data-content="icon"] > button {
304
+ padding-inline: 0;
305
+ }
306
+
307
+ .kui-toolbar-control-group[data-menu-inset="standard"] wa-dropdown::part(menu) {
308
+ padding: var(--kui-wa-surface-inset, 0.5rem);
309
+ }
310
+ .kui-toolbar-control-group[data-menu-inset="compact"] wa-dropdown::part(menu) {
311
+ padding: 0.25rem;
312
+ }
313
+ .kui-toolbar-control-group[data-menu-inset="list-zero"]
314
+ wa-dropdown::part(menu) {
315
+ padding: 0;
316
+ }
317
+
189
318
  /* Compact mixed controls keep the default horizontal breathing room. Their
190
319
  raised selection grows over the group's own border instead of becoming a
191
320
  smaller inset lozenge, while negative margins keep the outer geometry and
@@ -202,6 +331,13 @@
202
331
  border-radius: var(--kui-toolbar-group-radius);
203
332
  }
204
333
 
334
+ .kui-toolbar-control-group[data-size="compact"][data-content="mixed"]
335
+ > wa-dropdown,
336
+ .kui-toolbar-control-group[data-size="compact"][data-content="mixed"]
337
+ > wa-button {
338
+ margin: -2px;
339
+ }
340
+
205
341
  /* A compact icon-only trigger may stay square, but a mixed-content dropdown
206
342
  trigger must grow for its slotted label plus Web Awesome's caret. Otherwise
207
343
  the fixed 32px base centers both outside its host, painting the label across
@@ -216,20 +352,14 @@
216
352
  }
217
353
  .kui-toolbar-control-group[data-content="mixed"][data-nested-dropdown="true"]
218
354
  > wa-dropdown
219
- > wa-button {
220
- /* WebKit does not contribute a custom element's shadow-part caret to the
221
- host's intrinsic inline size. Give the standard short text trigger an
222
- engine-stable floor; max-content still wins for longer light-DOM labels,
223
- and consumers can raise the public variable for localized copy. */
224
- width: var(--kui-toolbar-dropdown-trigger-width, 4.125rem);
355
+ > wa-button::part(base) {
356
+ width: max-content;
225
357
  }
226
358
 
227
- .kui-toolbar-control-group[data-single="true"] > wa-dropdown,
228
- .kui-toolbar-control-group[data-single="true"] > wa-dropdown > wa-button,
229
359
  .kui-toolbar-control-group[data-single="true"]
230
360
  > wa-dropdown
231
361
  > wa-button::part(base) {
232
- width: 3rem;
362
+ width: max-content;
233
363
  }
234
364
 
235
365
  .kui-toolbar-control-group wa-button {
@@ -260,12 +390,13 @@
260
390
  }
261
391
 
262
392
  .kui-toolbar-control-group[data-single="true"]:has(
263
- > :is(button, wa-button, wa-dropdown)
393
+ > :is(button, wa-button, wa-dropdown, wa-select, .kui-toolbar-action-link)
264
394
  ):hover {
265
395
  background-color: var(--kui-toolbar-control-hover-background);
266
396
  }
267
397
 
268
- .kui-toolbar-control-group[data-single="true"] > :is(button, wa-button):hover,
398
+ .kui-toolbar-control-group[data-single="true"]
399
+ > :is(button, wa-button, .kui-toolbar-action-link):hover,
269
400
  .kui-toolbar-control-group[data-single="true"] wa-button:hover::part(base) {
270
401
  border-color: transparent;
271
402
  background: transparent;
@@ -276,15 +407,15 @@
276
407
  inner layer inset from the border (KF-J9P1ZD — a heading toolbar's lone Close/
277
408
  Done action). */
278
409
  .kui-toolbar-control-group:not([data-single="true"]):has(
279
- > :is(button, wa-button):only-child
410
+ > :is(button, wa-button, wa-select, .kui-toolbar-action-link):only-child
280
411
  ):hover {
281
412
  background-color: var(--kui-toolbar-control-hover-background);
282
413
  }
283
414
 
284
415
  .kui-toolbar-control-group:not([data-single="true"]):has(
285
- > :is(button, wa-button):only-child
416
+ > :is(button, wa-button, .kui-toolbar-action-link):only-child
286
417
  )
287
- > :is(button, wa-button):hover,
418
+ > :is(button, wa-button, .kui-toolbar-action-link):hover,
288
419
  .kui-toolbar-control-group:not([data-single="true"]):has(
289
420
  > :is(button, wa-button):only-child
290
421
  )
@@ -293,6 +424,15 @@
293
424
  background: transparent;
294
425
  }
295
426
 
427
+ /* A toolbar Select beside other controls highlights its own pill on hover,
428
+ like its button and dropdown siblings; a lone Select instead lifts the whole
429
+ group (above). */
430
+ .kui-toolbar-control-group:not([data-single="true"])
431
+ > wa-select:not(:only-child):hover::part(combobox) {
432
+ border-color: var(--kui-toolbar-control-border);
433
+ background: var(--kui-toolbar-control-hover-background);
434
+ }
435
+
296
436
  /* A plain <button> child paints its own box for the selected state. */
297
437
  .kui-toolbar-control-group[data-single="false"] > button[aria-pressed="true"] {
298
438
  border-color: var(--kui-toolbar-control-selected-border);
@@ -317,21 +457,48 @@
317
457
  box-shadow: var(--kui-toolbar-control-selected-shadow);
318
458
  }
319
459
 
320
- .kui-toolbar-control-group > :is(button, wa-button):focus-visible {
460
+ .kui-toolbar-control-group
461
+ > :is(button, wa-button, .kui-toolbar-action-link):focus-visible {
462
+ outline: var(--kui-focus-ring);
463
+ outline-offset: 1px;
464
+ }
465
+
466
+ /* With per-control rings, a composed Select paints its own ring even when it
467
+ was told the group owns it: nothing else would show focus. It matches the
468
+ sibling controls' ring and offset. */
469
+ .kui-toolbar-control-group[data-focus-ring="control"]
470
+ > wa-select:focus-within::part(combobox) {
471
+ outline: var(--kui-focus-ring);
472
+ outline-offset: 1px;
473
+ }
474
+
475
+ .kui-toolbar-control-group[data-focus-ring="outline"]:focus-within {
321
476
  outline: var(--kui-focus-ring);
322
477
  outline-offset: 1px;
323
478
  }
324
479
 
325
- /* A composed Select can delegate focus paint to the group so the visible ring
326
- follows the group's selected pill/rounded geometry instead of Web Awesome's
327
- form-control radius. */
328
- .kui-toolbar-control-group:has(
329
- > .kui-select[data-focus-ring-owner="group"]:is(:focus-within, [open])
330
- ) {
480
+ .kui-toolbar-control-group[data-focus-ring="halo"]:focus-within {
481
+ border-color: var(--kui-color-text-link);
482
+ box-shadow: 0 0 0 3px
483
+ color-mix(in srgb, var(--kui-color-text-link) 22%, transparent);
484
+ }
485
+
486
+ /* Chromium and WebKit do not propagate :focus-within from a focused
487
+ light-DOM child (an open wa-select's active wa-option) through the host's
488
+ popup shadow tree, so the group ring vanished while its Select listbox was
489
+ open. A focused light-DOM descendant still owns the group ring. Kept as
490
+ separate rules so an engine without :has() keeps the :focus-within ring. */
491
+ .kui-toolbar-control-group[data-focus-ring="outline"]:has(:focus) {
331
492
  outline: var(--kui-focus-ring);
332
493
  outline-offset: 1px;
333
494
  }
334
495
 
496
+ .kui-toolbar-control-group[data-focus-ring="halo"]:has(:focus) {
497
+ border-color: var(--kui-color-text-link);
498
+ box-shadow: 0 0 0 3px
499
+ color-mix(in srgb, var(--kui-color-text-link) 22%, transparent);
500
+ }
501
+
335
502
  .kui-toolbar-control-group[data-button-appearance="push"][data-single="true"]:has(
336
503
  > :is(button, wa-button)[aria-pressed="true"]
337
504
  ) {
@@ -346,6 +513,12 @@
346
513
  color: var(--kui-toolbar-control-pressed-color);
347
514
  }
348
515
 
516
+ @media (prefers-reduced-motion: reduce) {
517
+ .kui-toolbar-control-group[data-content="search"] {
518
+ transition-duration: 0s;
519
+ }
520
+ }
521
+
349
522
  /* Avatar controls paint the image as chrome rather than inserting a replaced
350
523
  <img> into the control. `background-size: contain` is the background-image
351
524
  equivalent of `object-fit: contain`: the whole avatar remains visible. A
@@ -18,6 +18,10 @@
18
18
  min-width: 0;
19
19
  max-width: 100%;
20
20
  overflow: hidden;
21
+ /* Keep the line box larger than the font's em square. Glyph ink can extend
22
+ below a 1em line box, so clipping for ellipsis must not also shave off
23
+ descenders such as g, j, p, q, and y. */
24
+ line-height: 1.2;
21
25
  white-space: nowrap;
22
26
  text-overflow: ellipsis;
23
27
  }
@@ -42,8 +46,11 @@
42
46
  font-size: var(--kui-font-s);
43
47
  }
44
48
 
49
+ /* Every size keeps the inherited UI sans stack: compact identity text is a
50
+ label, not code. (A monospace role here resolved through Web Awesome's
51
+ `ui-monospace, monospace` code stack; Chromium does not
52
+ recognize `ui-monospace`, so small labels fell back to generic monospace.) */
45
53
  .kui-toolbar-text[data-size="small"] {
46
- font-family: var(--kui-font-mono);
47
54
  font-size: var(--kui-font-xs);
48
55
  }
49
56
 
@@ -1,11 +1,7 @@
1
1
  .kui-toolbar {
2
2
  display: grid;
3
3
  width: 100%;
4
- min-height: calc(
5
- var(--kui-toolbar-group-size, calc(2px + 2.625rem)) +
6
- (2 * var(--kui-toolbar-gap, 0.5rem))
7
- );
8
- padding: var(--kui-toolbar-gap, 0.5rem);
4
+ /* min-height and padding: see the safe-area rules below. */
9
5
  box-sizing: border-box;
10
6
  color: var(--kui-color-text);
11
7
  background: transparent;
@@ -16,6 +12,78 @@
16
12
  font-family: var(--kui-font-sans);
17
13
  }
18
14
 
15
+ /* Safe areas: a toolbar compensates only for the inline edges its owner hands
16
+ it through `--kui-edge-inset-inline-*` (a Pane header or footer does), so its
17
+ box and dividers keep reaching the edge while its zones clear the unsafe
18
+ area. Unset means none: a toolbar embedded in content never pads for the
19
+ device. An app bar or bottom bar at a screen edge claims its sides with
20
+ `safeAreaEdges`; each claimed side pads by the routed edge context, or the
21
+ full device inset when nothing routes it (the Pane rule), so the top bar of
22
+ a shell clears the status area. A Pane header or footer clears the context
23
+ for its children, so a claimed side there never double-insets. Its zones
24
+ then see a cleared context. */
25
+ .kui-toolbar {
26
+ --_kui-toolbar-safe-block-start: 0px;
27
+ --_kui-toolbar-safe-block-end: 0px;
28
+ --_kui-toolbar-safe-inline-start: var(--kui-edge-inset-inline-start, 0px);
29
+ --_kui-toolbar-safe-inline-end: var(--kui-edge-inset-inline-end, 0px);
30
+ /* The minimum height grows by any claimed block inset, so a toolbar a flex
31
+ column shrinks still keeps a whole control row clear of the unsafe area. */
32
+ min-height: calc(
33
+ var(--kui-toolbar-group-size, calc(2px + 2.625rem)) +
34
+ (2 * var(--kui-toolbar-gap, 0.5rem)) +
35
+ var(--_kui-toolbar-safe-block-start) + var(--_kui-toolbar-safe-block-end)
36
+ );
37
+ padding-block: calc(
38
+ var(--kui-toolbar-gap, 0.5rem) + var(--_kui-toolbar-safe-block-start)
39
+ )
40
+ calc(
41
+ var(--kui-toolbar-gap, 0.5rem) + var(--_kui-toolbar-safe-block-end)
42
+ );
43
+ padding-inline: calc(
44
+ var(--kui-toolbar-gap, 0.5rem) +
45
+ var(--_kui-toolbar-safe-inline-start)
46
+ )
47
+ calc(
48
+ var(--kui-toolbar-gap, 0.5rem) + var(--_kui-toolbar-safe-inline-end)
49
+ );
50
+ }
51
+
52
+ .kui-toolbar[data-safe-area-block-start="true"] {
53
+ --_kui-toolbar-safe-block-start: var(
54
+ --kui-edge-inset-block-start,
55
+ var(--kui-safe-area-block-start, env(safe-area-inset-top, 0px))
56
+ );
57
+ }
58
+
59
+ .kui-toolbar[data-safe-area-block-end="true"] {
60
+ --_kui-toolbar-safe-block-end: var(
61
+ --kui-edge-inset-block-end,
62
+ var(--kui-safe-area-block-end, env(safe-area-inset-bottom, 0px))
63
+ );
64
+ }
65
+
66
+ .kui-toolbar[data-safe-area-inline-start="true"] {
67
+ --_kui-toolbar-safe-inline-start: var(
68
+ --kui-edge-inset-inline-start,
69
+ var(--kui-safe-area-inline-start, env(safe-area-inset-left, 0px))
70
+ );
71
+ }
72
+
73
+ .kui-toolbar[data-safe-area-inline-end="true"] {
74
+ --_kui-toolbar-safe-inline-end: var(
75
+ --kui-edge-inset-inline-end,
76
+ var(--kui-safe-area-inline-end, env(safe-area-inset-right, 0px))
77
+ );
78
+ }
79
+
80
+ .kui-toolbar > * {
81
+ --kui-edge-inset-block-start: 0px;
82
+ --kui-edge-inset-block-end: 0px;
83
+ --kui-edge-inset-inline-start: 0px;
84
+ --kui-edge-inset-inline-end: 0px;
85
+ }
86
+
19
87
  .kui-toolbar[data-has-center="false"] {
20
88
  grid-template-columns: minmax(0, 1fr) auto;
21
89
  }
@@ -85,9 +153,47 @@
85
153
  grid-column: 2;
86
154
  }
87
155
 
156
+ .kui-toolbar[data-center-align="stretch"] > .kui-toolbar__center {
157
+ justify-content: flex-start;
158
+ }
159
+
160
+ .kui-toolbar[data-center-align="stretch"] > .kui-toolbar__center > * {
161
+ width: 100%;
162
+ flex-basis: 100%;
163
+ }
164
+
88
165
  .kui-toolbar__trailing {
89
166
  justify-content: flex-end;
90
167
  grid-column: -2 / -1;
168
+ /* Trailing actions never clip (KF-4EYES0): the zone wraps its groups, so its
169
+ track can shrink only to the widest single group. When one row cannot hold
170
+ every group, the next group moves to a new trailing-aligned row instead of
171
+ overflowing the toolbar. */
172
+ flex-wrap: wrap;
173
+ }
174
+
175
+ /* Content-driven wrap: one row while every zone fits at its natural width;
176
+ otherwise the trailing zone moves below the identity, still trailing-aligned,
177
+ instead of truncating the leading title or clipping an action. For panel,
178
+ inspector, and dialog headings whose identity must stay whole. */
179
+ .kui-toolbar[data-responsive="wrap"] {
180
+ display: flex;
181
+ flex-wrap: wrap;
182
+ }
183
+
184
+ .kui-toolbar[data-responsive="wrap"] > .kui-toolbar__leading {
185
+ max-width: 100%;
186
+ flex: 1 1 auto;
187
+ }
188
+
189
+ .kui-toolbar[data-responsive="wrap"] > .kui-toolbar__center {
190
+ flex: 1 1 auto;
191
+ }
192
+
193
+ .kui-toolbar[data-responsive="wrap"] > .kui-toolbar__trailing {
194
+ max-width: 100%;
195
+ flex: 0 1 auto;
196
+ margin-inline-start: auto;
91
197
  }
92
198
 
93
199
  .kui-toolbar[data-has-center="false"] .kui-toolbar__center,
@@ -95,3 +201,61 @@
95
201
  .kui-toolbar__trailing:empty {
96
202
  display: none;
97
203
  }
204
+
205
+ /* Stacked topology. A container query only matches an ancestor container, so
206
+ these rules style the zones (whose query container is this toolbar) rather
207
+ than the toolbar's own grid template, which a self query can never reach.
208
+ Each zone spans every column track, one zone per row, so no empty track or
209
+ column gap narrows a stacked zone. Stacked control zones wrap at group
210
+ granularity (KF-4EYES0: a stacked trailing zone clipped its last action at
211
+ phone widths), so every group stays whole, reachable, and full size; the
212
+ leading identity keeps its single-line truncation. */
213
+ @container kui-toolbar (max-width: 52rem) {
214
+ .kui-toolbar[data-responsive="stack"][data-responsive-at="narrow"]
215
+ > :is(.kui-toolbar__leading, .kui-toolbar__center, .kui-toolbar__trailing) {
216
+ width: 100%;
217
+ grid-column: 1 / -1;
218
+ justify-content: flex-start;
219
+ }
220
+
221
+ .kui-toolbar[data-responsive="stack"][data-responsive-at="narrow"]
222
+ > :is(.kui-toolbar__center, .kui-toolbar__trailing) {
223
+ flex-wrap: wrap;
224
+ }
225
+ }
226
+
227
+ @container kui-toolbar (max-width: 44rem) {
228
+ .kui-toolbar[data-responsive="stack"][data-responsive-at="compact"]
229
+ > :is(.kui-toolbar__leading, .kui-toolbar__center, .kui-toolbar__trailing) {
230
+ width: 100%;
231
+ grid-column: 1 / -1;
232
+ justify-content: flex-start;
233
+ }
234
+
235
+ .kui-toolbar[data-responsive="stack"][data-responsive-at="compact"]
236
+ > :is(.kui-toolbar__center, .kui-toolbar__trailing) {
237
+ flex-wrap: wrap;
238
+ }
239
+ }
240
+
241
+ /* Center priority. As with the stacked topology, the toolbar cannot query its
242
+ own width, so these rules style the zones: while the center holds an expanded
243
+ control, the leading and trailing zones leave and the center spans every
244
+ column track (including the gaps the vacated tracks still own), taking the
245
+ whole row. */
246
+ @container kui-toolbar (max-width: 42rem) {
247
+ .kui-toolbar[data-responsive="center-priority"]:has(
248
+ > .kui-toolbar__center [data-expanded="true"]
249
+ )
250
+ > .kui-toolbar__center {
251
+ width: 100%;
252
+ grid-column: 1 / -1;
253
+ }
254
+
255
+ .kui-toolbar[data-responsive="center-priority"]:has(
256
+ > .kui-toolbar__center [data-expanded="true"]
257
+ )
258
+ > :is(.kui-toolbar__leading, .kui-toolbar__trailing) {
259
+ display: none;
260
+ }
261
+ }