@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
@@ -13,6 +13,7 @@ review_triggers: [public-api, behavior, layout, theming, accessibility]
13
13
  verified_by:
14
14
  [
15
15
  packages/core/src/Table/Table.test.tsx,
16
+ packages/core/src/Table/__tests__/TableScroll.a11y.chromium.spec.ts,
16
17
  packages/core/src/Table/Table.perf.test.tsx,
17
18
  packages/core/src/Table/plugins/selection/useTableSelection.test.tsx,
18
19
  packages/core/src/Table/plugins/sortable/useTableSortable.test.tsx,
@@ -33,7 +34,7 @@ architecture:
33
34
  architecture:public-component-api,
34
35
  ]
35
36
  contributing: []
36
- system_specs: []
37
+ system_specs: [spec:AST-025]
37
38
  ---
38
39
 
39
40
  # Table component contract
@@ -49,11 +50,13 @@ generated anatomy, accessibility, migration, and evidence belong to each listed
49
50
 
50
51
  ## Compatibility and migration
51
52
 
52
- - Released default preserved: `yes`
53
- - Compatibility class: additive documentation only; runtime, DOM, styling,
54
- targets, aliases, and public API remain unchanged
53
+ - Released default preserved: `no`; a fitting Table scroll region now passes
54
+ scrolling to its ancestor and stays out of the keyboard order, while an
55
+ overflowing region keeps its existing native scrolling path.
56
+ - Compatibility class: standards-conformance bug fix; no public prop, target,
57
+ alias, or semantic Table element changes.
55
58
  - Controlled/uncontrolled behavior: unchanged
56
- - Migration decision: none
59
+ - Migration decision: `spec:AST-025` FR12, FR14, FR19, FR21, and DEC-1
57
60
 
58
61
  Consumer migration instructions belong in consumer docs and release notes.
59
62
 
@@ -87,7 +90,7 @@ Consumer migration instructions belong in consumer docs and release notes.
87
90
  concerns for `useTableRowStatus`.
88
91
  - New targets for current untargeted plugin parts, or correction of current
89
92
  target-reachability gaps.
90
- - New runtime behavior, DOM, API, target, or alias.
93
+ - New public API, theme target, or alias.
91
94
 
92
95
  ## Public concepts
93
96
 
@@ -103,20 +106,20 @@ documented in `Table.doc.mjs` and the member and module docs.
103
106
 
104
107
  ## Behavioral and layout contract
105
108
 
106
- | ID | Invariant | Basis | Evidence state |
107
- | ---- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------ | ------------------------------------------------------------------------------- |
108
- | FR1 | Styled Table renders one keyboard-focusable Scroll region around one semantic Table. | Current source, docs, and tests | Verified current behavior; no new behavior decided |
109
- | FR2 | Data-driven mode renders a Body section and a Header section with Column header cells when columns are present. Each data item renders a standard Row and Cells; an empty data array instead renders the configured empty-state row when enabled. It never creates a Footer section. | Current source, docs, and tests | Verified current behavior; no new behavior decided |
110
- | FR3 | Children mode passes caller composition through to the Table. TableHeader, TableBody, and TableFooter provide the respective sections, and TableRow, TableHeaderCell, and TableCell provide standard rows and cells. | Current source, docs, and tests | Verified current composition; no new API or DOM rule |
111
- | FR4 | `Table.doc.mjs` is the canonical aggregate consumer owner for the eight current targets: `table`, `table-scroll-wrapper`, `table-header`, `table-body`, `table-footer`, `table-row`, `table-cell`, and `table-header-cell`. Member docs retain direct lookup metadata through `subComponentOf: 'Table'`. | Current docs and CLI target tests | Verified parent ownership; focused placement coverage is partial |
112
- | FR5 | For a sortable column, useTableSortable renders a Sort control around the column label, an Icon-owned Sort indicator glyph, and a numeric Sort priority only while multi-sort has more than one active entry. | Current source, docs, and tests | Control and priority are tested; glyph presence is source-inspected only |
113
- | FR6 | useTableSelection renders CheckboxInput-owned Selection controls in the generated selection Column header cell and each selectable body Cell; selection remains row state rather than separate anatomy. | Current source, docs, and tests | Verified stable delegated controls; no target or state change |
114
- | FR7 | For an expandable row, useTableRowExpansion renders an Expansion control with an Icon-owned Expansion glyph and conditionally appends an Expanded detail panel whose cell spans the column count captured by that plugin's `transformColumns` step. | Current source, docs, and tests | Verified stable plugin parts; current target gaps remain |
115
- | FR8 | Empty data renders the default compact EmptyState unless the caller supplies replacement content or disables it. | Current source, docs, and tests | Verified conditional delegation; caller content remains outside ownership |
116
- | FR9 | Table converts the caller's named plugin record into one ordered array after its built-in styling plugin. Known names use the current canonical sequence `columnSettings → sort → tree → selection → pagination`; every other name follows that known set while preserving its record insertion order. | Current source and docs | Current shared ordering; canonical-name coverage is source-inspected |
117
- | FR10 | Every applicable non-context transform runs sequentially in the resolved plugin-array order, so a later plugin receives the value returned by every earlier successful plugin. A throwing transform reports a development error and leaves the prior accumulated value in the pipeline. | Current source and tests | Sequential composition is tested; failure isolation is source-inspected |
118
- | FR11 | `transformColumns` completes before element transforms. Table then applies table, header-cell/header-row, body-cell/body-row, scroll-wrapper, and context phases at their render points. Header-cell contributions use `before`, `content`, `after`, `overlay`, and `below` slots. Context transforms run in reverse so the first plugin becomes the outermost provider. | Current source, types, and tests | Transform application is tested; complete cross-phase order is source-inspected |
119
- | FR12 | When built-in and named plugin references are unchanged, Table reuses the resolved plugin array; unknown/custom plugin value identity and insertion order remain stable inputs to memoization. | Current source and performance tests | Current performance contract; focused named-order coverage is partial |
109
+ | ID | Invariant | Basis | Evidence state |
110
+ | ---- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- |
111
+ | FR1 | By default, Styled Table renders one named Scroll region around one observed content box and one semantic Table. The Scroll region enters the keyboard order and contains inline overscroll only while inline content effectively overflows; fitting content passes scroll gestures to its ancestor. Explicit scroll-wrapper plugin HTML attributes remain authoritative. | `spec:AST-025` FR12, FR14, FR19, FR21; current source, docs, and tests | Verified fitting and inline-overflow transitions through the shared `useScrollableArea` behavior core |
112
+ | FR2 | Data-driven mode renders a Body section and a Header section with Column header cells when columns are present. Each data item renders a standard Row and Cells; an empty data array instead renders the configured empty-state row when enabled. It never creates a Footer section. | Current source, docs, and tests | Verified current behavior; no new behavior decided |
113
+ | FR3 | Children mode passes caller composition through to the Table. TableHeader, TableBody, and TableFooter provide the respective sections, and TableRow, TableHeaderCell, and TableCell provide standard rows and cells. | Current source, docs, and tests | Verified current composition; no new API or DOM rule |
114
+ | FR4 | `Table.doc.mjs` is the canonical aggregate consumer owner for the eight current targets: `table`, `table-scroll-wrapper`, `table-header`, `table-body`, `table-footer`, `table-row`, `table-cell`, and `table-header-cell`. Member docs retain direct lookup metadata through `subComponentOf: 'Table'`. | Current docs and CLI target tests | Verified parent ownership; focused placement coverage is partial |
115
+ | FR5 | For a sortable column, useTableSortable renders a Sort control around the column label, an Icon-owned Sort indicator glyph, and a numeric Sort priority only while multi-sort has more than one active entry. | Current source, docs, and tests | Control and priority are tested; glyph presence is source-inspected only |
116
+ | FR6 | useTableSelection renders CheckboxInput-owned Selection controls in the generated selection Column header cell and each selectable body Cell; selection remains row state rather than separate anatomy. | Current source, docs, and tests | Verified stable delegated controls; no target or state change |
117
+ | FR7 | For an expandable row, useTableRowExpansion renders an Expansion control with an Icon-owned Expansion glyph and conditionally appends an Expanded detail panel whose cell spans the column count captured by that plugin's `transformColumns` step. | Current source, docs, and tests | Verified stable plugin parts; current target gaps remain |
118
+ | FR8 | Empty data renders the default compact EmptyState unless the caller supplies replacement content or disables it. | Current source, docs, and tests | Verified conditional delegation; caller content remains outside ownership |
119
+ | FR9 | Table converts the caller's named plugin record into one ordered array after its built-in styling plugin. Known names use the current canonical sequence `columnSettings → sort → tree → selection → pagination`; every other name follows that known set while preserving its record insertion order. | Current source and docs | Current shared ordering; canonical-name coverage is source-inspected |
120
+ | FR10 | Every applicable non-context transform runs sequentially in the resolved plugin-array order, so a later plugin receives the value returned by every earlier successful plugin. A throwing transform reports a development error and leaves the prior accumulated value in the pipeline. | Current source and tests | Sequential composition is tested; failure isolation is source-inspected |
121
+ | FR11 | `transformColumns` completes before element transforms. Table then applies table, header-cell/header-row, body-cell/body-row, scroll-wrapper, and context phases at their render points. Header-cell contributions use `before`, `content`, `after`, `overlay`, and `below` slots. Context transforms run in reverse so the first plugin becomes the outermost provider. | Current source, types, and tests | Transform application is tested; complete cross-phase order is source-inspected |
122
+ | FR12 | When built-in and named plugin references are unchanged, Table reuses the resolved plugin array; unknown/custom plugin value identity and insertion order remain stable inputs to memoization. | Current source and performance tests | Current performance contract; focused named-order coverage is partial |
120
123
 
121
124
  ### Current evidence and gaps
122
125
 
@@ -193,11 +196,15 @@ documented in `Table.doc.mjs` and the member and module docs.
193
196
 
194
197
  ## Accessibility contract
195
198
 
196
- This contract does not change or extend the current native table semantics,
197
- focusable Scroll region, column-header scope, sort `aria-sort`, selection
198
- `aria-selected`, CheckboxInput labels, or expansion `aria-expanded` behavior.
199
- Each public module owns accessibility introduced by its transforms; the shared
200
- pipeline does not confer correctness on module output.
199
+ By default, the Scroll region is named as a `group`, enters sequential keyboard
200
+ navigation only while inline overflow is effective, and keeps native Arrow/Page
201
+ scrolling. A scroll-wrapper plugin may explicitly override its HTML accessibility
202
+ attributes. Losing overflow removes future default tab stops without moving current
203
+ focus. Effective inline scrolling contains overscroll at its edge; fitting content
204
+ leaves page scrolling available. Native table semantics, column-header scope, sort
205
+ `aria-sort`, selection `aria-selected`, CheckboxInput labels, and expansion
206
+ `aria-expanded` remain unchanged. Each public module owns accessibility introduced
207
+ by its transforms; the shared pipeline does not confer correctness on module output.
201
208
 
202
209
  ## Design relationships
203
210
 
@@ -294,24 +301,31 @@ aggregate ownership.
294
301
 
295
302
  ## Verification map
296
303
 
297
- | Contract | Verification | Representative states | Mutation or failure expectation | Audit section |
298
- | ------------------- | ---------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------- |
299
- | FR1-FR3 | `Table.test.tsx` render, structure, children-mode, section, and target assertions | Data-driven rows, empty data, and children composition | Removing Table, Scroll region, or configured structure fails existing role, structure, class, or prop-forwarding assertions; Row and Cell are conditional on rendered data or caller composition. | `audit:Table/anatomy` |
300
- | FR4 | CLI discovery and API target tests plus source inspection | Direct member docs and unfiltered/scoped target output | Duplicating a parent/member target or changing the canonical owner fails parent-aware discovery assertions; section target placement remains source-inspected. | `audit:Table/theming` |
301
- | FR5 | `plugins/sortable/useTableSortable.test.tsx` plus source inspection | Unsorted, ascending, descending, and multi-sort | Removing the Sort control, conditional priority, or ARIA state fails existing assertions. Removing the Sort indicator glyph does not currently fail a focused test; glyph presence and delegated Icon target placement remain source-inspected. | `audit:Table/anatomy` |
302
- | FR6 | `plugins/selection/useTableSelection.test.tsx` | Select all, individual, disabled, and non-selectable | Removing header/body Selection controls or row selection state fails existing structure, label, interaction, and ARIA assertions; delegated CheckboxInput target placement remains source-inspected. | `audit:Table/anatomy` |
303
- | FR7 | `plugins/rowExpansion/useTableRowExpansion.test.tsx` plus source inspection | Collapsed, expanded, and non-expandable rows | Removing the Expansion control, conditional detail panel, captured-count `colSpan`, or ARIA state fails existing assertions in the covered plugin order; later column transforms, delegated Icon target placement, and untargeted panel wrappers remain source-inspected. | `audit:Table/anatomy` |
304
- | FR8 | `Table.test.tsx` empty-state suite plus EmptyState public target metadata | Default, custom, disabled, and non-empty | Removing conditional empty behavior fails existing assertions; default EmptyState delegation remains source-inspected. | `audit:Table/anatomy` |
305
- | FR9-FR11 | `Table.test.tsx`, `types.ts`, `BaseTable.tsx`, and `useBaseTablePlugins.ts` | Built-in plus known and custom named plugins; every transform phase | Sequential composition, base-before-user behavior, transform application, and slot output have focused coverage; complete known-name sorting, phase order, exception continuation, and context nesting remain source-inspected. | `audit:Table/plugins` |
306
- | FR12, PR1 | `Table.perf.test.tsx` plus `useBaseTablePlugins.ts` source inspection | Same plugin references, recreated record, and changed plugin value | Unchanged plugin values must preserve the resolved array and representative no-op row-update budgets; focused named-record identity coverage remains partial. | `audit:Table/performance` |
307
- | Module backlink | `scripts/check-knowledge.mjs` | Active parent and colocated module record | A missing, duplicate, mis-parented, wrong-kind, misnamed, or undiscovered module record fails knowledge validation. | `audit:Table/modules` |
308
- | Theming anatomy map | `scripts/check-knowledge.mjs`, `themingTargets.test.ts`, and CLI parent-aware target discovery tests | Canonical anatomy, eight current targets, legacy alias | Missing, extra, duplicated, prefixed, stale, alias-backed, or independently owned member mappings fail repository validation or discovery coverage. | `audit:Table/theming` |
304
+ | Contract | Verification | Representative states | Mutation or failure expectation | Audit section |
305
+ | ------------------- | ----------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------- |
306
+ | FR1-FR3 | `Table.test.tsx` render, structure, fit/overflow transitions, children-mode, section, and target assertions | Fitting and inline-overflowing data-driven tables, empty data, and children composition | Removing Table, Scroll region, observed content box, conditional keyboard access, or effective-axis containment fails existing role, structure, state, class, style, or prop-forwarding assertions; Row and Cell are conditional on rendered data or caller composition. | `audit:Table/anatomy` |
307
+ | FR4 | CLI discovery and API target tests plus source inspection | Direct member docs and unfiltered/scoped target output | Duplicating a parent/member target or changing the canonical owner fails parent-aware discovery assertions; section target placement remains source-inspected. | `audit:Table/theming` |
308
+ | FR5 | `plugins/sortable/useTableSortable.test.tsx` plus source inspection | Unsorted, ascending, descending, and multi-sort | Removing the Sort control, conditional priority, or ARIA state fails existing assertions. Removing the Sort indicator glyph does not currently fail a focused test; glyph presence and delegated Icon target placement remain source-inspected. | `audit:Table/anatomy` |
309
+ | FR6 | `plugins/selection/useTableSelection.test.tsx` | Select all, individual, disabled, and non-selectable | Removing header/body Selection controls or row selection state fails existing structure, label, interaction, and ARIA assertions; delegated CheckboxInput target placement remains source-inspected. | `audit:Table/anatomy` |
310
+ | FR7 | `plugins/rowExpansion/useTableRowExpansion.test.tsx` plus source inspection | Collapsed, expanded, and non-expandable rows | Removing the Expansion control, conditional detail panel, captured-count `colSpan`, or ARIA state fails existing assertions in the covered plugin order; later column transforms, delegated Icon target placement, and untargeted panel wrappers remain source-inspected. | `audit:Table/anatomy` |
311
+ | FR8 | `Table.test.tsx` empty-state suite plus EmptyState public target metadata | Default, custom, disabled, and non-empty | Removing conditional empty behavior fails existing assertions; default EmptyState delegation remains source-inspected. | `audit:Table/anatomy` |
312
+ | FR9-FR11 | `Table.test.tsx`, `types.ts`, `BaseTable.tsx`, and `useBaseTablePlugins.ts` | Built-in plus known and custom named plugins; every transform phase | Sequential composition, base-before-user behavior, transform application, and slot output have focused coverage; complete known-name sorting, phase order, exception continuation, and context nesting remain source-inspected. | `audit:Table/plugins` |
313
+ | FR12, PR1 | `Table.perf.test.tsx` plus `useBaseTablePlugins.ts` source inspection | Same plugin references, recreated record, and changed plugin value | Unchanged plugin values must preserve the resolved array and representative no-op row-update budgets; focused named-record identity coverage remains partial. | `audit:Table/performance` |
314
+ | Module backlink | `scripts/check-knowledge.mjs` | Active parent and colocated module record | A missing, duplicate, mis-parented, wrong-kind, misnamed, or undiscovered module record fails knowledge validation. | `audit:Table/modules` |
315
+ | Theming anatomy map | `scripts/check-knowledge.mjs`, `themingTargets.test.ts`, and CLI parent-aware target discovery tests | Canonical anatomy, eight current targets, legacy alias | Missing, extra, duplicated, prefixed, stale, alias-backed, or independently owned member mappings fail repository validation or discovery coverage. | `audit:Table/theming` |
309
316
 
310
317
  ## Decision log
311
318
 
312
- None. This current contract records existing Table facts, approved canonical parent
313
- ownership, and the shared plugin protocol without introducing a component-local
314
- visual or runtime change.
319
+ ### DEC-1 — Table adopts the shared scroll behavior on its owned viewport
320
+
321
+ **Reference:** `component:Table/DEC-1`
322
+ **Decider:** `cixzhang`, 2026-09-20
323
+
324
+ Table uses `useScrollableArea` on its existing Scroll region with a private observed
325
+ content box. Inline overflow remains native and keyboard reachable. Containment is
326
+ active only while that axis can scroll, so a fitting Table does not create a dead
327
+ scroll zone for an ancestor. This keeps one Table-owned viewport and adds no public
328
+ prop or parallel overflow detector.
315
329
 
316
330
  ## Open questions
317
331
 
@@ -10,7 +10,7 @@
10
10
  */
11
11
 
12
12
  import {describe, it, expect, vi} from 'vitest';
13
- import {render, screen} from '@testing-library/react';
13
+ import {act, render, screen} from '@testing-library/react';
14
14
  import * as stylex from '@stylexjs/stylex';
15
15
  import {BaseTable} from './BaseTable';
16
16
  import {Table} from './Table';
@@ -837,22 +837,95 @@ describe('Table', () => {
837
837
  expect(screen.getAllByRole('row')).toHaveLength(4);
838
838
  });
839
839
 
840
- it('wraps table in a scroll container', () => {
840
+ it('wraps the table in an observed scroll content box', () => {
841
841
  render(<Table data={users} columns={columns} />);
842
842
  const table = screen.getByRole('table');
843
- const wrapper = table.parentElement;
843
+ const content = table.parentElement;
844
+ const wrapper = content?.parentElement;
845
+ expect(content).toHaveAttribute('data-scroll-content');
844
846
  expect(wrapper).toBeTruthy();
845
847
  expect(wrapper!.className).toContain('astryx-table-scroll-wrapper');
846
848
  });
847
849
 
848
- it('makes the scroll container keyboard-focusable', () => {
850
+ it('keeps a fitting scroll container out of the keyboard order', () => {
849
851
  render(<Table data={users} columns={columns} />);
850
- const table = screen.getByRole('table');
851
- const wrapper = table.parentElement;
852
- expect(wrapper).toBeTruthy();
853
- expect(wrapper!).toHaveAttribute('tabindex', '0');
854
- expect(wrapper!).toHaveAttribute('role', 'group');
855
- expect(wrapper!).toHaveAttribute('aria-label', 'Table');
852
+ const wrapper = screen.getByRole('group', {name: 'Table'});
853
+ expect(wrapper).not.toHaveAttribute('tabindex');
854
+ expect(wrapper.style.overscrollBehaviorX).toBe('auto');
855
+ });
856
+
857
+ it('preserves scroll-wrapper HTML attributes from plugins', () => {
858
+ const plugin: TablePlugin<User> = {
859
+ transformScrollWrapper: props => ({
860
+ ...props,
861
+ htmlProps: {
862
+ ...props.htmlProps,
863
+ role: 'region',
864
+ 'aria-label': 'Orders',
865
+ tabIndex: 2,
866
+ },
867
+ }),
868
+ };
869
+ render(<Table data={users} columns={columns} plugins={{custom: plugin}} />);
870
+ const wrapper = screen.getByRole('region', {name: 'Orders'});
871
+ expect(wrapper).toHaveAttribute('tabindex', '2');
872
+ });
873
+
874
+ it('contains overscroll only while the table scrolls', () => {
875
+ const frames: FrameRequestCallback[] = [];
876
+ vi.stubGlobal(
877
+ 'requestAnimationFrame',
878
+ vi.fn((callback: FrameRequestCallback) => {
879
+ frames.push(callback);
880
+ return frames.length;
881
+ }),
882
+ );
883
+ vi.stubGlobal('cancelAnimationFrame', vi.fn());
884
+
885
+ try {
886
+ render(<Table data={users} columns={columns} />);
887
+ const wrapper = screen.getByRole('group', {name: 'Table'});
888
+ Object.assign(wrapper.style, {overflowX: 'auto'});
889
+ for (const [key, value] of Object.entries({
890
+ clientWidth: 100,
891
+ clientHeight: 100,
892
+ scrollWidth: 180,
893
+ scrollHeight: 100,
894
+ scrollLeft: 0,
895
+ scrollTop: 0,
896
+ })) {
897
+ Object.defineProperty(wrapper, key, {
898
+ configurable: true,
899
+ value,
900
+ writable: true,
901
+ });
902
+ }
903
+
904
+ act(() => {
905
+ wrapper.dispatchEvent(new Event('scroll'));
906
+ frames.splice(0).forEach(callback => callback(performance.now()));
907
+ });
908
+
909
+ expect(wrapper).toHaveAttribute('tabindex', '0');
910
+ expect(wrapper).toHaveAttribute('data-scrollable-inline', 'true');
911
+ expect(wrapper.style.overscrollBehaviorX).toBe('contain');
912
+
913
+ Object.defineProperty(wrapper, 'scrollWidth', {
914
+ configurable: true,
915
+ value: 100,
916
+ writable: true,
917
+ });
918
+ act(() => {
919
+ wrapper.dispatchEvent(new Event('scroll'));
920
+ frames.splice(0).forEach(callback => callback(performance.now()));
921
+ });
922
+
923
+ expect(wrapper).not.toHaveAttribute('tabindex');
924
+ expect(wrapper).not.toHaveAttribute('data-scrollable-inline');
925
+ expect(wrapper.style.overscrollBehaviorX).toBe('auto');
926
+ } finally {
927
+ vi.unstubAllGlobals();
928
+ }
856
929
  });
857
930
 
858
931
  it('uses table-layout: auto in children mode', () => {
@@ -11,6 +11,7 @@
11
11
  * SYNC: When modified, update these files to stay in sync:
12
12
  * - /packages/core/src/Table/Table.doc.mjs (props table, features, usage examples)
13
13
  * - /packages/core/src/Table/Table.test.tsx (tests for new/changed behavior)
14
+ * - /packages/core/src/Table/__tests__/TableScroll.a11y.chromium.spec.ts (browser scroll behavior)
14
15
  * - /packages/core/src/Table/index.ts (exports if types change)
15
16
  * - /apps/storybook/stories/Table.stories.tsx (storybook stories)
16
17
  * - /packages/cli/assets/templates/blocks/components/Table/ (showcase blocks)
@@ -22,6 +23,7 @@ import {colorVars} from '../theme/tokens.stylex';
22
23
  import {BaseTable} from './BaseTable';
23
24
  import {TableContext} from './TableContext';
24
25
  import {useBaseTablePlugins} from './useBaseTablePlugins';
26
+ import {useScrollableArea} from '../hooks/useScrollableArea';
25
27
  import {mergeProps} from '../utils';
26
28
  import {themeProps} from '../utils/themeProps';
27
29
  import type {
@@ -149,30 +151,36 @@ function TableScrollWrapper({
149
151
  afterTable?: React.ReactNode;
150
152
  }) {
151
153
  const t = useTranslator();
154
+ const label = t('@astryx.table.label');
155
+ const {getViewportProps, getContentProps, state} = useScrollableArea({
156
+ axis: 'inline',
157
+ keyboardAccess: {owner: 'content'},
158
+ overscroll: 'contain',
159
+ });
152
160
  const {ref, ...restHtmlProps} = htmlProps ?? {};
161
+ const viewportProps = getViewportProps<HTMLDivElement>({
162
+ role: 'group',
163
+ 'aria-label': label,
164
+ ...(state.inline.isScrollable ? {tabIndex: 0} : {}),
165
+ ...restHtmlProps,
166
+ ref,
167
+ ...mergeProps(
168
+ themeProps('table-scroll-wrapper'),
169
+ stylex.props(
170
+ scrollWrapperStyles.base,
171
+ scrollWrapperStyles.containerBleed,
172
+ ...(pluginStyles ?? []),
173
+ ),
174
+ ),
175
+ });
176
+
153
177
  return (
154
- <div
155
- ref={ref}
156
- // Keyboard-focusable so keyboard users can scroll a horizontally
157
- // overflowing table. Uses role="group" (not "region") so multiple
158
- // tables on a page don't create duplicate same-named landmarks
159
- // (axe: landmark-unique). Callers may override role/aria-label via
160
- // htmlProps.
161
- tabIndex={0}
162
- role="group"
163
- aria-label={t('@astryx.table.label')}
164
- {...restHtmlProps}
165
- {...mergeProps(
166
- themeProps('table-scroll-wrapper'),
167
- stylex.props(
168
- scrollWrapperStyles.base,
169
- scrollWrapperStyles.containerBleed,
170
- ...(pluginStyles ?? []),
171
- ),
172
- )}>
173
- {beforeTable}
174
- {children}
175
- {afterTable}
178
+ <div {...viewportProps}>
179
+ <div {...getContentProps<HTMLDivElement>()}>
180
+ {beforeTable}
181
+ {children}
182
+ {afterTable}
183
+ </div>
176
184
  </div>
177
185
  );
178
186
  }
@@ -0,0 +1,137 @@
1
+ // Copyright (c) Meta Platforms, Inc. and affiliates.
2
+
3
+ /**
4
+ * @file TableScroll.a11y.chromium.spec.ts
5
+ * @input Built responsive Table story and real Chromium wheel input
6
+ * @output Browser evidence for conditional inline containment and scroll chaining
7
+ * @position Table integration proof for the shared useScrollableArea behavior
8
+ */
9
+
10
+ import {expect, test, type Locator, type Page} from '@playwright/test';
11
+ import {
12
+ DEFAULT_STORYBOOK_DIR,
13
+ serveStorybook,
14
+ type StaticServer,
15
+ } from '@astryxdesign/a11y-spec/storybook';
16
+
17
+ let storybook: StaticServer;
18
+ test.beforeAll(async () => {
19
+ storybook = await serveStorybook(
20
+ process.env.ASTRYX_STORYBOOK_DIR ?? DEFAULT_STORYBOOK_DIR,
21
+ );
22
+ });
23
+ test.afterAll(async () => {
24
+ await storybook?.close();
25
+ });
26
+
27
+ async function mount(page: Page) {
28
+ await page.goto(
29
+ `${storybook.origin}/iframe.html?id=core-table--responsive-scroll&viewMode=story`,
30
+ );
31
+ const wrappers = page.locator('.astryx-table-scroll-wrapper');
32
+ await expect(wrappers).toHaveCount(3);
33
+ return wrappers;
34
+ }
35
+
36
+ async function putInsideOuterScroller(
37
+ page: Page,
38
+ viewport: Locator,
39
+ viewportWidth: number,
40
+ contentWidth: number,
41
+ tableWidth: number,
42
+ ) {
43
+ await viewport.evaluate(
44
+ (node, sizes) => {
45
+ const outer = document.createElement('div');
46
+ outer.dataset.tableScrollOuter = '';
47
+ outer.style.inlineSize = `${sizes.viewportWidth}px`;
48
+ outer.style.overflowX = 'auto';
49
+ const content = document.createElement('div');
50
+ content.style.inlineSize = `${sizes.contentWidth}px`;
51
+ node.parentElement?.insertBefore(outer, node);
52
+ outer.append(content);
53
+ content.append(node);
54
+ (node as HTMLElement).style.inlineSize = `${sizes.tableWidth}px`;
55
+ },
56
+ {viewportWidth, contentWidth, tableWidth},
57
+ );
58
+ return page.locator('[data-table-scroll-outer]');
59
+ }
60
+
61
+ async function wheelInline(page: Page, target: Locator) {
62
+ const box = await target.boundingBox();
63
+ if (box == null) {
64
+ throw new Error('Table scroll viewport has no rendered bounds');
65
+ }
66
+ await page.mouse.move(box.x + Math.min(box.width / 2, 100), box.y + 20);
67
+ await page.mouse.wheel(200, 0);
68
+ }
69
+
70
+ test('an overflowing table contains horizontal wheel input at its edge', async ({
71
+ page,
72
+ }) => {
73
+ const wrappers = await mount(page);
74
+ const tableViewport = wrappers.nth(0);
75
+ await tableViewport.locator('table').evaluate(table => {
76
+ const viewport = table.closest<HTMLElement>('.astryx-table-scroll-wrapper');
77
+ if (viewport != null) {
78
+ table.style.minWidth = `${viewport.clientWidth + 400}px`;
79
+ }
80
+ });
81
+ await expect(tableViewport).toHaveAttribute('data-scrollable-inline', 'true');
82
+ await expect(tableViewport).toHaveAttribute('tabindex', '0');
83
+ await expect
84
+ .poll(async () =>
85
+ tableViewport.evaluate(
86
+ element => getComputedStyle(element).overscrollBehaviorX,
87
+ ),
88
+ )
89
+ .toBe('contain');
90
+
91
+ const outer = await putInsideOuterScroller(
92
+ page,
93
+ tableViewport,
94
+ 320,
95
+ 800,
96
+ 320,
97
+ );
98
+ await tableViewport.evaluate(element => {
99
+ element.scrollLeft = element.scrollWidth - element.clientWidth;
100
+ });
101
+ await wheelInline(page, tableViewport);
102
+ await expect
103
+ .poll(async () => outer.evaluate(element => element.scrollLeft))
104
+ .toBe(0);
105
+ });
106
+
107
+ test('a fitting table passes horizontal wheel input to its outer scroller', async ({
108
+ page,
109
+ }) => {
110
+ const wrappers = await mount(page);
111
+ const tableViewport = wrappers.nth(2);
112
+ const outer = await putInsideOuterScroller(
113
+ page,
114
+ tableViewport,
115
+ 320,
116
+ 800,
117
+ 800,
118
+ );
119
+
120
+ await expect(tableViewport).not.toHaveAttribute(
121
+ 'data-scrollable-inline',
122
+ 'true',
123
+ );
124
+ await expect(tableViewport).not.toHaveAttribute('tabindex');
125
+ await expect
126
+ .poll(async () =>
127
+ tableViewport.evaluate(
128
+ element => getComputedStyle(element).overscrollBehaviorX,
129
+ ),
130
+ )
131
+ .toBe('auto');
132
+
133
+ await wheelInline(page, tableViewport);
134
+ await expect
135
+ .poll(async () => outer.evaluate(element => element.scrollLeft))
136
+ .toBeGreaterThan(0);
137
+ });
@@ -95,9 +95,14 @@ const styles = stylex.create({
95
95
  paddingBlock: spacingVars['--spacing-1'],
96
96
  paddingInline: 'var(--_textarea-inline-padding)',
97
97
  fontFamily: typographyVars['--font-family-body'],
98
+ // The 16px floor is iOS-only: iOS Safari zooms the page when a focused
99
+ // control sits under 16px, and only iOS WebKit implements
100
+ // -webkit-touch-callout to key the coarse-pointer floor to it.
98
101
  fontSize: {
99
102
  default: typeScaleVars['--text-body-size'],
100
- '@media (pointer: coarse)': `max(1rem, ${typeScaleVars['--text-body-size']})`,
103
+ '@media (pointer: coarse)': {
104
+ '@supports (-webkit-touch-callout: none)': `max(1rem, ${typeScaleVars['--text-body-size']})`,
105
+ },
101
106
  },
102
107
  lineHeight: typeScaleVars['--text-body-leading'],
103
108
  color: colorVars['--color-text-primary'],
@@ -2,7 +2,8 @@
2
2
 
3
3
  /**
4
4
  * @file TextInput.test.tsx
5
- * @input Uses vitest, @testing-library/react, TextInput component
5
+ * @input Uses vitest, @testing-library/react, TextInput component, and the
6
+ * shared declaredValue StyleX read-back helper
6
7
  * @output Unit tests for TextInput component behavior
7
8
  * @position Testing; validates TextInput.tsx implementation
8
9
  *
@@ -13,6 +14,7 @@ import {describe, it, expect, vi, beforeEach} from 'vitest';
13
14
  import {render, screen, fireEvent, waitFor} from '@testing-library/react';
14
15
  import userEvent from '@testing-library/user-event';
15
16
  import {TestIcon} from '../__tests__/TestIcon';
17
+ import {declaredValue} from '../__tests__/stylexDeclarations';
16
18
  import {InputGroup} from '../InputGroup';
17
19
  import {TextInput} from './TextInput';
18
20
 
@@ -1113,3 +1115,20 @@ describe('TextInput clear button focus behavior', () => {
1113
1115
  rafSpy.mockRestore();
1114
1116
  });
1115
1117
  });
1118
+
1119
+ describe('TextInput text size', () => {
1120
+ it('renders the theme body size outside the iOS zoom gate', () => {
1121
+ // The 16px floor rides `@supports (-webkit-touch-callout: none)` inside
1122
+ // `@media (pointer: coarse)` — iOS Safari is the browser that zooms on
1123
+ // focus under 16px, so the floor targets it alone instead of every
1124
+ // coarse pointer. jsdom's CSSOM drops at-rule-wrapped declarations it
1125
+ // cannot parse, so the gate itself is pinned against the sources in
1126
+ // inputFontFloor.test.ts; what this asserts is the visible result off
1127
+ // the gate: the plain token size, not a floor.
1128
+ render(<TextInput label="Name" value="" onChange={() => {}} />);
1129
+ expect(declaredValue(screen.getByLabelText('Name'), 'font-size')).toBe(
1130
+ 'var(--text-body-size)',
1131
+ );
1132
+ });
1133
+ });
1134
+
@@ -58,9 +58,14 @@ const styles = stylex.create({
58
58
  borderStyle: 'none',
59
59
  padding: 0,
60
60
  fontFamily: typographyVars['--font-family-body'],
61
+ // The 16px floor is iOS-only: iOS Safari zooms the page when a focused
62
+ // control sits under 16px, and only iOS WebKit implements
63
+ // -webkit-touch-callout to key the coarse-pointer floor to it.
61
64
  fontSize: {
62
65
  default: typeScaleVars['--text-body-size'],
63
- '@media (pointer: coarse)': `max(1rem, ${typeScaleVars['--text-body-size']})`,
66
+ '@media (pointer: coarse)': {
67
+ '@supports (-webkit-touch-callout: none)': `max(1rem, ${typeScaleVars['--text-body-size']})`,
68
+ },
64
69
  },
65
70
  lineHeight: typeScaleVars['--text-body-leading'],
66
71
  color: colorVars['--color-text-primary'],
@@ -95,9 +95,14 @@ const styles = stylex.create({
95
95
  borderStyle: 'none',
96
96
  padding: 0,
97
97
  fontFamily: typographyVars['--font-family-body'],
98
+ // The 16px floor is iOS-only: iOS Safari zooms the page when a focused
99
+ // control sits under 16px, and only iOS WebKit implements
100
+ // -webkit-touch-callout to key the coarse-pointer floor to it.
98
101
  fontSize: {
99
102
  default: typeScaleVars['--text-body-size'],
100
- '@media (pointer: coarse)': `max(1rem, ${typeScaleVars['--text-body-size']})`,
103
+ '@media (pointer: coarse)': {
104
+ '@supports (-webkit-touch-callout: none)': `max(1rem, ${typeScaleVars['--text-body-size']})`,
105
+ },
101
106
  },
102
107
  lineHeight: typeScaleVars['--text-body-leading'],
103
108
  color: colorVars['--color-text-primary'],