@kerfjs/ui 5.0.0-beta.23 → 5.0.0-beta.24

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 (193) hide show
  1. package/README.md +1 -0
  2. package/ai/compile-time-contracts-v1.json +2 -1
  3. package/ai/component-catalog-v2-overrides.json +5 -12
  4. package/ai/component-catalog-v2.json +43 -32
  5. package/ai/component-catalog.json +56 -37
  6. package/ai/public-api-signatures-v1.md +29 -16
  7. package/ai/skill.md +4 -4
  8. package/ai/webawesome-jsx-signatures-v1.md +1 -1
  9. package/dist/app-tab.js +1 -1
  10. package/dist/browser/list.js +3 -0
  11. package/dist/catalog.d.ts +8 -4
  12. package/dist/catalog.js +19 -10
  13. package/dist/catalog.js.map +1 -1
  14. package/dist/{chunk-RYRIFZCT.js → chunk-7XRDUG4Y.js} +5 -5
  15. package/dist/{chunk-RYRIFZCT.js.map → chunk-7XRDUG4Y.js.map} +1 -1
  16. package/dist/{chunk-OHU6CI22.js → chunk-B3A3IVO5.js} +2 -2
  17. package/dist/{chunk-OHU6CI22.js.map → chunk-B3A3IVO5.js.map} +1 -1
  18. package/dist/{chunk-ELSJX4W7.js → chunk-FEAMR7S4.js} +2 -2
  19. package/dist/{chunk-ELSJX4W7.js.map → chunk-FEAMR7S4.js.map} +1 -1
  20. package/dist/{chunk-OZWU5ZPZ.js → chunk-IJBSZ4NX.js} +2 -2
  21. package/dist/{chunk-OZWU5ZPZ.js.map → chunk-IJBSZ4NX.js.map} +1 -1
  22. package/dist/chunk-J5BFYY7Q.js +35 -0
  23. package/dist/chunk-J5BFYY7Q.js.map +1 -0
  24. package/dist/{chunk-QQFJMRIB.js → chunk-KWWR5VMS.js} +2 -2
  25. package/dist/{chunk-QQFJMRIB.js.map → chunk-KWWR5VMS.js.map} +1 -1
  26. package/dist/{chunk-K57KRAOV.js → chunk-NWSEP5RT.js} +2 -2
  27. package/dist/{chunk-K57KRAOV.js.map → chunk-NWSEP5RT.js.map} +1 -1
  28. package/dist/{chunk-GP5DP5DL.js → chunk-OJWWHFH3.js} +39 -4
  29. package/dist/chunk-OJWWHFH3.js.map +1 -0
  30. package/dist/{chunk-DSNIYOZ3.js → chunk-PSKN344N.js} +2 -2
  31. package/dist/{chunk-DSNIYOZ3.js.map → chunk-PSKN344N.js.map} +1 -1
  32. package/dist/{chunk-W7YD6E4N.js → chunk-R7ZWUN64.js} +2 -2
  33. package/dist/{chunk-W7YD6E4N.js.map → chunk-R7ZWUN64.js.map} +1 -1
  34. package/dist/{chunk-PZQVSDLH.js → chunk-RKVQEH4J.js} +1 -1
  35. package/dist/chunk-RKVQEH4J.js.map +1 -0
  36. package/dist/{chunk-7L6EHUMV.js → chunk-SYDMYBPG.js} +3 -3
  37. package/dist/chunk-SYDMYBPG.js.map +1 -0
  38. package/dist/{chunk-W4CXQYSG.js → chunk-TB6DY7H5.js} +3 -1
  39. package/dist/chunk-TB6DY7H5.js.map +1 -0
  40. package/dist/{chunk-BBRXX6PF.js → chunk-UFZKLBCF.js} +2 -2
  41. package/dist/{chunk-BBRXX6PF.js.map → chunk-UFZKLBCF.js.map} +1 -1
  42. package/dist/{chunk-AASLYRGE.js → chunk-UKKSMZYT.js} +18 -7
  43. package/dist/chunk-UKKSMZYT.js.map +1 -0
  44. package/dist/{chunk-VLYV65LK.js → chunk-W5L2JSBY.js} +5 -3
  45. package/dist/chunk-W5L2JSBY.js.map +1 -0
  46. package/dist/{chunk-PIDTEQ3U.js → chunk-Y45PPBDV.js} +2 -2
  47. package/dist/{chunk-PIDTEQ3U.js.map → chunk-Y45PPBDV.js.map} +1 -1
  48. package/dist/divider-sides-267FA7sY.d.ts +4 -0
  49. package/dist/index.d.ts +3 -1
  50. package/dist/index.js +16 -15
  51. package/dist/list-action-row.js +1 -1
  52. package/dist/list-header.js +1 -1
  53. package/dist/list-item.js +1 -1
  54. package/dist/list.d.ts +19 -0
  55. package/dist/list.js +3 -0
  56. package/dist/list.js.map +1 -0
  57. package/dist/nav-stack.js +1 -1
  58. package/dist/panel-header.js +1 -1
  59. package/dist/segmented-control.js +1 -1
  60. package/dist/select.js +1 -1
  61. package/dist/skeleton.d.ts +1 -1
  62. package/dist/skeleton.js +1 -1
  63. package/dist/split-view.js +1 -1
  64. package/dist/state-banner.d.ts +4 -2
  65. package/dist/state-banner.js +1 -1
  66. package/dist/styles/catalog.css +8 -2
  67. package/dist/styles/list-item.css +6 -6
  68. package/dist/styles/list.css +43 -0
  69. package/dist/styles/state-banner.css +32 -1
  70. package/dist/styles/styles.css +1 -0
  71. package/dist/styles/sunken-panel.css +4 -0
  72. package/dist/styles/toolbar.css +38 -2
  73. package/dist/sunken-panel.d.ts +5 -2
  74. package/dist/sunken-panel.js +1 -1
  75. package/dist/toolbar-text.js +1 -1
  76. package/dist/toolbar.d.ts +5 -3
  77. package/dist/toolbar.js +1 -1
  78. package/dist/value-table.js +1 -1
  79. package/dist/wire-catalog.d.ts +4 -2
  80. package/dist/wire-catalog.js +95 -36
  81. package/dist/wire-catalog.js.map +1 -1
  82. package/dist/wire-tab-bars.js +1 -1
  83. package/dist/wire-token-search-fields.d.ts +1 -1
  84. package/dist/wire-token-search-fields.js +1 -1
  85. package/docs/accessibility.md +12 -3
  86. package/docs/catalog.md +17 -12
  87. package/docs/component-contract.md +14 -1
  88. package/docs/component-selection.md +6 -2
  89. package/docs/design/templates/empty-state/filtered-dark.svg +1 -1
  90. package/docs/design/templates/empty-state/filtered.svg +1 -1
  91. package/docs/design/templates/empty-state/with-action-dark.svg +1 -1
  92. package/docs/design/templates/empty-state/with-action.svg +1 -1
  93. package/docs/design/templates/empty-state-dark.svg +1 -7
  94. package/docs/design/templates/empty-state.svg +1 -7
  95. package/docs/design/templates/list/compact-dark.svg +1 -0
  96. package/docs/design/templates/list/compact.svg +1 -0
  97. package/docs/design/templates/list/stack-dark.svg +1 -0
  98. package/docs/design/templates/list/stack.svg +1 -0
  99. package/docs/design/templates/list-action-row/default-dark.svg +1 -1
  100. package/docs/design/templates/list-action-row/default.svg +1 -1
  101. package/docs/design/templates/list-action-row/selected-dark.svg +1 -1
  102. package/docs/design/templates/list-action-row/selected.svg +1 -1
  103. package/docs/design/templates/list-action-row-dark.svg +1 -7
  104. package/docs/design/templates/list-action-row.svg +1 -7
  105. package/docs/design/templates/list-dark.svg +1 -0
  106. package/docs/design/templates/list-header/action-dark.svg +1 -1
  107. package/docs/design/templates/list-header/action.svg +1 -1
  108. package/docs/design/templates/list-header/toggle-collapsed-dark.svg +1 -1
  109. package/docs/design/templates/list-header/toggle-collapsed.svg +1 -1
  110. package/docs/design/templates/list-header/toggle-expanded-dark.svg +1 -1
  111. package/docs/design/templates/list-header/toggle-expanded.svg +1 -1
  112. package/docs/design/templates/list-header-dark.svg +1 -11
  113. package/docs/design/templates/list-header.svg +1 -11
  114. package/docs/design/templates/list-item/default-dark.svg +1 -1
  115. package/docs/design/templates/list-item/default.svg +1 -1
  116. package/docs/design/templates/list-item/multiline-dark.svg +1 -1
  117. package/docs/design/templates/list-item/multiline.svg +1 -1
  118. package/docs/design/templates/list-item/selected-dark.svg +1 -1
  119. package/docs/design/templates/list-item/selected.svg +1 -1
  120. package/docs/design/templates/list-item/trailing-dark.svg +1 -1
  121. package/docs/design/templates/list-item/trailing.svg +1 -1
  122. package/docs/design/templates/list-item-dark.svg +1 -11
  123. package/docs/design/templates/list-item.svg +1 -11
  124. package/docs/design/templates/list.svg +1 -0
  125. package/docs/design/templates/panel-header/icon-actions-dark.svg +1 -1
  126. package/docs/design/templates/panel-header/icon-actions.svg +1 -1
  127. package/docs/design/templates/panel-header/icon-summary-actions-dark.svg +1 -1
  128. package/docs/design/templates/panel-header/icon-summary-actions.svg +1 -1
  129. package/docs/design/templates/panel-header-dark.svg +1 -13
  130. package/docs/design/templates/panel-header.svg +1 -13
  131. package/docs/design/templates/segmented-control-dark.svg +1 -7
  132. package/docs/design/templates/segmented-control.svg +1 -7
  133. package/docs/design/templates/skeleton-dark.svg +1 -9
  134. package/docs/design/templates/skeleton.svg +1 -9
  135. package/docs/design/templates/state-banner/danger-dark.svg +1 -1
  136. package/docs/design/templates/state-banner/danger.svg +1 -1
  137. package/docs/design/templates/state-banner/info-badge-dark.svg +1 -0
  138. package/docs/design/templates/state-banner/info-badge.svg +1 -0
  139. package/docs/design/templates/state-banner/info-dark.svg +1 -1
  140. package/docs/design/templates/state-banner/info.svg +1 -1
  141. package/docs/design/templates/state-banner/success-dark.svg +1 -1
  142. package/docs/design/templates/state-banner/success.svg +1 -1
  143. package/docs/design/templates/state-banner/warning-dark.svg +1 -1
  144. package/docs/design/templates/state-banner/warning.svg +1 -1
  145. package/docs/design/templates/state-banner-dark.svg +1 -11
  146. package/docs/design/templates/state-banner.svg +1 -11
  147. package/docs/design/templates/tab-bar/workspace-tabs-dark.svg +1 -1
  148. package/docs/design/templates/tab-bar/workspace-tabs.svg +1 -1
  149. package/docs/design/templates/tab-bar-dark.svg +1 -5
  150. package/docs/design/templates/tab-bar.svg +1 -5
  151. package/docs/design/templates/token-search-field/empty-dark.svg +1 -1
  152. package/docs/design/templates/token-search-field/empty.svg +1 -1
  153. package/docs/design/templates/token-search-field/tokens-dark.svg +1 -1
  154. package/docs/design/templates/token-search-field/tokens.svg +1 -1
  155. package/docs/design/templates/token-search-field-dark.svg +1 -7
  156. package/docs/design/templates/token-search-field.svg +1 -7
  157. package/docs/design/templates/toolbar/title-and-actions-dark.svg +1 -1
  158. package/docs/design/templates/toolbar/title-and-actions.svg +1 -1
  159. package/docs/design/templates/toolbar-control-group/borderless-single-dark.svg +1 -1
  160. package/docs/design/templates/toolbar-control-group/borderless-single.svg +1 -1
  161. package/docs/design/templates/toolbar-control-group/icon-buttons-dark.svg +1 -1
  162. package/docs/design/templates/toolbar-control-group/icon-buttons.svg +1 -1
  163. package/docs/design/templates/toolbar-control-group/push-buttons-dark.svg +1 -1
  164. package/docs/design/templates/toolbar-control-group/push-buttons.svg +1 -1
  165. package/docs/design/templates/toolbar-control-group/with-text-dark.svg +1 -1
  166. package/docs/design/templates/toolbar-control-group/with-text.svg +1 -1
  167. package/docs/design/templates/toolbar-control-group-dark.svg +1 -11
  168. package/docs/design/templates/toolbar-control-group.svg +1 -11
  169. package/docs/design/templates/toolbar-dark.svg +1 -5
  170. package/docs/design/templates/toolbar-text-dark.svg +1 -9
  171. package/docs/design/templates/toolbar-text.svg +1 -9
  172. package/docs/design/templates/toolbar.svg +1 -5
  173. package/docs/design/templates/value-table/details-dark.svg +1 -1
  174. package/docs/design/templates/value-table/details.svg +1 -1
  175. package/docs/design/templates/value-table-dark.svg +1 -5
  176. package/docs/design/templates/value-table.svg +1 -5
  177. package/docs/design/templates.md +25 -14
  178. package/docs/sunken-panel.md +11 -1
  179. package/docs/type-contracts.md +6 -3
  180. package/docs/ui-doctor.md +6 -4
  181. package/docs/ux-demo.md +1 -1
  182. package/doctor/index.mjs +5 -2
  183. package/llms.txt +15 -3
  184. package/package.json +8 -2
  185. package/traversal-exclusions.mjs +7 -1
  186. package/ux-demo/recipes/collapsible-sidebar.tsx +1 -1
  187. package/ux-demo/recipes/navigation-sidebar.tsx +1 -1
  188. package/dist/chunk-7L6EHUMV.js.map +0 -1
  189. package/dist/chunk-AASLYRGE.js.map +0 -1
  190. package/dist/chunk-GP5DP5DL.js.map +0 -1
  191. package/dist/chunk-PZQVSDLH.js.map +0 -1
  192. package/dist/chunk-VLYV65LK.js.map +0 -1
  193. package/dist/chunk-W4CXQYSG.js.map +0 -1
package/README.md CHANGED
@@ -122,6 +122,7 @@ as a `New` marker.
122
122
  | `ToolbarControlGroup` | `@kerfjs/ui/toolbar-control-group` | `@kerfjs/ui/toolbar-control-group.css` |
123
123
  | `FloatingToolbar` | `@kerfjs/ui/floating-toolbar` | `@kerfjs/ui/floating-toolbar.css` |
124
124
  | `ToolbarText` | `@kerfjs/ui/toolbar-text` | `@kerfjs/ui/toolbar-text.css` |
125
+ | `List` | `@kerfjs/ui/list` | `@kerfjs/ui/list.css` |
125
126
  | `ListActionRow` | `@kerfjs/ui/list-action-row` | `@kerfjs/ui/list-action-row.css` |
126
127
  | `ListItem` | `@kerfjs/ui/list-item` | `@kerfjs/ui/list-item.css` |
127
128
  | `ListHeader` | `@kerfjs/ui/list-header` | `@kerfjs/ui/list-header.css` |
@@ -87,6 +87,7 @@
87
87
  "id": "KUI-T011",
88
88
  "publicImport": "@kerfjs/ui",
89
89
  "symbols": [
90
+ "DividerSides",
90
91
  "StateBannerUrgency",
91
92
  "TabActivation",
92
93
  "ToolbarControlGroupAppearance",
@@ -95,7 +96,7 @@
95
96
  "ToolbarControlGroupTone"
96
97
  ],
97
98
  "kind": "finite-vocabulary",
98
- "summary": "Finite public variant vocabularies are named exported unions rather than anonymous string sets."
99
+ "summary": "Finite public variant vocabularies, including canonical divider-edge combinations, are named exported unions rather than anonymous string sets."
99
100
  }
100
101
  ]
101
102
  }
@@ -93,21 +93,14 @@
93
93
  ]
94
94
  },
95
95
  "@kerfjs/ui:list": {
96
- "_source": "docs/component-selection.md#correct-composition-and-duplicated-markup-trap",
97
- "contexts": ["navigation-list"],
96
+ "_source": "docs/component-selection.md#problem-to-component-matrix",
97
+ "contexts": ["application-ui", "navigation-list", "vertical-layout"],
98
98
  "children": {
99
- "mode": "listed",
100
- "concepts": ["list-header", "list-item", "list-action-row"],
99
+ "mode": "any",
100
+ "concepts": [],
101
101
  "requiredConcepts": []
102
102
  },
103
- "zones": [
104
- {
105
- "id": "rows",
106
- "accepts": ["list-header", "list-item", "list-action-row"],
107
- "cardinality": { "min": 1, "max": "unbounded" },
108
- "exclusiveWith": []
109
- }
110
- ]
103
+ "zones": []
111
104
  },
112
105
  "@kerfjs/ui:list-header": {
113
106
  "_source": "docs/accessibility.md#shared-rules",
@@ -522,6 +522,7 @@
522
522
  "owner": "application",
523
523
  "required": false
524
524
  },
525
+ { "id": "corner shape", "owner": "application", "required": false },
525
526
  { "id": "scroll ownership", "owner": "application", "required": false },
526
527
  {
527
528
  "id": "child ordering and content",
@@ -620,7 +621,7 @@
620
621
  "border": "conditional",
621
622
  "padding": "self",
622
623
  "notes": [
623
- "Padding belongs to the toolbar; the optional divider variant also owns its border."
624
+ "Padding belongs to the toolbar; dividerSides selects any canonical combination of its physical top, right, bottom, and left edges."
624
625
  ]
625
626
  }
626
627
  },
@@ -637,7 +638,11 @@
637
638
  "kui-toolbar__leading",
638
639
  "kui-toolbar__trailing"
639
640
  ],
640
- "publicTokens": ["--kui-color-border", "--kui-font-sans"]
641
+ "publicTokens": [
642
+ "--kui-color-border",
643
+ "--kui-font-sans",
644
+ "--kui-toolbar-divider-color"
645
+ ]
641
646
  },
642
647
  "diagnostics": [
643
648
  {
@@ -988,33 +993,26 @@
988
993
  "key": "@kerfjs/ui:list",
989
994
  "package": "@kerfjs/ui",
990
995
  "id": "list",
991
- "name": "List composition",
992
- "kind": "composition",
996
+ "name": "List",
997
+ "kind": "component",
993
998
  "source": "kerf",
994
999
  "parents": { "mode": "any", "entries": [] },
995
- "contexts": ["navigation-list"],
996
- "zones": [
997
- {
998
- "id": "rows",
999
- "accepts": ["list-header", "list-item", "list-action-row"],
1000
- "cardinality": { "min": 1, "max": "unbounded" },
1001
- "exclusiveWith": []
1002
- }
1003
- ],
1004
- "children": {
1005
- "mode": "listed",
1006
- "concepts": ["list-header", "list-item", "list-action-row"],
1007
- "requiredConcepts": []
1008
- },
1000
+ "contexts": ["application-ui", "navigation-list", "vertical-layout"],
1001
+ "zones": [],
1002
+ "children": { "mode": "any", "concepts": [], "requiredConcepts": [] },
1009
1003
  "state": [
1010
1004
  {
1011
- "id": "information architecture",
1005
+ "id": "child semantics and content",
1006
+ "owner": "application",
1007
+ "required": false
1008
+ },
1009
+ {
1010
+ "id": "the bounded height needed for scrolling",
1012
1011
  "owner": "application",
1013
1012
  "required": false
1014
1013
  },
1015
- { "id": "routing", "owner": "application", "required": false },
1016
1014
  {
1017
- "id": "responsive shell behavior",
1015
+ "id": "gap, flex, and divider choices",
1018
1016
  "owner": "application",
1019
1017
  "required": false
1020
1018
  }
@@ -1023,28 +1021,35 @@
1023
1021
  "responsive": { "owner": "not-applicable", "behaviors": [] },
1024
1022
  "layout": {
1025
1023
  "roles": ["navigation"],
1026
- "geometry": { "margin": "child", "border": "child", "padding": "child" }
1024
+ "geometry": {
1025
+ "margin": "none",
1026
+ "border": "conditional",
1027
+ "padding": "none",
1028
+ "notes": [
1029
+ "List adds no margin or padding; dividerSides draws only the selected physical edges without changing box geometry."
1030
+ ]
1031
+ }
1027
1032
  },
1028
1033
  "accessibility": {
1029
1034
  "obligations": [
1030
- "Use native links for link navigation, retain ListItem button semantics for actions, and keep standalone header and toolbar actions at least 44px square.",
1031
- "A ListHeader disclosure controls real content, keeps a stable accessible name and aria-expanded state, and uses the production DisclosureArrow visual."
1035
+ "List adds layout only and no list role; children retain responsibility for their native or ARIA semantics.",
1036
+ "Give a scrollable List a bounded block size and keep keyboard focus visible as its contents scroll."
1032
1037
  ]
1033
1038
  },
1034
1039
  "boundaries": {
1035
- "rootClass": "kui-content",
1036
- "publicClasses": ["kui-content", "kui-content-item"],
1040
+ "rootClass": "kui-list",
1041
+ "publicClasses": ["kui-list"],
1037
1042
  "publicTokens": [
1038
- "--kui-layout-content-gap",
1039
- "--kui-layout-inline-margin",
1040
- "--kui-layout-item-padding",
1041
- "--kui-layout-rounded-radius"
1043
+ "--kui-color-border",
1044
+ "--kui-layout-item-gap",
1045
+ "--kui-list-divider-color",
1046
+ "--kui-list-gap"
1042
1047
  ]
1043
1048
  },
1044
1049
  "diagnostics": [],
1045
1050
  "provenance": {
1046
1051
  "selection": "ai/component-catalog.json",
1047
- "composition": "docs/component-selection.md#correct-composition-and-duplicated-markup-trap"
1052
+ "composition": "docs/component-selection.md#problem-to-component-matrix"
1048
1053
  }
1049
1054
  },
1050
1055
  {
@@ -1799,6 +1804,7 @@
1799
1804
  "zones": [],
1800
1805
  "children": { "mode": "any", "concepts": [], "requiredConcepts": [] },
1801
1806
  "state": [
1807
+ { "id": "badge content", "owner": "application", "required": false },
1802
1808
  { "id": "state mapping", "owner": "application", "required": false },
1803
1809
  { "id": "message lifetime", "owner": "application", "required": false },
1804
1810
  { "id": "retry behavior", "owner": "application", "required": false },
@@ -1812,7 +1818,8 @@
1812
1818
  },
1813
1819
  "accessibility": {
1814
1820
  "obligations": [
1815
- "Use alert urgency only for an attention-requiring failure."
1821
+ "Use alert urgency only for an attention-requiring failure.",
1822
+ "Keep optional badge content terse and do not rely on its tone alone for meaning."
1816
1823
  ]
1817
1824
  },
1818
1825
  "boundaries": {
@@ -1820,7 +1827,9 @@
1820
1827
  "publicClasses": [
1821
1828
  "kui-state-banner",
1822
1829
  "kui-state-banner__action",
1830
+ "kui-state-banner__badge",
1823
1831
  "kui-state-banner__copy",
1832
+ "kui-state-banner__detail",
1824
1833
  "kui-state-banner__icon"
1825
1834
  ],
1826
1835
  "publicTokens": [
@@ -1847,6 +1856,8 @@
1847
1856
  "--kui-state-banner-action-background",
1848
1857
  "--kui-state-banner-action-hover-background",
1849
1858
  "--kui-state-banner-background",
1859
+ "--kui-state-banner-badge-background",
1860
+ "--kui-state-banner-badge-foreground",
1850
1861
  "--kui-state-banner-border",
1851
1862
  "--kui-state-banner-danger-background",
1852
1863
  "--kui-state-banner-danger-border",
@@ -644,14 +644,15 @@
644
644
  "category": "Structure",
645
645
  "kind": "component",
646
646
  "source": "kerf",
647
- "description": "A lowered application surface with one compact inset and a vertical content stack.",
647
+ "description": "A rounded or square-corner lowered application surface with one compact inset and a vertical content stack.",
648
648
  "uses": [],
649
- "purpose": "Group a vertical list of application content on a visually lowered surface with one owned 8px inset.",
649
+ "purpose": "Group a vertical list of application content on a visually lowered surface with one owned 8px inset and an explicit rounded or square-corner shape.",
650
650
  "publicExports": [
651
651
  "SunkenPanel"
652
652
  ],
653
653
  "useWhen": [
654
- "A main content region or nested work area needs a darker/lowered background and one compact inset around a vertical stack."
654
+ "A main content region or nested work area needs a darker/lowered background and one compact inset around a vertical stack.",
655
+ "Use the default rounded shape for an inset surface; choose square for a flush or edge-to-edge application area."
655
656
  ],
656
657
  "avoidWhen": [
657
658
  "Do not use it merely to add padding, as a substitute for Pane anatomy, or around children that already own the same outer surface."
@@ -665,10 +666,13 @@
665
666
  ],
666
667
  "appOwns": [
667
668
  "region semantics and accessible name",
669
+ "corner shape",
668
670
  "scroll ownership",
669
671
  "child ordering and content"
670
672
  ],
671
673
  "variants": [
674
+ "rounded surface",
675
+ "square-corner surface",
672
676
  "unnamed surface",
673
677
  "named region"
674
678
  ],
@@ -740,8 +744,9 @@
740
744
  "responsive relocation"
741
745
  ],
742
746
  "variants": [
743
- "divider",
744
- "no divider",
747
+ "bottom divider (default)",
748
+ "no dividers",
749
+ "top/right/bottom/left divider combinations",
745
750
  "centered content"
746
751
  ],
747
752
  "accessibility": [
@@ -752,7 +757,7 @@
752
757
  "border": "conditional",
753
758
  "padding": "self",
754
759
  "notes": [
755
- "Padding belongs to the toolbar; the optional divider variant also owns its border."
760
+ "Padding belongs to the toolbar; dividerSides selects any canonical combination of its physical top, right, bottom, and left edges."
756
761
  ]
757
762
  },
758
763
  "delivery": {
@@ -771,7 +776,8 @@
771
776
  ],
772
777
  "publicTokens": [
773
778
  "--kui-color-border",
774
- "--kui-font-sans"
779
+ "--kui-font-sans",
780
+ "--kui-toolbar-divider-color"
775
781
  ],
776
782
  "links": {
777
783
  "catalogRoute": "?component=toolbar",
@@ -1226,63 +1232,69 @@
1226
1232
  },
1227
1233
  {
1228
1234
  "id": "list",
1229
- "name": "List composition",
1235
+ "name": "List",
1230
1236
  "category": "Navigation",
1231
- "kind": "composition",
1237
+ "kind": "component",
1232
1238
  "source": "kerf",
1233
- "description": "Navigation rows and section headers composed as ordinary content items inside a pane.",
1239
+ "description": "A stretch-aligned vertical stack with optional gap, flex growth, vertical scrolling, and independently selectable divider edges.",
1234
1240
  "uses": [
1235
1241
  "list-header",
1236
1242
  "list-action-row",
1237
1243
  "list-item"
1238
1244
  ],
1239
- "purpose": "Compose navigation with the same pane, content stack, item, and toolbar geometry used throughout the application, including a controlled ListHeader disclosure only when it reveals real content.",
1240
- "publicExports": [],
1245
+ "purpose": "Standardize vertical component layout and its scroll/divider ownership instead of repeating ad-hoc flex-column wrappers.",
1246
+ "publicExports": [
1247
+ "List"
1248
+ ],
1241
1249
  "useWhen": [
1242
- "Compose navigation sections in a .kui-content stack, using ListHeader, ListItem, and ListActionRow children plus optional .kui-content-item surfaces."
1250
+ "Arrange component rows or sections in a vertical stretch-aligned stack.",
1251
+ "Let one bounded list own vertical scrolling, flex growth, or one or more physical-edge dividers."
1243
1252
  ],
1244
1253
  "avoidWhen": [
1245
- "Do not add sidebar-specific wrapper padding or use the pattern for unrelated inline controls.",
1246
- "Do not place a disclosure chevron on navigation that does not expand content."
1254
+ "Do not use List as semantic list markup; use ul/ol when list semantics are required and apply layout deliberately.",
1255
+ "Do not create nested scroll owners or use divider sides as a substitute for meaningful grouping."
1247
1256
  ],
1248
1257
  "alternatives": [],
1249
1258
  "appOwns": [
1250
- "information architecture",
1251
- "routing",
1252
- "responsive shell behavior"
1259
+ "child semantics and content",
1260
+ "the bounded height needed for scrolling",
1261
+ "gap, flex, and divider choices"
1253
1262
  ],
1254
1263
  "variants": [
1255
- "section",
1256
- "icon rows",
1257
- "iconless rows",
1258
- "content item",
1259
- "pane toolbar or footer"
1264
+ "no gap",
1265
+ "standard or custom gap",
1266
+ "boolean or custom flex",
1267
+ "scrollable",
1268
+ "top/right/bottom/left divider combinations"
1260
1269
  ],
1261
1270
  "accessibility": [
1262
- "Use native links for link navigation, retain ListItem button semantics for actions, and keep standalone header and toolbar actions at least 44px square.",
1263
- "A ListHeader disclosure controls real content, keeps a stable accessible name and aria-expanded state, and uses the production DisclosureArrow visual."
1271
+ "List adds layout only and no list role; children retain responsibility for their native or ARIA semantics.",
1272
+ "Give a scrollable List a bounded block size and keep keyboard focus visible as its contents scroll."
1264
1273
  ],
1265
1274
  "geometry": {
1266
- "margin": "child",
1267
- "border": "child",
1268
- "padding": "child"
1275
+ "margin": "none",
1276
+ "border": "conditional",
1277
+ "padding": "none",
1278
+ "notes": [
1279
+ "List adds no margin or padding; dividerSides draws only the selected physical edges without changing box geometry."
1280
+ ]
1269
1281
  },
1270
1282
  "delivery": {
1271
- "manualCssImport": "@kerfjs/ui/layout.css",
1283
+ "browserImport": "@kerfjs/ui/list",
1284
+ "manualCssImport": "@kerfjs/ui/list.css",
1272
1285
  "sideEffects": [
1273
- "css"
1286
+ "browser-condition-css"
1274
1287
  ]
1275
1288
  },
1276
1289
  "wiring": [],
1277
1290
  "publicClasses": [
1278
- "kui-content",
1279
- "kui-content-item"
1291
+ "kui-list"
1280
1292
  ],
1281
1293
  "publicTokens": [
1282
- "--kui-layout-content-gap",
1283
- "--kui-layout-inline-margin",
1284
- "--kui-layout-item-padding",
1285
- "--kui-layout-rounded-radius"
1294
+ "--kui-color-border",
1295
+ "--kui-layout-item-gap",
1296
+ "--kui-list-divider-color",
1297
+ "--kui-list-gap"
1286
1298
  ],
1287
1299
  "links": {
1288
1300
  "catalogRoute": "?component=list",
@@ -2385,6 +2397,7 @@
2385
2397
  }
2386
2398
  ],
2387
2399
  "appOwns": [
2400
+ "badge content",
2388
2401
  "state mapping",
2389
2402
  "message lifetime",
2390
2403
  "retry behavior",
@@ -2398,10 +2411,12 @@
2398
2411
  "danger",
2399
2412
  "status",
2400
2413
  "alert",
2414
+ "badge",
2401
2415
  "placeholder (loading)"
2402
2416
  ],
2403
2417
  "accessibility": [
2404
- "Use alert urgency only for an attention-requiring failure."
2418
+ "Use alert urgency only for an attention-requiring failure.",
2419
+ "Keep optional badge content terse and do not rely on its tone alone for meaning."
2405
2420
  ],
2406
2421
  "geometry": {
2407
2422
  "margin": "self",
@@ -2419,7 +2434,9 @@
2419
2434
  "publicClasses": [
2420
2435
  "kui-state-banner",
2421
2436
  "kui-state-banner__action",
2437
+ "kui-state-banner__badge",
2422
2438
  "kui-state-banner__copy",
2439
+ "kui-state-banner__detail",
2423
2440
  "kui-state-banner__icon"
2424
2441
  ],
2425
2442
  "publicTokens": [
@@ -2446,6 +2463,8 @@
2446
2463
  "--kui-state-banner-action-background",
2447
2464
  "--kui-state-banner-action-hover-background",
2448
2465
  "--kui-state-banner-background",
2466
+ "--kui-state-banner-badge-background",
2467
+ "--kui-state-banner-badge-foreground",
2449
2468
  "--kui-state-banner-border",
2450
2469
  "--kui-state-banner-danger-background",
2451
2470
  "--kui-state-banner-danger-border",
@@ -1,6 +1,6 @@
1
1
  # Public API signatures for the UI authoring corpus
2
2
 
3
- Generated from emitted declarations for `@kerfjs/ui@5.0.0-beta.23` and `kerfjs@5.0.0-beta.23`. This bounded reference covers only APIs used by the seven-task corpus. It is interface evidence, not an implementation or runtime guarantee.
3
+ Generated from emitted declarations for `@kerfjs/ui@5.0.0-beta.24` and `kerfjs@5.0.0-beta.24`. This bounded reference covers only APIs used by the seven-task corpus. It is interface evidence, not an implementation or runtime guarantee.
4
4
 
5
5
  ## `@kerfjs/ui/disclosure-arrow`
6
6
 
@@ -25,18 +25,20 @@ export { DisclosureArrow, type DisclosureArrowProps, type DisclosureDirection };
25
25
 
26
26
  ```ts
27
27
  import { SafeHtml } from 'kerfjs';
28
+ import { D as DividerSides } from './divider-sides-267FA7sY.js';
28
29
 
29
30
  interface ToolbarProps {
30
31
  leading?: SafeHtml;
31
32
  center?: SafeHtml;
32
33
  trailing?: SafeHtml;
33
34
  label?: string;
34
- divider?: boolean;
35
+ /** Physical divider edges in canonical top/right/bottom/left order. Defaults to bottom. */
36
+ dividerSides?: DividerSides;
35
37
  className?: string;
36
38
  }
37
- declare function Toolbar({ leading, center, trailing, label, divider, className, }: ToolbarProps): SafeHtml;
39
+ declare function Toolbar({ leading, center, trailing, label, dividerSides, className, }: ToolbarProps): SafeHtml;
38
40
 
39
- export { Toolbar, type ToolbarProps };
41
+ export { DividerSides, Toolbar, type ToolbarProps };
40
42
  ```
41
43
 
42
44
  ## `@kerfjs/ui/toolbar-text`
@@ -1087,10 +1089,10 @@ interface CatalogProps {
1087
1089
  /** Status line content shown at the start of the detail footer. */
1088
1090
  status?: SafeHtml;
1089
1091
  /**
1090
- * Whether to highlight transparent specimens' outer bounds and non-zero
1091
- * margins. Pass a boolean (rather than omitting the prop) when the active
1092
- * entry can switch between component and composition previews;
1093
- * `wireCatalogGeometryOverlay` keeps the overlay synchronized.
1092
+ * Whether to highlight specimens' computed borders (or transparent outer
1093
+ * bounds) and non-zero margins. Pass a boolean (rather than omitting the
1094
+ * prop) when the active entry can switch between component and composition
1095
+ * previews; `wireCatalogGeometryOverlay` keeps the overlay synchronized.
1094
1096
  */
1095
1097
  geometryOverlay?: boolean;
1096
1098
  selectAction?: string;
@@ -1120,11 +1122,15 @@ type CatalogExampleAlign = 'glyph' | 'inline-control' | 'none';
1120
1122
  type CatalogExampleRootAttributes = Readonly<Record<`data-${string}`, string | undefined> & {
1121
1123
  'data-catalog-example'?: never;
1122
1124
  'data-catalog-example-stack'?: never;
1125
+ 'data-catalog-example-label'?: never;
1126
+ 'data-catalog-example-note'?: never;
1123
1127
  'data-align'?: never;
1124
1128
  }>;
1125
1129
  type CatalogExampleStackRootAttributes = Readonly<Record<`data-${string}`, string | undefined> & {
1126
1130
  'data-catalog-example'?: never;
1127
1131
  'data-catalog-example-stack'?: never;
1132
+ 'data-catalog-example-label'?: never;
1133
+ 'data-catalog-example-note'?: never;
1128
1134
  'data-align'?: never;
1129
1135
  }>;
1130
1136
  interface CatalogExampleProps {
@@ -1249,8 +1255,10 @@ interface CatalogRevealOptions {
1249
1255
  declare function revealCatalogEntry(root: HTMLElement, id: string, { block, inline, behavior, media, }?: CatalogRevealOptions): () => void;
1250
1256
  /**
1251
1257
  * Keep a Catalog's opt-in geometry overlay synchronized with its preview.
1252
- * Transparent specimens receive a dashed outer bound and positive margins use
1253
- * devtools-style orange bands. Returns a disposer.
1258
+ * Specimens receive computed border highlights (or a dashed bound when they
1259
+ * have no border and are transparent), while positive computed margins use
1260
+ * devtools-style orange bands. CSS/stylesheet-only changes are observed too.
1261
+ * Returns a disposer.
1254
1262
  */
1255
1263
  declare function wireCatalogGeometryOverlay(root: HTMLElement): () => void;
1256
1264
  /**
@@ -1352,15 +1360,17 @@ type StateBannerUrgency = 'status' | 'alert';
1352
1360
  interface StateBannerProps {
1353
1361
  title: string;
1354
1362
  detail?: string;
1363
+ /** Optional compact status or count shown beside the title. */
1364
+ badge?: string;
1355
1365
  icon?: SafeHtml;
1356
1366
  action?: SafeHtml;
1357
1367
  tone?: StateBannerTone;
1358
1368
  urgency?: StateBannerUrgency;
1359
1369
  className?: string;
1360
- /** Render the title and detail as unanimated loading skeletons, keeping the icon and tone. */
1370
+ /** Render the title, badge, and detail as unanimated loading skeletons, keeping the icon and tone. */
1361
1371
  placeholder?: boolean;
1362
1372
  }
1363
- declare function StateBanner({ title, detail, icon, action, tone, urgency, className, placeholder, }: StateBannerProps): SafeHtml;
1373
+ declare function StateBanner({ title, detail, badge, icon, action, tone, urgency, className, placeholder, }: StateBannerProps): SafeHtml;
1364
1374
 
1365
1375
  export { StateBanner, type StateBannerProps, type StateBannerTone, type StateBannerUrgency };
1366
1376
  ```
@@ -1404,7 +1414,7 @@ export { LoadingSpinner, type LoadingSpinnerProps };
1404
1414
  import * as kerfjs from 'kerfjs';
1405
1415
 
1406
1416
  interface SkeletonProps {
1407
- /** Width as any CSS length (e.g. `remify(120px)`, `60%`). Defaults to filling its slot. */
1417
+ /** Width as any browser CSS length (e.g. `7.5rem`, `60%`). Defaults to filling its slot. */
1408
1418
  width?: string;
1409
1419
  /** Height as any CSS length. Defaults to a single text line. */
1410
1420
  height?: string;
@@ -1432,10 +1442,13 @@ export { Skeleton, type SkeletonProps };
1432
1442
  ```ts
1433
1443
  import { SafeHtml } from 'kerfjs';
1434
1444
 
1445
+ type SunkenPanelShape = 'rounded' | 'square';
1435
1446
  interface SunkenPanelProps {
1436
1447
  children?: SafeHtml | readonly SafeHtml[];
1437
1448
  /** Optional accessible landmark name for a distinct application region. */
1438
1449
  ariaLabel?: string;
1450
+ /** Corner shape: a rounded rectangle (default) or square corners. */
1451
+ shape?: SunkenPanelShape;
1439
1452
  className?: string;
1440
1453
  }
1441
1454
  /**
@@ -1443,9 +1456,9 @@ interface SunkenPanelProps {
1443
1456
  * stack. The panel owns its background and padding; children own their own
1444
1457
  * borders and internal geometry.
1445
1458
  */
1446
- declare function SunkenPanel({ children, ariaLabel, className, }: SunkenPanelProps): SafeHtml;
1459
+ declare function SunkenPanel({ children, ariaLabel, shape, className, }: SunkenPanelProps): SafeHtml;
1447
1460
 
1448
- export { SunkenPanel, type SunkenPanelProps };
1461
+ export { SunkenPanel, type SunkenPanelProps, type SunkenPanelShape };
1449
1462
  ```
1450
1463
 
1451
1464
  ## `@kerfjs/ui/token-search-field`
@@ -1578,7 +1591,7 @@ interface TokenSearchCollapsibleOptions {
1578
1591
  collapseOnEmptyBlur?: boolean;
1579
1592
  /** Collapse an empty field on Escape and restore focus to its trigger. Default: true. */
1580
1593
  collapseOnEscape?: boolean;
1581
- /** Focus the editor on expand and the trigger on Escape-collapse. Default: true. */
1594
+ /** Focus the editor on expand/controlled clear and the trigger on Escape-collapse. Default: true. */
1582
1595
  manageFocus?: boolean;
1583
1596
  /**
1584
1597
  * Keep an empty field expanded when focus moves to a caller-owned surface
package/ai/skill.md CHANGED
@@ -69,7 +69,7 @@ Quick routing:
69
69
  | Navigation row with a trailing action | `ListActionRow` | Use `ListItem` when the trailing region is dormant; never put controls inside either component's SafeHtml slots. Multiline leading icons stay aligned with the first text line. |
70
70
  | Page, panel, or dialog heading | `Toolbar` or `PanelHeader` | Toolbar is persistent chrome; `PanelHeader` heads a panel, dialog, or page. |
71
71
  | Exclusive choice | `TabBar`, `SegmentedControl`, or `Select` | Tabs switch tabpanels; segments expose a few choices; Select handles a longer value list. |
72
- | Status or absent content | `StateBanner` or `EmptyState` | Web Awesome callouts suit ecosystem content; toasts are transient and never the only record of important state. |
72
+ | Status or absent content | `StateBanner` or `EmptyState` | `StateBanner` accepts an optional terse, tone-tinted `badge` beside its title for a count or compact status; do not rely on color alone. Web Awesome callouts suit ecosystem content; toasts are transient and never the only record of important state. |
73
73
  | Loading placeholder | a component's `placeholder` prop, or `Skeleton` | Set `placeholder` on a value-bearing component (`Select`, `ListHeader`, `ListItem`, `ValueTableRow`, `PanelHeader`, `SegmentedControl`, `StateBanner`, `AppTab`, `ToolbarText`, `ListActionRow`) to render its real chrome with value slots as subtle **unanimated** skeletons and interactivity disabled — do not hand-rebuild an empty state. `Skeleton` is the standalone block for a custom slot. Use `LoadingSpinner` for known busy activity, not a skeleton; never animate a skeleton; prefer it over `wa-skeleton`. |
74
74
  | Adjustable or static columns | `ResizableRegion` or CSS grid | Use the component only for a user-operable controlled separator. |
75
75
  | Structured or ordinary search | `TokenSearchField` or an input | Use token search only when text and ordered filter chips form one editor. |
@@ -101,12 +101,12 @@ Hard rules:
101
101
  7. Decorative icons are hidden; controls are named; focus is visible; state never relies on color alone; reduced motion and increased contrast remain usable. `DisclosureArrow` defaults to an 18px root-scaled visual and exposes `--kui-disclosure-arrow-size` for consumer sizing; it never becomes the interaction or accessible-name owner. Put it in an owning native control with a stable accessible name and controlled `aria-expanded`. `ListHeader` toggle mode supplies it when `actionIcon` is omitted, but the app must reveal matching content; a custom icon replaces it. Author replacement icon content facing right before its configured direction transform is applied. Direction changes take the shortest rotation path, with counterclockwise chosen for a 180-degree closed-to-open tie. Kerf `Select` separately keeps its intrinsic Web Awesome expand glyph at `--kui-disclosure-icon-scale: .5`.
102
102
  8. `ResizableRegion` uses `wireResizableRegions()` for Arrow, Shift+Arrow, Home/End, and pointer behavior. The app owns size persistence. `handleIcon` replaces decorative dormant glyph content only.
103
103
  9. Use controlled `SegmentedControl` for a small exclusive choice set. Select `appearance="toolbar"` when nesting it inside `ToolbarControlGroup`; use rounded or pill shapes for standalone contexts. Handle its action, update `value`, keep meaningful choice labels, and preserve every enabled native button in sequential Tab order.
104
- 10. Compose `AppTab` inside controlled `TabBar`; call `wireTabBars()` once and retain its disposer. It owns same-bar drag mechanics, including proximity-based horizontal edge autoscroll, while the app applies `onReorder` and owns order, selection, panels, close policy, routing, and persistence. Arrow/Home/End select on move by default; pass `activation: 'manual'` (or `TabBar activation="manual"` per strip) so arrow keys move focus only and the user selects with Enter/Space/click — use it when selecting a tab is a heavy action. Use runtime-filtered `rootAttributes` for domain metadata and keep an optional `closeIcon` decorative and noninteractive.
105
- 11. Use token-controlled `TokenSearchField` when free text and removable structured filters share one editor. Editable text stays DOM-owned between token changes. The leading icon, first text line, clear action, and trailing slot share one fixed row when content wraps. The app owns parsing and suggestions; call `readTokenSearchField()` on input, empty `textContent` on clear, use `placeTokenSearchCaret()` after explicit controlled focus changes, and call `wireTokenSearchFields()` once so Enter submits without inserting a line break and keyboard chip deletion restores focus plus the text-relative caret after controlled replacement. Enable `collapsible` for an animated iconic closed state, standalone or inside `ToolbarControlGroup`; the field keeps text or tokens expanded, and `wireTokenSearchFields()` manages the transient expand/collapse/focus by default (activate to reveal + focus, Escape or empty blur to collapse). Bind the field's `expanded` to the returned handle's `expanded(id)` signal or adopt your own via `collapsible.signals`; opt a behavior out only when the app must own it. Do not hand-roll the open handler, the focusout collapse, or a clear-button mousedown guard — the helper owns them. For real-app adoption it also provides a focusout keep-open exception (`data-token-search-keep-open` regions or `collapsible.keepOpenOn(target)`, so a sibling suggestions/date/help surface does not collapse an empty field), opt-in atomic-chip keyboard (`keyboard`: Backspace/Delete remove the adjacent chip via `onRemoveToken`, ArrowRight moves the caret past a trailing chip), and an `onEdit({id, editor, event})` input callback (the `InputEvent` lets you gate on `inputType`/`data`) — reach for these instead of re-adding hand-rolled keydown/input handlers around the field.
104
+ 10. Compose `AppTab` inside controlled `TabBar`; call `wireTabBars()` once and retain its disposer. It owns same-bar drag mechanics, including proximity-based horizontal edge autoscroll, while the app applies `onReorder` and owns order, selection, panels, close policy, routing, and persistence. Arrow/Home/End select on move by default and restore focus by bar/tab identity when controlled activation replaces the strip; pass `activation: 'manual'` (or `TabBar activation="manual"` per strip) so arrow keys move focus only and the user selects with Enter/Space/click — use it when selecting a tab is a heavy action. Use runtime-filtered `rootAttributes` for domain metadata and keep an optional `closeIcon` decorative and noninteractive.
105
+ 11. Use token-controlled `TokenSearchField` when free text and removable structured filters share one editor. Editable text stays DOM-owned between token changes. The leading icon, first text line, clear action, and trailing slot share one fixed row when content wraps. The app owns parsing and suggestions; call `readTokenSearchField()` on input, empty `textContent` on clear, use `placeTokenSearchCaret()` after explicit controlled focus changes, and call `wireTokenSearchFields()` once so Enter submits without inserting a line break and keyboard chip deletion restores focus plus the text-relative caret after controlled replacement. Enable `collapsible` for an animated iconic closed state, standalone or inside `ToolbarControlGroup`; the field keeps text or tokens expanded, and `wireTokenSearchFields()` manages the transient expand/collapse/focus by default (activate to reveal + focus, Escape or empty blur to collapse). Bind the field's `expanded` to the returned handle's `expanded(id)` signal or adopt your own via `collapsible.signals`; opt a behavior out only when the app must own it. Do not hand-roll the open handler, the focusout collapse, a clear-button mousedown guard, or reopening after controlled clear — the helper keeps the replacement editor open and focused. For real-app adoption it also provides a focusout keep-open exception (`data-token-search-keep-open` regions or `collapsible.keepOpenOn(target)`, so a sibling suggestions/date/help surface does not collapse an empty field), opt-in atomic-chip keyboard (`keyboard`: Backspace/Delete remove the adjacent chip via `onRemoveToken`, ArrowRight moves the caret past a trailing chip), and an `onEdit({id, editor, event})` input callback (the `InputEvent` lets you gate on `inputType`/`data`) — reach for these instead of re-adding hand-rolled keydown/input handlers around the field.
106
106
  12. Demo work uses public production component subpaths and their browser-selected CSS. Give every public visual component its own category-grouped catalog route; list themed third-party components under a clearly labeled collapsible ecosystem section, with a focused route for each. For the complete focused/composition decision, `CatalogExample` / `CatalogExampleStack` row/group nesting, exact specimen selection, geometry-overlay legend and exclusions, skip-marker behavior, and metadata ownership, follow the single [Catalog demo authoring contract](../docs/catalog.md#catalog-demo-authoring-contract), discovered machine-readably through [`catalog-authoring.json`](./catalog-authoring.json). Never infer structure from private `kui-catalog-*` classes. Project each component's deterministic repository-relative demo source and existing documentation path so the detail can expose `View demo source` and `Read guidance` links without a runtime export; also derive first-party component implementation paths from their canonical browser imports, and label Web Awesome documentation as Kerf integration guidance. Declare direct `uses` relationships so `Used by` stays derivable, and theme shell chrome through the same semantic tokens as the stage instead of drawing a substitute. Enable `wireCatalog({ revealSelection: true })` for long desktop sidebars so controlled selections remain visible without moving focus; keep its default compact media guard unless compact scrolling is an explicit product behavior, and use `revealCatalogEntry` for an initial deep link.
107
107
  13. The Web Awesome theme makes Tooltip and Popover arrowless by default. Keep that default unless a pointer materially clarifies the anchor; opt back in with `--wa-tooltip-arrow-size`, `--kui-wa-popover-arrow-size`, or a popover's public `--arrow-size`, and use `without-arrow` when local no-arrow intent should survive theme changes. Its non-field chrome uses `--kui-wa-control-inset` (8px controls/items), `--kui-wa-surface-margin` / `--kui-wa-surface-inset` (8px around/inside Accordion, Card, Details, Callout, and Include), and `--kui-wa-container-inset` (16px Tab Panel content); override those tiers instead of restyling individual parts. Checkbox and Radio Group option regions, the Color Picker trigger, and Slider's complete interactive region receive the shared 8px logical inline outer inset because those controls have no bordered field shell. Known Date field captions and bordered text-like field hints align with values at the 9px border-plus-padding inset. OTP Input's label uses the same uppercase xs/650 treatment as other field labels, and both its label and hint use that 9px inset.
108
108
  14. Treat the complete Web Awesome catalog as support coverage, not a recommendation list. Its UX sidebar marks superseded and exceptional entries `Discouraged`. Consider Popup when it replaces custom anchored positioning. Prefer Kerf `Select` over direct Dropdown/Dropdown Item/Select/Option composition, `SegmentedControl` over Button Group, `TabBar` or `SegmentedControl` over Web Awesome Tabs, `LucideIcon` over Web Awesome Icon, and `ResizableRegion` over Split Panel. Use Tree/Tree Item, Animated Image, and Comparison only for a specific required behavior; avoid Zoomable Frame.
109
- 15. Build sidebars, main areas, inspectors, and dialogs from `@kerfjs/ui/layout.css`: an unpadded `.kui-pane`, optional `.kui-pane__toolbar`, one scrolling `.kui-pane__content`, and optional `.kui-pane__footer`. Add `.kui-content` for 24px major vertical separation and `.kui-content-item` for a child-owned 8px inline margin, 1px transparent-or-visible border, 8px padding, and 12px radius. Use the pill modifier for 22px. Do not pad pane shells or duplicate item geometry in wrappers.
109
+ 15. Build sidebars, main areas, inspectors, and dialogs from `@kerfjs/ui/layout.css`: an unpadded `.kui-pane`, optional `.kui-pane__toolbar`, one scrolling `.kui-pane__content`, and optional `.kui-pane__footer`. Use `List` instead of a hand-written flex-column wrapper when rows or sections need stretch alignment, standard/custom gap, flex growth, one vertical scroll owner, or physical-edge dividers; `dividerSides` uses canonical `t`/`r`/`b`/`l` order. Add `.kui-content` for 24px major vertical separation and `.kui-content-item` for a child-owned 8px inline margin, 1px transparent-or-visible border, 8px padding, and 12px radius. Use the pill modifier for 22px. Do not pad pane shells, duplicate item geometry in wrappers, or create nested scroll owners.
110
110
  16. Keep a visible collapsible pane's collapse control in its own toolbar. When hidden, move its restore control into the adjacent main toolbar on the corresponding logical edge: leading for an inline-start sidebar and trailing for an inline-end inspector. Collapse the pane completely; do not preserve an empty icon-only rail.
111
111
  17. The only direct children of a `Toolbar` zone (`leading`/`center`/`trailing`) are `ToolbarText` (identity/title text) and `ToolbarControlGroup`; never drop bare buttons, inputs, links, or arbitrary markup straight into a zone. `SegmentedControl`, `Select`, a collapsible `TokenSearchField`, and Web Awesome controls all live inside a `ToolbarControlGroup`. For an ordinary icon/action control inside a group, use a plain `<button>` (the group styles `> button` fully) — that is the default; reach for `wa-button` only when you need a Web Awesome feature, chiefly a `wa-dropdown` popup trigger. A popup menu in a toolbar is a `single` `ToolbarControlGroup` wrapping a `wa-dropdown` whose `slot="trigger"` `wa-button` is the toolbar button and whose `wa-dropdown-item`s are the menu, with the dropdown kept under `data-morph-skip-children`. `PanelHeader` composes these for you as a panel/dialog/page heading. Wrap every toolbar item, including dormant text, in `ToolbarControlGroup`. A group remains 44px outside (`calc(2px + remify(42px))`) when its border/background are transparent; use 8px between groups and inside items. Split dormant and interactive regions: `ListHeader` fills the available inline width and keeps its label and mutually exclusive semantic count or non-count `badge` together, with an independent logical-end 44px action unless disclosure mode makes the title cluster the button. Its action visual defaults to 18px through `--kui-list-header-action-icon-size`; never shrink the target to match it. Pass every non-negative safe-integer section quantity through `count` with a localized full spoken `countLabel`; never concatenate it into `label` or put a number in `badge`. `ListItem.trailing` is dormant; use `ListActionRow` when primary and trailing actions need sibling 44px native buttons. Its `label`, `icon`, and `trailingActionIcon` slots are also dormant and cannot contain controls. Let panes relocate at narrow widths instead of shrinking targets.
112
112
  18. When a recurring concept has no matching export or production recipe, keep its semantics in a thin application adapter while reusing the public layout vocabulary. The composer recipe uses one visible form surface, `PanelHeader` title/summary ids, shared 8px field/action gutters, 24px major rhythm, and a conditional StateBanner as its only nested semantic surface; do not turn every section into a card or double-inset intrinsically bordered controls. The application-local `../docs/examples/command-palette-adapter.tsx` is reference source for one such missing concept, not an `@kerfjs/ui` runtime export or catalog recipe. The application owns its registration, ranking, history, permissions, availability, shortcut policy, focus policy, dispatch, and copy. If a missing concept recurs across products, open an upstream component or recipe request.
@@ -1,6 +1,6 @@
1
1
  # Web Awesome JSX signatures for the UI authoring corpus
2
2
 
3
- Generated from the emitted `@kerfjs/ui@5.0.0-beta.23` declaration boundary. Import `@kerfjs/ui/webawesome` for type effects when authoring direct `wa-*` JSX. The module emits no runtime behavior and does not register custom elements.
3
+ Generated from the emitted `@kerfjs/ui@5.0.0-beta.24` declaration boundary. Import `@kerfjs/ui/webawesome` for type effects when authoring direct `wa-*` JSX. The module emits no runtime behavior and does not register custom elements.
4
4
 
5
5
  ```ts
6
6
  import { KerfCustomElement } from 'kerfjs/jsx-runtime';
package/dist/app-tab.js CHANGED
@@ -1,4 +1,4 @@
1
- export { AppTab } from './chunk-PIDTEQ3U.js';
1
+ export { AppTab } from './chunk-Y45PPBDV.js';
2
2
 
3
3
 
4
4
 
@@ -0,0 +1,3 @@
1
+ import '../styles/foundation.css';
2
+ import '../styles/list.css';
3
+ export * from '../list.js';