@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
@@ -2,34 +2,158 @@
2
2
  to zero (one reflow, no per-frame width/height animation) while the fixed-size
3
3
  content slides out via transform (composited, clipped by overflow). The same
4
4
  technique as Workbench and the catalog sidebar (docs/18). */
5
+ /* Safe areas: the panel docks to one screen edge, so its surface grows by
6
+ that edge's unsafe inset and its content compensates for every edge the
7
+ panel still touches, never its interior edge. An expanded inline panel also
8
+ takes its edge away from its direct siblings; collapsing it hands the edge
9
+ back. A panel wrapped in an app-owned grid cell cannot see its siblings, so
10
+ that app routes `--kui-edge-inset-*` itself (docs/app-layouts.md). */
5
11
  .kui-collapsible-panel {
12
+ --_kui-collapsible-panel-safe-block-start: var(
13
+ --kui-edge-inset-block-start,
14
+ var(--kui-safe-area-block-start, env(safe-area-inset-top, 0px))
15
+ );
16
+ --_kui-collapsible-panel-safe-block-end: var(
17
+ --kui-edge-inset-block-end,
18
+ var(--kui-safe-area-block-end, env(safe-area-inset-bottom, 0px))
19
+ );
20
+ --_kui-collapsible-panel-safe-inline-start: var(
21
+ --kui-edge-inset-inline-start,
22
+ var(--kui-safe-area-inline-start, env(safe-area-inset-left, 0px))
23
+ );
24
+ --_kui-collapsible-panel-safe-inline-end: var(
25
+ --kui-edge-inset-inline-end,
26
+ var(--kui-safe-area-inline-end, env(safe-area-inset-right, 0px))
27
+ );
6
28
  overflow: hidden;
7
29
  background: var(--kui-color-surface);
8
30
  }
9
31
 
10
32
  .kui-collapsible-panel--left,
11
33
  .kui-collapsible-panel--right {
12
- width: var(--kui-collapsible-panel-width, 17.5rem);
34
+ width: var(--_kui-collapsible-panel-extent);
13
35
  min-width: 0;
14
36
  height: 100%;
15
37
  }
16
38
 
17
39
  .kui-collapsible-panel--left {
40
+ --_kui-collapsible-panel-extent: calc(
41
+ var(--kui-collapsible-panel-width, 17.5rem) +
42
+ var(--_kui-collapsible-panel-safe-inline-start)
43
+ );
18
44
  border-inline-end: 1px solid var(--kui-color-border);
19
45
  }
20
46
 
21
47
  .kui-collapsible-panel--right {
48
+ --_kui-collapsible-panel-extent: calc(
49
+ var(--kui-collapsible-panel-width, 17.5rem) +
50
+ var(--_kui-collapsible-panel-safe-inline-end)
51
+ );
22
52
  border-inline-start: 1px solid var(--kui-color-border);
23
53
  }
24
54
 
25
55
  .kui-collapsible-panel--bottom {
56
+ --_kui-collapsible-panel-extent: calc(
57
+ var(--kui-collapsible-panel-height, 13.75rem) +
58
+ var(--_kui-collapsible-panel-safe-block-end)
59
+ );
26
60
  position: relative;
27
61
  width: 100%;
28
- height: var(--kui-collapsible-panel-height, 13.75rem);
62
+ height: var(--_kui-collapsible-panel-extent);
29
63
  min-height: 0;
30
64
  border-block-start: 1px solid var(--kui-color-border);
31
65
  }
32
66
 
67
+ /* The panel's content sees the edges it touches; its interior edge is clear. */
68
+ .kui-collapsible-panel > .kui-collapsible-panel__content {
69
+ --kui-edge-inset-block-start: var(--_kui-collapsible-panel-safe-block-start);
70
+ --kui-edge-inset-block-end: var(--_kui-collapsible-panel-safe-block-end);
71
+ --kui-edge-inset-inline-start: var(
72
+ --_kui-collapsible-panel-safe-inline-start
73
+ );
74
+ --kui-edge-inset-inline-end: var(--_kui-collapsible-panel-safe-inline-end);
75
+ }
76
+
77
+ .kui-collapsible-panel--left > .kui-collapsible-panel__content {
78
+ --kui-edge-inset-inline-end: 0px;
79
+ }
80
+
81
+ .kui-collapsible-panel--right > .kui-collapsible-panel__content {
82
+ --kui-edge-inset-inline-start: 0px;
83
+ }
84
+
85
+ .kui-collapsible-panel--bottom > .kui-collapsible-panel__content {
86
+ --kui-edge-inset-block-start: 0px;
87
+ }
88
+
89
+ /* Content whose only child is a Pane or layout lets that child own the insets;
90
+ anything else is padded here and sees a cleared context. */
91
+ .kui-collapsible-panel__content:not(
92
+ :has(
93
+ > :is(
94
+ [data-component="pane"],
95
+ [data-component="nav-stack"],
96
+ [data-component="split-view"],
97
+ [data-component="workbench"],
98
+ [data-component="tab-scaffold"]
99
+ ):only-child
100
+ )
101
+ ) {
102
+ padding-block: var(--kui-edge-inset-block-start)
103
+ var(--kui-edge-inset-block-end);
104
+ padding-inline: var(--kui-edge-inset-inline-start)
105
+ var(--kui-edge-inset-inline-end);
106
+ }
107
+
108
+ .kui-collapsible-panel__content:not(
109
+ :has(
110
+ > :is(
111
+ [data-component="pane"],
112
+ [data-component="nav-stack"],
113
+ [data-component="split-view"],
114
+ [data-component="workbench"],
115
+ [data-component="tab-scaffold"]
116
+ ):only-child
117
+ )
118
+ )
119
+ > * {
120
+ --kui-edge-inset-block-start: 0px;
121
+ --kui-edge-inset-block-end: 0px;
122
+ --kui-edge-inset-inline-start: 0px;
123
+ --kui-edge-inset-inline-end: 0px;
124
+ }
125
+
126
+ /* An expanded inline panel is the region at its edge, so its direct siblings
127
+ no longer reach that edge. */
128
+ .kui-collapsible-panel--left[data-presentation="inline"]:not(
129
+ [data-collapsed="true"],
130
+ [data-collapsible-overlay="true"] *,
131
+ [data-collapsible-responsive="hidden"] *
132
+ )
133
+ ~ * {
134
+ --kui-edge-inset-inline-start: 0px;
135
+ }
136
+
137
+ :has(
138
+ ~ .kui-collapsible-panel--right[data-presentation="inline"]:not(
139
+ [data-collapsed="true"],
140
+ [data-collapsible-overlay="true"] *,
141
+ [data-collapsible-responsive="hidden"] *
142
+ )
143
+ ) {
144
+ --kui-edge-inset-inline-end: 0px;
145
+ }
146
+
147
+ :has(
148
+ ~ .kui-collapsible-panel--bottom[data-presentation="inline"]:not(
149
+ [data-collapsed="true"],
150
+ [data-collapsible-overlay="true"] *,
151
+ [data-collapsible-responsive="hidden"] *
152
+ )
153
+ ) {
154
+ --kui-edge-inset-block-end: 0px;
155
+ }
156
+
33
157
  .kui-collapsible-panel[data-collapsed="true"] {
34
158
  border: 0;
35
159
  }
@@ -65,7 +189,7 @@
65
189
 
66
190
  .kui-collapsible-panel--left .kui-collapsible-panel__content,
67
191
  .kui-collapsible-panel--right .kui-collapsible-panel__content {
68
- width: var(--kui-collapsible-panel-width, 17.5rem);
192
+ width: var(--_kui-collapsible-panel-extent);
69
193
  }
70
194
 
71
195
  .kui-collapsible-panel--bottom .kui-collapsible-panel__content {
@@ -73,7 +197,7 @@
73
197
  inset-inline: 0;
74
198
  inset-block-end: 0;
75
199
  width: 100%;
76
- height: var(--kui-collapsible-panel-height, 13.75rem);
200
+ height: var(--_kui-collapsible-panel-extent);
77
201
  }
78
202
 
79
203
  .kui-collapsible-panel[data-collapse-motion="none"]
@@ -164,9 +288,13 @@
164
288
  );
165
289
  }
166
290
 
291
+ /* A button does not stretch between its insets the way a div does, so the
292
+ backdrop sizes itself to its containing block explicitly. */
167
293
  .kui-collapsible-panel__backdrop {
168
294
  position: fixed;
169
295
  inset: 0;
296
+ width: 100%;
297
+ height: 100%;
170
298
  z-index: var(--kui-collapsible-panel-backdrop-z, 39);
171
299
  border: 0;
172
300
  padding: 0;
@@ -0,0 +1,23 @@
1
+ *,
2
+ *::before,
3
+ *::after {
4
+ box-sizing: border-box;
5
+ }
6
+
7
+ html,
8
+ body,
9
+ .kui-app-root {
10
+ height: 100%;
11
+ }
12
+
13
+ body {
14
+ margin: 0;
15
+ color: var(--kui-color-text);
16
+ background: var(--kui-color-surface-lowered);
17
+ font-family: var(--kui-font-sans);
18
+ line-height: 1.45;
19
+ }
20
+
21
+ :where(a) {
22
+ color: var(--kui-color-text-link);
23
+ }
@@ -10,13 +10,13 @@
10
10
  "Segoe UI",
11
11
  sans-serif
12
12
  );
13
- --kui-font-mono: var(
14
- --wa-font-family-code,
15
- ui-monospace,
16
- SFMono-Regular,
17
- Menlo,
18
- monospace
19
- );
13
+ /* Kerf owns the code stack rather than deferring to Web Awesome's
14
+ `ui-monospace, monospace`: Chromium does not recognize `ui-monospace`, and
15
+ the generic `monospace` ends any stack, so named fallbacks after it would
16
+ never apply. Kerf's Web Awesome theme points `--wa-font-family-code` here. */
17
+ --kui-font-mono:
18
+ ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono",
19
+ monospace;
20
20
  --kui-font-2xs: var(--wa-font-size-2xs, 11px);
21
21
  --kui-font-xs: var(--wa-font-size-xs, 12px);
22
22
  --kui-font-s: var(--wa-font-size-s, 14px);
@@ -64,6 +64,15 @@
64
64
  --kui-toolbar-group-inner-size: 2.625rem;
65
65
  --kui-toolbar-group-size: calc(2px + var(--kui-toolbar-group-inner-size));
66
66
  --kui-toolbar-gap: var(--kui-layout-item-gap);
67
+ /* Device safe-area insets, in logical terms. Panes and layouts read these
68
+ through the inherited `--kui-edge-inset-*` edge context: surfaces paint
69
+ through the unsafe area while their content gains compensating padding on
70
+ the edges it still touches (docs/app-layouts.md "Safe areas"). Override
71
+ them to simulate a device or to reserve space for app-owned chrome. */
72
+ --kui-safe-area-block-start: env(safe-area-inset-top, 0px);
73
+ --kui-safe-area-block-end: env(safe-area-inset-bottom, 0px);
74
+ --kui-safe-area-inline-start: env(safe-area-inset-left, 0px);
75
+ --kui-safe-area-inline-end: env(safe-area-inset-right, 0px);
67
76
  --kui-radius-s: var(--wa-border-radius-s, 0.1875rem);
68
77
  --kui-radius-m: var(--wa-border-radius-m, 0.375rem);
69
78
  --kui-radius-l: var(--wa-border-radius-l, 0.75rem);
@@ -386,6 +395,11 @@
386
395
  );
387
396
  }
388
397
 
398
+ :root:dir(rtl) {
399
+ --kui-safe-area-inline-start: env(safe-area-inset-right, 0px);
400
+ --kui-safe-area-inline-end: env(safe-area-inset-left, 0px);
401
+ }
402
+
389
403
  @media (prefers-contrast: more) {
390
404
  :root {
391
405
  --kui-color-pop-fill-quiet: Canvas;
@@ -1,5 +1,9 @@
1
1
  .kui-grid {
2
2
  --kui-grid-gap: var(--kui-layout-item-gap, 0.5rem);
3
+ /* Private per-instance values are reset on every Grid so a nested Grid never
4
+ inherits its ancestor's; the inline style overrides them per prop. */
5
+ --_kui-grid-gap: var(--kui-grid-gap);
6
+ --_kui-grid-flex: 0 1 auto;
3
7
 
4
8
  display: grid;
5
9
  min-width: 0;
@@ -9,3 +13,9 @@
9
13
  grid-template-columns: repeat(var(--_kui-grid-columns), minmax(0, 1fr));
10
14
  gap: var(--_kui-grid-gap, var(--kui-grid-gap));
11
15
  }
16
+
17
+ /* `fill`: the layout root of a definite-height parent (an app root or a
18
+ fixed-height frame) takes its full height. Inside a flex layout use `flex`. */
19
+ .kui-grid[data-fill="true"] {
20
+ height: 100%;
21
+ }
@@ -46,6 +46,10 @@
46
46
  vertical-align: middle;
47
47
  }
48
48
 
49
+ .kui-list-header[data-width="content"]:not([data-inline="true"]) {
50
+ width: auto;
51
+ }
52
+
49
53
  .kui-list-header[data-inline="true"] > .kui-list-header__title,
50
54
  .kui-list-header[data-inline="true"] > .kui-list-header__action {
51
55
  vertical-align: middle;
@@ -96,66 +100,6 @@
96
100
  white-space: nowrap;
97
101
  }
98
102
 
99
- /* Passive labels use Text for semantic heading markup. The title wrapper
100
- already owns the transparent alignment border, so avoid counting a second
101
- border before Text's standard content padding. */
102
- .kui-list-header__label.kui-text {
103
- border: 0;
104
- }
105
-
106
- .kui-list-header__badge {
107
- display: inline-flex;
108
- min-height: 1.5rem;
109
- padding-inline: var(--kui-layout-item-padding, 0.5rem);
110
- box-sizing: border-box;
111
- border: 1px solid transparent;
112
- border-radius: var(--kui-layout-pill-radius, calc(1px + 1.3125rem));
113
- color: var(--kui-color-neutral-on-quiet);
114
- background: var(--kui-color-neutral-fill-quiet);
115
- align-items: center;
116
- flex: none;
117
- font-size: var(--kui-font-xs);
118
- line-height: 1;
119
- }
120
-
121
- .kui-list-header__count {
122
- display: inline-grid;
123
- min-width: 1.35rem;
124
- height: 1.35rem;
125
- padding-inline: 0.35rem;
126
- box-sizing: border-box;
127
- border-radius: var(--kui-layout-pill-radius, calc(1px + 1.3125rem));
128
- color: var(--kui-color-neutral-on-quiet);
129
- background: var(--kui-color-neutral-fill-quiet);
130
- place-items: center;
131
- flex: none;
132
- font-size: var(
133
- --kui-list-header-count-font-size,
134
- var(--wa-font-size-3xs, 0.625rem)
135
- );
136
- font-weight: 700;
137
- letter-spacing: 0;
138
- line-height: 1;
139
- }
140
-
141
- .kui-list-header[data-indicator-tone="accent"]
142
- :is(.kui-list-header__count, .kui-list-header__badge) {
143
- color: var(--kui-color-brand-on-normal);
144
- background: var(--kui-color-brand-fill-normal);
145
- }
146
-
147
- .kui-list-header[data-indicator-tone="pop"]
148
- :is(.kui-list-header__count, .kui-list-header__badge) {
149
- color: var(--kui-color-pop-on-normal);
150
- background: var(--kui-color-pop-fill-normal);
151
- }
152
-
153
- .kui-list-header[data-indicator-tone="danger"]
154
- :is(.kui-list-header__count, .kui-list-header__badge) {
155
- color: var(--kui-color-danger-on-normal);
156
- background: var(--kui-color-danger-fill-normal);
157
- }
158
-
159
103
  .kui-list-header__action,
160
104
  .kui-list-header__action-layer {
161
105
  display: grid;
@@ -179,11 +123,56 @@
179
123
  padding: var(--kui-layout-item-padding, 0.5rem);
180
124
  align-items: center;
181
125
  justify-content: center;
126
+ position: relative;
182
127
  align-self: center;
183
128
  cursor: pointer;
184
129
  flex: none;
185
130
  }
186
131
 
132
+ /* The fitted square is the visual and hover surface; the pointer target is at
133
+ least 44px in both dimensions. A transparent, out-of-flow layer extends the
134
+ button's hit area evenly around the square without moving layout or painting
135
+ anything, and hovering it lights the unchanged fitted square. Standard headers
136
+ are 44px tall and reserve the 4px inline slot at the logical end, so the
137
+ extension stays inside the header; the leading 4px falls in the 8px gap before
138
+ the dormant title. Offsets are from the padding box, hence the extra 1px for the
139
+ border. */
140
+ .kui-list-header__action::before {
141
+ --_kui-list-header-action-hit-outset: min(
142
+ 0px,
143
+ calc((var(--_kui-list-header-action-size) - 2.75rem) / 2)
144
+ );
145
+ content: "";
146
+ position: absolute;
147
+ inset: calc(var(--_kui-list-header-action-hit-outset) - 1px);
148
+ }
149
+
150
+ /* Compact headers are 36px tall like the rest of the compact List family, so the
151
+ hit area widens to 44px but never reaches past the header into a neighboring
152
+ row or header. */
153
+ .kui-list-header[data-density="compact"] .kui-list-header__action::before {
154
+ inset-block: -1px;
155
+ }
156
+
157
+ /* Trailing icon actions share one axis: a toolbar control centers its glyph in a
158
+ 44px group slot flush with the 8px inline margin, so the fitted action centers
159
+ itself in a slot of that same size instead of sitting flush at the margin
160
+ (which put its glyph ~4px outside a Pane header's trailing toolbar glyph). The
161
+ slot, not the button, grows by the difference, so the fitted hover square and
162
+ its 18px visual are unchanged. Inline headers carry no outer geometry. */
163
+ .kui-list-header:not([data-inline="true"]) > .kui-list-header__action {
164
+ margin-inline-end: max(
165
+ 0px,
166
+ calc(
167
+ (
168
+ var(--kui-toolbar-group-size, calc(2px + 2.625rem)) -
169
+ var(--_kui-list-header-action-size)
170
+ ) /
171
+ 2
172
+ )
173
+ );
174
+ }
175
+
187
176
  .kui-list-header__toggle {
188
177
  padding: var(--kui-layout-item-padding, 0.5rem);
189
178
  appearance: none;
@@ -1,11 +1,18 @@
1
1
  .kui-list-inset-control {
2
2
  display: flex;
3
3
  margin: 0;
4
- justify-content: stretch;
5
4
  align-items: stretch;
6
5
  gap: 0.5rem;
7
6
  }
8
7
 
8
+ /* `justify-content: stretch` is a no-op on a flex row, so the documented
9
+ stretch comes from the children: each grows from its natural width to share
10
+ the row, and may shrink below its intrinsic minimum instead of overflowing. */
11
+ .kui-list-inset-control > * {
12
+ min-width: 0;
13
+ flex: 1 1 auto;
14
+ }
15
+
9
16
  .kui-list-inset-control[data-sides*="t"] {
10
17
  margin-top: var(--kui-layout-inline-margin, 0.5rem);
11
18
  }
@@ -139,6 +139,12 @@
139
139
  .kui-list-item[data-multiline="true"] {
140
140
  height: fit-content;
141
141
  white-space: normal;
142
+ /* Size the single grid row to its content and center that track in the
143
+ 44px minimum, instead of stretching it. The start-aligned icon then
144
+ measures its first-line offset from the same edge the centered label
145
+ starts at; a stretched track left a short label centered 1.4px below
146
+ the icon's first-line position. */
147
+ align-content: center;
142
148
  }
143
149
 
144
150
  .kui-list-item[data-multiline="true"] .kui-list-item__label {
@@ -1,6 +1,11 @@
1
1
  .kui-list {
2
2
  --kui-list-divider-color: var(--kui-color-border);
3
3
  --kui-list-gap: var(--kui-layout-item-gap, 0.5rem);
4
+ /* Private per-instance values are reset on every List so a nested List that
5
+ omits `gap` or `flex` never inherits its ancestor's; the component's inline
6
+ style overrides these defaults for the props it does set. */
7
+ --_kui-list-gap: 0;
8
+ --_kui-list-flex: 0 1 auto;
4
9
  --_kui-list-inset-top: 0;
5
10
  --_kui-list-inset-right: 0;
6
11
  --_kui-list-inset-bottom: 0;
@@ -120,3 +125,9 @@
120
125
  .kui-list[divider-sides*="l"] {
121
126
  --_kui-list-divider-left: var(--kui-list-divider-color);
122
127
  }
128
+
129
+ /* `fill`: the layout root of a definite-height parent (an app root or a
130
+ fixed-height frame) takes its full height. Inside a flex layout use `flex`. */
131
+ .kui-list[data-fill="true"] {
132
+ height: 100%;
133
+ }
@@ -7,10 +7,33 @@
7
7
  overflow: hidden;
8
8
  flex-direction: column;
9
9
  background: var(--kui-color-surface);
10
+ /* Safe areas: the stack's surfaces paint through unsafe areas; its chrome,
11
+ bottom toolbar, and each view compensate for the edges the stack still
12
+ touches (see pane.css for the `--kui-edge-inset-*` edge context). */
13
+ --_kui-nav-stack-safe-block-start: var(
14
+ --kui-edge-inset-block-start,
15
+ var(--kui-safe-area-block-start, env(safe-area-inset-top, 0px))
16
+ );
17
+ --_kui-nav-stack-safe-block-end: var(
18
+ --kui-edge-inset-block-end,
19
+ var(--kui-safe-area-block-end, env(safe-area-inset-bottom, 0px))
20
+ );
21
+ --_kui-nav-stack-safe-inline-start: var(
22
+ --kui-edge-inset-inline-start,
23
+ var(--kui-safe-area-inline-start, env(safe-area-inset-left, 0px))
24
+ );
25
+ --_kui-nav-stack-safe-inline-end: var(
26
+ --kui-edge-inset-inline-end,
27
+ var(--kui-safe-area-inline-end, env(safe-area-inset-right, 0px))
28
+ );
10
29
  }
11
30
 
12
31
  .kui-nav-stack__chrome,
13
32
  .kui-nav-stack__bottom {
33
+ --kui-edge-inset-block-start: 0px;
34
+ --kui-edge-inset-block-end: 0px;
35
+ --kui-edge-inset-inline-start: 0px;
36
+ --kui-edge-inset-inline-end: 0px;
14
37
  transition: opacity var(--kui-nav-stack-transition-duration, 200ms) ease;
15
38
  }
16
39
 
@@ -38,8 +61,12 @@
38
61
  .kui-nav-stack__chrome {
39
62
  display: flex;
40
63
  min-width: 0;
41
- min-height: calc(2px + 2.625rem);
42
- padding-inline: var(--kui-space-xs);
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));
43
70
  align-items: center;
44
71
  gap: var(--kui-space-xs);
45
72
  background: var(--kui-color-surface);
@@ -94,12 +121,28 @@
94
121
  }
95
122
 
96
123
  .kui-nav-stack__viewport {
124
+ --kui-edge-inset-block-start: var(--_kui-nav-stack-safe-block-start);
125
+ --kui-edge-inset-block-end: var(--_kui-nav-stack-safe-block-end);
126
+ --kui-edge-inset-inline-start: var(--_kui-nav-stack-safe-inline-start);
127
+ --kui-edge-inset-inline-end: var(--_kui-nav-stack-safe-inline-end);
97
128
  position: relative;
98
129
  flex: 1;
99
130
  min-height: 0;
100
131
  overflow: hidden;
101
132
  }
102
133
 
134
+ /* The top chrome and the bottom toolbar own their edges; transient chrome
135
+ copies from a transition do not. */
136
+ .kui-nav-stack__chrome ~ .kui-nav-stack__viewport {
137
+ --kui-edge-inset-block-start: 0px;
138
+ }
139
+
140
+ .kui-nav-stack__viewport:has(
141
+ ~ .kui-nav-stack__bottom:not(.kui-nav-stack__chrome-copy)
142
+ ) {
143
+ --kui-edge-inset-block-end: 0px;
144
+ }
145
+
103
146
  .kui-nav-stack__view {
104
147
  position: absolute;
105
148
  overflow: auto;
@@ -108,6 +151,47 @@
108
151
  inset: 0;
109
152
  }
110
153
 
154
+ /* Each view is its region's scroll owner: block insets become padding inside
155
+ the scroller so content scrolls under an unsafe edge but can always be
156
+ scrolled clear. A view whose only child is a Pane or layout lets that child
157
+ own the insets instead. */
158
+ .kui-nav-stack__view:not(
159
+ :has(
160
+ > :is(
161
+ [data-component="pane"],
162
+ [data-component="nav-stack"],
163
+ [data-component="split-view"],
164
+ [data-component="workbench"],
165
+ [data-component="tab-scaffold"]
166
+ ):only-child
167
+ )
168
+ ) {
169
+ padding-block: var(--kui-edge-inset-block-start)
170
+ var(--kui-edge-inset-block-end);
171
+ padding-inline: var(--kui-edge-inset-inline-start)
172
+ var(--kui-edge-inset-inline-end);
173
+ scroll-padding-block: var(--kui-edge-inset-block-start)
174
+ var(--kui-edge-inset-block-end);
175
+ }
176
+
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
+ > * {
189
+ --kui-edge-inset-block-start: 0px;
190
+ --kui-edge-inset-block-end: 0px;
191
+ --kui-edge-inset-inline-start: 0px;
192
+ --kui-edge-inset-inline-end: 0px;
193
+ }
194
+
111
195
  /* Only the active view (and any view mid-exit) is shown; lower entries stay
112
196
  mounted for state/focus but hidden behind it. */
113
197
  .kui-nav-stack__view[data-nav-active="false"] {
@@ -127,6 +211,9 @@
127
211
  }
128
212
 
129
213
  .kui-nav-stack__bottom {
214
+ padding-block-end: var(--_kui-nav-stack-safe-block-end);
215
+ padding-inline: var(--_kui-nav-stack-safe-inline-start)
216
+ var(--_kui-nav-stack-safe-inline-end);
130
217
  border-block-start: 1px solid var(--kui-color-border);
131
218
  background: var(--kui-color-surface);
132
219
  }