@kerfjs/ui 5.0.0-beta.76 → 5.0.0-beta.78

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 (147) hide show
  1. package/README.md +15 -0
  2. package/ai/application-ui-diagnostic-ids-v1.json +3 -0
  3. package/ai/component-catalog.json +333 -28
  4. package/ai/component-composition.json +224 -17
  5. package/ai/components/nav-stack.md +4 -3
  6. package/ai/components/select.md +1 -0
  7. package/ai/components/split-view.md +1 -0
  8. package/ai/components/surface-scaffold.md +11 -2
  9. package/ai/components/text.md +4 -2
  10. package/ai/components/toolbar-control-group.md +22 -3
  11. package/ai/components/toolbar-text.md +21 -4
  12. package/ai/components/toolbar.md +12 -4
  13. package/ai/public-api-signatures-v1.md +99 -127
  14. package/ai/skill.md +37 -3
  15. package/ai/webawesome-jsx-signatures-v1.md +1 -1
  16. package/dist/browser/nav-stack.js +2 -0
  17. package/dist/browser/split-view.js +2 -0
  18. package/dist/catalog-resources.d.ts +3 -3
  19. package/dist/catalog.d.ts +3 -3
  20. package/dist/catalog.js +6 -6
  21. package/dist/chunk-2GOCOLQL.js +270 -0
  22. package/dist/chunk-2GOCOLQL.js.map +1 -0
  23. package/dist/{chunk-ZVYA6TLR.js → chunk-4Y4L5YEI.js} +3 -1
  24. package/dist/chunk-4Y4L5YEI.js.map +1 -0
  25. package/dist/{chunk-XIZRXI7N.js → chunk-A7DYEERU.js} +13 -1
  26. package/dist/chunk-A7DYEERU.js.map +1 -0
  27. package/dist/{chunk-7QWIJEK5.js → chunk-DSLRNR43.js} +9 -8
  28. package/dist/chunk-DSLRNR43.js.map +1 -0
  29. package/dist/{chunk-AOAW55JN.js → chunk-DXQZ3BEO.js} +4 -1
  30. package/dist/chunk-DXQZ3BEO.js.map +1 -0
  31. package/dist/chunk-IKCUPTR2.js +170 -0
  32. package/dist/chunk-IKCUPTR2.js.map +1 -0
  33. package/dist/{chunk-HGSTMZZ6.js → chunk-JL4BBZP4.js} +5 -4
  34. package/dist/chunk-JL4BBZP4.js.map +1 -0
  35. package/dist/{chunk-IVLTEBBT.js → chunk-M6BWQMQY.js} +2 -2
  36. package/dist/{chunk-IVLTEBBT.js.map → chunk-M6BWQMQY.js.map} +1 -1
  37. package/dist/{chunk-72LLWYP2.js → chunk-NVKRZ5DI.js} +1 -1
  38. package/dist/chunk-NVKRZ5DI.js.map +1 -0
  39. package/dist/{chunk-GO2CZX4M.js → chunk-RRCD3A6G.js} +13 -5
  40. package/dist/chunk-RRCD3A6G.js.map +1 -0
  41. package/dist/{chunk-5PAVAR4B.js → chunk-VHXHLZ6R.js} +10 -1
  42. package/dist/chunk-VHXHLZ6R.js.map +1 -0
  43. package/dist/collapsible-panel.js +2 -2
  44. package/dist/index.d.ts +4 -3
  45. package/dist/index.js +9 -8
  46. package/dist/list-header.d.ts +1 -0
  47. package/dist/list-header.js +1 -1
  48. package/dist/nav-stack-B1Qc2e5q.d.ts +101 -0
  49. package/dist/nav-stack.d.ts +12 -93
  50. package/dist/nav-stack.js +5 -1
  51. package/dist/pane.d.ts +5 -2
  52. package/dist/pane.js +1 -1
  53. package/dist/select-register.js +3 -0
  54. package/dist/select-register.js.map +1 -1
  55. package/dist/select.d.ts +1 -0
  56. package/dist/select.js +1 -1
  57. package/dist/split-view.d.ts +9 -4
  58. package/dist/split-view.js +7 -3
  59. package/dist/split-view.js.map +1 -1
  60. package/dist/styles/components/actions/toolbar/toolbar.css +32 -0
  61. package/dist/styles/components/actions/toolbar-control-group/toolbar-control-group.css +105 -7
  62. package/dist/styles/components/actions/toolbar-text/toolbar-text.css +17 -0
  63. package/dist/styles/components/layout/pane/pane.css +7 -0
  64. package/dist/styles/components/navigation/nav-stack/nav-stack.css +17 -12
  65. package/dist/styles/components/navigation/tab-scaffold/tab-scaffold.css +17 -0
  66. package/dist/styles/components/surfaces/surface-scaffold/surface-scaffold.css +55 -0
  67. package/dist/styles/components/typography/text/text.css +19 -0
  68. package/dist/styles/nav-stack.css +17 -12
  69. package/dist/styles/pane.css +7 -0
  70. package/dist/styles/surface-scaffold.css +55 -0
  71. package/dist/styles/tab-scaffold.css +17 -0
  72. package/dist/styles/text.css +19 -0
  73. package/dist/styles/toolbar-control-group.css +105 -7
  74. package/dist/styles/toolbar-text.css +17 -0
  75. package/dist/styles/toolbar.css +32 -0
  76. package/dist/surface-scaffold-register.d.ts +4 -0
  77. package/dist/surface-scaffold-register.js +59 -0
  78. package/dist/surface-scaffold-register.js.map +1 -0
  79. package/dist/surface-scaffold.d.ts +10 -2
  80. package/dist/surface-scaffold.js +1 -1
  81. package/dist/tab-scaffold.d.ts +2 -0
  82. package/dist/tab-scaffold.js +1 -0
  83. package/dist/tab-scaffold.js.map +1 -1
  84. package/dist/text.d.ts +5 -2
  85. package/dist/text.js +1 -1
  86. package/dist/toolbar-control-group.d.ts +14 -2
  87. package/dist/toolbar-control-group.js +1 -1
  88. package/dist/toolbar-text.d.ts +10 -2
  89. package/dist/toolbar-text.js +1 -1
  90. package/dist/wire-nav-stack.js +58 -22
  91. package/dist/wire-nav-stack.js.map +1 -1
  92. package/dist/wire-toolbar-visibility.d.ts +13 -0
  93. package/dist/wire-toolbar-visibility.js +3 -0
  94. package/dist/wire-toolbar-visibility.js.map +1 -0
  95. package/dist/workbench.d.ts +5 -13
  96. package/dist/workbench.js +1 -1
  97. package/docs/accessibility.md +15 -0
  98. package/docs/collapsible-panel.md +4 -0
  99. package/docs/component-contract.md +38 -0
  100. package/docs/component-selection.md +56 -2
  101. package/docs/design/templates/toolbar/width-visibility-320-dark.svg +1 -0
  102. package/docs/design/templates/toolbar/width-visibility-320.svg +1 -0
  103. package/docs/design/templates/toolbar/width-visibility-600-dark.svg +1 -0
  104. package/docs/design/templates/toolbar/width-visibility-600.svg +1 -0
  105. package/docs/design/templates/toolbar-control-group/icon-tile-brand-dark.svg +1 -0
  106. package/docs/design/templates/toolbar-control-group/icon-tile-brand.svg +1 -0
  107. package/docs/design/templates/toolbar-control-group/icon-tile-danger-dark.svg +1 -0
  108. package/docs/design/templates/toolbar-control-group/icon-tile-danger.svg +1 -0
  109. package/docs/design/templates/toolbar-control-group/icon-tile-neutral-dark.svg +1 -0
  110. package/docs/design/templates/toolbar-control-group/icon-tile-neutral.svg +1 -0
  111. package/docs/design/templates/toolbar-control-group/icon-tile-success-dark.svg +1 -0
  112. package/docs/design/templates/toolbar-control-group/icon-tile-success.svg +1 -0
  113. package/docs/design/templates/toolbar-control-group/icon-tile-warning-dark.svg +1 -0
  114. package/docs/design/templates/toolbar-control-group/icon-tile-warning.svg +1 -0
  115. package/docs/design/templates/toolbar-control-group-dark.svg +1 -1
  116. package/docs/design/templates/toolbar-control-group.svg +1 -1
  117. package/docs/design/templates/toolbar-dark.svg +1 -1
  118. package/docs/design/templates/toolbar-text/dark-tone-dark.svg +1 -0
  119. package/docs/design/templates/toolbar-text/dark-tone.svg +1 -0
  120. package/docs/design/templates/toolbar-text-dark.svg +1 -1
  121. package/docs/design/templates/toolbar-text.svg +1 -1
  122. package/docs/design/templates/toolbar.svg +1 -1
  123. package/docs/design/templates.md +2 -0
  124. package/docs/layout.md +32 -1
  125. package/docs/nav-stack.md +35 -19
  126. package/docs/recipes.md +5 -1
  127. package/docs/split-view.md +7 -4
  128. package/docs/surface-scaffold.md +46 -0
  129. package/docs/tab-scaffold.md +57 -0
  130. package/docs/ui-doctor.md +23 -0
  131. package/docs/workbench.md +3 -2
  132. package/doctor/component-style-checks.mjs +224 -0
  133. package/doctor/index.mjs +42 -13
  134. package/llms.txt +34 -0
  135. package/package.json +11 -2
  136. package/ux-demo/recipes/list-detail-dialog.tsx +4 -0
  137. package/ux-demo/recipes/navigation-stack.tsx +2 -2
  138. package/dist/chunk-5PAVAR4B.js.map +0 -1
  139. package/dist/chunk-72LLWYP2.js.map +0 -1
  140. package/dist/chunk-7QWIJEK5.js.map +0 -1
  141. package/dist/chunk-AOAW55JN.js.map +0 -1
  142. package/dist/chunk-GO2CZX4M.js.map +0 -1
  143. package/dist/chunk-HGSTMZZ6.js.map +0 -1
  144. package/dist/chunk-SJY7KC45.js +0 -123
  145. package/dist/chunk-SJY7KC45.js.map +0 -1
  146. package/dist/chunk-XIZRXI7N.js.map +0 -1
  147. package/dist/chunk-ZVYA6TLR.js.map +0 -1
@@ -697,7 +697,7 @@
697
697
  "required": false
698
698
  },
699
699
  {
700
- "id": "view content and titles",
700
+ "id": "view content and structured top and bottom toolbar configurations",
701
701
  "owner": "application",
702
702
  "required": false
703
703
  },
@@ -712,7 +712,7 @@
712
712
  "required": false
713
713
  },
714
714
  {
715
- "id": "per-view bottom toolbar content or a persistent fallback",
715
+ "id": "per-view bottom toolbar or a persistent structured fallback",
716
716
  "owner": "application",
717
717
  "required": false
718
718
  },
@@ -722,12 +722,12 @@
722
722
  "required": false
723
723
  },
724
724
  {
725
- "id": "per-view fixed header content above the active view's scroll area",
725
+ "id": "per-view header and footer with List and Pane configuration",
726
726
  "owner": "application",
727
727
  "required": false
728
728
  },
729
729
  {
730
- "id": "top-toolbar configuration, title size, and heading level",
730
+ "id": "top-toolbar defaults, title size, and heading level",
731
731
  "owner": "application",
732
732
  "required": false
733
733
  },
@@ -754,6 +754,12 @@
754
754
  "helper": "wireNavStack",
755
755
  "meaning": "Marks the inert, aria-hidden snapshot of the outgoing chrome shown during the cross-fade."
756
756
  },
757
+ {
758
+ "name": "data-nav-revealed",
759
+ "on": "kui-nav-stack__view",
760
+ "helper": "wireNavStack",
761
+ "meaning": "\"true\" on the preserved, aria-hidden previous view while an incoming view slides over it."
762
+ },
757
763
  {
758
764
  "name": "data-nav-exiting",
759
765
  "on": "kui-nav-stack__view",
@@ -806,7 +812,6 @@
806
812
  "kui-nav-stack__chrome-copy",
807
813
  "kui-nav-stack__chrome-copy--bottom",
808
814
  "kui-nav-stack__chrome-copy--exiting",
809
- "kui-nav-stack__header",
810
815
  "kui-nav-stack__viewport",
811
816
  "kui-nav-stack__view",
812
817
  "kui-nav-stack__view--entering",
@@ -908,6 +913,12 @@
908
913
  "helper": "wireNavStack",
909
914
  "meaning": "Marks the inert, aria-hidden snapshot of the outgoing chrome shown during the cross-fade."
910
915
  },
916
+ {
917
+ "name": "data-nav-revealed",
918
+ "on": "kui-nav-stack__view",
919
+ "helper": "wireNavStack",
920
+ "meaning": "\"true\" on the preserved, aria-hidden previous view while an incoming view slides over it."
921
+ },
911
922
  {
912
923
  "name": "data-nav-exiting",
913
924
  "on": "kui-nav-stack__view",
@@ -1460,7 +1471,7 @@
1460
1471
  ],
1461
1472
  "wiring": {
1462
1473
  "required": false,
1463
- "helpers": ["wireScrollDividers"],
1474
+ "helpers": ["wireScrollDividers", "wireToolbarVisibility"],
1464
1475
  "obligations": [],
1465
1476
  "stateAttributes": [
1466
1477
  {
@@ -1474,6 +1485,30 @@
1474
1485
  "on": "a Toolbar named as targets chrome",
1475
1486
  "helper": "wireScrollDividers",
1476
1487
  "meaning": "The sides, in t/r/b/l order, on which this chrome currently draws its scroll divider: the side facing the scroller while content is hidden beyond it. Re-applied if a re-render drops it."
1488
+ },
1489
+ {
1490
+ "name": "data-toolbar-width-hidden",
1491
+ "on": "ToolbarText, ToolbarControlGroup and its paired busy status",
1492
+ "helper": "wireToolbarVisibility",
1493
+ "meaning": "True when typed hideBelow/showBelow thresholds hide this item at the nearest Toolbar content width. Re-applied after rendering; disposal restores prior markers."
1494
+ },
1495
+ {
1496
+ "name": "data-toolbar-visibility-probe",
1497
+ "on": "private aria-hidden measurement boxes under Toolbar",
1498
+ "helper": "wireToolbarVisibility",
1499
+ "meaning": "Internal out-of-flow CSS length resolver; created and removed by wireToolbarVisibility."
1500
+ },
1501
+ {
1502
+ "name": "data-morph-preserve",
1503
+ "on": "private aria-hidden measurement boxes and visibility state children",
1504
+ "helper": "wireToolbarVisibility",
1505
+ "meaning": "Keeps helper-owned geometry and state across Kerf renders; replacement and explicit removal are repaired, and disposal removes them."
1506
+ },
1507
+ {
1508
+ "name": "data-toolbar-visibility-state",
1509
+ "on": "private hidden children of width-managed items and paired busy statuses",
1510
+ "helper": "wireToolbarVisibility",
1511
+ "meaning": "Preserves actual CSS visibility while rendering removes a transient parent marker, preventing geometry-driven render feedback."
1477
1512
  }
1478
1513
  ]
1479
1514
  },
@@ -1570,9 +1605,34 @@
1570
1605
  ],
1571
1606
  "wiring": {
1572
1607
  "required": false,
1573
- "helpers": [],
1608
+ "helpers": ["wireToolbarVisibility"],
1574
1609
  "obligations": [],
1575
- "stateAttributes": []
1610
+ "stateAttributes": [
1611
+ {
1612
+ "name": "data-toolbar-width-hidden",
1613
+ "on": "ToolbarText, ToolbarControlGroup and its paired busy status",
1614
+ "helper": "wireToolbarVisibility",
1615
+ "meaning": "True when typed hideBelow/showBelow thresholds hide this item at the nearest Toolbar content width. Re-applied after rendering; disposal restores prior markers."
1616
+ },
1617
+ {
1618
+ "name": "data-toolbar-visibility-probe",
1619
+ "on": "private aria-hidden measurement boxes under Toolbar",
1620
+ "helper": "wireToolbarVisibility",
1621
+ "meaning": "Internal out-of-flow CSS length resolver; created and removed by wireToolbarVisibility."
1622
+ },
1623
+ {
1624
+ "name": "data-morph-preserve",
1625
+ "on": "private aria-hidden measurement boxes and visibility state children",
1626
+ "helper": "wireToolbarVisibility",
1627
+ "meaning": "Keeps helper-owned geometry and state across Kerf renders; replacement and explicit removal are repaired, and disposal removes them."
1628
+ },
1629
+ {
1630
+ "name": "data-toolbar-visibility-state",
1631
+ "on": "private hidden children of width-managed items and paired busy statuses",
1632
+ "helper": "wireToolbarVisibility",
1633
+ "meaning": "Preserves actual CSS visibility while rendering removes a transient parent marker, preventing geometry-driven render feedback."
1634
+ }
1635
+ ]
1576
1636
  },
1577
1637
  "responsive": { "owner": "not-applicable", "behaviors": [] },
1578
1638
  "layout": {
@@ -1585,7 +1645,30 @@
1585
1645
  "Name an icon-only button or link with aria-label, not title. Once any help-tag installer is imported (select/register, popup-menu/register, or help-tags/register), it shows an aria-hidden Web Awesome help tag repeating that name after a 500ms hover and at once on keyboard focus, hidden on a press and on Escape, and never joins aria-labelledby. A native title keeps the browser tooltip and gets no second tag."
1586
1646
  ]
1587
1647
  },
1588
- "cssValueProps": [],
1648
+ "cssValueProps": [
1649
+ {
1650
+ "path": "hideBelow",
1651
+ "grammar": "length",
1652
+ "helpers": ["px", "rem", "em", "pct", "space", "lengthVar", "calc"],
1653
+ "nonStandaloneHelpers": ["plus"],
1654
+ "shorthands": [],
1655
+ "canonicalShorthands": [],
1656
+ "exceptionalShorthands": [],
1657
+ "rawPolicy": "forbid",
1658
+ "examples": ["hideBelow={px(416)}"]
1659
+ },
1660
+ {
1661
+ "path": "showBelow",
1662
+ "grammar": "length",
1663
+ "helpers": ["px", "rem", "em", "pct", "space", "lengthVar", "calc"],
1664
+ "nonStandaloneHelpers": ["plus"],
1665
+ "shorthands": [],
1666
+ "canonicalShorthands": [],
1667
+ "exceptionalShorthands": [],
1668
+ "rawPolicy": "forbid",
1669
+ "examples": ["showBelow={px(416)}"]
1670
+ }
1671
+ ],
1589
1672
  "boundaries": {
1590
1673
  "rootClass": "kui-toolbar-control-group",
1591
1674
  "publicClasses": [
@@ -1617,7 +1700,20 @@
1617
1700
  "--kui-toolbar-control-pressed-color",
1618
1701
  "--kui-toolbar-control-selected-background",
1619
1702
  "--kui-toolbar-control-selected-color",
1620
- "--kui-toolbar-control-selected-shadow"
1703
+ "--kui-toolbar-control-selected-shadow",
1704
+ "--kui-color-neutral-fill-quiet",
1705
+ "--kui-color-neutral-border-quiet",
1706
+ "--kui-color-brand-fill-quiet",
1707
+ "--kui-color-brand-border-quiet",
1708
+ "--kui-color-success-fill-quiet",
1709
+ "--kui-color-success-border-quiet",
1710
+ "--kui-color-success-on-quiet",
1711
+ "--kui-color-warning-fill-quiet",
1712
+ "--kui-color-warning-border-quiet",
1713
+ "--kui-color-warning-on-quiet",
1714
+ "--kui-color-danger-fill-quiet",
1715
+ "--kui-color-danger-border-quiet",
1716
+ "--kui-color-danger-on-quiet"
1621
1717
  ]
1622
1718
  },
1623
1719
  "diagnostics": [],
@@ -1669,7 +1765,68 @@
1669
1765
  "Use popup surfaces only for real dropdown menus with named triggers."
1670
1766
  ]
1671
1767
  },
1672
- "cssValueProps": [],
1768
+ "cssValueProps": [
1769
+ {
1770
+ "path": "preferredWidth",
1771
+ "grammar": "length",
1772
+ "helpers": [
1773
+ "px",
1774
+ "rem",
1775
+ "remify",
1776
+ "em",
1777
+ "pct",
1778
+ "space",
1779
+ "lengthVar",
1780
+ "calc"
1781
+ ],
1782
+ "nonStandaloneHelpers": ["plus"],
1783
+ "shorthands": [],
1784
+ "canonicalShorthands": [],
1785
+ "exceptionalShorthands": [],
1786
+ "rawPolicy": "forbid",
1787
+ "examples": ["preferredWidth={remify(832)}"]
1788
+ },
1789
+ {
1790
+ "path": "viewportGutter",
1791
+ "grammar": "length",
1792
+ "helpers": [
1793
+ "px",
1794
+ "rem",
1795
+ "remify",
1796
+ "em",
1797
+ "pct",
1798
+ "space",
1799
+ "lengthVar",
1800
+ "calc"
1801
+ ],
1802
+ "nonStandaloneHelpers": ["plus"],
1803
+ "shorthands": [],
1804
+ "canonicalShorthands": [],
1805
+ "exceptionalShorthands": [],
1806
+ "rawPolicy": "forbid",
1807
+ "examples": ["viewportGutter={remify(8)}"]
1808
+ },
1809
+ {
1810
+ "path": "maxHeight",
1811
+ "grammar": "length",
1812
+ "helpers": [
1813
+ "px",
1814
+ "rem",
1815
+ "remify",
1816
+ "em",
1817
+ "pct",
1818
+ "space",
1819
+ "lengthVar",
1820
+ "calc"
1821
+ ],
1822
+ "nonStandaloneHelpers": ["plus"],
1823
+ "shorthands": ["viewport"],
1824
+ "canonicalShorthands": ["viewport"],
1825
+ "exceptionalShorthands": [],
1826
+ "rawPolicy": "forbid",
1827
+ "examples": ["maxHeight=\"viewport\"", "maxHeight={remify(640)}"]
1828
+ }
1829
+ ],
1673
1830
  "boundaries": {
1674
1831
  "rootClass": "kui-dialog-surface",
1675
1832
  "publicClasses": ["kui-dialog-surface", "kui-popup-surface"],
@@ -1775,9 +1932,34 @@
1775
1932
  ],
1776
1933
  "wiring": {
1777
1934
  "required": false,
1778
- "helpers": [],
1935
+ "helpers": ["wireToolbarVisibility"],
1779
1936
  "obligations": [],
1780
- "stateAttributes": []
1937
+ "stateAttributes": [
1938
+ {
1939
+ "name": "data-toolbar-width-hidden",
1940
+ "on": "ToolbarText, ToolbarControlGroup and its paired busy status",
1941
+ "helper": "wireToolbarVisibility",
1942
+ "meaning": "True when typed hideBelow/showBelow thresholds hide this item at the nearest Toolbar content width. Re-applied after rendering; disposal restores prior markers."
1943
+ },
1944
+ {
1945
+ "name": "data-toolbar-visibility-probe",
1946
+ "on": "private aria-hidden measurement boxes under Toolbar",
1947
+ "helper": "wireToolbarVisibility",
1948
+ "meaning": "Internal out-of-flow CSS length resolver; created and removed by wireToolbarVisibility."
1949
+ },
1950
+ {
1951
+ "name": "data-morph-preserve",
1952
+ "on": "private aria-hidden measurement boxes and visibility state children",
1953
+ "helper": "wireToolbarVisibility",
1954
+ "meaning": "Keeps helper-owned geometry and state across Kerf renders; replacement and explicit removal are repaired, and disposal removes them."
1955
+ },
1956
+ {
1957
+ "name": "data-toolbar-visibility-state",
1958
+ "on": "private hidden children of width-managed items and paired busy statuses",
1959
+ "helper": "wireToolbarVisibility",
1960
+ "meaning": "Preserves actual CSS visibility while rendering removes a transient parent marker, preventing geometry-driven render feedback."
1961
+ }
1962
+ ]
1781
1963
  },
1782
1964
  "responsive": { "owner": "not-applicable", "behaviors": [] },
1783
1965
  "layout": {
@@ -1790,7 +1972,30 @@
1790
1972
  "Actionable text is a native button with its full text as its accessible name; action cannot be combined with headingLevel, placeholder, or wrap."
1791
1973
  ]
1792
1974
  },
1793
- "cssValueProps": [],
1975
+ "cssValueProps": [
1976
+ {
1977
+ "path": "hideBelow",
1978
+ "grammar": "length",
1979
+ "helpers": ["px", "rem", "em", "pct", "space", "lengthVar", "calc"],
1980
+ "nonStandaloneHelpers": ["plus"],
1981
+ "shorthands": [],
1982
+ "canonicalShorthands": [],
1983
+ "exceptionalShorthands": [],
1984
+ "rawPolicy": "forbid",
1985
+ "examples": ["hideBelow={px(416)}"]
1986
+ },
1987
+ {
1988
+ "path": "showBelow",
1989
+ "grammar": "length",
1990
+ "helpers": ["px", "rem", "em", "pct", "space", "lengthVar", "calc"],
1991
+ "nonStandaloneHelpers": ["plus"],
1992
+ "shorthands": [],
1993
+ "canonicalShorthands": [],
1994
+ "exceptionalShorthands": [],
1995
+ "rawPolicy": "forbid",
1996
+ "examples": ["showBelow={px(416)}"]
1997
+ }
1998
+ ],
1794
1999
  "boundaries": {
1795
2000
  "rootClass": "kui-toolbar-text",
1796
2001
  "publicClasses": ["kui-toolbar-text"],
@@ -1802,7 +2007,8 @@
1802
2007
  "--kui-font-l",
1803
2008
  "--kui-font-m",
1804
2009
  "--kui-font-s",
1805
- "--kui-font-xs"
2010
+ "--kui-font-xs",
2011
+ "--kui-color-neutral-on-loud"
1806
2012
  ]
1807
2013
  },
1808
2014
  "diagnostics": [],
@@ -1849,11 +2055,12 @@
1849
2055
  "layout": {
1850
2056
  "roles": ["structure"],
1851
2057
  "geometry": {
1852
- "margin": "none",
2058
+ "margin": "self",
1853
2059
  "border": "self",
1854
2060
  "padding": "self",
1855
2061
  "notes": [
1856
- "Block Text variants reset native margins and add a 1px transparent border plus the standard 8px item padding; flush removes the border and padding. Tight line height is available for compact copy. Span has no margin, border, or padding. FieldLabel mirrors the themed Web Awesome label typography, 9px inline inset, and bottom gap."
2062
+ "Block Text variants reset native margins and add a 1px transparent border plus the standard 8px item padding; flush removes the border and padding. Tight line height is available for compact copy. Span has no margin by default, border, or padding. FieldLabel mirrors the themed Web Awesome label typography, 9px inline inset, and bottom gap.",
2063
+ "controlMargins adds the shared control gutter outside selected physical edges without changing border or padding; avoid duplicating a parent inset. Spans retain inline display and native inline margin behavior."
1857
2064
  ]
1858
2065
  }
1859
2066
  },
@@ -57,7 +57,7 @@ Exact prop names and types: [`@kerfjs/ui/nav-stack`](../public-api-signatures-v1
57
57
 
58
58
  ## State and wiring
59
59
 
60
- **The app owns:** ordered view stack and stable keys; view content and titles; push and pop actions; preferred initial focus targets when DOM order is insufficient; per-view bottom toolbar content or a persistent fallback; per-view leading, center, and trailing top-toolbar groups; per-view fixed header content above the active view's scroll area; top-toolbar configuration, title size, and heading level; whether the chrome and bottom-toolbar dividers follow the scroll, always show, or never show (chromeDividers).
60
+ **The app owns:** ordered view stack and stable keys; view content and structured top and bottom toolbar configurations; push and pop actions; preferred initial focus targets when DOM order is insufficient; per-view bottom toolbar or a persistent structured fallback; per-view leading, center, and trailing top-toolbar groups; per-view header and footer with List and Pane configuration; top-toolbar defaults, title size, and heading level; whether the chrome and bottom-toolbar dividers follow the scroll, always show, or never show (chromeDividers).
61
61
 
62
62
  **Wiring:** `wireNavStack`, `wireScrollDividers` is required.
63
63
 
@@ -67,6 +67,7 @@ Exact prop names and types: [`@kerfjs/ui/nav-stack`](../public-api-signatures-v1
67
67
 
68
68
  - `data-nav-chrome-transition` on `kui-nav-stack` (`wireNavStack`): "true" while the chrome cross-fades between the outgoing and incoming view.
69
69
  - `data-nav-chrome-copy` on `kui-nav-stack__chrome-copy` (`wireNavStack`): Marks the inert, aria-hidden snapshot of the outgoing chrome shown during the cross-fade.
70
+ - `data-nav-revealed` on `kui-nav-stack__view` (`wireNavStack`): "true" on the preserved, aria-hidden previous view while an incoming view slides over it.
70
71
  - `data-nav-exiting` on `kui-nav-stack__view` (`wireNavStack`): "true" on a popped view the helper briefly re-inserts to slide it out.
71
72
  - `data-scroll-overflow` on `the active kui-nav-stack__view, or the kui-pane__content of a sole Pane in it` (`wireScrollDividers`): The physical edges, in canonical t/r/b/l order, beyond which content is scrolled out of view; absent when nothing is hidden (content that fits never reports its far edges). Re-applied if a re-render drops it.
72
73
  - `data-scroll-divider` on `kui-nav-stack__chrome and kui-nav-stack__bottom` (`wireScrollDividers`): The sides, in t/r/b/l order, on which this chrome currently draws its scroll divider: the side facing the scroller while content is hidden beyond it. Re-applied if a re-render drops it.
@@ -89,9 +90,9 @@ Margin: none · border: conditional · padding: child (layout role: structure).
89
90
 
90
91
  The component owns its own styles. Configure it through its props and variants; do not override its internals.
91
92
 
92
- Public class hooks (select for layout placement only, never to change the component's look): `kui-nav-stack`, `kui-nav-stack__chrome`, `kui-nav-stack__bottom`, `kui-nav-stack__chrome--entering`, `kui-nav-stack__chrome-copy`, `kui-nav-stack__chrome-copy--bottom`, `kui-nav-stack__chrome-copy--exiting`, `kui-nav-stack__header`, `kui-nav-stack__viewport`, `kui-nav-stack__view`, `kui-nav-stack__view--entering`, `kui-nav-stack__view--exiting`.
93
+ Public class hooks (select for layout placement only, never to change the component's look): `kui-nav-stack`, `kui-nav-stack__chrome`, `kui-nav-stack__bottom`, `kui-nav-stack__chrome--entering`, `kui-nav-stack__chrome-copy`, `kui-nav-stack__chrome-copy--bottom`, `kui-nav-stack__chrome-copy--exiting`, `kui-nav-stack__viewport`, `kui-nav-stack__view`, `kui-nav-stack__view--entering`, `kui-nav-stack__view--exiting`.
93
94
 
94
- Never put `kui-nav-stack`, `kui-nav-stack__chrome`, `kui-nav-stack__bottom`, `kui-nav-stack__chrome--entering`, `kui-nav-stack__chrome-copy`, `kui-nav-stack__chrome-copy--bottom`, `kui-nav-stack__chrome-copy--exiting`, `kui-nav-stack__header`, `kui-nav-stack__viewport`, `kui-nav-stack__view`, `kui-nav-stack__view--entering`, `kui-nav-stack__view--exiting` on an element you write; render `NavStack` instead (`KUI-L103`).
95
+ Never put `kui-nav-stack`, `kui-nav-stack__chrome`, `kui-nav-stack__bottom`, `kui-nav-stack__chrome--entering`, `kui-nav-stack__chrome-copy`, `kui-nav-stack__chrome-copy--bottom`, `kui-nav-stack__chrome-copy--exiting`, `kui-nav-stack__viewport`, `kui-nav-stack__view`, `kui-nav-stack__view--entering`, `kui-nav-stack__view--exiting` on an element you write; render `NavStack` instead (`KUI-L103`).
95
96
 
96
97
  Public tokens it reads: `--kui-nav-stack-transition-duration`. Set a token only where its public contract allows; prefer a prop.
97
98
 
@@ -12,6 +12,7 @@ Choose one or more controlled values, keep unavailable choices visible, and opti
12
12
 
13
13
  - Choose a controlled value from a moderate or long list, including grouped and icon-bearing choices.
14
14
  - Color an optional choice icon with a CssForegroundColor: uiColor() with a foreground token such as success-on-quiet, foregroundColorVar() for an app-owned property, or foregroundColor() for a direct custom CSS color. Fill tokens such as success are backgrounds that leave the icon nearly invisible, so they, lengths, raw color strings, and unqualified colorVar() values are rejected.
15
+ - Use the default content-sized menu for long option labels; native popup shifting keeps it within 10px viewport gutters. fitMenu instead matches trigger width and wraps labels.
15
16
 
16
17
  **Not when:**
17
18
 
@@ -70,6 +70,7 @@ Zones (a zone is bound to JSX only through its listed prop; never assume the zon
70
70
  - `data-resizing` on `kui-resizable-region` (`wireResizableRegions`): "true" during an active pointer drag of the handle.
71
71
  - `data-nav-chrome-transition` on `kui-nav-stack` (`wireNavStack`): "true" while the chrome cross-fades between the outgoing and incoming view.
72
72
  - `data-nav-chrome-copy` on `kui-nav-stack__chrome-copy` (`wireNavStack`): Marks the inert, aria-hidden snapshot of the outgoing chrome shown during the cross-fade.
73
+ - `data-nav-revealed` on `kui-nav-stack__view` (`wireNavStack`): "true" on the preserved, aria-hidden previous view while an incoming view slides over it.
73
74
  - `data-nav-exiting` on `kui-nav-stack__view` (`wireNavStack`): "true" on a popped view the helper briefly re-inserts to slide it out.
74
75
 
75
76
  ## Geometry
@@ -4,7 +4,7 @@
4
4
 
5
5
  `@kerfjs/ui:surface-scaffold` · Kerf UI · component · Structure
6
6
 
7
- Typed Web Awesome dialog and popup surface sizing, presentation, and inset composition.
7
+ Typed Web Awesome dialog preferred widths and viewport bounds, presentation, and popup inset composition.
8
8
 
9
9
  ## When to use
10
10
 
@@ -12,6 +12,7 @@ Configure recurring dialog and popup geometry without consumer ::part() override
12
12
 
13
13
  - A Web Awesome dialog or dropdown needs a standard size, presentation, body/footer inset, or list-compatible menu inset.
14
14
  - A dialog body should compose rows, sections, or aligned bare prose through List and ListInsetText.
15
+ - A modal needs a typed preferred width, viewport gutter, or dynamic viewport-bounded height cap while retaining native body scrolling and footer actions.
15
16
 
16
17
  **Not when:**
17
18
 
@@ -22,7 +23,8 @@ Configure recurring dialog and popup geometry without consumer ::part() override
22
23
 
23
24
  - JavaScript: `@kerfjs/ui/surface-scaffold` — exports `DialogSurface`, `PopupSurface`.
24
25
  - CSS: the browser build of `@kerfjs/ui/surface-scaffold` pulls its CSS automatically; import `@kerfjs/ui/surface-scaffold.css` manually only without the `browser` export condition.
25
- - Declared side effects: browser-condition-css.
26
+ - Registration: import `@kerfjs/ui/surface-scaffold/register` once (a side effect).
27
+ - Declared side effects: browser-condition-css, custom-element-registration.
26
28
 
27
29
  ## Props
28
30
 
@@ -32,9 +34,16 @@ Exact prop names and types: [`@kerfjs/ui/surface-scaffold`](../public-api-signat
32
34
 
33
35
  - small, medium, or large dialog
34
36
  - modal, side-sheet, or fullscreen dialog
37
+ - typed modal preferred width, viewport gutter, and maximum height, including viewport cap
35
38
  - none, compact, or comfortable body and footer inset
36
39
  - standard, compact, or zero-inset popup menu
37
40
 
41
+ **CSS-value props** (typed builders from `@kerfjs/ui/css-values`; raw CSS strings are rejected):
42
+
43
+ - `preferredWidth`: length grammar; raw values: forbid; helpers `px`, `rem`, `remify`, `em`, `pct`, `space`, `lengthVar`, `calc` — e.g. `preferredWidth={remify(832)}`
44
+ - `viewportGutter`: length grammar; raw values: forbid; helpers `px`, `rem`, `remify`, `em`, `pct`, `space`, `lengthVar`, `calc` — e.g. `viewportGutter={remify(8)}`
45
+ - `maxHeight`: length grammar; raw values: forbid; shorthands `viewport`; helpers `px`, `rem`, `remify`, `em`, `pct`, `space`, `lengthVar`, `calc` — e.g. `maxHeight="viewport"`
46
+
38
47
  ## Composition
39
48
 
40
49
  - Parents: any.
@@ -40,6 +40,7 @@ Exact prop names and types: [`@kerfjs/ui/text`](../public-api-signatures-v1.md#k
40
40
  - compact, default, large, or xlarge size
41
41
  - default or monospace font
42
42
  - flush item geometry and tight line height
43
+ - controlMargins selects exterior 8px gutters with canonical physical Sides
43
44
 
44
45
  ## Composition
45
46
 
@@ -55,9 +56,10 @@ No wiring helper.
55
56
 
56
57
  ## Geometry
57
58
 
58
- Margin: none · border: self · padding: self (layout role: structure). `self` means the component already owns it — do not add wrapper padding, margin, or borders around it.
59
+ Margin: self · border: self · padding: self (layout role: structure). `self` means the component already owns it — do not add wrapper padding, margin, or borders around it.
59
60
 
60
- - Block Text variants reset native margins and add a 1px transparent border plus the standard 8px item padding; flush removes the border and padding. Tight line height is available for compact copy. Span has no margin, border, or padding. FieldLabel mirrors the themed Web Awesome label typography, 9px inline inset, and bottom gap.
61
+ - Block Text variants reset native margins and add a 1px transparent border plus the standard 8px item padding; flush removes the border and padding. Tight line height is available for compact copy. Span has no margin by default, border, or padding. FieldLabel mirrors the themed Web Awesome label typography, 9px inline inset, and bottom gap.
62
+ - controlMargins adds the shared control gutter outside selected physical edges without changing border or padding; avoid duplicating a parent inset. Spans retain inline display and native inline margin behavior.
61
63
 
62
64
  ## Accessibility
63
65
 
@@ -15,6 +15,9 @@ Provide complete toolbar action geometry through configuration, including semant
15
15
  - Fill it with plain \<button> controls (the group styles > button fully); use wa-button only for a Web Awesome feature. A popup menu is a PopupMenu in a single group with nestedDropdown; it renders its own trigger, so never hand-write wa-dropdown markup. Each control stays whole: an icon sits beside its label on one row and no trigger gets a fixed width. Use overflow=wrap for independent links that should move as whole actions to another row on narrow surfaces.
16
16
  - For an avatar control, set content=avatar and avatarImage instead of inserting an img; one button paints the group and multiple buttons paint only the pressed highlight.
17
17
  - In a Workbench or CollapsiblePanel toolbar, mark a group relocateOnCollapse to keep it available in the work-area toolbar when the panel closes; place it directly or in an array in any toolbar zone.
18
+ - Use tileTone for a contained single group containing only a direct decorative SVG icon; interactive or mixed groups retain their existing control chrome.
19
+ - Set expandedOverflow=visible on an expanded search to anchor application suggestions, date pickers, or help below the group without overriding its geometry.
20
+ - Use typed hideBelow/showBelow lengths with wireToolbarVisibility(root) for per-item toolbar priority; keep primary actions available and provide a showBelow overflow alternative.
18
21
 
19
22
  **Not when:**
20
23
 
@@ -30,11 +33,12 @@ Provide complete toolbar action geometry through configuration, including semant
30
33
 
31
34
  - JavaScript: `@kerfjs/ui/toolbar-control-group` — exports `ToolbarActionLink`, `ToolbarControlGroup`.
32
35
  - CSS: the browser build of `@kerfjs/ui/toolbar-control-group` pulls its CSS automatically; import `@kerfjs/ui/toolbar-control-group.css` manually only without the `browser` export condition.
36
+ - Wiring: `wireToolbarVisibility` from `@kerfjs/ui/wire-toolbar-visibility` (optional).
33
37
  - Declared side effects: browser-condition-css.
34
38
 
35
39
  ## Props
36
40
 
37
- Exact prop names and types: [`@kerfjs/ui/toolbar-control-group`](../public-api-signatures-v1.md#kerfjsuitoolbar-control-group) in `public-api-signatures-v1.md`. Do not infer props from examples.
41
+ Exact prop names and types: [`@kerfjs/ui/toolbar-control-group`](../public-api-signatures-v1.md#kerfjsuitoolbar-control-group), [`@kerfjs/ui/wire-toolbar-visibility`](../public-api-signatures-v1.md#kerfjsuiwire-toolbar-visibility) in `public-api-signatures-v1.md`. Do not infer props from examples.
38
42
 
39
43
  **Variants (configure, do not restyle):**
40
44
 
@@ -54,6 +58,14 @@ Exact prop names and types: [`@kerfjs/ui/toolbar-control-group`](../public-api-s
54
58
  - relocate on panel collapse
55
59
  - avatar scrim
56
60
  - contained avatar background on a single group or selected multi-button highlight
61
+ - neutral, brand, success, warning, or danger quiet icon tile tone
62
+ - clip or visible app-owned overflow while a search is expanded
63
+ - typed hideBelow/showBelow thresholds at the nearest Toolbar content width
64
+
65
+ **CSS-value props** (typed builders from `@kerfjs/ui/css-values`; raw CSS strings are rejected):
66
+
67
+ - `hideBelow`: length grammar; raw values: forbid; helpers `px`, `rem`, `em`, `pct`, `space`, `lengthVar`, `calc` — e.g. `hideBelow={px(416)}`
68
+ - `showBelow`: length grammar; raw values: forbid; helpers `px`, `rem`, `em`, `pct`, `space`, `lengthVar`, `calc` — e.g. `showBelow={px(416)}`
57
69
 
58
70
  ## Composition
59
71
 
@@ -70,7 +82,14 @@ Zones (a zone is bound to JSX only through its listed prop; never assume the zon
70
82
 
71
83
  **The app owns:** actions; link destination and copy; pressed state; expanded state; avatar image URL.
72
84
 
73
- No wiring helper.
85
+ **Wiring:** `wireToolbarVisibility` is optional.
86
+
87
+ **Wiring-owned state attributes** — never render, remove, or branch on these as app state:
88
+
89
+ - `data-toolbar-width-hidden` on `ToolbarText, ToolbarControlGroup and its paired busy status` (`wireToolbarVisibility`): True when typed hideBelow/showBelow thresholds hide this item at the nearest Toolbar content width. Re-applied after rendering; disposal restores prior markers.
90
+ - `data-toolbar-visibility-probe` on `private aria-hidden measurement boxes under Toolbar` (`wireToolbarVisibility`): Internal out-of-flow CSS length resolver; created and removed by wireToolbarVisibility.
91
+ - `data-morph-preserve` on `private aria-hidden measurement boxes and visibility state children` (`wireToolbarVisibility`): Keeps helper-owned geometry and state across Kerf renders; replacement and explicit removal are repaired, and disposal removes them.
92
+ - `data-toolbar-visibility-state` on `private hidden children of width-managed items and paired busy statuses` (`wireToolbarVisibility`): Preserves actual CSS visibility while rendering removes a transient parent marker, preventing geometry-driven render feedback.
74
93
 
75
94
  ## Geometry
76
95
 
@@ -91,7 +110,7 @@ Never put `kui-toolbar-action-link` on an element you write; render `ToolbarActi
91
110
 
92
111
  Never put `kui-toolbar-control-group` on an element you write; render `ToolbarControlGroup` instead (`KUI-L103`).
93
112
 
94
- Public tokens it reads: `--kui-color-brand-on-quiet`, `--kui-color-pop-border-normal`, `--kui-color-pop-fill-normal`, `--kui-color-pop-on-normal`, `--kui-color-pop-on-quiet`, `--kui-color-neutral-border-loud`, `--kui-color-neutral-border-normal`, `--kui-color-neutral-fill-loud`, `--kui-color-neutral-fill-normal`, `--kui-color-neutral-on-loud`, `--kui-color-neutral-on-quiet`, `--kui-color-surface`, `--kui-focus-ring`, `--kui-shadow-s`, `--kui-toolbar-control-background`, `--kui-toolbar-control-border`, `--kui-toolbar-control-color`, `--kui-toolbar-control-dark-border`, `--kui-toolbar-control-hover-background`, `--kui-toolbar-control-pressed-background`, `--kui-toolbar-control-pressed-border`, `--kui-toolbar-control-pressed-color`, `--kui-toolbar-control-selected-background`, `--kui-toolbar-control-selected-color`, `--kui-toolbar-control-selected-shadow`. Set a token only where its public contract allows; prefer a prop.
113
+ Public tokens it reads: `--kui-color-brand-on-quiet`, `--kui-color-pop-border-normal`, `--kui-color-pop-fill-normal`, `--kui-color-pop-on-normal`, `--kui-color-pop-on-quiet`, `--kui-color-neutral-border-loud`, `--kui-color-neutral-border-normal`, `--kui-color-neutral-fill-loud`, `--kui-color-neutral-fill-normal`, `--kui-color-neutral-on-loud`, `--kui-color-neutral-on-quiet`, `--kui-color-surface`, `--kui-focus-ring`, `--kui-shadow-s`, `--kui-toolbar-control-background`, `--kui-toolbar-control-border`, `--kui-toolbar-control-color`, `--kui-toolbar-control-dark-border`, `--kui-toolbar-control-hover-background`, `--kui-toolbar-control-pressed-background`, `--kui-toolbar-control-pressed-border`, `--kui-toolbar-control-pressed-color`, `--kui-toolbar-control-selected-background`, `--kui-toolbar-control-selected-color`, `--kui-toolbar-control-selected-shadow`, `--kui-color-neutral-fill-quiet`, `--kui-color-neutral-border-quiet`, `--kui-color-brand-fill-quiet`, `--kui-color-brand-border-quiet`, `--kui-color-success-fill-quiet`, `--kui-color-success-border-quiet`, `--kui-color-success-on-quiet`, `--kui-color-warning-fill-quiet`, `--kui-color-warning-border-quiet`, `--kui-color-warning-on-quiet`, `--kui-color-danger-fill-quiet`, `--kui-color-danger-border-quiet`, `--kui-color-danger-on-quiet`. Set a token only where its public contract allows; prefer a prop.
95
114
 
96
115
  Everything else is internal: `kerf-ui-analyze` reports private or unknown `.kui-*` selectors (`KUI-L001`, `KUI-L010`), unknown or private tokens (`KUI-L002`, `KUI-L012`), and any application rule that restyles the component, forced dimensions included (`KUI-L019`).
97
116
 
@@ -10,11 +10,13 @@ Extra-large through extra-small toolbar identity text.
10
10
 
11
11
  - Render toolbar identity or heading text at a supported hierarchy size; pass headingLevel for heading semantics.
12
12
  - Use action for an editable toolbar title: it renders a native button that shrinks and ellipsizes beside sibling status chips.
13
+ - Use tone=dark for title or filename text on a loud toolbar surface, matching dark ToolbarControlGroups.
14
+ - Use typed hideBelow/showBelow lengths with wireToolbarVisibility(root) for per-item toolbar priority; keep primary actions available and provide a showBelow overflow alternative.
13
15
 
14
16
  **Not when:**
15
17
 
16
18
  - Do not omit headingLevel when the text is the page or section heading.
17
- - Large, default, and small are intentionally quiet toolbar identity text and have no tone option. Use xlarge-fixed for a normal-color toolbar heading at the fixed font-l step; use Text with an h2-h6 variant for a content subsection title, or ListHeader for a list or menu section.
19
+ - Large, default, and small are intentionally quiet toolbar identity text in default tone. Use xlarge-fixed for a normal-color toolbar heading at the fixed font-l step; use Text with an h2-h6 variant for a content subsection title, or ListHeader for a list or menu section.
18
20
 
19
21
  **Alternatives:**
20
22
 
@@ -25,11 +27,12 @@ Extra-large through extra-small toolbar identity text.
25
27
 
26
28
  - JavaScript: `@kerfjs/ui/toolbar-text` — exports `ToolbarText`.
27
29
  - CSS: the browser build of `@kerfjs/ui/toolbar-text` pulls its CSS automatically; import `@kerfjs/ui/toolbar-text.css` manually only without the `browser` export condition.
30
+ - Wiring: `wireToolbarVisibility` from `@kerfjs/ui/wire-toolbar-visibility` (optional).
28
31
  - Declared side effects: browser-condition-css.
29
32
 
30
33
  ## Props
31
34
 
32
- Exact prop names and types: [`@kerfjs/ui/toolbar-text`](../public-api-signatures-v1.md#kerfjsuitoolbar-text) in `public-api-signatures-v1.md`. Do not infer props from examples.
35
+ Exact prop names and types: [`@kerfjs/ui/toolbar-text`](../public-api-signatures-v1.md#kerfjsuitoolbar-text), [`@kerfjs/ui/wire-toolbar-visibility`](../public-api-signatures-v1.md#kerfjsuiwire-toolbar-visibility) in `public-api-signatures-v1.md`. Do not infer props from examples.
33
36
 
34
37
  **Variants (configure, do not restyle):**
35
38
 
@@ -40,6 +43,13 @@ Exact prop names and types: [`@kerfjs/ui/toolbar-text`](../public-api-signatures
40
43
  - small
41
44
  - xsmall
42
45
  - placeholder (loading)
46
+ - dark (loud-surface foreground)
47
+ - typed hideBelow/showBelow thresholds at the nearest Toolbar content width
48
+
49
+ **CSS-value props** (typed builders from `@kerfjs/ui/css-values`; raw CSS strings are rejected):
50
+
51
+ - `hideBelow`: length grammar; raw values: forbid; helpers `px`, `rem`, `em`, `pct`, `space`, `lengthVar`, `calc` — e.g. `hideBelow={px(416)}`
52
+ - `showBelow`: length grammar; raw values: forbid; helpers `px`, `rem`, `em`, `pct`, `space`, `lengthVar`, `calc` — e.g. `showBelow={px(416)}`
43
53
 
44
54
  ## Composition
45
55
 
@@ -51,7 +61,14 @@ Exact prop names and types: [`@kerfjs/ui/toolbar-text`](../public-api-signatures
51
61
 
52
62
  **The app owns:** text; responsive priority; the delegated action handler and display-to-input editing swap.
53
63
 
54
- No wiring helper.
64
+ **Wiring:** `wireToolbarVisibility` is optional.
65
+
66
+ **Wiring-owned state attributes** — never render, remove, or branch on these as app state:
67
+
68
+ - `data-toolbar-width-hidden` on `ToolbarText, ToolbarControlGroup and its paired busy status` (`wireToolbarVisibility`): True when typed hideBelow/showBelow thresholds hide this item at the nearest Toolbar content width. Re-applied after rendering; disposal restores prior markers.
69
+ - `data-toolbar-visibility-probe` on `private aria-hidden measurement boxes under Toolbar` (`wireToolbarVisibility`): Internal out-of-flow CSS length resolver; created and removed by wireToolbarVisibility.
70
+ - `data-morph-preserve` on `private aria-hidden measurement boxes and visibility state children` (`wireToolbarVisibility`): Keeps helper-owned geometry and state across Kerf renders; replacement and explicit removal are repaired, and disposal removes them.
71
+ - `data-toolbar-visibility-state` on `private hidden children of width-managed items and paired busy statuses` (`wireToolbarVisibility`): Preserves actual CSS visibility while rendering removes a transient parent marker, preventing geometry-driven render feedback.
55
72
 
56
73
  ## Geometry
57
74
 
@@ -70,7 +87,7 @@ Public class hooks (select for layout placement only, never to change the compon
70
87
 
71
88
  Never put `kui-toolbar-text` on an element you write; render `ToolbarText` instead (`KUI-L103`).
72
89
 
73
- Public tokens it reads: `--kui-color-neutral-on-quiet`, `--kui-color-text`, `--kui-font-2xs`, `--kui-font-2xl`, `--kui-font-l`, `--kui-font-m`, `--kui-font-s`, `--kui-font-xs`. Set a token only where its public contract allows; prefer a prop.
90
+ Public tokens it reads: `--kui-color-neutral-on-quiet`, `--kui-color-text`, `--kui-font-2xs`, `--kui-font-2xl`, `--kui-font-l`, `--kui-font-m`, `--kui-font-s`, `--kui-font-xs`, `--kui-color-neutral-on-loud`. Set a token only where its public contract allows; prefer a prop.
74
91
 
75
92
  Everything else is internal: `kerf-ui-analyze` reports private or unknown `.kui-*` selectors (`KUI-L001`, `KUI-L010`), unknown or private tokens (`KUI-L002`, `KUI-L012`), and any application rule that restyles the component, forced dimensions included (`KUI-L019`).
76
93