@kerfjs/ui 5.0.0-beta.82 → 5.0.0-beta.83

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 (140) hide show
  1. package/README.md +1 -0
  2. package/ai/catalog-authoring.json +1 -3
  3. package/ai/catalog-authoring.schema.json +3 -7
  4. package/ai/component-catalog.json +73 -2
  5. package/ai/component-composition.json +64 -1
  6. package/ai/components/README.md +1 -0
  7. package/ai/components/anchored-surface.md +86 -0
  8. package/ai/components/tab-navigator.md +3 -2
  9. package/ai/public-api-signatures-v1.md +74 -30
  10. package/ai/skill.md +2 -2
  11. package/ai/webawesome-jsx-signatures-v1.md +1 -1
  12. package/dist/anchored-surface.d.ts +30 -0
  13. package/dist/anchored-surface.js +3 -0
  14. package/dist/anchored-surface.js.map +1 -0
  15. package/dist/app-tab.js +1 -1
  16. package/dist/browser/anchored-surface.js +3 -0
  17. package/dist/browser/catalog.js +1 -1
  18. package/dist/catalog-resources.d.ts +1 -1
  19. package/dist/catalog.d.ts +3 -3
  20. package/dist/catalog.js +34 -31
  21. package/dist/catalog.js.map +1 -1
  22. package/dist/{chunk-I4SDIMFA.js → chunk-2YPPNFYT.js} +2 -2
  23. package/dist/{chunk-I4SDIMFA.js.map → chunk-2YPPNFYT.js.map} +1 -1
  24. package/dist/{chunk-CVKIADIS.js → chunk-3BXDWEGB.js} +5 -5
  25. package/dist/{chunk-CVKIADIS.js.map → chunk-3BXDWEGB.js.map} +1 -1
  26. package/dist/{chunk-VHXHLZ6R.js → chunk-3DXHNLME.js} +3 -3
  27. package/dist/{chunk-VHXHLZ6R.js.map → chunk-3DXHNLME.js.map} +1 -1
  28. package/dist/{chunk-HFQDSSED.js → chunk-3PO7JEK7.js} +4 -4
  29. package/dist/{chunk-HFQDSSED.js.map → chunk-3PO7JEK7.js.map} +1 -1
  30. package/dist/chunk-6IVNMC6R.js +19 -0
  31. package/dist/chunk-6IVNMC6R.js.map +1 -0
  32. package/dist/{chunk-VR7MWD2X.js → chunk-CD5TOO22.js} +4 -13
  33. package/dist/chunk-CD5TOO22.js.map +1 -0
  34. package/dist/{chunk-H7ZJEI3H.js → chunk-DL55BSQX.js} +3 -3
  35. package/dist/{chunk-H7ZJEI3H.js.map → chunk-DL55BSQX.js.map} +1 -1
  36. package/dist/{chunk-LQKY5S4F.js → chunk-EA5R75B5.js} +4 -4
  37. package/dist/{chunk-LQKY5S4F.js.map → chunk-EA5R75B5.js.map} +1 -1
  38. package/dist/{chunk-VIGVNDXZ.js → chunk-GPCAXYMT.js} +4 -4
  39. package/dist/{chunk-VIGVNDXZ.js.map → chunk-GPCAXYMT.js.map} +1 -1
  40. package/dist/chunk-IOS2NXW7.js +53 -0
  41. package/dist/chunk-IOS2NXW7.js.map +1 -0
  42. package/dist/{chunk-HFLGWMG3.js → chunk-KAJVVN7Q.js} +3 -3
  43. package/dist/{chunk-HFLGWMG3.js.map → chunk-KAJVVN7Q.js.map} +1 -1
  44. package/dist/{chunk-NVKRZ5DI.js → chunk-LFPW4YC6.js} +4 -4
  45. package/dist/{chunk-NVKRZ5DI.js.map → chunk-LFPW4YC6.js.map} +1 -1
  46. package/dist/{chunk-75I3SNUJ.js → chunk-MN3POJFN.js} +2 -2
  47. package/dist/{chunk-75I3SNUJ.js.map → chunk-MN3POJFN.js.map} +1 -1
  48. package/dist/{chunk-5D3WDMIK.js → chunk-MORVLMDG.js} +4 -16
  49. package/dist/chunk-MORVLMDG.js.map +1 -0
  50. package/dist/{chunk-RRCD3A6G.js → chunk-MTCTX25G.js} +2 -2
  51. package/dist/{chunk-RRCD3A6G.js.map → chunk-MTCTX25G.js.map} +1 -1
  52. package/dist/{chunk-PQQQXJGV.js → chunk-NP3FSLNX.js} +2 -2
  53. package/dist/{chunk-PQQQXJGV.js.map → chunk-NP3FSLNX.js.map} +1 -1
  54. package/dist/{chunk-ARZ4RSQO.js → chunk-PGL6TXFW.js} +3 -3
  55. package/dist/{chunk-ARZ4RSQO.js.map → chunk-PGL6TXFW.js.map} +1 -1
  56. package/dist/{chunk-NVRJ7C3W.js → chunk-QQICWWNX.js} +4 -16
  57. package/dist/chunk-QQICWWNX.js.map +1 -0
  58. package/dist/{chunk-JZM3G6RT.js → chunk-TTGIHMDR.js} +4 -4
  59. package/dist/{chunk-JZM3G6RT.js.map → chunk-TTGIHMDR.js.map} +1 -1
  60. package/dist/{chunk-LRAIS3YB.js → chunk-U657IHFB.js} +1 -1
  61. package/dist/chunk-U657IHFB.js.map +1 -0
  62. package/dist/{chunk-3SXWV2IR.js → chunk-VLGQIYZ5.js} +2 -2
  63. package/dist/{chunk-3SXWV2IR.js.map → chunk-VLGQIYZ5.js.map} +1 -1
  64. package/dist/{chunk-YLJ6X3AC.js → chunk-XK4E225T.js} +2 -2
  65. package/dist/{chunk-YLJ6X3AC.js.map → chunk-XK4E225T.js.map} +1 -1
  66. package/dist/{chunk-BJLXE56E.js → chunk-XKZPBRU7.js} +4 -4
  67. package/dist/{chunk-BJLXE56E.js.map → chunk-XKZPBRU7.js.map} +1 -1
  68. package/dist/{chunk-62VMNBV2.js → chunk-XNXKIPU5.js} +2 -2
  69. package/dist/{chunk-62VMNBV2.js.map → chunk-XNXKIPU5.js.map} +1 -1
  70. package/dist/{chunk-EFDCALR3.js → chunk-Y43B6DS3.js} +2 -2
  71. package/dist/{chunk-EFDCALR3.js.map → chunk-Y43B6DS3.js.map} +1 -1
  72. package/dist/{chunk-3RE2JMZU.js → chunk-YOKEL75M.js} +2 -2
  73. package/dist/{chunk-3RE2JMZU.js.map → chunk-YOKEL75M.js.map} +1 -1
  74. package/dist/collapsible-panel.js +4 -3
  75. package/dist/collapsible-panel.js.map +1 -1
  76. package/dist/css-values.d.ts +8 -1
  77. package/dist/css-values.js +1 -1
  78. package/dist/disclosure-arrow.js +1 -1
  79. package/dist/empty-state.js +1 -1
  80. package/dist/grid.d.ts +5 -4
  81. package/dist/grid.js +2 -1
  82. package/dist/index.d.ts +2 -0
  83. package/dist/index.js +26 -24
  84. package/dist/list-action-row.js +1 -1
  85. package/dist/list-header.js +1 -1
  86. package/dist/list-item.js +1 -1
  87. package/dist/list.d.ts +5 -4
  88. package/dist/list.js +2 -1
  89. package/dist/loading-spinner.js +1 -1
  90. package/dist/lucide-icon.js +1 -1
  91. package/dist/nav-stack.js +2 -1
  92. package/dist/row.d.ts +5 -4
  93. package/dist/row.js +2 -1
  94. package/dist/select.js +1 -1
  95. package/dist/skeleton.js +1 -1
  96. package/dist/spacer.js +1 -1
  97. package/dist/split-view.js +2 -1
  98. package/dist/split-view.js.map +1 -1
  99. package/dist/state-banner.js +1 -1
  100. package/dist/styles/anchored-surface.css +15 -0
  101. package/dist/styles/catalog/components/catalog-example.css +1 -1
  102. package/dist/styles/catalog/components/catalog-stage.css +26 -42
  103. package/dist/styles/catalog/components/catalog.css +0 -11
  104. package/dist/styles/components/collections/list/list.css +4 -1
  105. package/dist/styles/components/feedback/anchored-surface/anchored-surface.css +15 -0
  106. package/dist/styles/components/layout/grid/grid.css +4 -1
  107. package/dist/styles/components/layout/row/row.css +4 -1
  108. package/dist/styles/components/navigation/tab-navigator/tab-navigator.css +25 -9
  109. package/dist/styles/grid.css +4 -1
  110. package/dist/styles/list.css +4 -1
  111. package/dist/styles/row.css +4 -1
  112. package/dist/styles/styles.css +1 -0
  113. package/dist/styles/tab-navigator.css +25 -9
  114. package/dist/tab-navigator.d.ts +10 -3
  115. package/dist/tab-navigator.js +2 -0
  116. package/dist/tab-navigator.js.map +1 -1
  117. package/dist/token-search-field.js +1 -1
  118. package/dist/toolbar-control-group.js +1 -1
  119. package/dist/toolbar-text.js +1 -1
  120. package/dist/{types-C9BubXfz.d.ts → types-CXrh9Wyx.d.ts} +6 -2
  121. package/dist/value-table.js +1 -1
  122. package/dist/wire-catalog.d.ts +1 -9
  123. package/dist/wire-catalog.js +2 -200
  124. package/dist/wire-catalog.js.map +1 -1
  125. package/dist/wire-token-search-fields.js +1 -1
  126. package/dist/workbench.js +2 -1
  127. package/docs/anchored-surface.md +51 -0
  128. package/docs/catalog.md +37 -82
  129. package/docs/component-contract.md +3 -1
  130. package/docs/component-selection.md +19 -1
  131. package/docs/layout.md +13 -2
  132. package/docs/tab-navigator.md +12 -4
  133. package/docs/type-contracts.md +2 -0
  134. package/docs/ux-demo.md +4 -4
  135. package/llms.txt +8 -3
  136. package/package.json +7 -1
  137. package/dist/chunk-5D3WDMIK.js.map +0 -1
  138. package/dist/chunk-LRAIS3YB.js.map +0 -1
  139. package/dist/chunk-NVRJ7C3W.js.map +0 -1
  140. package/dist/chunk-VR7MWD2X.js.map +0 -1
package/README.md CHANGED
@@ -218,6 +218,7 @@ interchangeable. `ListItem` and `ListActionRow` deliberately expose no raw
218
218
  | `DialogSurface`, `PopupSurface` | `@kerfjs/ui/surface-scaffold` | `@kerfjs/ui/surface-scaffold.css` |
219
219
  | `FloatingToolbar` | `@kerfjs/ui/floating-toolbar` | `@kerfjs/ui/floating-toolbar.css` |
220
220
  | `PopupMenu` (register with `@kerfjs/ui/popup-menu/register`) | `@kerfjs/ui/popup-menu` | `@kerfjs/ui/popup-menu.css` |
221
+ | `openAnchoredSurface`, `openAnchoredSurfaceAt` | `@kerfjs/ui/anchored-surface` | `@kerfjs/ui/anchored-surface.css` |
221
222
  | `ToolbarText` | `@kerfjs/ui/toolbar-text` | `@kerfjs/ui/toolbar-text.css` |
222
223
  | `Text`, `FieldLabel` | `@kerfjs/ui/text` | `@kerfjs/ui/text.css` |
223
224
  | `List` | `@kerfjs/ui/list` | `@kerfjs/ui/list.css` |
@@ -14,7 +14,6 @@
14
14
  "CatalogExample",
15
15
  "CatalogExampleStack",
16
16
  "wireCatalog",
17
- "wireCatalogGeometryOverlay",
18
17
  "revealCatalogEntry"
19
18
  ],
20
19
  "taxonomy": {
@@ -30,7 +29,6 @@
30
29
  },
31
30
  "metadata": {
32
31
  "slot": "rootAttributes",
33
- "demo": "data-demo",
34
- "geometryOverlaySkip": "data-catalog-geometry-overlay-skip"
32
+ "demo": "data-demo"
35
33
  }
36
34
  }
@@ -38,11 +38,10 @@
38
38
  "CatalogExample",
39
39
  "CatalogExampleStack",
40
40
  "wireCatalog",
41
- "wireCatalogGeometryOverlay",
42
41
  "revealCatalogEntry"
43
42
  ]
44
43
  },
45
- "minItems": 6,
44
+ "minItems": 5,
46
45
  "uniqueItems": true
47
46
  },
48
47
  "taxonomy": {
@@ -94,13 +93,10 @@
94
93
  },
95
94
  "metadata": {
96
95
  "type": "object",
97
- "required": ["slot", "demo", "geometryOverlaySkip"],
96
+ "required": ["slot", "demo"],
98
97
  "properties": {
99
98
  "slot": { "const": "rootAttributes" },
100
- "demo": { "const": "data-demo" },
101
- "geometryOverlaySkip": {
102
- "const": "data-catalog-geometry-overlay-skip"
103
- }
99
+ "demo": { "const": "data-demo" }
104
100
  },
105
101
  "additionalProperties": false
106
102
  }
@@ -1059,6 +1059,7 @@
1059
1059
  "routing and persistence",
1060
1060
  "responsive replacement on larger device classes",
1061
1061
  "whether the bar divider follows the scroll, always shows, or never shows (chromeDividers)",
1062
+ "whether the bar's top separator follows a sunken active surface or stays hidden (separator)",
1062
1063
  "optional active-scene focus (tabIndex) and persistent outline (outlined)"
1063
1064
  ],
1064
1065
  "variants": [
@@ -1067,7 +1068,8 @@
1067
1068
  "badged tabs (count or text-free dot)",
1068
1069
  "one NavStack per tab",
1069
1070
  "bar divider only while the active scene continues below it (wired by wireScrollDividers)",
1070
- "permanent or no bar divider (chromeDividers always or none)"
1071
+ "permanent or no bar divider (chromeDividers always or none)",
1072
+ "sunken active-scene separator (separator auto or hidden)"
1071
1073
  ],
1072
1074
  "accessibility": [
1073
1075
  "Give the tablist an accessible label and keep exactly the active tab in the sequential focus order.",
@@ -1081,7 +1083,7 @@
1081
1083
  "padding": "self",
1082
1084
  "notes": [
1083
1085
  "The navigator owns the full-height scene region and safe-area-aware bottom bar; scene content owns its internal geometry.",
1084
- "The bar's top line is scroll state (wireScrollDividers): it shows only while the active scene's content continues below the bar, by coloring the bar's always-present 1px top border."
1086
+ "The bar's reserved 1px top edge separates a sunken active scene or nested Pane by default; on flat surfaces it follows scroll state (wireScrollDividers). separator=hidden suppresses it."
1085
1087
  ]
1086
1088
  },
1087
1089
  "delivery": {
@@ -2568,6 +2570,7 @@
2568
2570
  "rawPolicy": "forbid",
2569
2571
  "examples": [
2570
2572
  "gap=\"xs\"",
2573
+ "gap={{ column: \"none\", row: \"m\" }}",
2571
2574
  "gap={space(\"m\")}",
2572
2575
  "gap={calc(plus(rem(0.25), pct(10)))}"
2573
2576
  ]
@@ -2744,6 +2747,7 @@
2744
2747
  "rawPolicy": "forbid",
2745
2748
  "examples": [
2746
2749
  "gap=\"m\"",
2750
+ "gap={{ column: \"none\", row: \"m\" }}",
2747
2751
  "gap={space(\"m\")}",
2748
2752
  "gap={calc(plus(rem(0.25), pct(10)))}"
2749
2753
  ]
@@ -3087,6 +3091,7 @@
3087
3091
  "rawPolicy": "forbid",
3088
3092
  "examples": [
3089
3093
  "gap=\"xs\"",
3094
+ "gap={{ column: \"none\", row: \"m\" }}",
3090
3095
  "gap={rem(0.25)}",
3091
3096
  "gap={calc(plus(rem(0.25), pct(10)))}"
3092
3097
  ]
@@ -4657,6 +4662,72 @@
4657
4662
  "recipe": "docs/component-selection.md#web-awesome-overlap-policy"
4658
4663
  }
4659
4664
  },
4665
+ {
4666
+ "id": "anchored-surface",
4667
+ "name": "AnchoredSurface",
4668
+ "category": "Feedback",
4669
+ "kind": "component",
4670
+ "source": "kerf",
4671
+ "description": "A styled non-modal surface for app-owned interactive help or popup content, anchored to an element or pointer.",
4672
+ "uses": [],
4673
+ "purpose": "Present arbitrary app-owned content next to an element or pointer with Kerf UI surface styling and kerfjs/overlay lifecycle.",
4674
+ "publicExports": [
4675
+ "openAnchoredSurface",
4676
+ "openAnchoredSurfaceAt"
4677
+ ],
4678
+ "useWhen": [
4679
+ "Show interactive help or other arbitrary content near a control or pointer, including inside a modal dialog."
4680
+ ],
4681
+ "avoidWhen": [
4682
+ "Use PopupMenu for a typed action menu, Select for a choice, and a modal dialog for a task that must block the page."
4683
+ ],
4684
+ "alternatives": [
4685
+ { "id": "popup-menu", "relationship": "nearest" },
4686
+ { "id": "wa-popup", "relationship": "prefer-over" }
4687
+ ],
4688
+ "appOwns": [
4689
+ "content and action policy",
4690
+ "opening trigger and programmatic close after an action",
4691
+ "accessible name"
4692
+ ],
4693
+ "variants": [
4694
+ "element anchor",
4695
+ "pointer anchor",
4696
+ "top or bottom placement",
4697
+ "modal-dialog host"
4698
+ ],
4699
+ "usageExamples": [
4700
+ {
4701
+ "title": "Interactive help",
4702
+ "description": "The trigger owns when to open; the returned handle closes when an action completes.",
4703
+ "code": "const handle = openAnchoredSurface(button, () => <HelpPanel />, { label: 'Field help' });\n// Close from the app's action handler: handle.close();"
4704
+ }
4705
+ ],
4706
+ "accessibility": [
4707
+ "The non-modal surface has role dialog and the required label. Focus moves to the first focusable descendant by default and returns to the opener on close; initialFocus: false leaves focus on the trigger. Escape and outside press dismiss by default."
4708
+ ],
4709
+ "geometry": {
4710
+ "margin": "none",
4711
+ "border": "self",
4712
+ "padding": "self"
4713
+ },
4714
+ "delivery": {
4715
+ "browserImport": "@kerfjs/ui/anchored-surface",
4716
+ "manualCssImport": "@kerfjs/ui/anchored-surface.css",
4717
+ "sideEffects": ["browser-condition-css"]
4718
+ },
4719
+ "wiring": [],
4720
+ "publicClasses": [],
4721
+ "publicTokens": [
4722
+ "--kui-anchored-surface-inset",
4723
+ "--kui-anchored-surface-radius"
4724
+ ],
4725
+ "links": {
4726
+ "catalogRoute": "?component=anchored-surface",
4727
+ "documentation": "docs/anchored-surface.md",
4728
+ "recipe": "docs/anchored-surface.md"
4729
+ }
4730
+ },
4660
4731
  {
4661
4732
  "id": "popup-menu",
4662
4733
  "name": "PopupMenu",
@@ -1013,6 +1013,11 @@
1013
1013
  "owner": "application",
1014
1014
  "required": false
1015
1015
  },
1016
+ {
1017
+ "id": "whether the bar's top separator follows a sunken active surface or stays hidden (separator)",
1018
+ "owner": "application",
1019
+ "required": false
1020
+ },
1016
1021
  {
1017
1022
  "id": "optional active-scene focus (tabIndex) and persistent outline (outlined)",
1018
1023
  "owner": "application",
@@ -1047,7 +1052,7 @@
1047
1052
  "padding": "self",
1048
1053
  "notes": [
1049
1054
  "The navigator owns the full-height scene region and safe-area-aware bottom bar; scene content owns its internal geometry.",
1050
- "The bar's top line is scroll state (wireScrollDividers): it shows only while the active scene's content continues below the bar, by coloring the bar's always-present 1px top border."
1055
+ "The bar's reserved 1px top edge separates a sunken active scene or nested Pane by default; on flat surfaces it follows scroll state (wireScrollDividers). separator=hidden suppresses it."
1051
1056
  ]
1052
1057
  }
1053
1058
  },
@@ -2289,6 +2294,7 @@
2289
2294
  "rawPolicy": "forbid",
2290
2295
  "examples": [
2291
2296
  "gap=\"xs\"",
2297
+ "gap={{ column: \"none\", row: \"m\" }}",
2292
2298
  "gap={space(\"m\")}",
2293
2299
  "gap={calc(plus(rem(0.25), pct(10)))}"
2294
2300
  ]
@@ -2392,6 +2398,7 @@
2392
2398
  "rawPolicy": "forbid",
2393
2399
  "examples": [
2394
2400
  "gap=\"m\"",
2401
+ "gap={{ column: \"none\", row: \"m\" }}",
2395
2402
  "gap={space(\"m\")}",
2396
2403
  "gap={calc(plus(rem(0.25), pct(10)))}"
2397
2404
  ]
@@ -2591,6 +2598,7 @@
2591
2598
  "rawPolicy": "forbid",
2592
2599
  "examples": [
2593
2600
  "gap=\"xs\"",
2601
+ "gap={{ column: \"none\", row: \"m\" }}",
2594
2602
  "gap={rem(0.25)}",
2595
2603
  "gap={calc(plus(rem(0.25), pct(10)))}"
2596
2604
  ]
@@ -3797,6 +3805,61 @@
3797
3805
  "composition": "README.md#web-awesome-theme"
3798
3806
  }
3799
3807
  },
3808
+ {
3809
+ "key": "@kerfjs/ui:anchored-surface",
3810
+ "package": "@kerfjs/ui",
3811
+ "id": "anchored-surface",
3812
+ "name": "AnchoredSurface",
3813
+ "kind": "component",
3814
+ "source": "kerf",
3815
+ "parents": { "mode": "any", "entries": [] },
3816
+ "contexts": ["application-ui"],
3817
+ "zones": [],
3818
+ "children": { "mode": "any", "concepts": [], "requiredConcepts": [] },
3819
+ "state": [
3820
+ {
3821
+ "id": "content and action policy",
3822
+ "owner": "application",
3823
+ "required": false
3824
+ },
3825
+ {
3826
+ "id": "opening trigger and programmatic close after an action",
3827
+ "owner": "application",
3828
+ "required": false
3829
+ },
3830
+ { "id": "accessible name", "owner": "application", "required": false }
3831
+ ],
3832
+ "wiring": {
3833
+ "required": false,
3834
+ "helpers": [],
3835
+ "obligations": [],
3836
+ "stateAttributes": []
3837
+ },
3838
+ "responsive": { "owner": "not-applicable", "behaviors": [] },
3839
+ "layout": {
3840
+ "roles": ["feedback"],
3841
+ "geometry": { "margin": "none", "border": "self", "padding": "self" }
3842
+ },
3843
+ "accessibility": {
3844
+ "obligations": [
3845
+ "The non-modal surface has role dialog and the required label. Focus moves to the first focusable descendant by default and returns to the opener on close; initialFocus: false leaves focus on the trigger. Escape and outside press dismiss by default."
3846
+ ]
3847
+ },
3848
+ "cssValueProps": [],
3849
+ "boundaries": {
3850
+ "rootClass": null,
3851
+ "publicClasses": [],
3852
+ "publicTokens": [
3853
+ "--kui-anchored-surface-inset",
3854
+ "--kui-anchored-surface-radius"
3855
+ ]
3856
+ },
3857
+ "diagnostics": [],
3858
+ "provenance": {
3859
+ "selection": "ai/component-catalog.json",
3860
+ "composition": "generated-permissive-default"
3861
+ }
3862
+ },
3800
3863
  {
3801
3864
  "key": "@kerfjs/ui:popup-menu",
3802
3865
  "package": "@kerfjs/ui",
@@ -60,6 +60,7 @@ Exact prop and callback types live in [`public-api-signatures-v1.md`](../public-
60
60
 
61
61
  ## Kerf UI — Feedback
62
62
 
63
+ - [AnchoredSurface](./anchored-surface.md) — Present arbitrary app-owned content next to an element or pointer with Kerf UI surface styling and kerfjs/overlay lifecycle.
63
64
  - [Feedback](./feedback.md) — Banners, empty states, and labeled progress.
64
65
  - [StateBanner](./state-banner.md) — Present persistent inline feedback or attractive non-status emphasis with a named semantic tone.
65
66
  - [EmptyState](./empty-state.md) — Actionable empty and busy content states.
@@ -0,0 +1,86 @@
1
+ # AnchoredSurface
2
+
3
+ <!-- Generated by scripts/sync-component-docs.mjs from ai/component-catalog.json and ai/component-composition.json. Do not edit; run `npm run catalog:sync`. -->
4
+
5
+ `@kerfjs/ui:anchored-surface` · Kerf UI · component · Feedback
6
+
7
+ A styled non-modal surface for app-owned interactive help or popup content, anchored to an element or pointer.
8
+
9
+ ## When to use
10
+
11
+ Present arbitrary app-owned content next to an element or pointer with Kerf UI surface styling and kerfjs/overlay lifecycle.
12
+
13
+ - Show interactive help or other arbitrary content near a control or pointer, including inside a modal dialog.
14
+
15
+ **Not when:**
16
+
17
+ - Use PopupMenu for a typed action menu, Select for a choice, and a modal dialog for a task that must block the page.
18
+
19
+ **Alternatives:**
20
+
21
+ - [PopupMenu](./popup-menu.md) (nearest)
22
+ - [Popup](./wa-popup.md) (prefer-over)
23
+
24
+ ## Imports
25
+
26
+ - JavaScript: `@kerfjs/ui/anchored-surface` — exports `openAnchoredSurface`, `openAnchoredSurfaceAt`.
27
+ - CSS: the browser build of `@kerfjs/ui/anchored-surface` pulls its CSS automatically; import `@kerfjs/ui/anchored-surface.css` manually only without the `browser` export condition.
28
+ - Declared side effects: browser-condition-css.
29
+
30
+ ## Props
31
+
32
+ Exact prop names and types: [`@kerfjs/ui/anchored-surface`](../public-api-signatures-v1.md#kerfjsuianchored-surface) in `public-api-signatures-v1.md`. Do not infer props from examples.
33
+
34
+ **Variants (configure, do not restyle):**
35
+
36
+ - element anchor
37
+ - pointer anchor
38
+ - top or bottom placement
39
+ - modal-dialog host
40
+
41
+ ## Composition
42
+
43
+ - Parents: any.
44
+ - Contexts: `application-ui`.
45
+ - Children: unrestricted.
46
+
47
+ ## State and wiring
48
+
49
+ **The app owns:** content and action policy; opening trigger and programmatic close after an action; accessible name.
50
+
51
+ No wiring helper.
52
+
53
+ ## Geometry
54
+
55
+ Margin: none · border: self · padding: self (layout role: feedback). `self` means the component already owns it — do not add wrapper padding, margin, or borders around it.
56
+
57
+ ## Accessibility
58
+
59
+ - The non-modal surface has role dialog and the required label. Focus moves to the first focusable descendant by default and returns to the opener on close; initialFocus: false leaves focus on the trigger. Escape and outside press dismiss by default.
60
+
61
+ ## Usage examples
62
+
63
+ ### Interactive help
64
+
65
+ The trigger owns when to open; the returned handle closes when an action completes.
66
+
67
+ ```tsx
68
+ const handle = openAnchoredSurface(button, () => <HelpPanel />, {
69
+ label: 'Field help',
70
+ });
71
+ // Close from the app's action handler: handle.close();
72
+ ```
73
+
74
+ ## Styling boundary
75
+
76
+ The component owns its own styles. Configure it through its props and variants; do not override its internals.
77
+
78
+ Public tokens it reads: `--kui-anchored-surface-inset`, `--kui-anchored-surface-radius`. Set a token only where its public contract allows; prefer a prop.
79
+
80
+ 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`).
81
+
82
+ ## Related
83
+
84
+ - Components: [PopupMenu](./popup-menu.md), [Popup](./wa-popup.md).
85
+ - Docs: [`docs/anchored-surface.md`](../../docs/anchored-surface.md).
86
+ - UX catalog route: `?component=anchored-surface`.
@@ -43,6 +43,7 @@ Exact prop names and types: [`@kerfjs/ui/tab-navigator`](../public-api-signature
43
43
  - one NavStack per tab
44
44
  - bar divider only while the active scene continues below it (wired by wireScrollDividers)
45
45
  - permanent or no bar divider (chromeDividers always or none)
46
+ - sunken active-scene separator (separator auto or hidden)
46
47
 
47
48
  ## Composition
48
49
 
@@ -53,7 +54,7 @@ Exact prop names and types: [`@kerfjs/ui/tab-navigator`](../public-api-signature
53
54
 
54
55
  ## State and wiring
55
56
 
56
- **The app owns:** controlled active tab id; tab labels, icons, and content; tab badge counts or dots and their localized badgeLabel phrases; routing and persistence; responsive replacement on larger device classes; whether the bar divider follows the scroll, always shows, or never shows (chromeDividers); optional active-scene focus (tabIndex) and persistent outline (outlined).
57
+ **The app owns:** controlled active tab id; tab labels, icons, and content; tab badge counts or dots and their localized badgeLabel phrases; routing and persistence; responsive replacement on larger device classes; whether the bar divider follows the scroll, always shows, or never shows (chromeDividers); whether the bar's top separator follows a sunken active surface or stays hidden (separator); optional active-scene focus (tabIndex) and persistent outline (outlined).
57
58
 
58
59
  **Wiring:** `wireTabNavigator`, `wireScrollDividers` is required.
59
60
 
@@ -69,7 +70,7 @@ Exact prop names and types: [`@kerfjs/ui/tab-navigator`](../public-api-signature
69
70
  Margin: none · border: conditional · padding: self (layout role: structure). `self` means the component already owns it — do not add wrapper padding, margin, or borders around it.
70
71
 
71
72
  - The navigator owns the full-height scene region and safe-area-aware bottom bar; scene content owns its internal geometry.
72
- - The bar's top line is scroll state (wireScrollDividers): it shows only while the active scene's content continues below the bar, by coloring the bar's always-present 1px top border.
73
+ - The bar's reserved 1px top edge separates a sunken active scene or nested Pane by default; on flat surfaces it follows scroll state (wireScrollDividers). separator=hidden suppresses it.
73
74
 
74
75
  ## Accessibility
75
76
 
@@ -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.82` and `kerfjs@5.0.0-beta.82`. 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.83` and `kerfjs@5.0.0-beta.83`. 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/css-values`
6
6
 
@@ -66,6 +66,13 @@ type UiColorName = (typeof uiColorNames)[number];
66
66
  type UiForegroundColorName = Extract<UiColorName, `${string}-on-${string}` | 'text' | 'text-quiet' | 'text-link'>;
67
67
  /** Kerf UI's complete spacing-token vocabulary. `s` and `xl` are exceptions. */
68
68
  type UiSpaceName = 'none' | '2xs' | 'xs' | 's' | 'm' | 'l' | 'xl';
69
+ /** A token or complete typed length for one gap axis. */
70
+ type UiGapValue = UiSpaceName | CssLength;
71
+ /** A shared gap or independent column and row gaps. */
72
+ type UiGap = UiGapValue | Readonly<{
73
+ column: UiGapValue;
74
+ row: UiGapValue;
75
+ }>;
69
76
  /** Create a complete pixel length. */
70
77
  declare function px(value: number): CssLength;
71
78
  /** Create a complete root-font-relative length. */
@@ -116,7 +123,7 @@ declare function foregroundColorVar(name: `--${string}`, fallback?: CssForegroun
116
123
  */
117
124
  declare function foregroundColor(value: string): CssForegroundColor;
118
125
 
119
- export { type CssColor, type CssFlex, type CssFlexBasis, type CssFlexKeyword, type CssForegroundColor, type CssLength, type CssLengthExpression, type CssSize, type CssSizeKeyword, type CssValue, type UiColor, type UiColorName, type UiForegroundColorName, type UiSpaceName, calc, colorVar, em, flex, foregroundColor, foregroundColorVar, lengthVar, pct, plus, px, rem, remify, space, uiColor };
126
+ export { type CssColor, type CssFlex, type CssFlexBasis, type CssFlexKeyword, type CssForegroundColor, type CssLength, type CssLengthExpression, type CssSize, type CssSizeKeyword, type CssValue, type UiColor, type UiColorName, type UiForegroundColorName, type UiGap, type UiGapValue, type UiSpaceName, calc, colorVar, em, flex, foregroundColor, foregroundColorVar, lengthVar, pct, plus, px, rem, remify, space, uiColor };
120
127
  ```
121
128
 
122
129
  ## `@kerfjs/ui/disclosure-arrow`
@@ -651,7 +658,8 @@ import { K as KerfUiContent } from './semantic-content-BbzjvSu9.js';
651
658
  import { H as HorizontalAlignment, L as ListVerticalAlignment } from './flex-alignment-4ms8ZbV8.js';
652
659
  export { V as VerticalAlignment } from './flex-alignment-4ms8ZbV8.js';
653
660
  import { S as Sides } from './sides-BPSWde0A.js';
654
- import { UiSpaceName, CssLength, CssFlexKeyword, CssFlex } from './css-values.js';
661
+ import { UiGap, CssFlexKeyword, CssFlex } from './css-values.js';
662
+ export { CssLength, UiGapValue, UiSpaceName } from './css-values.js';
655
663
 
656
664
  type ListRootAttributes = Readonly<Record<`data-${string}`, string | undefined> & {
657
665
  'data-component'?: never;
@@ -670,8 +678,8 @@ interface ListProps {
670
678
  selectionMode?: 'multiple';
671
679
  /** Accessible name for the multi-select grid. */
672
680
  ariaLabel?: string;
673
- /** Use the standard item gap, a named UI spacing token, or a typed CSS length. Defaults to no gap. */
674
- gap?: boolean | UiSpaceName | CssLength;
681
+ /** Standard gap (`true`), one spacing value, or separate column and row values. Defaults to no gap. */
682
+ gap?: boolean | UiGap;
675
683
  /** Allow this list to grow/shrink, use a keyword, or supply a typed CSS flex shorthand. */
676
684
  flex?: boolean | CssFlexKeyword | CssFlex;
677
685
  /**
@@ -708,7 +716,7 @@ type ListConfig = Pick<ListProps, 'gap' | 'hAlign' | 'vAlign' | 'dividerSides' |
708
716
  /** A stretch-aligned vertical stack with optional gap, flex, fill, scroll, and dividers. */
709
717
  declare function List({ children, selectionMode, ariaLabel, gap, flex, fill, hAlign, vAlign, scrollable, dividerSides, textInsets, controlInsets, className, rootAttributes, slot, }: ListProps): kerfjs.SafeHtml;
710
718
 
711
- export { CssFlex, CssFlexKeyword, CssLength, HorizontalAlignment, List, type ListConfig, type ListProps, ListVerticalAlignment, Sides, UiSpaceName };
719
+ export { CssFlex, CssFlexKeyword, HorizontalAlignment, List, type ListConfig, type ListProps, ListVerticalAlignment, Sides, UiGap };
712
720
  ```
713
721
 
714
722
  ## `@kerfjs/ui/list-action-row`
@@ -2200,14 +2208,21 @@ interface TabNavigatorProps<Id extends string = string> {
2200
2208
  tabs: readonly TabNavigatorTab<Id>[];
2201
2209
  /** The controlled active tab id (the app owns selection). */
2202
2210
  active: NoInfer<Id>;
2211
+ /**
2212
+ * The bar's top separator. `auto` (default) draws it against a sunken active
2213
+ * work surface and otherwise follows `chromeDividers`; `hidden` suppresses
2214
+ * the line, including a scroll divider.
2215
+ */
2216
+ separator?: 'auto' | 'hidden';
2203
2217
  /**
2204
2218
  * The line over the tab bar, where it meets the active scene. `scroll`
2205
2219
  * (default) shows it only while more of the scene's content lies below —
2206
2220
  * never at the scroll end or when the content fits — once
2207
2221
  * `wireScrollDividers` (`@kerfjs/ui/wire-scroll-dividers`) is wired above
2208
2222
  * the scaffold; unwired, it does not show. `always` shows it without the
2209
- * wiring; `none` never, even when wired. The line is the bar's own 1px top
2210
- * border, so no state moves the bar or a tab.
2223
+ * wiring; `none` suppresses that scroll divider. A sunken active work
2224
+ * surface still draws the separator unless `separator="hidden"`. The line
2225
+ * is the bar's own 1px top border, so no state moves the bar or a tab.
2211
2226
  */
2212
2227
  chromeDividers?: 'scroll' | 'always' | 'none';
2213
2228
  className?: string;
@@ -2222,7 +2237,7 @@ interface TabNavigatorProps<Id extends string = string> {
2222
2237
  * On larger classes, promote the tabs to a `Workbench` rail or sidebar instead of
2223
2238
  * a bottom bar. See `docs/23-app-layouts.md` §3.4.
2224
2239
  */
2225
- declare function TabNavigator<Id extends string>({ id, label, tabs, active, chromeDividers, className, slot, }: TabNavigatorProps<Id>): SafeHtml;
2240
+ declare function TabNavigator<Id extends string>({ id, label, tabs, active, separator, chromeDividers, className, slot, }: TabNavigatorProps<Id>): SafeHtml;
2226
2241
 
2227
2242
  export { TabNavigator, type TabNavigatorProps, type TabNavigatorTab };
2228
2243
  ```
@@ -2393,8 +2408,8 @@ export { DEFAULT_BREAKPOINTS, type DeviceBreakpoints, type DeviceClass, type Dev
2393
2408
  ```ts
2394
2409
  import * as kerfjs from 'kerfjs';
2395
2410
  import { SafeHtml } from 'kerfjs';
2396
- import { a as CatalogProps } from './types-C9BubXfz.js';
2397
- export { b as CatalogBrand, c as CatalogEntry, d as CatalogRelated, C as CatalogResource, e as CatalogSecondaryGroup, f as CatalogSection, g as CatalogStageRootAttributes } from './types-C9BubXfz.js';
2411
+ import { a as CatalogProps } from './types-CXrh9Wyx.js';
2412
+ export { b as CatalogBackgroundStyle, c as CatalogBrand, d as CatalogEntry, e as CatalogRelated, C as CatalogResource, f as CatalogSecondaryGroup, g as CatalogSection, h as CatalogStageRootAttributes } from './types-CXrh9Wyx.js';
2398
2413
  import { K as KerfUiContent } from './semantic-content-BbzjvSu9.js';
2399
2414
  import './toolbar.js';
2400
2415
  import './sides-BPSWde0A.js';
@@ -2417,7 +2432,7 @@ import './resizable-region.js';
2417
2432
  * standard toggle moves into the entry toolbar while it is collapsed, and on
2418
2433
  * a small screen the sidebar overlays the stage like any Workbench rail.
2419
2434
  */
2420
- declare function Catalog({ id, brand, sections, active, content, collapsed, theme, headerActions, secondarySections, sidebarFooter, status, geometryOverlay, stageRootAttributes, selectAction, toggleSidebarAction, toggleThemeAction, toggleSecondaryAction, headerPlacement, footerPlacement, sidebar, mainToolbar, footerToolbar, className, slot, }: CatalogProps): kerfjs.SafeHtml;
2435
+ declare function Catalog({ id, brand, sections, active, content, collapsed, theme, headerActions, secondarySections, sidebarFooter, status, backgroundStyle, stageRootAttributes, selectAction, toggleSidebarAction, toggleThemeAction, toggleSecondaryAction, headerPlacement, footerPlacement, sidebar, mainToolbar, footerToolbar, className, slot, }: CatalogProps): kerfjs.SafeHtml;
2421
2436
 
2422
2437
  /** How a specimen aligns its visible edge with its `ListHeader` label. */
2423
2438
  type CatalogExampleAlign = 'glyph' | 'inline-control' | 'text-trigger' | 'none';
@@ -2488,7 +2503,7 @@ export { Catalog, CatalogExample, type CatalogExampleAlign, type CatalogExampleP
2488
2503
  ## `@kerfjs/ui/catalog-resources`
2489
2504
 
2490
2505
  ```ts
2491
- import { C as CatalogResource } from './types-C9BubXfz.js';
2506
+ import { C as CatalogResource } from './types-CXrh9Wyx.js';
2492
2507
  import './toolbar.js';
2493
2508
  import 'kerfjs';
2494
2509
  import './semantic-content-BbzjvSu9.js';
@@ -2603,14 +2618,6 @@ interface CatalogRevealOptions {
2603
2618
  * moving focus. Returns a cancellation function for rapid selection changes.
2604
2619
  */
2605
2620
  declare function revealCatalogEntry(root: HTMLElement, id: string, { block, inline, behavior, media, }?: CatalogRevealOptions): () => void;
2606
- /**
2607
- * Keep a Catalog's opt-in geometry overlay synchronized with its preview.
2608
- * Specimens receive computed border highlights (or a dashed bound when they
2609
- * have no border and are transparent), while positive computed margins use
2610
- * devtools-style orange bands. CSS/stylesheet-only changes are observed too.
2611
- * Returns a disposer.
2612
- */
2613
- declare function wireCatalogGeometryOverlay(root: HTMLElement): () => void;
2614
2621
  /**
2615
2622
  * Wire a {@link Catalog}'s interactions with one delegated listener set: sidebar
2616
2623
  * item selection (and the related-entry popup menu), the sidebar collapse toggle, and
@@ -2622,7 +2629,7 @@ declare function wireCatalogGeometryOverlay(root: HTMLElement): () => void;
2622
2629
  */
2623
2630
  declare function wireCatalog(root: HTMLElement, { onSelect, onToggleSidebar, onToggleTheme, onToggleSecondary, urlParam, revealSelection, selectAction, toggleSidebarAction, toggleThemeAction, toggleSecondaryAction, collapsed, sidebarSize, sidebarStorageKey, id: catalogId, }: WireCatalogOptions): () => void;
2624
2631
 
2625
- export { type CatalogRevealOptions, type WireCatalogOptions, revealCatalogEntry, wireCatalog, wireCatalogGeometryOverlay };
2632
+ export { type CatalogRevealOptions, type WireCatalogOptions, revealCatalogEntry, wireCatalog };
2626
2633
  ```
2627
2634
 
2628
2635
  ## `@kerfjs/ui/segmented-control`
@@ -3420,7 +3427,8 @@ import * as kerfjs from 'kerfjs';
3420
3427
  import { K as KerfUiContent } from './semantic-content-BbzjvSu9.js';
3421
3428
  import { H as HorizontalAlignment, V as VerticalAlignment } from './flex-alignment-4ms8ZbV8.js';
3422
3429
  import { S as Sides } from './sides-BPSWde0A.js';
3423
- import { UiSpaceName, CssLength, CssFlexKeyword, CssFlex } from './css-values.js';
3430
+ import { UiGap, CssFlexKeyword, CssFlex } from './css-values.js';
3431
+ export { CssLength, UiGapValue, UiSpaceName } from './css-values.js';
3424
3432
 
3425
3433
  type RowRootAttributes = Readonly<Record<`data-${string}`, string | undefined> & {
3426
3434
  'data-component'?: never;
@@ -3438,8 +3446,8 @@ interface RowProps {
3438
3446
  hAlign?: HorizontalAlignment;
3439
3447
  /** Vertical alignment and wrapped-line distribution. Defaults to full. */
3440
3448
  vAlign?: VerticalAlignment;
3441
- /** A named UI spacing token or typed CSS length. Defaults to xs. */
3442
- gap?: UiSpaceName | CssLength;
3449
+ /** One spacing value or separate column and row values. Defaults to xs. */
3450
+ gap?: UiGap;
3443
3451
  /** Allow this row to grow/shrink, use a keyword, or supply a typed CSS flex shorthand. */
3444
3452
  flex?: boolean | CssFlexKeyword | CssFlex;
3445
3453
  /**
@@ -3463,7 +3471,7 @@ interface RowProps {
3463
3471
  /** A horizontal flex row with explicit physical-axis alignment and spacing. */
3464
3472
  declare function Row({ children, hAlign, vAlign, gap, flex, fill, wrap, textInsets, controlInsets, className, rootAttributes, slot, }: RowProps): kerfjs.SafeHtml;
3465
3473
 
3466
- export { CssFlex, CssFlexKeyword, CssLength, HorizontalAlignment, Row, type RowProps, Sides, UiSpaceName, VerticalAlignment };
3474
+ export { CssFlex, CssFlexKeyword, HorizontalAlignment, Row, type RowProps, Sides, UiGap, VerticalAlignment };
3467
3475
  ```
3468
3476
 
3469
3477
  ## `@kerfjs/ui/grid`
@@ -3472,7 +3480,8 @@ export { CssFlex, CssFlexKeyword, CssLength, HorizontalAlignment, Row, type RowP
3472
3480
  import * as kerfjs from 'kerfjs';
3473
3481
  import { K as KerfUiContent } from './semantic-content-BbzjvSu9.js';
3474
3482
  import { S as Sides } from './sides-BPSWde0A.js';
3475
- import { UiSpaceName, CssLength, CssFlexKeyword, CssFlex } from './css-values.js';
3483
+ import { UiGap, CssFlexKeyword, CssFlex, CssLength } from './css-values.js';
3484
+ export { UiGapValue, UiSpaceName } from './css-values.js';
3476
3485
 
3477
3486
  type GridRootAttributes = Readonly<Record<`data-${string}`, string | undefined> & {
3478
3487
  'data-component'?: never;
@@ -3490,8 +3499,8 @@ interface GridCommonProps {
3490
3499
  selectionMode?: 'multiple';
3491
3500
  /** Accessible name for the multi-select grid. */
3492
3501
  ariaLabel?: string;
3493
- /** A named UI spacing token or typed CSS length. Defaults to xs. */
3494
- gap?: UiSpaceName | CssLength;
3502
+ /** One spacing value or separate column and row values. Defaults to xs. */
3503
+ gap?: UiGap;
3495
3504
  /** Allow this grid to grow/shrink, use a keyword, or supply a typed CSS flex shorthand. */
3496
3505
  flex?: boolean | CssFlexKeyword | CssFlex;
3497
3506
  /**
@@ -3525,7 +3534,7 @@ type GridProps = GridCommonProps & ({
3525
3534
  /** Render equal tracks with a fixed count or a responsive minimum width. */
3526
3535
  declare function Grid({ children, selectionMode, ariaLabel, columns, minColumnWidth, autoFill, gap, flex, fill, textInsets, controlInsets, className, rootAttributes, slot, }: GridProps): kerfjs.SafeHtml;
3527
3536
 
3528
- export { CssFlex, CssFlexKeyword, CssLength, Grid, type GridProps, Sides, UiSpaceName };
3537
+ export { CssFlex, CssFlexKeyword, CssLength, Grid, type GridProps, Sides, UiGap };
3529
3538
  ```
3530
3539
 
3531
3540
  ## `@kerfjs/ui/spacer`
@@ -3558,3 +3567,38 @@ export { d as TokenSearchModel, e as TokenSearchModelOptions, f as TokenSearchRe
3558
3567
  import 'kerfjs';
3559
3568
  import './semantic-content-BbzjvSu9.js';
3560
3569
  ```
3570
+
3571
+ ## `@kerfjs/ui/anchored-surface`
3572
+
3573
+ ```ts
3574
+ import { PopoverOptions, OverlayContent, OverlayHandle } from 'kerfjs/overlay';
3575
+
3576
+ /** App-facing options for a non-modal, arbitrary-content help surface. */
3577
+ interface AnchoredSurfaceOptions extends Pick<PopoverOptions, 'placement' | 'align' | 'gap' | 'dismiss' | 'initialFocus' | 'onDismiss' | 'outsideIgnore'> {
3578
+ /** Accessible name for the non-modal dialog. */
3579
+ label: string;
3580
+ }
3581
+ /** A viewport pointer location; `context` is the element under the pointer. */
3582
+ interface AnchoredSurfacePoint {
3583
+ x: number;
3584
+ y: number;
3585
+ /** Pass the event target when opening from inside a modal dialog. */
3586
+ context?: Element;
3587
+ }
3588
+ /**
3589
+ * Open app-owned content beside an element. The surface owns its Kerf UI chrome;
3590
+ * kerfjs/overlay owns positioning, top-layer/modal hosting, focus, and dismissal.
3591
+ * The caller owns content, action policy, and calling `close()` when an action
3592
+ * completes. `initialFocus` defaults to the first focusable descendant; set it
3593
+ * to `false` for read-only help that should leave focus on its trigger.
3594
+ */
3595
+ declare function openAnchoredSurface(anchor: Element, content: OverlayContent, options: AnchoredSurfaceOptions): OverlayHandle;
3596
+ /**
3597
+ * Open the same surface at pointer coordinates. The temporary anchor has no
3598
+ * layout or hit target. `context` keeps a surface opened inside a modal dialog
3599
+ * in that dialog's interactive host slot; it is removed on close or failure.
3600
+ */
3601
+ declare function openAnchoredSurfaceAt(point: AnchoredSurfacePoint, content: OverlayContent, options: AnchoredSurfaceOptions): OverlayHandle;
3602
+
3603
+ export { type AnchoredSurfaceOptions, type AnchoredSurfacePoint, openAnchoredSurface, openAnchoredSurfaceAt };
3604
+ ```