@astryxdesign/core 0.6.2 → 0.6.3-canary.0899f21

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 (549) hide show
  1. package/CHANGELOG.md +81 -0
  2. package/dist/BottomSheet/BottomSheet.d.ts +1 -1
  3. package/dist/BottomSheet/BottomSheet.d.ts.map +1 -1
  4. package/dist/BottomSheet/BottomSheet.js +3 -1
  5. package/dist/BottomSheet/BottomSheetPanel.d.ts +7 -5
  6. package/dist/BottomSheet/BottomSheetPanel.d.ts.map +1 -1
  7. package/dist/BottomSheet/BottomSheetPanel.js +56 -19
  8. package/dist/Button/Button.d.ts.map +1 -1
  9. package/dist/Button/Button.js +13 -28
  10. package/dist/Chat/ChatComposer.d.ts.map +1 -1
  11. package/dist/Chat/ChatComposer.js +10 -5
  12. package/dist/Chat/ChatComposerDrawer.d.ts +19 -5
  13. package/dist/Chat/ChatComposerDrawer.d.ts.map +1 -1
  14. package/dist/Chat/ChatComposerDrawer.js +48 -23
  15. package/dist/Chat/ChatComposerInput.d.ts +11 -3
  16. package/dist/Chat/ChatComposerInput.d.ts.map +1 -1
  17. package/dist/Chat/ChatComposerInput.js +63 -16
  18. package/dist/Chat/ChatDictationButton.d.ts +3 -2
  19. package/dist/Chat/ChatDictationButton.d.ts.map +1 -1
  20. package/dist/Chat/ChatDictationButton.js +6 -4
  21. package/dist/Chat/ChatLayout.d.ts +19 -0
  22. package/dist/Chat/ChatLayout.d.ts.map +1 -1
  23. package/dist/Chat/ChatLayout.js +19 -0
  24. package/dist/Chat/ChatLayoutScrollButton.d.ts.map +1 -1
  25. package/dist/Chat/ChatLayoutScrollButton.js +44 -34
  26. package/dist/Chat/ChatMessageBubble.d.ts +2 -0
  27. package/dist/Chat/ChatMessageBubble.d.ts.map +1 -1
  28. package/dist/Chat/ChatMessageBubble.js +5 -3
  29. package/dist/Chat/ChatMessageList.d.ts +2 -1
  30. package/dist/Chat/ChatMessageList.d.ts.map +1 -1
  31. package/dist/Chat/ChatMessageList.js +4 -3
  32. package/dist/Chat/ChatMessageMetadata.d.ts +5 -4
  33. package/dist/Chat/ChatMessageMetadata.d.ts.map +1 -1
  34. package/dist/Chat/ChatMessageMetadata.js +12 -9
  35. package/dist/Chat/ChatSendButton.js +1 -1
  36. package/dist/Chat/index.d.ts +1 -1
  37. package/dist/Chat/index.d.ts.map +1 -1
  38. package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
  39. package/dist/CheckboxInput/CheckboxInput.js +12 -2
  40. package/dist/Citation/Citation.d.ts +1 -1
  41. package/dist/Citation/Citation.d.ts.map +1 -1
  42. package/dist/Citation/Citation.js +3 -2
  43. package/dist/CodeBlock/highlightRanges.d.ts.map +1 -1
  44. package/dist/CodeBlock/highlightRanges.js +14 -3
  45. package/dist/Collapsible/Collapsible.d.ts.map +1 -1
  46. package/dist/Collapsible/Collapsible.js +6 -1
  47. package/dist/CommandPalette/CommandPaletteInput.d.ts.map +1 -1
  48. package/dist/CommandPalette/CommandPaletteInput.js +1 -1
  49. package/dist/ComplexSelector/ComplexSelector.d.ts.map +1 -1
  50. package/dist/ComplexSelector/ComplexSelector.js +1 -1
  51. package/dist/DateInput/DateInput.d.ts.map +1 -1
  52. package/dist/DateInput/DateInput.js +4 -4
  53. package/dist/DateInput/NativeDateField.d.ts.map +1 -1
  54. package/dist/DateInput/NativeDateField.js +16 -16
  55. package/dist/DateInput/TouchDateField.d.ts.map +1 -1
  56. package/dist/DateInput/TouchDateField.js +2 -2
  57. package/dist/DateRangeInput/DateRangeInput.d.ts.map +1 -1
  58. package/dist/DateRangeInput/DateRangeInput.js +4 -4
  59. package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
  60. package/dist/DateTimeInput/DateTimeInput.js +8 -8
  61. package/dist/DateTimeInput/TouchDateTimeField.d.ts.map +1 -1
  62. package/dist/DateTimeInput/TouchDateTimeField.js +4 -4
  63. package/dist/DateTimeInput/nativePickerSegmentStyles.d.ts +9 -3
  64. package/dist/DateTimeInput/nativePickerSegmentStyles.d.ts.map +1 -1
  65. package/dist/DateTimeInput/nativePickerSegmentStyles.js +3 -3
  66. package/dist/Dialog/DialogHeader.d.ts +8 -1
  67. package/dist/Dialog/DialogHeader.d.ts.map +1 -1
  68. package/dist/Dialog/DialogHeader.js +13 -4
  69. package/dist/Field/InputClearButton.d.ts +4 -2
  70. package/dist/Field/InputClearButton.d.ts.map +1 -1
  71. package/dist/Field/InputClearButton.js +4 -2
  72. package/dist/Field/PanelSearchInput.d.ts.map +1 -1
  73. package/dist/Field/PanelSearchInput.js +1 -1
  74. package/dist/FileInput/FileInput.d.ts.map +1 -1
  75. package/dist/FileInput/FileInput.js +7 -7
  76. package/dist/Icon/Icon.d.ts +6 -31
  77. package/dist/Icon/Icon.d.ts.map +1 -1
  78. package/dist/Icon/Icon.js +8 -71
  79. package/dist/Icon/IconDefaultSizeContext.d.ts +4 -0
  80. package/dist/Icon/IconDefaultSizeContext.d.ts.map +1 -0
  81. package/dist/Icon/IconDefaultSizeContext.js +18 -0
  82. package/dist/Icon/IconSize.stylex.d.ts +65 -0
  83. package/dist/Icon/IconSize.stylex.d.ts.map +1 -0
  84. package/dist/Icon/IconSize.stylex.js +75 -0
  85. package/dist/Item/Item.d.ts +1 -1
  86. package/dist/Item/Item.d.ts.map +1 -1
  87. package/dist/Item/Item.js +4 -3
  88. package/dist/Kbd/Kbd.d.ts +5 -3
  89. package/dist/Kbd/Kbd.d.ts.map +1 -1
  90. package/dist/Kbd/Kbd.js +36 -42
  91. package/dist/Link/Link.d.ts.map +1 -1
  92. package/dist/Link/Link.js +6 -2
  93. package/dist/Link/useLinkComponent.d.ts +5 -15
  94. package/dist/Link/useLinkComponent.d.ts.map +1 -1
  95. package/dist/Link/useLinkComponent.js +34 -51
  96. package/dist/List/List.d.ts +19 -1
  97. package/dist/List/List.d.ts.map +1 -1
  98. package/dist/List/List.js +9 -2
  99. package/dist/List/ListContext.d.ts +1 -0
  100. package/dist/List/ListContext.d.ts.map +1 -1
  101. package/dist/List/ListContext.js +2 -1
  102. package/dist/List/ListItem.d.ts +1 -1
  103. package/dist/List/ListItem.d.ts.map +1 -1
  104. package/dist/List/ListItem.js +9 -2
  105. package/dist/Markdown/Markdown.d.ts +8 -2
  106. package/dist/Markdown/Markdown.d.ts.map +1 -1
  107. package/dist/Markdown/Markdown.fr23.bench.d.ts +2 -0
  108. package/dist/Markdown/Markdown.fr23.bench.d.ts.map +1 -0
  109. package/dist/Markdown/Markdown.fr23.bench.js +150 -0
  110. package/dist/Markdown/Markdown.fr23.sampling.d.ts +2 -0
  111. package/dist/Markdown/Markdown.fr23.sampling.d.ts.map +1 -0
  112. package/dist/Markdown/Markdown.fr23.sampling.js +43 -0
  113. package/dist/Markdown/Markdown.js +262 -109
  114. package/dist/Markdown/ast.d.ts +162 -0
  115. package/dist/Markdown/ast.d.ts.map +1 -0
  116. package/dist/Markdown/ast.js +74 -0
  117. package/dist/Markdown/index.d.ts +5 -3
  118. package/dist/Markdown/index.d.ts.map +1 -1
  119. package/dist/Markdown/index.js +3 -2
  120. package/dist/Markdown/parser/index.d.ts +10 -0
  121. package/dist/Markdown/parser/index.d.ts.map +1 -0
  122. package/dist/Markdown/parser/index.js +10 -0
  123. package/dist/Markdown/parser.d.ts +126 -58
  124. package/dist/Markdown/parser.d.ts.map +1 -1
  125. package/dist/Markdown/parser.js +716 -167
  126. package/dist/Markdown/plugins/frontmatter.d.ts +32 -0
  127. package/dist/Markdown/plugins/frontmatter.d.ts.map +1 -0
  128. package/dist/Markdown/plugins/frontmatter.js +132 -0
  129. package/dist/Markdown/plugins/index.d.ts +17 -0
  130. package/dist/Markdown/plugins/index.d.ts.map +1 -0
  131. package/dist/Markdown/plugins/index.js +14 -0
  132. package/dist/Markdown/plugins/protocol.d.ts +191 -0
  133. package/dist/Markdown/plugins/protocol.d.ts.map +1 -0
  134. package/dist/Markdown/plugins/protocol.js +957 -0
  135. package/dist/Markdown/plugins/semanticFence.d.ts +36 -0
  136. package/dist/Markdown/plugins/semanticFence.d.ts.map +1 -0
  137. package/dist/Markdown/plugins/semanticFence.js +213 -0
  138. package/dist/Markdown/plugins/softBreaks.d.ts +3 -0
  139. package/dist/Markdown/plugins/softBreaks.d.ts.map +1 -0
  140. package/dist/Markdown/plugins/softBreaks.js +172 -0
  141. package/dist/Markdown/plugins/sourceDecoration.d.ts +76 -0
  142. package/dist/Markdown/plugins/sourceDecoration.d.ts.map +1 -0
  143. package/dist/Markdown/plugins/sourceDecoration.js +393 -0
  144. package/dist/Markdown/plugins/textTransform.d.ts +30 -0
  145. package/dist/Markdown/plugins/textTransform.d.ts.map +1 -0
  146. package/dist/Markdown/plugins/textTransform.js +374 -0
  147. package/dist/Markdown/remark.d.ts +196 -0
  148. package/dist/Markdown/remark.d.ts.map +1 -0
  149. package/dist/Markdown/remark.js +1062 -0
  150. package/dist/Markdown/url.d.ts +6 -0
  151. package/dist/Markdown/url.d.ts.map +1 -0
  152. package/dist/Markdown/url.js +31 -0
  153. package/dist/Markdown/utils.d.ts +4 -2
  154. package/dist/Markdown/utils.d.ts.map +1 -1
  155. package/dist/Markdown/utils.js +2 -1
  156. package/dist/MetadataList/MetadataList.js +3 -3
  157. package/dist/NumberInput/NumberInput.d.ts.map +1 -1
  158. package/dist/NumberInput/NumberInput.js +4 -4
  159. package/dist/Outline/index.d.ts +1 -0
  160. package/dist/Outline/index.d.ts.map +1 -1
  161. package/dist/Outline/parseOutlineFromMarkdown.d.ts +7 -1
  162. package/dist/Outline/parseOutlineFromMarkdown.d.ts.map +1 -1
  163. package/dist/Outline/parseOutlineFromMarkdown.js +14 -8
  164. package/dist/Outline/useOutlineFromMarkdown.d.ts +3 -1
  165. package/dist/Outline/useOutlineFromMarkdown.d.ts.map +1 -1
  166. package/dist/Outline/useOutlineFromMarkdown.js +8 -3
  167. package/dist/PowerSearch/PowerSearchEditPopover.d.ts.map +1 -1
  168. package/dist/PowerSearch/PowerSearchEditPopover.js +46 -30
  169. package/dist/PowerSearch/PowerSearchValueEditor.d.ts.map +1 -1
  170. package/dist/PowerSearch/PowerSearchValueEditor.js +5 -0
  171. package/dist/ProgressBar/ProgressBar.d.ts.map +1 -1
  172. package/dist/ProgressBar/ProgressBar.js +36 -31
  173. package/dist/RadioList/RadioListItem.d.ts.map +1 -1
  174. package/dist/RadioList/RadioListItem.js +13 -1
  175. package/dist/ScrollableArea/ScrollableArea.d.ts +1 -0
  176. package/dist/ScrollableArea/ScrollableArea.d.ts.map +1 -1
  177. package/dist/ScrollableArea/ScrollableArea.js +1 -0
  178. package/dist/SegmentedControl/SegmentedControlItem.d.ts.map +1 -1
  179. package/dist/SegmentedControl/SegmentedControlItem.js +5 -5
  180. package/dist/Selector/Selector.d.ts +9 -7
  181. package/dist/Selector/Selector.d.ts.map +1 -1
  182. package/dist/Selector/Selector.js +16 -7
  183. package/dist/SideNav/SideNav.d.ts +2 -1
  184. package/dist/SideNav/SideNav.d.ts.map +1 -1
  185. package/dist/SideNav/SideNav.js +9 -3
  186. package/dist/Slider/Slider.d.ts.map +1 -1
  187. package/dist/Slider/Slider.js +28 -12
  188. package/dist/Spinner/Spinner.d.ts.map +1 -1
  189. package/dist/Spinner/Spinner.js +23 -7
  190. package/dist/Switch/Switch.d.ts.map +1 -1
  191. package/dist/Switch/Switch.js +11 -0
  192. package/dist/TabList/Tab.d.ts +1 -1
  193. package/dist/TabList/Tab.d.ts.map +1 -1
  194. package/dist/TabList/Tab.js +20 -7
  195. package/dist/Table/Table.d.ts +1 -0
  196. package/dist/Table/Table.d.ts.map +1 -1
  197. package/dist/Table/Table.js +29 -13
  198. package/dist/TextArea/TextArea.d.ts.map +1 -1
  199. package/dist/TextArea/TextArea.js +1 -1
  200. package/dist/TextInput/TextInput.d.ts.map +1 -1
  201. package/dist/TextInput/TextInput.js +2 -2
  202. package/dist/TimeInput/TimeInput.d.ts.map +1 -1
  203. package/dist/TimeInput/TimeInput.js +4 -4
  204. package/dist/Timer/Timer.d.ts +49 -0
  205. package/dist/Timer/Timer.d.ts.map +1 -0
  206. package/dist/Timer/Timer.js +158 -0
  207. package/dist/Timer/index.d.ts +9 -0
  208. package/dist/Timer/index.d.ts.map +1 -0
  209. package/dist/Timer/index.js +10 -0
  210. package/dist/ToggleButton/ToggleButton.d.ts +9 -6
  211. package/dist/ToggleButton/ToggleButton.d.ts.map +1 -1
  212. package/dist/ToggleButton/ToggleButton.js +15 -27
  213. package/dist/TopNav/TopNavMenu.d.ts +1 -1
  214. package/dist/TopNav/TopNavMenu.d.ts.map +1 -1
  215. package/dist/TopNav/TopNavMenu.js +3 -2
  216. package/dist/TreeList/TreeList.d.ts.map +1 -1
  217. package/dist/TreeList/TreeList.js +3 -0
  218. package/dist/TreeList/TreeListItem.d.ts +6 -1
  219. package/dist/TreeList/TreeListItem.d.ts.map +1 -1
  220. package/dist/TreeList/TreeListItem.js +12 -2
  221. package/dist/TreeList/TreeListTypes.d.ts +8 -1
  222. package/dist/TreeList/TreeListTypes.d.ts.map +1 -1
  223. package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
  224. package/dist/Typeahead/BaseTypeahead.js +16 -7
  225. package/dist/astryx.css +27 -11
  226. package/dist/hooks/scrollKeyboardDelegation.d.ts +3 -0
  227. package/dist/hooks/scrollKeyboardDelegation.d.ts.map +1 -0
  228. package/dist/hooks/scrollKeyboardDelegation.js +146 -0
  229. package/dist/hooks/useClickableContainer.d.ts +10 -1
  230. package/dist/hooks/useClickableContainer.d.ts.map +1 -1
  231. package/dist/hooks/useClickableContainer.js +15 -4
  232. package/dist/hooks/useScrollableArea.d.ts +6 -2
  233. package/dist/hooks/useScrollableArea.d.ts.map +1 -1
  234. package/dist/hooks/useScrollableArea.js +17 -5
  235. package/dist/index.d.ts +1 -0
  236. package/dist/index.d.ts.map +1 -1
  237. package/dist/index.js +3 -0
  238. package/dist/theme/declarationBoundary.d.ts +17 -0
  239. package/dist/theme/declarationBoundary.d.ts.map +1 -0
  240. package/dist/theme/declarationBoundary.js +343 -0
  241. package/dist/theme/derivedVarRegistry.d.ts.map +1 -1
  242. package/dist/theme/derivedVarRegistry.js +4 -0
  243. package/dist/theme/generateThemeRules.d.ts +13 -7
  244. package/dist/theme/generateThemeRules.d.ts.map +1 -1
  245. package/dist/theme/generateThemeRules.js +140 -34
  246. package/dist/utils/interactionOverlay.stylex.d.ts +8 -0
  247. package/dist/utils/interactionOverlay.stylex.d.ts.map +1 -1
  248. package/dist/utils/interactionOverlay.stylex.js +9 -0
  249. package/dist/utils/safeUrl.d.ts +11 -0
  250. package/dist/utils/safeUrl.d.ts.map +1 -0
  251. package/dist/utils/safeUrl.js +78 -0
  252. package/locales/af-ZA.json +530 -1
  253. package/locales/ar-SA.json +490 -1
  254. package/locales/ca-ES.json +514 -1
  255. package/locales/cs-CZ.json +498 -1
  256. package/locales/da-DK.json +522 -1
  257. package/locales/de-DE.json +522 -1
  258. package/locales/el-GR.json +498 -1
  259. package/locales/es-ES.json +510 -1
  260. package/locales/fi-FI.json +498 -1
  261. package/locales/fr-FR.json +534 -1
  262. package/locales/he-IL.json +498 -1
  263. package/locales/hu-HU.json +498 -1
  264. package/locales/it-IT.json +510 -1
  265. package/locales/ja-JP.json +490 -1
  266. package/locales/ko-KR.json +498 -1
  267. package/locales/nl-NL.json +534 -1
  268. package/locales/no-NO.json +510 -1
  269. package/locales/pl-PL.json +506 -1
  270. package/locales/pt-BR.json +506 -1
  271. package/locales/pt-PT.json +506 -1
  272. package/locales/ro-RO.json +506 -1
  273. package/locales/ru-RU.json +498 -1
  274. package/locales/sr-SP.json +498 -1
  275. package/locales/sv-SE.json +502 -1
  276. package/locales/tr-TR.json +498 -1
  277. package/locales/uk-UA.json +498 -1
  278. package/locales/vi-VN.json +502 -1
  279. package/locales/zh-CN.json +490 -1
  280. package/locales/zh-TW.json +490 -1
  281. package/package.json +24 -4
  282. package/src/BottomSheet/BottomSheet.doc.mjs +8 -1
  283. package/src/BottomSheet/BottomSheet.spec.md +46 -20
  284. package/src/BottomSheet/BottomSheet.test.tsx +6 -3
  285. package/src/BottomSheet/BottomSheet.tsx +3 -1
  286. package/src/BottomSheet/BottomSheetKeyboard.test.tsx +195 -0
  287. package/src/BottomSheet/BottomSheetPanel.test.tsx +11 -1
  288. package/src/BottomSheet/BottomSheetPanel.tsx +49 -16
  289. package/src/BottomSheet/__tests__/BottomSheetKeyboard.a11y.browser.spec.ts +344 -0
  290. package/src/Button/Button.doc.mjs +5 -5
  291. package/src/Button/Button.tsx +15 -13
  292. package/src/Button/__tests__/Button.a11y.chromium.spec.ts +17 -1
  293. package/src/Button/__tests__/Button.a11y.known-failures.ts +0 -29
  294. package/src/Button/__tests__/Button.a11y.renders.tsx +9 -2
  295. package/src/Button/__tests__/Button.a11y.states.ts +9 -0
  296. package/src/Chat/ChatComposer.doc.mjs +14 -0
  297. package/src/Chat/ChatComposer.spec.md +230 -0
  298. package/src/Chat/ChatComposer.test.tsx +57 -0
  299. package/src/Chat/ChatComposer.tsx +21 -9
  300. package/src/Chat/ChatComposerDrawer.doc.mjs +63 -5
  301. package/src/Chat/ChatComposerDrawer.spec.md +267 -0
  302. package/src/Chat/ChatComposerDrawer.test.tsx +81 -12
  303. package/src/Chat/ChatComposerDrawer.tsx +38 -9
  304. package/src/Chat/ChatComposerInput.doc.mjs +114 -26
  305. package/src/Chat/ChatComposerInput.spec.md +185 -0
  306. package/src/Chat/ChatComposerInput.test.tsx +113 -3
  307. package/src/Chat/ChatComposerInput.tsx +78 -13
  308. package/src/Chat/ChatComposerTokenElement.spec.md +152 -0
  309. package/src/Chat/ChatComposerTokenElement.test.tsx +85 -0
  310. package/src/Chat/ChatDictationButton.doc.mjs +3 -3
  311. package/src/Chat/ChatDictationButton.spec.md +160 -0
  312. package/src/Chat/ChatDictationButton.test.tsx +92 -27
  313. package/src/Chat/ChatDictationButton.tsx +8 -6
  314. package/src/Chat/ChatLayout.doc.mjs +12 -4
  315. package/src/Chat/ChatLayout.spec.md +271 -0
  316. package/src/Chat/ChatLayout.test.tsx +28 -0
  317. package/src/Chat/ChatLayout.tsx +19 -0
  318. package/src/Chat/ChatLayoutScrollButton.spec.md +338 -0
  319. package/src/Chat/ChatLayoutScrollButton.test.tsx +31 -0
  320. package/src/Chat/ChatLayoutScrollButton.tsx +31 -14
  321. package/src/Chat/ChatMessageBubble.doc.mjs +28 -15
  322. package/src/Chat/ChatMessageBubble.spec.md +263 -0
  323. package/src/Chat/ChatMessageBubble.test.tsx +93 -0
  324. package/src/Chat/ChatMessageBubble.tsx +8 -3
  325. package/src/Chat/ChatMessageList.spec.md +222 -0
  326. package/src/Chat/ChatMessageList.test.tsx +64 -2
  327. package/src/Chat/ChatMessageList.tsx +4 -3
  328. package/src/Chat/ChatMessageMetadata.doc.mjs +57 -3
  329. package/src/Chat/ChatMessageMetadata.spec.md +220 -0
  330. package/src/Chat/ChatMessageMetadata.test.tsx +34 -0
  331. package/src/Chat/ChatMessageMetadata.tsx +13 -13
  332. package/src/Chat/ChatSendButton.test.tsx +1 -4
  333. package/src/Chat/ChatSendButton.tsx +1 -1
  334. package/src/Chat/__tests__/ChatLayoutScrollButton.a11y.chromium.spec.ts +514 -0
  335. package/src/Chat/__tests__/ChatLayoutScrollButtonSurface.a11y.chromium.spec.ts +740 -0
  336. package/src/Chat/__tests__/ChatMessageBubble.a11y.chromium.spec.ts +457 -0
  337. package/src/Chat/__tests__/ChatMessageBubble.auditProvenance.test.ts +91 -0
  338. package/src/Chat/__tests__/ChatMessageBubble.auditProvenance.ts +91 -0
  339. package/src/Chat/__tests__/ChatMessageList.a11y.chromium.spec.ts +456 -0
  340. package/src/Chat/__tests__/ChatMessageMetadata.a11y.chromium.spec.ts +413 -0
  341. package/src/Chat/index.ts +1 -0
  342. package/src/CheckboxInput/CheckboxInput.doc.mjs +11 -0
  343. package/src/CheckboxInput/CheckboxInput.test.tsx +34 -0
  344. package/src/CheckboxInput/CheckboxInput.tsx +21 -1
  345. package/src/Citation/Citation.doc.mjs +2 -2
  346. package/src/Citation/Citation.test.tsx +17 -0
  347. package/src/Citation/Citation.tsx +4 -2
  348. package/src/ClickableCard/ClickableCard.doc.mjs +2 -2
  349. package/src/ClickableCard/ClickableCard.test.tsx +102 -5
  350. package/src/CodeBlock/highlightRanges.test.ts +143 -1
  351. package/src/CodeBlock/highlightRanges.ts +15 -5
  352. package/src/Collapsible/Collapsible.doc.mjs +11 -0
  353. package/src/Collapsible/Collapsible.test.tsx +21 -0
  354. package/src/Collapsible/Collapsible.tsx +5 -0
  355. package/src/CommandPalette/CommandPaletteInput.tsx +6 -1
  356. package/src/ComplexSelector/ComplexSelector.tsx +6 -1
  357. package/src/DateInput/DateInput.tsx +6 -1
  358. package/src/DateInput/NativeDateField.tsx +24 -8
  359. package/src/DateInput/TouchDateField.tsx +6 -2
  360. package/src/DateRangeInput/DateRangeInput.tsx +6 -1
  361. package/src/DateTimeInput/DateTimeInput.tsx +6 -1
  362. package/src/DateTimeInput/TouchDateTimeField.tsx +6 -1
  363. package/src/DateTimeInput/nativePickerSegmentStyles.ts +24 -8
  364. package/src/Dialog/Dialog.doc.mjs +2 -0
  365. package/src/Dialog/DialogHeader.doc.mjs +22 -0
  366. package/src/Dialog/DialogHeader.test.tsx +167 -3
  367. package/src/Dialog/DialogHeader.tsx +37 -6
  368. package/src/Dialog/modules/DialogHeader.spec.md +101 -42
  369. package/src/DropdownMenu/DropdownMenu.test.tsx +5 -2
  370. package/src/Field/InputClearButton.test.tsx +17 -3
  371. package/src/Field/InputClearButton.tsx +5 -2
  372. package/src/Field/PanelSearchInput.tsx +5 -2
  373. package/src/FieldStatus/__tests__/StatusMessage.a11y.states.ts +1 -1
  374. package/src/FileInput/FileInput.tsx +11 -2
  375. package/src/Icon/Icon.doc.mjs +7 -5
  376. package/src/Icon/Icon.spec.md +81 -40
  377. package/src/Icon/Icon.test.tsx +6 -3
  378. package/src/Icon/Icon.tsx +20 -68
  379. package/src/Icon/IconDefaultSizeContext.ts +23 -0
  380. package/src/Icon/IconSize.stylex.ts +70 -0
  381. package/src/IconButton/IconButton.doc.mjs +3 -3
  382. package/src/IconButton/IconButton.test.tsx +40 -0
  383. package/src/Item/Item.doc.mjs +6 -2
  384. package/src/Item/Item.tsx +9 -3
  385. package/src/Kbd/Kbd.doc.mjs +3 -3
  386. package/src/Kbd/Kbd.test.tsx +57 -1
  387. package/src/Kbd/Kbd.tsx +57 -37
  388. package/src/Layout/LayoutFooter.doc.mjs +17 -0
  389. package/src/Link/Link.doc.mjs +17 -4
  390. package/src/Link/Link.test.tsx +24 -0
  391. package/src/Link/Link.tsx +5 -0
  392. package/src/Link/LinkProvider.doc.mjs +2 -2
  393. package/src/Link/__tests__/Link.navigation.a11y.chromium.spec.ts +261 -0
  394. package/src/Link/useLinkComponent.test.tsx +333 -0
  395. package/src/Link/useLinkComponent.ts +29 -57
  396. package/src/List/List.doc.mjs +6 -0
  397. package/src/List/List.spec.md +200 -0
  398. package/src/List/List.test.tsx +117 -1
  399. package/src/List/List.tsx +22 -2
  400. package/src/List/ListContext.tsx +3 -1
  401. package/src/List/ListItem.doc.mjs +2 -2
  402. package/src/List/ListItem.source-build.test.mjs +41 -0
  403. package/src/List/ListItem.tsx +26 -2
  404. package/src/Markdown/Markdown.doc.mjs +300 -2
  405. package/src/Markdown/Markdown.fr23.bench.ts +174 -0
  406. package/src/Markdown/Markdown.fr23.perf.test.ts +249 -0
  407. package/src/Markdown/Markdown.fr23.sampling.ts +49 -0
  408. package/src/Markdown/Markdown.helpers.perf.test.ts +489 -0
  409. package/src/Markdown/Markdown.public.test.ts +130 -3
  410. package/src/Markdown/Markdown.renderBoundary.test.tsx +72 -0
  411. package/src/Markdown/Markdown.spec.md +203 -45
  412. package/src/Markdown/Markdown.test.tsx +63 -0
  413. package/src/Markdown/Markdown.tsx +414 -135
  414. package/src/Markdown/ast.test.ts +307 -0
  415. package/src/Markdown/ast.ts +337 -0
  416. package/src/Markdown/incremental.test.ts +12 -0
  417. package/src/Markdown/index.ts +37 -1
  418. package/src/Markdown/modules/remark.spec.md +269 -0
  419. package/src/Markdown/modules/softBreaks.spec.md +137 -0
  420. package/src/Markdown/parser/index.ts +64 -0
  421. package/src/Markdown/parser.public.test.ts +103 -0
  422. package/src/Markdown/parser.test.ts +20 -0
  423. package/src/Markdown/parser.ts +1180 -235
  424. package/src/Markdown/plugins/frontmatter.test.tsx +125 -0
  425. package/src/Markdown/plugins/frontmatter.ts +198 -0
  426. package/src/Markdown/plugins/index.ts +54 -0
  427. package/src/Markdown/plugins/protocol.test.tsx +1022 -0
  428. package/src/Markdown/plugins/protocol.ts +1618 -0
  429. package/src/Markdown/plugins/semanticFence.test.tsx +546 -0
  430. package/src/Markdown/plugins/semanticFence.ts +424 -0
  431. package/src/Markdown/plugins/softBreaks.test.tsx +172 -0
  432. package/src/Markdown/plugins/softBreaks.ts +169 -0
  433. package/src/Markdown/plugins/sourceDecoration.test.tsx +799 -0
  434. package/src/Markdown/plugins/sourceDecoration.ts +539 -0
  435. package/src/Markdown/plugins/textTransform.test.ts +467 -0
  436. package/src/Markdown/plugins/textTransform.ts +554 -0
  437. package/src/Markdown/remark.test.tsx +1877 -0
  438. package/src/Markdown/remark.ts +1574 -0
  439. package/src/Markdown/url.ts +36 -0
  440. package/src/Markdown/utils.ts +13 -1
  441. package/src/MetadataList/MetadataList.test.tsx +4 -2
  442. package/src/MetadataList/MetadataList.tsx +3 -3
  443. package/src/MultiSelector/MultiSelector.test.tsx +1 -35
  444. package/src/MultiSelector/__tests__/MultiSelector.listbox.a11y.test.tsx +128 -0
  445. package/src/NumberInput/NumberInput.tsx +6 -1
  446. package/src/Outline/Outline.doc.mjs +7 -5
  447. package/src/Outline/Outline.spec.md +1 -1
  448. package/src/Outline/index.ts +1 -0
  449. package/src/Outline/modules/parseOutlineFromMarkdown.spec.md +142 -0
  450. package/src/Outline/parseOutlineFromMarkdown.ts +40 -10
  451. package/src/Outline/useOutlineFromMarkdown.ts +15 -3
  452. package/src/PowerSearch/PowerSearch.doc.mjs +2 -2
  453. package/src/PowerSearch/PowerSearchEditPopover.test.tsx +150 -1
  454. package/src/PowerSearch/PowerSearchEditPopover.tsx +51 -28
  455. package/src/PowerSearch/PowerSearchValueEditor.test.tsx +51 -0
  456. package/src/PowerSearch/PowerSearchValueEditor.tsx +4 -0
  457. package/src/ProgressBar/ProgressBar.test.tsx +29 -11
  458. package/src/ProgressBar/ProgressBar.tsx +59 -72
  459. package/src/RadioList/RadioList.doc.mjs +11 -0
  460. package/src/RadioList/RadioList.test.tsx +32 -0
  461. package/src/RadioList/RadioListItem.tsx +25 -1
  462. package/src/ScrollableArea/ScrollableArea.tsx +1 -0
  463. package/src/ScrollableArea/modules/useScrollableArea.spec.md +50 -22
  464. package/src/SegmentedControl/SegmentedControl.doc.mjs +2 -2
  465. package/src/SegmentedControl/SegmentedControl.test.tsx +31 -0
  466. package/src/SegmentedControl/SegmentedControlItem.tsx +6 -9
  467. package/src/Selector/Selector.doc.mjs +2 -2
  468. package/src/Selector/Selector.spec.md +51 -49
  469. package/src/Selector/Selector.test.tsx +61 -55
  470. package/src/Selector/Selector.tsx +34 -15
  471. package/src/Selector/__tests__/Listbox.a11y.chromium.spec.ts +130 -0
  472. package/src/Selector/__tests__/Listbox.a11y.dom.ts +38 -0
  473. package/src/Selector/__tests__/Listbox.a11y.inventory.test.ts +63 -0
  474. package/src/Selector/__tests__/Listbox.a11y.known-failures.ts +37 -0
  475. package/src/Selector/__tests__/Listbox.a11y.states.ts +232 -0
  476. package/src/Selector/__tests__/Selector.a11y.chromium.spec.ts +45 -0
  477. package/src/Selector/__tests__/Selector.listbox.a11y.test.tsx +121 -0
  478. package/src/SideNav/SideNav.doc.mjs +1 -1
  479. package/src/SideNav/SideNav.test.tsx +10 -0
  480. package/src/SideNav/SideNav.tsx +14 -2
  481. package/src/Slider/Slider.doc.mjs +17 -3
  482. package/src/Slider/Slider.test.tsx +221 -0
  483. package/src/Slider/Slider.tsx +40 -9
  484. package/src/Spinner/Spinner.test.tsx +4 -0
  485. package/src/Spinner/Spinner.tsx +31 -18
  486. package/src/Switch/Switch.doc.mjs +11 -0
  487. package/src/Switch/Switch.test.tsx +16 -0
  488. package/src/Switch/Switch.tsx +28 -0
  489. package/src/TabList/Tab.tsx +35 -7
  490. package/src/TabList/TabList.doc.mjs +11 -0
  491. package/src/TabList/TabList.spec.md +204 -0
  492. package/src/TabList/TabList.test.tsx +66 -0
  493. package/src/TabList/__tests__/Tabs.a11y.known-failures.ts +1 -34
  494. package/src/Table/Table.doc.mjs +1 -1
  495. package/src/Table/Table.spec.md +54 -40
  496. package/src/Table/Table.test.tsx +83 -10
  497. package/src/Table/Table.tsx +30 -22
  498. package/src/Table/__tests__/TableScroll.a11y.chromium.spec.ts +137 -0
  499. package/src/TextArea/TextArea.tsx +6 -1
  500. package/src/TextInput/TextInput.test.tsx +20 -1
  501. package/src/TextInput/TextInput.tsx +6 -1
  502. package/src/TimeInput/TimeInput.tsx +6 -1
  503. package/src/Timer/Timer.doc.mjs +183 -0
  504. package/src/Timer/Timer.spec.md +215 -0
  505. package/src/Timer/Timer.test.tsx +302 -0
  506. package/src/Timer/Timer.tsx +258 -0
  507. package/src/Timer/index.ts +11 -0
  508. package/src/ToggleButton/ToggleButton.doc.mjs +3 -3
  509. package/src/ToggleButton/ToggleButton.test.tsx +299 -4
  510. package/src/ToggleButton/ToggleButton.tsx +26 -33
  511. package/src/ToggleButton/ToggleButtonGroup.doc.mjs +3 -3
  512. package/src/ToggleButton/__tests__/ToggleButton.a11y.chromium.spec.ts +209 -0
  513. package/src/Token/Token.doc.mjs +2 -2
  514. package/src/Tokenizer/Tokenizer.spec.md +142 -75
  515. package/src/TopNav/TopNavMenu.doc.mjs +2 -2
  516. package/src/TopNav/TopNavMenu.test.tsx +30 -0
  517. package/src/TopNav/TopNavMenu.tsx +7 -2
  518. package/src/TreeList/TreeList.doc.mjs +3 -3
  519. package/src/TreeList/TreeList.spec.md +123 -75
  520. package/src/TreeList/TreeList.test.tsx +29 -0
  521. package/src/TreeList/TreeList.tsx +3 -0
  522. package/src/TreeList/TreeListItem.tsx +15 -1
  523. package/src/TreeList/TreeListTypes.ts +11 -1
  524. package/src/Typeahead/BaseTypeahead.spec.md +4 -3
  525. package/src/Typeahead/BaseTypeahead.tsx +21 -7
  526. package/src/Typeahead/Typeahead.test.tsx +53 -0
  527. package/src/__tests__/PressedState.a11y.chromium.spec.ts +813 -0
  528. package/src/__tests__/pressState.ts +93 -0
  529. package/src/hooks/scrollKeyboardDelegation.test.ts +155 -0
  530. package/src/hooks/scrollKeyboardDelegation.ts +233 -0
  531. package/src/hooks/useClickableContainer.test.tsx +236 -0
  532. package/src/hooks/useClickableContainer.ts +20 -4
  533. package/src/hooks/useScrollableArea.doc.mjs +15 -3
  534. package/src/hooks/useScrollableArea.test.tsx +59 -1
  535. package/src/hooks/useScrollableArea.ts +34 -10
  536. package/src/index.ts +3 -0
  537. package/src/inputFontFloor.test.ts +106 -0
  538. package/src/tailwind-theme.css +0 -6
  539. package/src/theme/Theme.test.tsx +32 -0
  540. package/src/theme/declarationBoundary.test.ts +126 -0
  541. package/src/theme/declarationBoundary.ts +347 -0
  542. package/src/theme/derivedVarRegistry.test.ts +7 -0
  543. package/src/theme/derivedVarRegistry.ts +1 -0
  544. package/src/theme/generateThemeRules.test.ts +526 -1
  545. package/src/theme/generateThemeRules.ts +228 -50
  546. package/src/theme/tokenValueCompat.test.ts +4 -1
  547. package/src/utils/interactionOverlay.stylex.ts +20 -0
  548. package/src/utils/safeUrl.test.ts +88 -0
  549. package/src/utils/safeUrl.ts +85 -0
@@ -92,6 +92,13 @@ export interface ButtonBindingState {
92
92
  * typo here is reported as a stale inventory, not as a standards failure.
93
93
  */
94
94
  readonly visibleLabel: string | null;
95
+ /**
96
+ * The surface that receives pointer input when it is not the role-bearing
97
+ * element. ClickableCard keeps its button/link hidden for role, name, and
98
+ * keyboard focus, and takes the pointer on the card surface; a binding that
99
+ * aimed the pointer at the hidden control would be testing the wrong surface.
100
+ */
101
+ readonly pointerTargetSelector?: string;
95
102
  /** The checked-in Storybook story the Chromium lane drives. */
96
103
  readonly storyId: string;
97
104
  /**
@@ -220,6 +227,7 @@ export const BUTTON_BINDING_STATES = [
220
227
  "a card whose whole surface performs an action, through the hidden button that carries the card's role and name",
221
228
  facts: facts(),
222
229
  visibleLabel: null,
230
+ pointerTargetSelector: '[data-a11y-pointer-target]',
223
231
  storyId: 'a11y-button-pattern--clickable-card-default',
224
232
  },
225
233
  {
@@ -228,6 +236,7 @@ export const BUTTON_BINDING_STATES = [
228
236
  summary: 'a disabled action card',
229
237
  facts: facts({operable: false, focusable: false, unavailable: true}),
230
238
  visibleLabel: null,
239
+ pointerTargetSelector: '[data-a11y-pointer-target]',
231
240
  storyId: 'a11y-button-pattern--clickable-card-disabled',
232
241
  },
233
242
 
@@ -8,6 +8,20 @@ export const docs = {
8
8
  displayName: 'Chat Composer',
9
9
  description:
10
10
  'Layout shell for a chat composer. Arranges named slots (drawer, header, input, footer, send) with page-radius container, elevation, a keyboard-only editor focus ring, and concentric inner radius for child elements.',
11
+ usage: {
12
+ description:
13
+ 'ChatComposer is the message-entry shell for a chat surface. It coordinates a controlled or uncontrolled draft, provides a default token-capable input and send/stop action, and arranges optional drawer, header, footer, and status content. Custom inputs and send controls can join the same value, submission, disabled, stop, and focus contract through useChatComposerContext().',
14
+ anatomy: [
15
+ {name: 'Composer frame', required: true, description: 'Outer composition root that groups the body with an optional status message above or below it.'},
16
+ {name: 'Composer body', required: true, description: 'Rounded, elevated surface containing the header, input, and footer.'},
17
+ {name: 'Drawer', required: false, description: 'Content before the body for attachments or other expandable context, typically ChatComposerDrawer.'},
18
+ {name: 'Header', required: false, description: 'Row for start-aligned actions and end-aligned contextual information.'},
19
+ {name: 'Input', required: true, description: 'Default ChatComposerInput or a custom editor connected through useChatComposerContext().'},
20
+ {name: 'Footer', required: true, description: 'Row for caller-supplied footer and send actions plus the primary action.'},
21
+ {name: 'Send or stop action', required: true, description: 'Default ChatSendButton or a custom sendButton; it submits the current draft or requests interruption.'},
22
+ {name: 'Status message', required: false, description: 'Error or warning feedback rendered before or after the composer body.'},
23
+ ],
24
+ },
11
25
  playground: {
12
26
  wrapper: {component: 'Stack', props: {width: 480}},
13
27
  },
@@ -0,0 +1,230 @@
1
+ ---
2
+ schema_version: 3
3
+ template_version: 5
4
+ kind: component
5
+ id: component:ChatComposer
6
+ authority: draft
7
+ archive_reason: null
8
+ superseded_by: null
9
+ approved_by: null
10
+ approved_at: null
11
+ owners: [cixzhang]
12
+ review_triggers: [public-api, behavior, layout, theming, accessibility]
13
+ verified_by:
14
+ [
15
+ packages/core/src/Chat/ChatComposer.test.tsx,
16
+ packages/core/src/Chat/ChatComposerInput.test.tsx,
17
+ packages/core/src/Chat/ChatSendButton.test.tsx,
18
+ apps/storybook/stories/ChatComposer.stories.tsx,
19
+ apps/storybook/stories/ChatComposerCustomInput.stories.tsx,
20
+ ]
21
+ modules: []
22
+ families: []
23
+ design_specs: []
24
+ architecture:
25
+ [
26
+ architecture:component-test-sufficiency,
27
+ architecture:component-theming-surface,
28
+ architecture:public-component-api,
29
+ architecture:interaction-modality,
30
+ architecture:react-component-runtime,
31
+ architecture:component-style-authoring,
32
+ architecture:knowledge-contracts,
33
+ ]
34
+ contributing: []
35
+ system_specs:
36
+ [
37
+ spec:AST-002,
38
+ spec:AST-009,
39
+ spec:AST-017,
40
+ spec:AST-020,
41
+ spec:AST-027,
42
+ spec:AST-029,
43
+ ]
44
+ ---
45
+
46
+ # ChatComposer component contract
47
+
48
+ ## Contract at a glance
49
+
50
+ | Area | Contract |
51
+ | ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
52
+ | Public contract | No new API shape or default. The exported context submits its supplied value; the default disabled editor exposes its disabled state; and an explicitly shown Stop action remains operable while message editing is disabled. |
53
+ | Behavior | ChatComposer coordinates a controlled or uncontrolled draft, trims a submitted value, clears through the existing value channel, composes caller slots, and keeps the default send/stop action synchronized with context. |
54
+ | End-user impact | Screen-reader users can identify the disabled editor, pointer and touch users can stop an interruptible response, and users of a custom editor send the draft that editor supplied instead of stale composer state. |
55
+ | Builder impact | None. Existing props, defaults, exports, and slot shapes remain; custom inputs can rely on the published `onSubmit(value)` context operation. |
56
+ | Compatibility/readiness | Patch-compatible corrections to released behavior. This observational draft is non-authoritative; body theming, BaseProps ownership, spacious density, and a stop state without `onStop` remain unresolved owner choices. |
57
+ | Review checks | Reject ignored context submission arguments, a disabled state hidden from the default textbox, an ancestor that blocks an enabled Stop action, or any change that presents the open questions below as settled policy. |
58
+ | Governing rules | `architecture:interaction-modality/INV4, INV7, INV9`; `architecture:public-component-api/INV5–INV6, INV9, INV12`; `architecture:component-theming-surface/INV4, INV6`; `spec:AST-020/FR1`; `spec:AST-029/DEC-4`. |
59
+
60
+ This table is a review projection; the body below is authoritative.
61
+
62
+ ## Intent
63
+
64
+ ChatComposer is the message-entry shell for a chat surface. It coordinates the
65
+ current draft and submission operation, lays out an optional drawer, header,
66
+ status, footer, and send-area content around a default or caller-supplied input,
67
+ and owns keyboard-only editor focus indication. Products own message transport,
68
+ streaming state, validation policy, and the content placed in each slot.
69
+
70
+ ## Compatibility and migration
71
+
72
+ - Released default preserved: yes for ordinary editing, submission, layout, and visual defaults.
73
+ - Compatibility class: patch-compatible behavioral correction; the public context operation now uses the value its caller supplies, and disabled-plus-stop restores the already enabled Stop path.
74
+ - Controlled/uncontrolled behavior: unchanged; a successful submission still clears through `onChange` in controlled mode and local state otherwise.
75
+ - Migration decision: `spec:AST-029/DEC-4`; each behavior correction was reproduced by a failing test before implementation changed.
76
+
77
+ Consumer migration instructions belong in consumer docs and release notes.
78
+
79
+ ## Ownership boundary
80
+
81
+ **Owns**
82
+
83
+ - Coordinating a controlled or uncontrolled serialized draft value with the input and submit action.
84
+ - Providing the default token-capable editor and send/stop action while allowing either to be replaced.
85
+ - Laying out the drawer, header, input, footer, send, and status regions.
86
+ - Applying composer density, elevation, disabled presentation, and keyboard-only editor focus indication.
87
+ - Publishing the composition context used by custom inputs and send controls.
88
+
89
+ **Does not own / non-goals**
90
+
91
+ - Sending, retrying, cancelling, or persisting a message — owned by the product callsite.
92
+ - Deciding when a response is streaming or whether it is interruptible — owned by the product callsite.
93
+ - Attachment data, model selection, speech recognition, or validation policy — owned by the supplied slot components and product callsite.
94
+ - A product's accessible conversation transcript or live response announcements — owned by the surrounding chat surface.
95
+
96
+ ## Public concepts
97
+
98
+ | Concept | Closed values or states | Meaning | Availability by variant/orientation/state | Default | Owner | Stability | Invalid-value behavior |
99
+ | ----------------------- | ------------------------------------------------------------ | ------------------------------------------------------------------------------------------------ | ------------------------------------------------ | --------------------------- | ----------------------------------- | --------- | ----------------------------------------------------------------------------- |
100
+ | Draft ownership | uncontrolled; controlled `value` + `onChange` | Selects where the serialized input draft is stored and how clearing is reported. | Every ChatComposer | uncontrolled empty string | `component:ChatComposer` | stable | Controlled `value` without an updating owner remains caller-controlled. |
101
+ | Submission | input submit; default send; custom context `onSubmit(value)` | Delivers one trimmed, non-empty supplied value and clears the draft through the current channel. | Enabled composer with a non-empty supplied value | no submission | `component:ChatComposer` | stable | Empty values and submissions while disabled are ignored. |
102
+ | Input composition | default ChatComposerInput; custom React node | Supplies the editing surface and optional registered focus control. | Every ChatComposer | ChatComposerInput | `component:ChatComposer` | stable | A custom input without a registered control gets textarea focus fallback. |
103
+ | Editing availability | enabled; disabled | Controls whether the draft can be edited or submitted. | Every ChatComposer | enabled | `component:ChatComposer` | stable | Disabled submission is ignored. |
104
+ | Primary action | send; stop | Sends the current draft or requests interruption. | Default ChatSendButton or a custom sendButton | send | `component:ChatComposer` | stable | A shown Stop action without `onStop` is currently rendered but inert. |
105
+ | Density | compact; balanced; spacious | Selects composer spacing. | Every ChatComposer | balanced | `component:ChatComposer` | stable | Unknown values are rejected by TypeScript. |
106
+ | Elevation | low; none | Selects a raised body or a flat bordered body. | Every ChatComposer | low | `component:ChatComposer` | stable | Unknown values are rejected by TypeScript. |
107
+ | Status | absent; error; warning; top; bottom | Adds semantic feedback before or after the body. | Optional status object | absent; bottom when present | `component:ChatComposer` | stable | An omitted message currently leaves the semantic status region empty. |
108
+ | Named composition slots | drawer; header actions/context; input; footer/send actions | Lets callers compose supporting controls and information around the draft. | Optional, independently supplied | omitted | `component:ChatComposer` | stable | Omitted slot groups emit no empty header; footer remains for the send action. |
109
+ | BaseProps surface | ref; DOM props/events; className/style; xstyle | Extends the component with DOM identity, behavior, and styling. | Every ChatComposer | omitted | `architecture:public-component-api` | stable | These surfaces currently have split root/body ownership; see OQ2. |
110
+
111
+ ## Behavioral and layout contract
112
+
113
+ Draft requirements identify their basis so observed code is not mistaken for an
114
+ intentional decision. A `current` contract contains no unresolved rows.
115
+
116
+ | ID | Candidate invariant | Basis | Draft review state |
117
+ | ---- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------- | ------------------ |
118
+ | FR1 | Controlled mode MUST report changes through `onChange`; uncontrolled mode MUST retain them locally. Every successful submit MUST trim and deliver the value supplied to that operation, then clear through the same value channel. | public types and docs; `architecture:public-component-api/INV3, INV9, INV12`; focused tests | settled |
119
+ | FR2 | The default editor MUST serialize its current text/tokens, submit Enter without Shift, preserve Shift+Enter, defer during IME composition, and allow a caller key handler to prevent the default operation. | implementation, docs, and focused tests | verify |
120
+ | FR3 | `isDisabled` MUST prevent draft edits and submissions and MUST expose `aria-disabled="true"` on the default textbox; removing the prop MUST remove that state. | `spec:AST-020/FR1` (WCAG 2.2 4.1.2); `architecture:interaction-modality/INV5`; red/green focused test | settled |
121
+ | FR4 | When `isStopShown` is true, the default primary action MUST remain an enabled, named Stop button and call `onStop`; if editing is also disabled, ancestor styling MUST NOT block its pointer, touch, or keyboard activation. | `architecture:interaction-modality/INV4, INV7, INV9`; red/green focused and browser-story tests | settled |
122
+ | FR5 | Omitted header slots MUST omit the header row; the drawer precedes the body; input fills the body between header and footer; footer actions precede send actions and the primary action; status follows `statusPosition`. | implementation, props, stories, and blocks | verify |
123
+ | FR6 | Compact currently reduces body padding and gap. Balanced and spacious currently use the same body spacing. Whether spacious needs distinct output MUST remain unresolved until a component/design owner decides it. | implementation and published union; no current owner selects distinct spacious geometry | human decision |
124
+ | FR7 | `low` currently applies low rest and medium hover/focus-within elevation; `none` applies no shadow and a border. Public theme reachability MUST cover the painting body or the public target/model MUST change through an approved compatibility path. | implementation; `architecture:component-theming-surface/INV4, INV6`; existing public issue | human decision |
125
+ | FR8 | Keyboard focus entering the registered/default editor MUST add the shared focus indication to the body; pointer focus MUST not add that extra ring. Clicking non-interactive body space MUST focus the registered control, then a textarea fallback. | implementation; `architecture:interaction-modality/INV1–INV3, INV9`; focused tests | verify |
126
+ | FR9 | Error status currently renders an alert; warning status renders a status; both pair a semantic icon with color and can render above or below the body. | implementation, docs, and stories; `spec:AST-020/FR1` | verify |
127
+ | FR10 | BaseProps currently split across elements: ref, DOM props/events, `className`, and `style` reach the outer frame while `xstyle` reaches the painted body. The owning element MUST remain unresolved pending compatibility review. | implementation; `architecture:public-component-api/INV5–INV6, INV8` | human decision |
128
+ | FR11 | The exported context MUST expose the current value, change and submit operations, placeholder, disabled/stop/send state, stop callback, and mutable input focus control to custom composition. | public export, types, docs, stories, and focused tests; `architecture:public-component-api/INV12` | verify |
129
+
130
+ ### Allowed variation
131
+
132
+ - **AV1 — Slot content.** Callers may omit or replace each named slot while preserving the composer's value, submit, focus, and disabled contracts.
133
+ - **AV2 — Product workflow.** Callers decide when to show status or Stop and what their callbacks do; ChatComposer owns only the local affordance and dispatch.
134
+ - **AV3 — Editor implementation.** A custom input may be a textarea, contenteditable editor, or other control when it follows the exported context and focus-control contract.
135
+
136
+ ### Representative states
137
+
138
+ | State | Required invariant | Allowed variation |
139
+ | ---------------------------- | --------------------------------------------------------------------------------------------------- | ------------------------------------------------------------ |
140
+ | Empty draft | Default send action is disabled and submission does not fire. | Placeholder and optional slots vary. |
141
+ | Non-empty draft | Enter or Send submits one trimmed value and clears through the active ownership channel. | Serialized token representation and transport behavior vary. |
142
+ | Controlled draft | Caller value remains authoritative; onChange receives edits and clear requests. | The caller may accept or defer each update. |
143
+ | Custom input | Context operations act on the supplied value and body click uses its registered focus control. | DOM/editor implementation varies. |
144
+ | Disabled editing | Default textbox exposes disabled state and cannot edit or submit. | Supporting content remains visible. |
145
+ | Disabled, interruptible work | Stop remains named, enabled, and reachable by pointer, touch, and keyboard. | Product cancellation behavior varies. |
146
+ | Flat elevation | Body has no shadow and uses its bordered presentation; keyboard focus indication remains available. | Theme tokens vary. |
147
+ | Status above or below | Semantic role, icon, color, and selected placement remain synchronized. | Message content and status type vary. |
148
+ | Narrow viewport | Composer remains within its containing inline size and the primary action remains operable. | Available inline size and optional slot content vary. |
149
+
150
+ ### Transformation and precedence order
151
+
152
+ - **ORD1 — Value update.** Receive an editor value → publish through `onChange` when controlled or update local state when uncontrolled → derive current context value and send availability.
153
+ - **ORD2 — Submission.** Receive the operation's supplied value → trim → reject empty or disabled submission → call public `onSubmit` once → request clearing through the current value channel.
154
+ - **ORD3 — Primary action.** Resolve `isStopShown` → expose Stop and dispatch `onStop`, otherwise derive send availability from current draft and disabled state → submit the current context value.
155
+ - **ORD4 — Composition order.** Optional top status → drawer → body header → input → footer actions → send actions → primary action → optional bottom status.
156
+
157
+ ### Performance and resources
158
+
159
+ - **PR1 — Context stability.** The exported context value SHOULD retain referential stability while none of its public members changes.
160
+ - **PR2 — Focus coordination.** The component MUST NOT add document listeners or observers to implement body-click focus or modality-specific focus indication.
161
+
162
+ ## Accessibility contract
163
+
164
+ - **AR1 — Editing state.** The default contenteditable surface acts as the textbox and MUST expose disabled state through `aria-disabled` when editing is unavailable.
165
+ - **AR2 — Native actions.** The default Send and Stop controls remain native buttons with translated accessible names; disabled Send uses native disabled behavior, while explicit Stop remains operable.
166
+ - **AR3 — Keyboard editing.** Enter submission MUST preserve Shift+Enter newline behavior, IME composition, and caller cancellation through `preventDefault()`.
167
+ - **AR4 — Focus indication.** Keyboard focus in the editor MUST produce the shared visible focus treatment; pointer focus does not claim keyboard modality, and focus on an internal action remains owned by that action.
168
+ - **AR5 — Status feedback.** Error feedback uses `role="alert"`; warning feedback uses `role="status"`; visible icon and color do not replace the caller's message content.
169
+
170
+ ## Design relationships
171
+
172
+ | Anatomy or state | Design requirement | Representation authority | Hierarchy role | Component contract |
173
+ | ------------------- | ------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- | -------------- | ------------------ |
174
+ | Composer frame | Groups body and optional status into one compositional shell. | observed implementation | container | FR5 |
175
+ | Composer body | Provides the painted rounded input/action surface and elevation. | elevation is shipped; public theme reachability is unsettled | prominent | FR7 |
176
+ | Drawer | Places attachment/context content before the body. | delegated to `component:ChatComposerDrawer` | supporting | FR5 |
177
+ | Header | Places caller actions at start and caller context at end. | observed implementation | supporting | FR5 |
178
+ | Input | Owns or hosts the editing surface and its focus control. | delegated to `component:ChatComposerInput` or caller custom input | prominent | FR1–FR3, FR8, FR11 |
179
+ | Footer | Places caller actions and the primary action on the final body row. | observed implementation | supporting | FR4–FR5 |
180
+ | Send or stop action | Presents the current primary operation. | delegated to `component:ChatSendButton` or caller custom send button | prominent | FR1, FR4 |
181
+ | Status message | Adds error or warning feedback before or after the body. | semantic role/color are shipped; separate public theme reachability is not asserted here | supporting | FR5, FR9, AR5 |
182
+
183
+ The aggregate Chat record currently owns the public `chat-composer` target. That
184
+ target sits on the frame and cannot select the body's non-inherited elevation and
185
+ border properties. This draft records the reachability gap without opting into a
186
+ machine theming map, selecting a new target name, or moving the released target.
187
+
188
+ ## Family and system relationships
189
+
190
+ - No current family or design record governs ChatComposer-specific behavior.
191
+ - `architecture:public-component-api` owns BaseProps element ownership, callback semantics, and the exported composition context.
192
+ - `architecture:interaction-modality` owns modality parity, focus ownership, and the requirement that enabled Stop remain reachable.
193
+ - `architecture:component-theming-surface` owns the anatomy-to-target disposition and makes the current body reachability mismatch blocking without deciding its repair shape.
194
+ - `architecture:component-test-sufficiency` owns public-state partitions, negative assertions, observable output, and the exact-head browser boundary.
195
+ - `architecture:react-component-runtime` owns render-derived state and browser/server boundaries.
196
+ - `architecture:knowledge-contracts` keeps consumer syntax in `ChatComposer.doc.mjs` and observed system behavior in this draft.
197
+ - `spec:AST-020/FR1` carries the current WCAG 2.2 accessibility baseline.
198
+ - `spec:AST-029/DEC-4` owns red-before-green behavior remediation; the broader Night Watch contract owns this observational backfill, finite evidence inventory, and fail-closed readiness report.
199
+
200
+ ## Verification map
201
+
202
+ | Contract | Verification | Representative states | Mutation or failure expectation | Audit section |
203
+ | ------------ | ---------------------------------------------------------------------------------- | ------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------- | ----------------------------------- |
204
+ | FR1, FR11 | `ChatComposer.test.tsx`; `ChatSendButton.test.tsx`; custom-input stories | controlled/uncontrolled, context-supplied value, default/custom send | Ignoring the context argument submits stale state; default Send passes no draft; clearing skips the active channel. | `audit:ChatComposer/api-behavior` |
205
+ | FR2 | `ChatComposerInput.test.tsx` | Enter, Shift+Enter, composing, cancelled keydown, text and token serialization | A key path sends during IME, loses newline behavior, bypasses caller cancellation, or emits the wrong string. | `audit:ChatComposer/input-behavior` |
206
+ | FR3 | red/green disabled-state assertion; focused input tests; exact-head axe | disabled and re-enabled default textbox | The textbox loses its ARIA state, remains editable, or accepts a disabled submit. | `audit:ChatComposer/accessibility` |
207
+ | FR4 | red/green pointer assertion; disabled-streaming Storybook play; exact-head test-ui | enabled send, shown Stop, disabled-plus-shown Stop | An ancestor blocks pointer hit-testing, Stop becomes native-disabled, or `onStop` does not fire. | `audit:ChatComposer/modality` |
208
+ | FR5, FR9 | ChatComposer stories, CLI block examples, production Storybook build | omitted/full slots, attachments, top/bottom status, error/warning | Slot order changes, an empty header appears, or status semantics and placement disagree. | `audit:ChatComposer/composition` |
209
+ | FR6 | source and future owner-selected density comparison | compact, balanced, spacious | The audit invents distinct spacious styling without authority or silently changes one public density. | `audit:ChatComposer/design-gap` |
210
+ | FR7 | elevation focused test; flat story; current theming guards; owner review pending | low rest/hover/focus, none, public target | Elevation output disappears or the reachability gap is represented as solved without an approved target mapping. | `audit:ChatComposer/theming` |
211
+ | FR8, AR4 | `ChatComposer.test.tsx`; exact-head browser/visual gates | keyboard, pointer, programmatic focus, internal action, body click | Pointer focus gains the keyboard ring, editor keyboard focus loses it, or body click bypasses the registered control. | `audit:ChatComposer/focus` |
212
+ | FR10 | source/DOM ownership review; owner decision pending | ref, DOM props, className/style, xstyle | A compatibility-affecting root/body move is made without deciding one public owner. | `audit:ChatComposer/api-gap` |
213
+ | narrow state | disabled-streaming mobile Storybook fixture and exact-head test-ui | 320px viewport with default input and Stop | The composer widens its viewport or the primary action becomes unreachable. | `audit:ChatComposer/responsive` |
214
+
215
+ ## Decision log
216
+
217
+ None. This draft records shipped behavior plus corrections already required by
218
+ current shared authority. It does not approve new ChatComposer policy.
219
+
220
+ ## Open questions
221
+
222
+ - **OQ1 — Body theming reachability.** Should a new stable body target be added, should the released `chat-composer` target move, or should elevation be projected through the existing root target by another compatible mechanism? (`human-api`)
223
+ - **OQ2 — BaseProps owner.** Should ref, neutral DOM props/events, `className`, `style`, and `xstyle` all own the outer frame or the painted body, and what compatibility path preserves existing consumers? (`human-api`)
224
+ - **OQ3 — Spacious density.** Should `spacious` intentionally alias `balanced`, or should it receive distinct spacing selected by design? (`human-design`)
225
+ - **OQ4 — Stop callback invariant.** When `isStopShown` is true without `onStop`, should the component reject the combination, disable or hide Stop, or keep the currently inert action? (`human-api`)
226
+
227
+ ## Content boundary
228
+
229
+ This file does not duplicate consumer prop tables/examples, current audit
230
+ results, implementation steps, or shared system rules. It links to their owners.
@@ -2,6 +2,7 @@
2
2
 
3
3
  import {beforeEach, describe, it, expect, vi} from 'vitest';
4
4
  import {act, render, fireEvent} from '@testing-library/react';
5
+ import userEvent from '@testing-library/user-event';
5
6
  import {useEffect, useRef} from 'react';
6
7
  import {ChatComposer} from './ChatComposer';
7
8
  import {useChatComposerContext} from './ChatContext';
@@ -118,6 +119,36 @@ describe('ChatComposer focus indication', () => {
118
119
  });
119
120
  });
120
121
 
122
+ describe('ChatComposer disabled contract', () => {
123
+ it('exposes disabled state on the default textbox and clears it when enabled', () => {
124
+ const {getByRole, rerender} = render(
125
+ <ChatComposer onSubmit={() => {}} isDisabled />,
126
+ );
127
+
128
+ expect(getByRole('textbox')).toHaveAttribute('aria-disabled', 'true');
129
+
130
+ rerender(<ChatComposer onSubmit={() => {}} />);
131
+ expect(getByRole('textbox')).not.toHaveAttribute('aria-disabled');
132
+ });
133
+
134
+ it('keeps the Stop action pointer-operable while editing is disabled', async () => {
135
+ const user = userEvent.setup();
136
+ const onStop = vi.fn();
137
+ const {getByRole} = render(
138
+ <ChatComposer
139
+ onSubmit={() => {}}
140
+ onStop={onStop}
141
+ isDisabled
142
+ isStopShown
143
+ />,
144
+ );
145
+
146
+ await user.click(getByRole('button', {name: 'Stop'}));
147
+
148
+ expect(onStop).toHaveBeenCalledTimes(1);
149
+ });
150
+ });
151
+
121
152
  // A custom input that participates in the composer's composition contract:
122
153
  // reads value/submit from the exported context, and registers a focus control
123
154
  // so the shell can drive body-click-to-focus without knowing its DOM shape.
@@ -151,7 +182,33 @@ function CustomContextInput({focusSpy}: {focusSpy: () => void}) {
151
182
  );
152
183
  }
153
184
 
185
+ function ContextSubmitButton() {
186
+ const ctx = useChatComposerContext();
187
+ return (
188
+ <button
189
+ type="button"
190
+ onClick={() => ctx?.onSubmit(' custom input draft ')}>
191
+ Submit custom input
192
+ </button>
193
+ );
194
+ }
195
+
154
196
  describe('ChatComposer input composition contract', () => {
197
+ it('submits the value supplied through the public context operation', () => {
198
+ const onSubmit = vi.fn();
199
+ const {getByRole} = render(
200
+ <ChatComposer
201
+ onSubmit={onSubmit}
202
+ value="captured composer draft"
203
+ input={<ContextSubmitButton />}
204
+ />,
205
+ );
206
+
207
+ fireEvent.click(getByRole('button', {name: 'Submit custom input'}));
208
+
209
+ expect(onSubmit).toHaveBeenCalledWith('custom input draft');
210
+ });
211
+
155
212
  it('exposes value/onChange/placeholder/isDisabled to a custom input via context', () => {
156
213
  const {getByTestId} = render(
157
214
  <ChatComposer
@@ -223,6 +223,11 @@ const styles = stylex.create({
223
223
  alignItems: 'center',
224
224
  gap: spacingVars['--spacing-1'],
225
225
  },
226
+ interruptibleFooter: {
227
+ // The composer may disable editing while a response is streaming. Restore
228
+ // pointer hit-testing for the footer so its Stop action stays reachable.
229
+ pointerEvents: 'auto',
230
+ },
226
231
  statusBar: {
227
232
  position: 'relative',
228
233
  zIndex: 0,
@@ -386,14 +391,17 @@ export function ChatComposer(props: ChatComposerProps) {
386
391
  [isControlled, onChange],
387
392
  );
388
393
 
389
- const handleSubmit = useCallback(() => {
390
- const trimmed = currentValue.trim();
391
- if (!trimmed || isDisabled) {
392
- return;
393
- }
394
- onSubmit(trimmed);
395
- updateValue('');
396
- }, [currentValue, isDisabled, onSubmit, updateValue]);
394
+ const handleSubmit = useCallback(
395
+ (value: string) => {
396
+ const trimmed = value.trim();
397
+ if (!trimmed || isDisabled) {
398
+ return;
399
+ }
400
+ onSubmit(trimmed);
401
+ updateValue('');
402
+ },
403
+ [isDisabled, onSubmit, updateValue],
404
+ );
397
405
 
398
406
  const canSend = currentValue.trim().length > 0 && !isDisabled;
399
407
 
@@ -530,7 +538,11 @@ export function ChatComposer(props: ChatComposerProps) {
530
538
 
531
539
  <div {...stylex.props(styles.footer)}>
532
540
  <div {...stylex.props(styles.footerLeft)}>{footerActions}</div>
533
- <div {...stylex.props(styles.footerRight)}>
541
+ <div
542
+ {...stylex.props(
543
+ styles.footerRight,
544
+ isDisabled && isStopShown && styles.interruptibleFooter,
545
+ )}>
534
546
  {sendActions}
535
547
  {sendButton ?? <ChatSendButton />}
536
548
  </div>
@@ -7,7 +7,58 @@ export const docs = {
7
7
  subComponentOf: 'Chat',
8
8
  displayName: 'Chat Composer Drawer',
9
9
  isHiddenFromOverview: true,
10
- description: "Collapsible drawer panel that sits above the chat input inside ChatComposer. Pass it to the composer's `drawer` slot to show attachments, context chips, or any supplementary content. When `count` is provided the drawer gains a collapse toggle: collapsed state shows a badge and label, expanded state shows all children.",
10
+ description: "Collapsible drawer panel that sits above the chat input inside ChatComposer. Pass it to the composer's `drawer` slot to show attachments, context chips, or any supplementary content. When `count` is provided the drawer gains a collapse toggle: collapsed state shows the default Badge and label or caller-provided `collapsedSummary`, while expanded state shows all children.",
11
+ usage: {
12
+ description:
13
+ 'Use ChatComposerDrawer in the ChatComposer drawer slot for supplementary content such as attachments, context chips, or previews. Provide count only when people should be able to collapse that content.',
14
+ bestPractices: [
15
+ {
16
+ guidance: true,
17
+ description:
18
+ 'Give label a concrete plural noun such as "Attachments" so the expand and collapse actions have a useful accessible name.',
19
+ },
20
+ {
21
+ guidance: true,
22
+ description:
23
+ 'Use controlled isCollapsed with onCollapsedChange when another part of the page owns drawer state; otherwise use defaultIsCollapsed.',
24
+ },
25
+ {
26
+ guidance: false,
27
+ description:
28
+ 'Put primary composer actions in the drawer; use ChatComposer footer or send-action slots so those controls remain available when the drawer is collapsed.',
29
+ },
30
+ ],
31
+ anatomy: [
32
+ {
33
+ name: 'Root surface',
34
+ required: true,
35
+ description: 'The drawer surface that composes above the ChatComposer body.',
36
+ },
37
+ {
38
+ name: 'Disclosure toggle',
39
+ required: false,
40
+ description: 'The keyboard- and pointer-operable collapse control rendered when count is provided.',
41
+ },
42
+ {
43
+ name: 'Collapsed summary',
44
+ required: false,
45
+ description: 'The default count Badge and label, or caller-provided visual content, presented while the drawer is collapsed.',
46
+ },
47
+ {
48
+ name: 'Content area',
49
+ required: true,
50
+ description: 'The caller-provided supplementary content; collapsed descendants are unavailable to keyboard and assistive technology.',
51
+ },
52
+ ],
53
+ },
54
+ theming: {
55
+ targets: [
56
+ {
57
+ className: 'astryx-chat-composer-drawer',
58
+ visualProps: ['collapsed'],
59
+ },
60
+ ],
61
+ },
11
62
  playground: {
12
63
  wrapper: {component: 'Stack', props: {width: 480}},
13
64
  defaults: {
@@ -35,9 +86,14 @@ export const docs = {
35
86
  {
36
87
  name: 'label',
37
88
  type: 'string',
38
- description: 'Label shown next to the count in collapsed state.',
89
+ description: 'Label shown next to the count in the default collapsed summary and used to name the expand/collapse action.',
39
90
  default: "'Items'",
40
91
  },
92
+ {
93
+ name: 'collapsedSummary',
94
+ type: 'ReactNode',
95
+ description: 'Visual content for the complete Collapsed summary anatomy part. When count enables collapse, this replaces the default neutral Badge and label while the component retains disclosure behavior and accessible naming.',
96
+ },
41
97
  {
42
98
  name: 'isCollapsed',
43
99
  type: 'boolean',
@@ -65,7 +121,8 @@ export const docsZh = {
65
121
  propDescriptions: {
66
122
  children: '抽屉内渲染的内容——标记、标签、预览或任何 React 元素。',
67
123
  count: '折叠徽章中显示的总数。提供时,抽屉获得折叠/展开切换。',
68
- label: '折叠状态下显示在数量旁边的标签。',
124
+ label: '默认折叠摘要中显示在数量旁边的标签,并用于命名展开/折叠操作。',
125
+ collapsedSummary: '折叠摘要解剖部分的自定义视觉内容。提供 count 时替换默认的徽章和标签;组件仍负责折叠行为与无障碍命名,该内容仅用于展示。',
69
126
  isCollapsed: '受控折叠状态。与 onCollapsedChange 一起使用。',
70
127
  defaultIsCollapsed: '非受控模式的初始折叠状态。',
71
128
  onCollapsedChange: '用户切换抽屉时触发的回调。',
@@ -79,8 +136,9 @@ export const docsDense = {
79
136
  description: 'collapsible drawer above chat input; pass to composer `drawer` slot for attachments, context chips, previews. `count` enables collapse toggle',
80
137
  propDescriptions: {
81
138
  children: 'drawer content: tokens, chips, previews, any React elements',
82
- count: 'total count for collapsed badge; enables collapse/expand toggle',
83
- label: 'collapsed label next to count badge',
139
+ count: 'total count for collapsed summary; enables collapse/expand toggle',
140
+ label: 'collapsed label next to the default count badge; names the disclosure action',
141
+ collapsedSummary: 'custom visual content replacing the complete Collapsed summary anatomy; requires count; presentation-only; default keeps Badge + label',
84
142
  isCollapsed: 'controlled collapsed state',
85
143
  defaultIsCollapsed: 'initial collapsed state (uncontrolled)',
86
144
  onCollapsedChange: 'callback on collapse toggle',