@astryxdesign/core 0.1.9 → 0.2.0-canary.068bda9

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 (601) hide show
  1. package/CHANGELOG.md +107 -0
  2. package/dist/Avatar/Avatar.d.ts +42 -3
  3. package/dist/Avatar/Avatar.d.ts.map +1 -1
  4. package/dist/Avatar/Avatar.js +190 -59
  5. package/dist/Avatar/AvatarStatusDot.d.ts +6 -4
  6. package/dist/Avatar/AvatarStatusDot.d.ts.map +1 -1
  7. package/dist/AvatarGroup/AvatarGroup.d.ts +7 -1
  8. package/dist/AvatarGroup/AvatarGroup.d.ts.map +1 -1
  9. package/dist/AvatarGroup/AvatarGroup.js +58 -6
  10. package/dist/AvatarGroup/AvatarGroupOverflow.d.ts +1 -1
  11. package/dist/AvatarGroup/AvatarGroupOverflow.d.ts.map +1 -1
  12. package/dist/AvatarGroup/AvatarGroupOverflow.js +7 -2
  13. package/dist/Banner/Banner.js +2 -2
  14. package/dist/Breadcrumbs/BreadcrumbItem.d.ts.map +1 -1
  15. package/dist/Breadcrumbs/BreadcrumbItem.js +11 -4
  16. package/dist/Breadcrumbs/index.d.ts +1 -0
  17. package/dist/Breadcrumbs/index.d.ts.map +1 -1
  18. package/dist/Breadcrumbs/index.js +2 -1
  19. package/dist/Button/Button.d.ts +1 -1
  20. package/dist/Button/Button.d.ts.map +1 -1
  21. package/dist/Button/Button.js +6 -4
  22. package/dist/Calendar/Calendar.d.ts.map +1 -1
  23. package/dist/Calendar/Calendar.js +50 -9
  24. package/dist/Calendar/dayCellUtils.d.ts +4 -4
  25. package/dist/Calendar/dayCellUtils.js +2 -2
  26. package/dist/Calendar/styles.d.ts +30 -31
  27. package/dist/Calendar/styles.d.ts.map +1 -1
  28. package/dist/Calendar/styles.js +30 -31
  29. package/dist/Card/Card.js +1 -1
  30. package/dist/Carousel/Carousel.d.ts.map +1 -1
  31. package/dist/Carousel/Carousel.js +22 -12
  32. package/dist/Chat/ChatComposerInput.js +1 -1
  33. package/dist/Chat/ChatDictationButton.d.ts.map +1 -1
  34. package/dist/Chat/ChatDictationButton.js +3 -1
  35. package/dist/Chat/ChatLayout.js +4 -4
  36. package/dist/Chat/ChatMessageBubble.d.ts.map +1 -1
  37. package/dist/Chat/ChatMessageBubble.js +8 -8
  38. package/dist/Chat/ChatToolCalls.d.ts.map +1 -1
  39. package/dist/Chat/ChatToolCalls.js +10 -3
  40. package/dist/Chat/useTriggerMenu.js +2 -2
  41. package/dist/CheckboxInput/CheckboxInput.d.ts.map +1 -1
  42. package/dist/CheckboxInput/CheckboxInput.js +6 -6
  43. package/dist/CheckboxList/CheckboxListItem.d.ts.map +1 -1
  44. package/dist/CheckboxList/CheckboxListItem.js +19 -4
  45. package/dist/Citation/Citation.d.ts +22 -1
  46. package/dist/Citation/Citation.d.ts.map +1 -1
  47. package/dist/Citation/Citation.js +20 -6
  48. package/dist/CodeBlock/CodeBlock.d.ts.map +1 -1
  49. package/dist/CodeBlock/CodeBlock.js +16 -10
  50. package/dist/Collapsible/Collapsible.d.ts.map +1 -1
  51. package/dist/Collapsible/Collapsible.js +3 -1
  52. package/dist/CommandPalette/CommandPalette.d.ts +1 -1
  53. package/dist/CommandPalette/CommandPalette.d.ts.map +1 -1
  54. package/dist/CommandPalette/CommandPalette.js +42 -3
  55. package/dist/CommandPalette/CommandPaletteItem.js +1 -1
  56. package/dist/ContextMenu/ContextMenu.d.ts.map +1 -1
  57. package/dist/ContextMenu/ContextMenu.js +23 -5
  58. package/dist/ContextMenu/index.d.ts +1 -0
  59. package/dist/ContextMenu/index.d.ts.map +1 -1
  60. package/dist/ContextMenu/index.js +3 -1
  61. package/dist/DateInput/DateInput.d.ts +10 -2
  62. package/dist/DateInput/DateInput.d.ts.map +1 -1
  63. package/dist/DateInput/DateInput.js +33 -19
  64. package/dist/DateRangeInput/DateRangeInput.d.ts +10 -2
  65. package/dist/DateRangeInput/DateRangeInput.d.ts.map +1 -1
  66. package/dist/DateRangeInput/DateRangeInput.js +23 -20
  67. package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
  68. package/dist/DateTimeInput/DateTimeInput.js +23 -18
  69. package/dist/Divider/Divider.d.ts +2 -2
  70. package/dist/Divider/Divider.d.ts.map +1 -1
  71. package/dist/Divider/Divider.js +13 -0
  72. package/dist/DropdownMenu/DropdownMenu.d.ts +6 -0
  73. package/dist/DropdownMenu/DropdownMenu.d.ts.map +1 -1
  74. package/dist/DropdownMenu/DropdownMenu.js +22 -5
  75. package/dist/DropdownMenu/DropdownMenuCheckboxItem.d.ts.map +1 -1
  76. package/dist/DropdownMenu/DropdownMenuCheckboxItem.js +4 -1
  77. package/dist/DropdownMenu/DropdownMenuItem.d.ts.map +1 -1
  78. package/dist/DropdownMenu/DropdownMenuItem.js +5 -2
  79. package/dist/DropdownMenu/DropdownMenuRadioGroup.d.ts +8 -11
  80. package/dist/DropdownMenu/DropdownMenuRadioGroup.d.ts.map +1 -1
  81. package/dist/DropdownMenu/DropdownMenuRadioGroup.js +3 -1
  82. package/dist/DropdownMenu/DropdownMenuRadioItem.d.ts +1 -1
  83. package/dist/DropdownMenu/DropdownMenuRadioItem.d.ts.map +1 -1
  84. package/dist/DropdownMenu/DropdownMenuRadioItem.js +5 -2
  85. package/dist/DropdownMenu/DropdownMenuSubMenu.d.ts +104 -0
  86. package/dist/DropdownMenu/DropdownMenuSubMenu.d.ts.map +1 -0
  87. package/dist/DropdownMenu/DropdownMenuSubMenu.js +435 -0
  88. package/dist/DropdownMenu/index.d.ts +10 -0
  89. package/dist/DropdownMenu/index.d.ts.map +1 -1
  90. package/dist/DropdownMenu/index.js +13 -0
  91. package/dist/DropdownMenu/menuItemHover.d.ts +24 -0
  92. package/dist/DropdownMenu/menuItemHover.d.ts.map +1 -0
  93. package/dist/DropdownMenu/menuItemHover.js +34 -0
  94. package/dist/DropdownMenu/menuItemRoles.d.ts +8 -0
  95. package/dist/DropdownMenu/menuItemRoles.d.ts.map +1 -1
  96. package/dist/DropdownMenu/menuItemRoles.js +10 -1
  97. package/dist/DropdownMenu/renderDropdownItems.d.ts.map +1 -1
  98. package/dist/DropdownMenu/renderDropdownItems.js +21 -6
  99. package/dist/Field/Field.d.ts +3 -1
  100. package/dist/Field/Field.d.ts.map +1 -1
  101. package/dist/Field/Field.js +4 -1
  102. package/dist/Field/FieldLabel.d.ts +2 -1
  103. package/dist/Field/FieldLabel.d.ts.map +1 -1
  104. package/dist/Field/FieldLabel.js +9 -5
  105. package/dist/Field/inputStyles.stylex.d.ts +1 -0
  106. package/dist/Field/inputStyles.stylex.d.ts.map +1 -1
  107. package/dist/Field/inputStyles.stylex.js +1 -0
  108. package/dist/FieldStatus/FieldStatus.d.ts +10 -0
  109. package/dist/FieldStatus/FieldStatus.d.ts.map +1 -1
  110. package/dist/FieldStatus/FieldStatus.js +51 -5
  111. package/dist/FileInput/FileInput.d.ts +10 -2
  112. package/dist/FileInput/FileInput.d.ts.map +1 -1
  113. package/dist/FileInput/FileInput.js +93 -65
  114. package/dist/Heading/Heading.d.ts.map +1 -1
  115. package/dist/Heading/Heading.js +3 -2
  116. package/dist/HoverCard/useHoverCard.d.ts.map +1 -1
  117. package/dist/HoverCard/useHoverCard.js +10 -4
  118. package/dist/Icon/Icon.d.ts +15 -1
  119. package/dist/Icon/Icon.d.ts.map +1 -1
  120. package/dist/Icon/Icon.js +19 -3
  121. package/dist/Item/Item.d.ts +16 -3
  122. package/dist/Item/Item.d.ts.map +1 -1
  123. package/dist/Item/Item.js +31 -6
  124. package/dist/Layer/layerAnimations.stylex.d.ts.map +1 -1
  125. package/dist/Layer/layerAnimations.stylex.js +10 -2
  126. package/dist/Lightbox/Lightbox.d.ts.map +1 -1
  127. package/dist/Lightbox/Lightbox.js +34 -15
  128. package/dist/List/List.d.ts.map +1 -1
  129. package/dist/List/List.js +6 -3
  130. package/dist/List/ListItem.d.ts +11 -1
  131. package/dist/List/ListItem.d.ts.map +1 -1
  132. package/dist/List/ListItem.js +2 -0
  133. package/dist/Markdown/Markdown.d.ts.map +1 -1
  134. package/dist/Markdown/Markdown.js +7 -0
  135. package/dist/MetadataList/MetadataList.d.ts +1 -1
  136. package/dist/MetadataList/MetadataList.d.ts.map +1 -1
  137. package/dist/MetadataList/MetadataList.js +4 -2
  138. package/dist/MultiSelector/MultiSelector.d.ts +9 -1
  139. package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
  140. package/dist/MultiSelector/MultiSelector.js +81 -43
  141. package/dist/NavMenu/NavHeadingMenuItem.js +1 -1
  142. package/dist/NumberInput/NumberInput.d.ts +10 -2
  143. package/dist/NumberInput/NumberInput.d.ts.map +1 -1
  144. package/dist/NumberInput/NumberInput.js +22 -17
  145. package/dist/Outline/Outline.js +2 -2
  146. package/dist/Pagination/Pagination.d.ts.map +1 -1
  147. package/dist/Pagination/Pagination.js +11 -3
  148. package/dist/PowerSearch/PowerSearch.d.ts +9 -2
  149. package/dist/PowerSearch/PowerSearch.d.ts.map +1 -1
  150. package/dist/PowerSearch/PowerSearch.js +2 -0
  151. package/dist/ProgressBar/ProgressBar.d.ts.map +1 -1
  152. package/dist/ProgressBar/ProgressBar.js +6 -1
  153. package/dist/RadioList/RadioList.d.ts +2 -2
  154. package/dist/RadioList/RadioListItem.d.ts.map +1 -1
  155. package/dist/RadioList/RadioListItem.js +5 -5
  156. package/dist/Resizable/ResizeHandle.d.ts.map +1 -1
  157. package/dist/Resizable/ResizeHandle.js +49 -19
  158. package/dist/SegmentedControl/SegmentedControlItem.d.ts +1 -1
  159. package/dist/SegmentedControl/SegmentedControlItem.d.ts.map +1 -1
  160. package/dist/SegmentedControl/SegmentedControlItem.js +5 -3
  161. package/dist/Selector/Selector.d.ts +8 -0
  162. package/dist/Selector/Selector.d.ts.map +1 -1
  163. package/dist/Selector/Selector.js +66 -17
  164. package/dist/SideNav/SideNav.d.ts.map +1 -1
  165. package/dist/SideNav/SideNav.js +5 -5
  166. package/dist/SideNav/SideNavCollapseButton.d.ts.map +1 -1
  167. package/dist/SideNav/SideNavCollapseButton.js +13 -10
  168. package/dist/SideNav/SideNavItem.d.ts +1 -1
  169. package/dist/SideNav/SideNavItem.d.ts.map +1 -1
  170. package/dist/SideNav/SideNavItem.js +12 -10
  171. package/dist/Skeleton/Skeleton.d.ts.map +1 -1
  172. package/dist/Skeleton/Skeleton.js +2 -2
  173. package/dist/Slider/Slider.d.ts.map +1 -1
  174. package/dist/Slider/Slider.js +87 -34
  175. package/dist/Spinner/Spinner.d.ts +3 -2
  176. package/dist/Spinner/Spinner.d.ts.map +1 -1
  177. package/dist/Spinner/Spinner.js +11 -2
  178. package/dist/Switch/Switch.d.ts +8 -1
  179. package/dist/Switch/Switch.d.ts.map +1 -1
  180. package/dist/Switch/Switch.js +171 -91
  181. package/dist/TabList/Tab.js +2 -2
  182. package/dist/TabList/TabList.d.ts +2 -11
  183. package/dist/TabList/TabList.d.ts.map +1 -1
  184. package/dist/TabList/TabList.js +5 -9
  185. package/dist/TabList/TabListContext.d.ts +0 -5
  186. package/dist/TabList/TabListContext.d.ts.map +1 -1
  187. package/dist/TabList/TabListContext.js +0 -5
  188. package/dist/TabList/TabMenu.js +1 -1
  189. package/dist/Table/BaseTable.d.ts.map +1 -1
  190. package/dist/Table/BaseTable.js +30 -4
  191. package/dist/Table/TableCell.js +3 -3
  192. package/dist/Table/TableHeaderCell.js +3 -3
  193. package/dist/Table/plugins/groupedRows/useTableGroupedRows.d.ts.map +1 -1
  194. package/dist/Table/plugins/groupedRows/useTableGroupedRows.js +15 -11
  195. package/dist/Table/plugins/rowExpansion/useTableRowExpansion.d.ts.map +1 -1
  196. package/dist/Table/plugins/rowExpansion/useTableRowExpansion.js +37 -27
  197. package/dist/Table/plugins/selection/useTableSelection.d.ts.map +1 -1
  198. package/dist/Table/plugins/selection/useTableSelection.js +3 -0
  199. package/dist/Table/plugins/stickyColumns/useTableStickyColumns.d.ts.map +1 -1
  200. package/dist/Table/plugins/stickyColumns/useTableStickyColumns.js +15 -7
  201. package/dist/Table/plugins/tree/useTableTreeData.d.ts.map +1 -1
  202. package/dist/Table/plugins/tree/useTableTreeData.js +29 -23
  203. package/dist/Table/types.d.ts +32 -0
  204. package/dist/Table/types.d.ts.map +1 -1
  205. package/dist/Text/Text.d.ts +10 -1
  206. package/dist/Text/Text.d.ts.map +1 -1
  207. package/dist/Text/Text.js +25 -2
  208. package/dist/Text/index.d.ts +2 -2
  209. package/dist/Text/index.d.ts.map +1 -1
  210. package/dist/TextArea/TextArea.d.ts +10 -1
  211. package/dist/TextArea/TextArea.d.ts.map +1 -1
  212. package/dist/TextArea/TextArea.js +119 -52
  213. package/dist/TextInput/TextInput.d.ts +10 -2
  214. package/dist/TextInput/TextInput.d.ts.map +1 -1
  215. package/dist/TextInput/TextInput.js +20 -17
  216. package/dist/Thumbnail/Thumbnail.d.ts.map +1 -1
  217. package/dist/Thumbnail/Thumbnail.js +51 -45
  218. package/dist/TimeInput/TimeInput.d.ts +10 -2
  219. package/dist/TimeInput/TimeInput.d.ts.map +1 -1
  220. package/dist/TimeInput/TimeInput.js +17 -17
  221. package/dist/Timestamp/Timestamp.d.ts +31 -3
  222. package/dist/Timestamp/Timestamp.d.ts.map +1 -1
  223. package/dist/Timestamp/Timestamp.js +48 -77
  224. package/dist/Timestamp/formatInstant.d.ts +41 -0
  225. package/dist/Timestamp/formatInstant.d.ts.map +1 -0
  226. package/dist/Timestamp/formatInstant.js +177 -0
  227. package/dist/Timestamp/index.d.ts +1 -0
  228. package/dist/Timestamp/index.d.ts.map +1 -1
  229. package/dist/Timestamp/tooltipEntries.d.ts +56 -0
  230. package/dist/Timestamp/tooltipEntries.d.ts.map +1 -0
  231. package/dist/Timestamp/tooltipEntries.js +163 -0
  232. package/dist/Toast/ToastViewport.d.ts.map +1 -1
  233. package/dist/Toast/ToastViewport.js +61 -9
  234. package/dist/ToggleButton/ToggleButton.d.ts.map +1 -1
  235. package/dist/ToggleButton/ToggleButton.js +3 -1
  236. package/dist/Token/Token.d.ts +34 -4
  237. package/dist/Token/Token.d.ts.map +1 -1
  238. package/dist/Token/Token.js +85 -45
  239. package/dist/Token/TokenLink.d.ts +62 -0
  240. package/dist/Token/TokenLink.d.ts.map +1 -0
  241. package/dist/Token/TokenLink.js +76 -0
  242. package/dist/Token/index.d.ts +1 -1
  243. package/dist/Token/index.d.ts.map +1 -1
  244. package/dist/Tokenizer/Tokenizer.d.ts +9 -2
  245. package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
  246. package/dist/Tokenizer/Tokenizer.js +4 -2
  247. package/dist/Tooltip/useTooltip.d.ts.map +1 -1
  248. package/dist/Tooltip/useTooltip.js +17 -1
  249. package/dist/TopNav/TopNavItem.d.ts +3 -1
  250. package/dist/TopNav/TopNavItem.d.ts.map +1 -1
  251. package/dist/TopNav/TopNavItem.js +30 -3
  252. package/dist/TopNav/TopNavMegaMenu.d.ts.map +1 -1
  253. package/dist/TopNav/TopNavMegaMenu.js +9 -3
  254. package/dist/TreeList/TreeList.d.ts.map +1 -1
  255. package/dist/TreeList/TreeList.js +1 -0
  256. package/dist/TreeList/TreeListBranches.d.ts.map +1 -1
  257. package/dist/TreeList/TreeListBranches.js +8 -6
  258. package/dist/TreeList/TreeListItem.d.ts.map +1 -1
  259. package/dist/TreeList/TreeListItem.js +32 -14
  260. package/dist/Typeahead/BaseTypeahead.d.ts +9 -0
  261. package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
  262. package/dist/Typeahead/BaseTypeahead.js +22 -11
  263. package/dist/Typeahead/Typeahead.d.ts +9 -2
  264. package/dist/Typeahead/Typeahead.d.ts.map +1 -1
  265. package/dist/Typeahead/Typeahead.js +11 -2
  266. package/dist/Typeahead/TypeaheadItem.d.ts +1 -1
  267. package/dist/Typeahead/TypeaheadItem.d.ts.map +1 -1
  268. package/dist/Typeahead/TypeaheadItem.js +20 -10
  269. package/dist/astryx.css +114 -35
  270. package/dist/astryx.umd.js +50 -50
  271. package/dist/astryx.umd.js.map +4 -4
  272. package/dist/hooks/containerReveal.pool.stylex.d.ts +281 -0
  273. package/dist/hooks/containerReveal.pool.stylex.d.ts.map +1 -0
  274. package/dist/hooks/containerReveal.pool.stylex.js +281 -0
  275. package/dist/hooks/index.d.ts +4 -0
  276. package/dist/hooks/index.d.ts.map +1 -1
  277. package/dist/hooks/index.js +3 -1
  278. package/dist/hooks/isRtlElement.d.ts +18 -0
  279. package/dist/hooks/isRtlElement.d.ts.map +1 -0
  280. package/dist/hooks/isRtlElement.js +27 -0
  281. package/dist/hooks/useAnnounce.d.ts +3 -0
  282. package/dist/hooks/useAnnounce.d.ts.map +1 -1
  283. package/dist/hooks/useAnnounce.js +39 -1
  284. package/dist/hooks/useContainerReveal.d.ts +83 -0
  285. package/dist/hooks/useContainerReveal.d.ts.map +1 -0
  286. package/dist/hooks/useContainerReveal.js +123 -0
  287. package/dist/hooks/useFocusTrap.d.ts.map +1 -1
  288. package/dist/hooks/useFocusTrap.js +52 -11
  289. package/dist/hooks/useGridFocus.d.ts +6 -1
  290. package/dist/hooks/useGridFocus.d.ts.map +1 -1
  291. package/dist/hooks/useGridFocus.js +12 -9
  292. package/dist/hooks/useHotkeys.d.ts +9 -0
  293. package/dist/hooks/useHotkeys.d.ts.map +1 -1
  294. package/dist/hooks/useHotkeys.js +9 -0
  295. package/dist/hooks/useInputStatusIcon.d.ts +38 -0
  296. package/dist/hooks/useInputStatusIcon.d.ts.map +1 -0
  297. package/dist/hooks/useInputStatusIcon.js +169 -0
  298. package/dist/hooks/useKeyboardHint.d.ts +1 -1
  299. package/dist/hooks/useKeyboardHint.d.ts.map +1 -1
  300. package/dist/hooks/useKeyboardHint.js +4 -2
  301. package/dist/hooks/useListFocus.d.ts +39 -1
  302. package/dist/hooks/useListFocus.d.ts.map +1 -1
  303. package/dist/hooks/useListFocus.js +54 -9
  304. package/dist/i18n/InternationalizationContext.d.ts +1 -0
  305. package/dist/i18n/InternationalizationContext.d.ts.map +1 -1
  306. package/dist/i18n/InternationalizationContext.js +3 -0
  307. package/dist/i18n/InternationalizationProvider.d.ts +8 -1
  308. package/dist/i18n/InternationalizationProvider.d.ts.map +1 -1
  309. package/dist/i18n/InternationalizationProvider.js +5 -1
  310. package/dist/i18n/getLocaleDirection.d.ts +18 -0
  311. package/dist/i18n/getLocaleDirection.d.ts.map +1 -0
  312. package/dist/i18n/getLocaleDirection.js +29 -0
  313. package/dist/i18n/index.d.ts +6 -0
  314. package/dist/i18n/index.d.ts.map +1 -1
  315. package/dist/i18n/index.js +7 -1
  316. package/dist/i18n/useDirection.d.ts +2 -0
  317. package/dist/i18n/useDirection.d.ts.map +1 -0
  318. package/dist/i18n/useDirection.js +27 -0
  319. package/dist/theme/derivedVarRegistry.d.ts.map +1 -1
  320. package/dist/theme/derivedVarRegistry.js +13 -0
  321. package/dist/theme/index.d.ts +3 -3
  322. package/dist/theme/index.d.ts.map +1 -1
  323. package/dist/theme/types.d.ts +39 -2
  324. package/dist/theme/types.d.ts.map +1 -1
  325. package/dist/utils/index.d.ts +1 -0
  326. package/dist/utils/index.d.ts.map +1 -1
  327. package/dist/utils/index.js +2 -1
  328. package/dist/utils/plainDate.d.ts +17 -0
  329. package/dist/utils/plainDate.d.ts.map +1 -1
  330. package/dist/utils/plainDate.js +23 -4
  331. package/dist/utils/rtlStyles.d.ts +24 -0
  332. package/dist/utils/rtlStyles.d.ts.map +1 -0
  333. package/dist/utils/rtlStyles.js +27 -0
  334. package/locales/en.json +120 -0
  335. package/locales/pseudo.json +90 -0
  336. package/package.json +7 -2
  337. package/src/Avatar/Avatar.doc.mjs +50 -3
  338. package/src/Avatar/Avatar.test.tsx +218 -0
  339. package/src/Avatar/Avatar.tsx +285 -79
  340. package/src/Avatar/AvatarStatusDot.doc.mjs +4 -4
  341. package/src/Avatar/AvatarStatusDot.tsx +6 -4
  342. package/src/AvatarGroup/AvatarGroup.doc.mjs +2 -0
  343. package/src/AvatarGroup/AvatarGroup.test.tsx +162 -2
  344. package/src/AvatarGroup/AvatarGroup.tsx +58 -3
  345. package/src/AvatarGroup/AvatarGroupOverflow.tsx +5 -2
  346. package/src/Banner/Banner.tsx +6 -6
  347. package/src/Breadcrumbs/BreadcrumbItem.tsx +10 -10
  348. package/src/Breadcrumbs/Breadcrumbs.test.tsx +52 -1
  349. package/src/Breadcrumbs/index.ts +4 -0
  350. package/src/Button/Button.doc.mjs +0 -4
  351. package/src/Button/Button.test.tsx +16 -0
  352. package/src/Button/Button.tsx +6 -4
  353. package/src/Calendar/Calendar.test.tsx +170 -20
  354. package/src/Calendar/Calendar.tsx +73 -16
  355. package/src/Calendar/dayCellUtils.test.ts +18 -18
  356. package/src/Calendar/dayCellUtils.ts +2 -2
  357. package/src/Calendar/styles.ts +33 -39
  358. package/src/Card/Card.tsx +1 -1
  359. package/src/Carousel/Carousel.tsx +25 -6
  360. package/src/Chat/ChatComposer.doc.mjs +2 -2
  361. package/src/Chat/ChatComposerInput.doc.mjs +1 -1
  362. package/src/Chat/ChatComposerInput.tsx +2 -2
  363. package/src/Chat/ChatDictationButton.tsx +7 -1
  364. package/src/Chat/ChatLayout.tsx +4 -4
  365. package/src/Chat/ChatMessageBubble.tsx +15 -10
  366. package/src/Chat/ChatSystemMessage.test.tsx +5 -0
  367. package/src/Chat/ChatToolCalls.tsx +9 -2
  368. package/src/Chat/useTriggerMenu.tsx +1 -1
  369. package/src/CheckboxInput/CheckboxInput.doc.mjs +6 -0
  370. package/src/CheckboxInput/CheckboxInput.test.tsx +23 -0
  371. package/src/CheckboxInput/CheckboxInput.tsx +21 -6
  372. package/src/CheckboxList/CheckboxList.doc.mjs +6 -0
  373. package/src/CheckboxList/CheckboxList.test.tsx +94 -3
  374. package/src/CheckboxList/CheckboxListItem.tsx +17 -10
  375. package/src/Citation/Citation.doc.mjs +4 -3
  376. package/src/Citation/Citation.test.tsx +97 -0
  377. package/src/Citation/Citation.tsx +43 -11
  378. package/src/CodeBlock/CodeBlock.test.tsx +17 -0
  379. package/src/CodeBlock/CodeBlock.tsx +38 -11
  380. package/src/Collapsible/Collapsible.doc.mjs +1 -0
  381. package/src/Collapsible/Collapsible.test.tsx +7 -0
  382. package/src/Collapsible/Collapsible.tsx +16 -6
  383. package/src/CommandPalette/CommandPalette.test.tsx +95 -1
  384. package/src/CommandPalette/CommandPalette.tsx +41 -2
  385. package/src/CommandPalette/CommandPaletteItem.tsx +1 -1
  386. package/src/ContextMenu/ContextMenu.test.tsx +59 -2
  387. package/src/ContextMenu/ContextMenu.tsx +22 -11
  388. package/src/ContextMenu/index.ts +5 -0
  389. package/src/DateInput/DateInput.doc.mjs +25 -0
  390. package/src/DateInput/DateInput.test.tsx +230 -0
  391. package/src/DateInput/DateInput.tsx +51 -29
  392. package/src/DateRangeInput/DateRangeInput.doc.mjs +16 -0
  393. package/src/DateRangeInput/DateRangeInput.test.tsx +140 -0
  394. package/src/DateRangeInput/DateRangeInput.tsx +42 -30
  395. package/src/DateTimeInput/DateTimeInput.doc.mjs +22 -1
  396. package/src/DateTimeInput/DateTimeInput.test.tsx +112 -0
  397. package/src/DateTimeInput/DateTimeInput.tsx +44 -39
  398. package/src/Divider/Divider.test.tsx +32 -8
  399. package/src/Divider/Divider.tsx +14 -1
  400. package/src/DropdownMenu/DropdownMenu.test.tsx +60 -0
  401. package/src/DropdownMenu/DropdownMenu.tsx +31 -12
  402. package/src/DropdownMenu/DropdownMenuCheckboxItem.tsx +8 -2
  403. package/src/DropdownMenu/DropdownMenuItem.tsx +9 -3
  404. package/src/DropdownMenu/DropdownMenuRadioGroup.doc.mjs +4 -12
  405. package/src/DropdownMenu/DropdownMenuRadioGroup.tsx +9 -10
  406. package/src/DropdownMenu/DropdownMenuRadioItem.tsx +9 -3
  407. package/src/DropdownMenu/DropdownMenuSelectable.test.tsx +20 -2
  408. package/src/DropdownMenu/DropdownMenuSubMenu.doc.mjs +88 -0
  409. package/src/DropdownMenu/DropdownMenuSubMenu.test.tsx +663 -0
  410. package/src/DropdownMenu/DropdownMenuSubMenu.tsx +561 -0
  411. package/src/DropdownMenu/index.ts +16 -0
  412. package/src/DropdownMenu/menuItemHover.ts +40 -0
  413. package/src/DropdownMenu/menuItemRoles.ts +9 -0
  414. package/src/DropdownMenu/renderDropdownItems.tsx +29 -15
  415. package/src/Field/Field.doc.mjs +4 -0
  416. package/src/Field/Field.tsx +14 -9
  417. package/src/Field/FieldLabel.test.tsx +25 -0
  418. package/src/Field/FieldLabel.tsx +12 -3
  419. package/src/Field/inputStyles.stylex.ts +2 -0
  420. package/src/FieldStatus/FieldStatus.doc.mjs +1 -0
  421. package/src/FieldStatus/FieldStatus.test.tsx +133 -0
  422. package/src/FieldStatus/FieldStatus.tsx +61 -4
  423. package/src/FileInput/FileInput.doc.mjs +23 -2
  424. package/src/FileInput/FileInput.test.tsx +104 -13
  425. package/src/FileInput/FileInput.tsx +106 -79
  426. package/src/Heading/Heading.tsx +2 -1
  427. package/src/HoverCard/useHoverCard.tsx +15 -3
  428. package/src/Icon/Icon.doc.mjs +13 -0
  429. package/src/Icon/Icon.test.tsx +89 -0
  430. package/src/Icon/Icon.tsx +51 -3
  431. package/src/Item/Item.doc.mjs +5 -0
  432. package/src/Item/Item.test.tsx +88 -0
  433. package/src/Item/Item.tsx +57 -11
  434. package/src/Layer/layerAnimations.stylex.ts +23 -0
  435. package/src/Lightbox/Lightbox.test.tsx +33 -0
  436. package/src/Lightbox/Lightbox.tsx +30 -10
  437. package/src/List/List.test.tsx +17 -29
  438. package/src/List/List.tsx +6 -1
  439. package/src/List/ListItem.doc.mjs +12 -0
  440. package/src/List/ListItem.tsx +13 -0
  441. package/src/Markdown/Markdown.test.tsx +21 -0
  442. package/src/Markdown/Markdown.tsx +4 -0
  443. package/src/MetadataList/MetadataList.test.tsx +24 -0
  444. package/src/MetadataList/MetadataList.tsx +6 -2
  445. package/src/MultiSelector/MultiSelector.doc.mjs +20 -0
  446. package/src/MultiSelector/MultiSelector.test.tsx +402 -0
  447. package/src/MultiSelector/MultiSelector.tsx +126 -64
  448. package/src/NavMenu/NavHeadingMenuItem.tsx +1 -1
  449. package/src/NumberInput/NumberInput.doc.mjs +21 -0
  450. package/src/NumberInput/NumberInput.test.tsx +71 -0
  451. package/src/NumberInput/NumberInput.tsx +35 -26
  452. package/src/Outline/Outline.test.tsx +12 -12
  453. package/src/Outline/Outline.tsx +2 -2
  454. package/src/Pagination/Pagination.tsx +11 -3
  455. package/src/PowerSearch/PowerSearch.doc.mjs +15 -0
  456. package/src/PowerSearch/PowerSearch.test.tsx +23 -0
  457. package/src/PowerSearch/PowerSearch.tsx +10 -1
  458. package/src/ProgressBar/ProgressBar.test.tsx +34 -0
  459. package/src/ProgressBar/ProgressBar.tsx +16 -1
  460. package/src/RadioList/RadioList.doc.mjs +6 -0
  461. package/src/RadioList/RadioList.test.tsx +26 -4
  462. package/src/RadioList/RadioList.tsx +2 -2
  463. package/src/RadioList/RadioListItem.tsx +12 -5
  464. package/src/Resizable/ResizeHandle.test.tsx +94 -0
  465. package/src/Resizable/ResizeHandle.tsx +70 -20
  466. package/src/SegmentedControl/SegmentedControl.test.tsx +28 -0
  467. package/src/SegmentedControl/SegmentedControlItem.tsx +22 -2
  468. package/src/Selector/Selector.doc.mjs +15 -0
  469. package/src/Selector/Selector.test.tsx +370 -0
  470. package/src/Selector/Selector.tsx +88 -20
  471. package/src/SideNav/SideNav.tsx +1 -8
  472. package/src/SideNav/SideNavCollapseButton.tsx +9 -7
  473. package/src/SideNav/SideNavItem.tsx +5 -3
  474. package/src/Skeleton/Skeleton.test.tsx +16 -0
  475. package/src/Skeleton/Skeleton.tsx +13 -1
  476. package/src/Slider/Slider.doc.mjs +6 -0
  477. package/src/Slider/Slider.test.tsx +240 -12
  478. package/src/Slider/Slider.tsx +96 -23
  479. package/src/Spinner/Spinner.test.tsx +10 -8
  480. package/src/Spinner/Spinner.tsx +15 -5
  481. package/src/Switch/Switch.doc.mjs +142 -42
  482. package/src/Switch/Switch.test.tsx +111 -0
  483. package/src/Switch/Switch.tsx +149 -32
  484. package/src/TabList/Tab.tsx +2 -2
  485. package/src/TabList/TabList.doc.mjs +0 -6
  486. package/src/TabList/TabList.test.tsx +3 -15
  487. package/src/TabList/TabList.tsx +6 -17
  488. package/src/TabList/TabListContext.ts +0 -6
  489. package/src/TabList/TabMenu.tsx +2 -2
  490. package/src/Table/BaseTable.tsx +34 -2
  491. package/src/Table/Table.doc.mjs +11 -0
  492. package/src/Table/Table.test.tsx +85 -0
  493. package/src/Table/TableCell.tsx +3 -3
  494. package/src/Table/TableHeaderCell.tsx +3 -3
  495. package/src/Table/plugins/groupedRows/useTableGroupedRows.tsx +9 -6
  496. package/src/Table/plugins/rowExpansion/useTableRowExpansion.test.tsx +19 -0
  497. package/src/Table/plugins/rowExpansion/useTableRowExpansion.tsx +27 -18
  498. package/src/Table/plugins/selection/useTableSelection.test.tsx +61 -3
  499. package/src/Table/plugins/selection/useTableSelection.tsx +3 -0
  500. package/src/Table/plugins/stickyColumns/useTableStickyColumns.tsx +38 -9
  501. package/src/Table/plugins/tree/useTableTreeData.tsx +17 -13
  502. package/src/Table/types.ts +33 -0
  503. package/src/Table/useTableRowStatus.doc.mjs +1 -1
  504. package/src/Text/Heading.doc.mjs +3 -3
  505. package/src/Text/Text.doc.mjs +1 -1
  506. package/src/Text/Text.test.tsx +42 -0
  507. package/src/Text/Text.tsx +25 -1
  508. package/src/Text/index.ts +2 -6
  509. package/src/TextArea/TextArea.doc.mjs +23 -2
  510. package/src/TextArea/TextArea.test.tsx +132 -4
  511. package/src/TextArea/TextArea.tsx +161 -67
  512. package/src/TextInput/TextInput.doc.mjs +21 -0
  513. package/src/TextInput/TextInput.test.tsx +150 -0
  514. package/src/TextInput/TextInput.tsx +28 -25
  515. package/src/Thumbnail/Thumbnail.doc.mjs +1 -1
  516. package/src/Thumbnail/Thumbnail.test.tsx +24 -1
  517. package/src/Thumbnail/Thumbnail.tsx +28 -35
  518. package/src/TimeInput/TimeInput.doc.mjs +21 -0
  519. package/src/TimeInput/TimeInput.test.tsx +23 -0
  520. package/src/TimeInput/TimeInput.tsx +24 -25
  521. package/src/Timestamp/Timestamp.doc.mjs +32 -6
  522. package/src/Timestamp/Timestamp.test.tsx +371 -0
  523. package/src/Timestamp/Timestamp.tsx +96 -93
  524. package/src/Timestamp/formatInstant.ts +218 -0
  525. package/src/Timestamp/index.ts +4 -0
  526. package/src/Timestamp/tooltipEntries.test.ts +552 -0
  527. package/src/Timestamp/tooltipEntries.ts +210 -0
  528. package/src/Toast/ToastViewport.test.tsx +218 -8
  529. package/src/Toast/ToastViewport.tsx +71 -12
  530. package/src/ToggleButton/ToggleButton.test.tsx +24 -0
  531. package/src/ToggleButton/ToggleButton.tsx +19 -1
  532. package/src/Token/Token.test.tsx +166 -15
  533. package/src/Token/Token.tsx +104 -47
  534. package/src/Token/TokenLink.tsx +107 -0
  535. package/src/Token/index.ts +1 -1
  536. package/src/Tokenizer/Tokenizer.doc.mjs +23 -1
  537. package/src/Tokenizer/Tokenizer.test.tsx +23 -0
  538. package/src/Tokenizer/Tokenizer.tsx +14 -2
  539. package/src/Tooltip/Tooltip.test.tsx +46 -0
  540. package/src/Tooltip/useTooltip.tsx +20 -0
  541. package/src/TopNav/TopNav.test.tsx +93 -2
  542. package/src/TopNav/TopNavItem.doc.mjs +3 -3
  543. package/src/TopNav/TopNavItem.tsx +35 -6
  544. package/src/TopNav/TopNavMegaMenu.tsx +26 -2
  545. package/src/TopNav/TopNavMegaMenuFeaturedCard.doc.mjs +1 -1
  546. package/src/TreeList/TreeList.doc.mjs +6 -0
  547. package/src/TreeList/TreeList.test.tsx +50 -10
  548. package/src/TreeList/TreeList.tsx +5 -0
  549. package/src/TreeList/TreeListBranches.tsx +8 -6
  550. package/src/TreeList/TreeListItem.tsx +33 -11
  551. package/src/Typeahead/BaseTypeahead.tsx +42 -15
  552. package/src/Typeahead/Typeahead.doc.mjs +13 -0
  553. package/src/Typeahead/Typeahead.test.tsx +112 -0
  554. package/src/Typeahead/Typeahead.tsx +17 -1
  555. package/src/Typeahead/TypeaheadItem.tsx +2 -1
  556. package/src/__tests__/babelPluginAddExtensions.test.ts +190 -0
  557. package/src/__tests__/forcedColors.ts +60 -0
  558. package/src/__tests__/inputWidthContract.test.tsx +62 -0
  559. package/src/doc-mjs.d.ts +19 -0
  560. package/src/hooks/containerReveal.pool.stylex.ts +464 -0
  561. package/src/hooks/index.ts +13 -0
  562. package/src/hooks/isRtlElement.ts +27 -0
  563. package/src/hooks/useAnnounce.test.tsx +75 -2
  564. package/src/hooks/useAnnounce.ts +47 -1
  565. package/src/hooks/useContainerReveal.test.tsx +116 -0
  566. package/src/hooks/useContainerReveal.ts +180 -0
  567. package/src/hooks/useFocusTrap.test.tsx +104 -0
  568. package/src/hooks/useFocusTrap.ts +61 -12
  569. package/src/hooks/useGridFocus.doc.mjs +3 -3
  570. package/src/hooks/useGridFocus.test.tsx +41 -0
  571. package/src/hooks/useGridFocus.ts +21 -10
  572. package/src/hooks/useHotkeys.ts +9 -0
  573. package/src/hooks/useInputStatusIcon.test.tsx +221 -0
  574. package/src/hooks/useInputStatusIcon.tsx +235 -0
  575. package/src/hooks/useKeyboardHint.test.tsx +22 -0
  576. package/src/hooks/useKeyboardHint.tsx +6 -2
  577. package/src/hooks/useListFocus.doc.mjs +25 -3
  578. package/src/hooks/useListFocus.test.tsx +153 -1
  579. package/src/hooks/useListFocus.ts +102 -9
  580. package/src/i18n/InternationalizationContext.ts +4 -0
  581. package/src/i18n/InternationalizationProvider.tsx +12 -2
  582. package/src/i18n/__tests__/getLocaleDirection.test.ts +40 -0
  583. package/src/i18n/__tests__/useDirection.test.tsx +66 -0
  584. package/src/i18n/getLocaleDirection.ts +29 -0
  585. package/src/i18n/index.ts +6 -0
  586. package/src/i18n/useDirection.ts +29 -0
  587. package/src/reset.css +0 -26
  588. package/src/reset.test.ts +60 -0
  589. package/src/theme/derivedVarRegistry.test.ts +1 -0
  590. package/src/theme/derivedVarRegistry.ts +6 -0
  591. package/src/theme/generateThemeRules.test.ts +42 -0
  592. package/src/theme/index.ts +4 -8
  593. package/src/theme/types.ts +43 -13
  594. package/src/utils/index.ts +2 -0
  595. package/src/utils/plainDate.test.ts +24 -6
  596. package/src/utils/plainDate.ts +18 -4
  597. package/src/utils/rtlStyles.ts +27 -0
  598. package/dist/Thumbnail/thumbnail.markers.stylex.d.ts +0 -9
  599. package/dist/Thumbnail/thumbnail.markers.stylex.d.ts.map +0 -1
  600. package/dist/Thumbnail/thumbnail.markers.stylex.js +0 -14
  601. package/src/Thumbnail/thumbnail.markers.stylex.ts +0 -12
@@ -11,6 +11,7 @@
11
11
 
12
12
  import {describe, it, expect, vi} from 'vitest';
13
13
  import {render, screen} from '@testing-library/react';
14
+ import * as stylex from '@stylexjs/stylex';
14
15
  import {TestIcon} from '../__tests__/TestIcon';
15
16
  import {Icon} from './Icon';
16
17
 
@@ -279,4 +280,92 @@ describe('Icon', () => {
279
280
  );
280
281
  });
281
282
  });
283
+
284
+ describe('styling prop handling', () => {
285
+ it('composes a consumer className with the internal classes (string mode)', () => {
286
+ render(
287
+ <Icon icon="check" className="consumer-target" data-testid="icon" />,
288
+ );
289
+ const icon = screen.getByTestId('icon');
290
+ // Consumer className must survive alongside the stable astryx-icon class
291
+ // and the StyleX classes — previously it was clobbered by the later
292
+ // internal spread.
293
+ expect(icon).toHaveClass('consumer-target');
294
+ expect(icon).toHaveClass('astryx-icon');
295
+ // At least one StyleX-generated class is still present.
296
+ expect(icon.className.split(' ').length).toBeGreaterThan(2);
297
+ });
298
+
299
+ it('forwards a consumer className in component (SVG) mode', () => {
300
+ render(
301
+ <Icon icon={TestIcon} className="consumer-target" data-testid="icon" />,
302
+ );
303
+ const icon = screen.getByTestId('icon');
304
+ expect(icon).toHaveClass('consumer-target');
305
+ expect(icon).toHaveClass('astryx-icon');
306
+ });
307
+
308
+ it('merges a consumer style onto the rendered element (string mode)', () => {
309
+ render(<Icon icon="check" style={{opacity: 0.5}} data-testid="icon" />);
310
+ expect(screen.getByTestId('icon')).toHaveStyle({opacity: '0.5'});
311
+ });
312
+
313
+ it('merges a consumer style onto the rendered element (component mode)', () => {
314
+ render(
315
+ <Icon icon={TestIcon} style={{opacity: 0.5}} data-testid="icon" />,
316
+ );
317
+ expect(screen.getByTestId('icon')).toHaveStyle({opacity: '0.5'});
318
+ });
319
+
320
+ it('applies xstyle to the rendered element (string mode)', () => {
321
+ const overrides = stylex.create({root: {opacity: 0.25}});
322
+ render(<Icon icon="check" xstyle={overrides.root} data-testid="icon" />);
323
+ const icon = screen.getByTestId('icon');
324
+ // xstyle is folded into stylex.props, so it contributes a StyleX class
325
+ // (and, in jsdom's stylex runtime, an inline style) alongside the base
326
+ // color/size classes rather than clobbering them.
327
+ expect(icon).toHaveClass('astryx-icon');
328
+ expect(icon).toHaveStyle({opacity: '0.25'});
329
+ });
330
+
331
+ it('applies xstyle to the rendered element (component mode)', () => {
332
+ const overrides = stylex.create({root: {opacity: 0.25}});
333
+ render(
334
+ <Icon icon={TestIcon} xstyle={overrides.root} data-testid="icon" />,
335
+ );
336
+ const icon = screen.getByTestId('icon');
337
+ expect(icon).toHaveClass('astryx-icon');
338
+ expect(icon).toHaveStyle({opacity: '0.25'});
339
+ });
340
+
341
+ it('leaves default rendering unchanged when no styling props are passed (string mode)', () => {
342
+ const {container} = render(
343
+ <Icon icon="check" size="sm" color="secondary" />,
344
+ );
345
+ const icon = container.querySelector('.astryx-icon') as HTMLElement;
346
+ const {container: refContainer} = render(
347
+ <Icon icon="check" size="sm" color="secondary" />,
348
+ );
349
+ const refIcon = refContainer.querySelector('.astryx-icon') as HTMLElement;
350
+ // Default output is identical to itself — the styling-prop handling adds
351
+ // nothing (no extra class, no inline style) unless a prop is passed.
352
+ expect(icon.className).toBe(refIcon.className);
353
+ expect(icon.getAttribute('style')).toBe(refIcon.getAttribute('style'));
354
+ });
355
+
356
+ it('leaves default rendering unchanged when no styling props are passed (component mode)', () => {
357
+ const {container} = render(
358
+ <Icon icon={TestIcon} size="sm" color="secondary" />,
359
+ );
360
+ const icon = container.querySelector('.astryx-icon') as HTMLElement;
361
+ const {container: refContainer} = render(
362
+ <Icon icon={TestIcon} size="sm" color="secondary" />,
363
+ );
364
+ const refIcon = refContainer.querySelector('.astryx-icon') as HTMLElement;
365
+ // SVGElement.className is an SVGAnimatedString, so compare the class
366
+ // attribute string rather than the property object.
367
+ expect(icon.getAttribute('class')).toBe(refIcon.getAttribute('class'));
368
+ expect(icon.getAttribute('style')).toBe(refIcon.getAttribute('style'));
369
+ });
370
+ });
282
371
  });
package/src/Icon/Icon.tsx CHANGED
@@ -24,6 +24,7 @@
24
24
 
25
25
  import React, {type ComponentType, type SVGProps} from 'react';
26
26
  import * as stylex from '@stylexjs/stylex';
27
+ import type {StyleXStyles} from '@stylexjs/stylex';
27
28
  import {colorVars} from '../theme/tokens.stylex';
28
29
  import {getIcon} from './globalIconRegistry';
29
30
  import type {IconName} from './globalIconRegistry';
@@ -244,6 +245,19 @@ export interface IconProps extends Omit<
244
245
  * ```
245
246
  */
246
247
  label?: string;
248
+ /**
249
+ * StyleX styles created via `stylex.create()`. Folded into the icon's own
250
+ * `stylex.props()` call (as the last argument) so it merges with the base
251
+ * color/size styles for optimal deduplication, matching how other Astryx
252
+ * components accept `xstyle`.
253
+ *
254
+ * @example
255
+ * ```
256
+ * const overrides = stylex.create({ root: { opacity: 0.5 } });
257
+ * <Icon icon="search" xstyle={overrides.root} />
258
+ * ```
259
+ */
260
+ xstyle?: StyleXStyles;
247
261
  }
248
262
 
249
263
  /**
@@ -283,6 +297,9 @@ export function Icon({
283
297
  size = 'md',
284
298
  label,
285
299
  ref,
300
+ className,
301
+ style,
302
+ xstyle,
286
303
  ...props
287
304
  }: IconProps) {
288
305
  // Derive ARIA from `label`: decorative (aria-hidden) by default, or a
@@ -297,6 +314,9 @@ export function Icon({
297
314
  color={color}
298
315
  size={size}
299
316
  a11yProps={a11yProps}
317
+ className={className}
318
+ style={style}
319
+ xstyle={xstyle}
300
320
  spanProps={props}
301
321
  />
302
322
  );
@@ -311,9 +331,16 @@ export function Icon({
311
331
  // BEFORE {...props} so an explicit aria-hidden/role/aria-label from the
312
332
  // consumer still wins as an escape hatch.
313
333
  {...a11yProps}
334
+ // The styling props (className, style, xstyle) are handled here so they
335
+ // COMPOSE with the internal classes/styles instead of clobbering them:
336
+ // xstyle folds into stylex.props, and className/style merge via
337
+ // mergeProps. The remaining rest props keep their prior last-spread
338
+ // precedence as escape hatches.
314
339
  {...mergeProps(
315
340
  themeProps('icon', {size, color}),
316
- stylex.props(styles.root, colorStyles[color], sizeStyles[size]),
341
+ stylex.props(styles.root, colorStyles[color], sizeStyles[size], xstyle),
342
+ className ?? undefined,
343
+ style,
317
344
  )}
318
345
  {...props}
319
346
  />
@@ -338,12 +365,18 @@ function IconFromRegistry({
338
365
  color,
339
366
  size,
340
367
  a11yProps,
368
+ className,
369
+ style,
370
+ xstyle,
341
371
  spanProps,
342
372
  }: {
343
373
  name: IconName;
344
374
  color: IconColor;
345
375
  size: IconSize;
346
376
  a11yProps: {role: 'img'; 'aria-label': string} | {'aria-hidden': 'true'};
377
+ className?: string;
378
+ style?: React.CSSProperties;
379
+ xstyle?: StyleXStyles;
347
380
  spanProps?: Omit<SVGProps<SVGSVGElement>, 'ref' | 'color'>;
348
381
  }) {
349
382
  const resolvedIcon = getIcon(name);
@@ -352,6 +385,14 @@ function IconFromRegistry({
352
385
  return null;
353
386
  }
354
387
 
388
+ // The styling props (className, style, xstyle) are handled here so they
389
+ // COMPOSE with the internal astryx-icon + StyleX classes/styles instead of
390
+ // being shadowed by the later spread: xstyle folds into stylex.props, and
391
+ // className/style merge via mergeProps. Other span props keep their prior
392
+ // precedence (spread before the internal merge).
393
+ const restSpanProps =
394
+ (spanProps as React.HTMLAttributes<HTMLSpanElement>) ?? {};
395
+
355
396
  return (
356
397
  <span
357
398
  // Derived a11y — decorative (aria-hidden) by default, or a meaningful
@@ -359,10 +400,17 @@ function IconFromRegistry({
359
400
  // prop spread so consumers can still override it with explicit
360
401
  // aria-hidden/role/aria-label. This mirrors component-mode Icon.
361
402
  {...a11yProps}
362
- {...(spanProps as React.HTMLAttributes<HTMLSpanElement>)}
403
+ {...restSpanProps}
363
404
  {...mergeProps(
364
405
  themeProps('icon', {size, color}),
365
- stylex.props(styles.span, colorStyles[color], spanSizeStyles[size]),
406
+ stylex.props(
407
+ styles.span,
408
+ colorStyles[color],
409
+ spanSizeStyles[size],
410
+ xstyle,
411
+ ),
412
+ className ?? undefined,
413
+ style,
366
414
  )}>
367
415
  {resolvedIcon}
368
416
  </span>
@@ -37,6 +37,7 @@ export const docs = {
37
37
  {name: 'labelLines', type: 'number', description: 'Max lines before label truncates with ellipsis.'},
38
38
  {name: 'descriptionLines', type: 'number', description: 'Max lines before description truncates with ellipsis.'},
39
39
  {name: 'onClick', type: '(event: MouseEvent) => void', description: 'Click handler. Makes the item clickable with button semantics.'},
40
+ {name: 'interactiveRef', type: 'RefObject<HTMLElement | null>', description: 'Ref to a nested control (e.g. a checkbox in startContent) that owns the item\'s keyboard access and action. The row becomes an enlarged click/tap target that delegates surface clicks to it (useClickableContainer) and renders no invisible button/anchor, so the row adds no second tab stop (WCAG 4.1.2). Mutually exclusive with onClick/href — those are ignored when set.'},
40
41
  {name: 'href', type: 'string', description: 'Link URL. Makes the item a link via an invisible anchor element.'},
41
42
  {name: 'target', type: "'_blank' | '_self'", description: 'Link target. Only used with href. target="_blank" automatically adds noopener noreferrer.'},
42
43
  {name: 'rel', type: 'string', description: 'Link relationship tokens. noopener noreferrer are merged automatically for target="_blank".'},
@@ -90,6 +91,8 @@ export const docsZh = {
90
91
  labelLines: '标签截断前的最大行数。',
91
92
  descriptionLines: '描述截断前的最大行数。',
92
93
  onClick: '点击处理函数。使项目可点击,具有按钮语义。',
94
+ interactiveRef:
95
+ '指向嵌套控件(如 startContent 中的复选框)的 ref,该控件承载项目的键盘访问和操作。行成为更大的点击/触摸目标,将表面点击委托给该控件(useClickableContainer),且不渲染不可见按钮/锚点,因此行不会增加第二个 Tab 停留点(WCAG 4.1.2)。与 onClick/href 互斥——设置后二者将被忽略。',
93
96
  href: '链接 URL。通过不可见锚点元素使项目成为链接。',
94
97
  target: '链接目标。仅与 href 一起使用。target="_blank" 会自动添加 noopener noreferrer。',
95
98
  rel: '链接关系标记。target="_blank" 会自动合并 noopener noreferrer。',
@@ -157,6 +160,8 @@ export const docsDense = {
157
160
  labelLines: 'Max label lines before truncation.',
158
161
  descriptionLines: 'Max description lines before truncation.',
159
162
  onClick: 'Click handler; enables button semantics.',
163
+ interactiveRef:
164
+ 'Ref to a nested control that owns the item\'s keyboard access/action; row delegates surface clicks to it (useClickableContainer), no invisible button/anchor, no second tab stop (WCAG 4.1.2). Mutually exclusive with onClick/href.',
160
165
  href: 'Link URL; enables anchor semantics.',
161
166
  target:
162
167
  'Link target, only with href. target="_blank" auto-adds noopener noreferrer.',
@@ -9,11 +9,35 @@
9
9
  * SYNC: When Item component changes, update tests to match new behavior
10
10
  */
11
11
 
12
+ import {useRef} from 'react';
12
13
  import {describe, it, expect, vi} from 'vitest';
13
14
  import {render, screen} from '@testing-library/react';
14
15
  import userEvent from '@testing-library/user-event';
15
16
  import {Item} from './Item';
16
17
 
18
+ /**
19
+ * Item in delegation mode: `interactiveRef` points at a nested control that
20
+ * owns the row's keyboard access and action. The row is an enlarged tap target
21
+ * that forwards surface clicks to that control (useClickableContainer).
22
+ */
23
+ function DelegatingItem({onToggle}: {onToggle?: () => void}) {
24
+ const ref = useRef<HTMLInputElement>(null);
25
+ return (
26
+ <Item
27
+ label="Row"
28
+ interactiveRef={ref}
29
+ startContent={
30
+ <input
31
+ ref={ref}
32
+ type="checkbox"
33
+ aria-label="Pick row"
34
+ onChange={onToggle}
35
+ />
36
+ }
37
+ />
38
+ );
39
+ }
40
+
17
41
  describe('Item', () => {
18
42
  // ===========================================================================
19
43
  // Basic rendering
@@ -190,6 +214,70 @@ describe('Item', () => {
190
214
  expect(buttons).toHaveLength(1);
191
215
  });
192
216
 
217
+ // ===========================================================================
218
+ // Interactive — interactiveRef (delegation to a nested control)
219
+ // ===========================================================================
220
+
221
+ it('renders no invisible button in interactiveRef (delegation) mode', () => {
222
+ const {container} = render(<DelegatingItem />);
223
+ // The nested control provides keyboard access — the row must not add a
224
+ // second focusable control for the same action (WCAG 4.1.2).
225
+ expect(container.querySelector('button')).not.toBeInTheDocument();
226
+ });
227
+
228
+ it('keeps the nested control as the only tab stop in interactiveRef mode', async () => {
229
+ const user = userEvent.setup();
230
+ render(<DelegatingItem />);
231
+ await user.tab();
232
+ expect(screen.getByRole('checkbox')).toHaveFocus();
233
+ // Next tab leaves the item entirely — the row itself is not focusable.
234
+ await user.tab();
235
+ expect(screen.getByRole('checkbox')).not.toHaveFocus();
236
+ expect(document.body).toHaveFocus();
237
+ });
238
+
239
+ it('delegates a row-surface click to the interactive control', async () => {
240
+ const user = userEvent.setup();
241
+ const onToggle = vi.fn();
242
+ render(<DelegatingItem onToggle={onToggle} />);
243
+ // Clicking the label (row surface) is forwarded to the checkbox.
244
+ await user.click(screen.getByText('Row'));
245
+ expect(onToggle).toHaveBeenCalledTimes(1);
246
+ });
247
+
248
+ it('does not double-fire when the interactive control itself is clicked', async () => {
249
+ const user = userEvent.setup();
250
+ const onToggle = vi.fn();
251
+ render(<DelegatingItem onToggle={onToggle} />);
252
+ await user.click(screen.getByRole('checkbox'));
253
+ // The row must not re-forward the control's own click back to it.
254
+ expect(onToggle).toHaveBeenCalledTimes(1);
255
+ });
256
+
257
+ it('ignores onClick when interactiveRef is set (delegation wins, single tab stop)', async () => {
258
+ const user = userEvent.setup();
259
+ const onClick = vi.fn();
260
+ function ItemWithBoth() {
261
+ const ref = useRef<HTMLInputElement>(null);
262
+ return (
263
+ <Item
264
+ label="Row"
265
+ onClick={onClick}
266
+ interactiveRef={ref}
267
+ startContent={
268
+ <input ref={ref} type="checkbox" aria-label="Pick row" />
269
+ }
270
+ />
271
+ );
272
+ }
273
+ const {container} = render(<ItemWithBoth />);
274
+ // No invisible button (onClick is ignored in delegation mode)...
275
+ expect(container.querySelector('button')).not.toBeInTheDocument();
276
+ // ...and the checkbox is still the sole tab stop.
277
+ await user.tab();
278
+ expect(screen.getByRole('checkbox')).toHaveFocus();
279
+ });
280
+
193
281
  // ===========================================================================
194
282
  // Interactive — href (invisible anchor pattern)
195
283
  // ===========================================================================
package/src/Item/Item.tsx CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  /**
6
6
  * @file Item.tsx
7
- * @input Uses React, ReactNode, StyleXStyles, theme tokens
7
+ * @input Uses React, ReactNode, StyleXStyles, theme tokens, useClickableContainer
8
8
  * @output Exports Item component, ItemProps type
9
9
  * @position Core layout primitive; consumed by index.ts, tested by Item.test.tsx
10
10
  *
@@ -16,7 +16,7 @@
16
16
  * - /packages/cli/templates/blocks/components/Item/ (showcase blocks)
17
17
  */
18
18
 
19
- import type {ReactNode} from 'react';
19
+ import {useRef, type ReactNode} from 'react';
20
20
  import * as stylex from '@stylexjs/stylex';
21
21
  import {
22
22
  colorVars,
@@ -27,9 +27,11 @@ import {
27
27
  typeScaleVars,
28
28
  } from '../theme/tokens.stylex';
29
29
  import type {BaseProps} from '../BaseProps';
30
- import {mergeProps} from '../utils';
30
+ import {mergeProps, mergeRefs} from '../utils';
31
31
  import {computeTargetAndRel} from '../Link/computeTargetAndRel';
32
32
  import {useLinkComponent} from '../Link/useLinkComponent';
33
+ import {useClickableContainer} from '../hooks/useClickableContainer';
34
+ import {useDevWarning} from '../hooks/useDevWarning';
33
35
  import {themeProps} from '../utils/themeProps';
34
36
 
35
37
  // =============================================================================
@@ -108,6 +110,20 @@ export interface ItemProps extends BaseProps<HTMLElement> {
108
110
  */
109
111
  onClick?: (event: React.MouseEvent) => void;
110
112
 
113
+ /**
114
+ * Ref to a nested control inside the item (e.g. a checkbox in
115
+ * `startContent`) that already provides the item's keyboard access and
116
+ * action. When set, the item becomes an enlarged click/tap target that
117
+ * delegates surface clicks to that control via the `useClickableContainer`
118
+ * pattern: it renders no invisible button/anchor, so the row adds no second
119
+ * tab stop (WCAG 4.1.2 — one focusable control per option). Clicks on the
120
+ * control itself, and on any other nested interactive element, are left to
121
+ * that element. Mutually exclusive with `onClick`/`href` — when
122
+ * `interactiveRef` is set those are ignored (the nested control is the sole
123
+ * action).
124
+ */
125
+ interactiveRef?: React.RefObject<HTMLElement | null>;
126
+
111
127
  /**
112
128
  * Link URL. Makes the item a link via an invisible anchor element.
113
129
  */
@@ -349,6 +365,7 @@ export function Item({
349
365
  labelLines,
350
366
  descriptionLines,
351
367
  onClick,
368
+ interactiveRef,
352
369
  href,
353
370
  target: targetFromProps,
354
371
  rel: relFromProps,
@@ -363,7 +380,29 @@ export function Item({
363
380
  ...restProps
364
381
  }: ItemProps) {
365
382
  const LinkComponent = useLinkComponent();
366
- const isInteractive = onClick != null || href != null;
383
+
384
+ // Delegation mode: the row is an enlarged click/tap target for a nested
385
+ // control (e.g. a checkbox) that owns the keyboard access and action. The
386
+ // control is the row's only tab stop; the row proxies surface clicks to it.
387
+ const isDelegate = interactiveRef != null;
388
+ const containerRef = useRef<HTMLElement | null>(null);
389
+ // Only onClick is needed: onMouseUp handles middle-click href navigation,
390
+ // which delegation mode never has (href is ignored here).
391
+ const {onClick: delegatedOnClick} = useClickableContainer({
392
+ containerRef,
393
+ interactiveRef: interactiveRef ?? undefined,
394
+ disabled: isDisabled,
395
+ });
396
+
397
+ useDevWarning(
398
+ 'Item',
399
+ '`interactiveRef` is mutually exclusive with `onClick`/`href`. In ' +
400
+ 'delegation mode the row only forwards clicks to the referenced control, ' +
401
+ 'so `onClick`/`href` are ignored. Drop one of them.',
402
+ isDelegate && (onClick != null || href != null),
403
+ );
404
+
405
+ const isInteractive = onClick != null || href != null || isDelegate;
367
406
  const {target, rel} = computeTargetAndRel(targetFromProps, relFromProps);
368
407
  // When a semantic role is provided (e.g. "menuitem"), a parent component
369
408
  // handles keyboard access. Skip the invisible button/anchor and put
@@ -441,7 +480,10 @@ export function Item({
441
480
  <span {...stylex.props(styles.startContent)}>{startContent}</span>
442
481
  )}
443
482
 
444
- {hasParentRole ? (
483
+ {hasParentRole || isDelegate ? (
484
+ // Delegation mode (and parent-role mode) put the label in a plain span:
485
+ // keyboard access lives on the nested control, so no invisible
486
+ // button/anchor is rendered and the row adds no second tab stop.
445
487
  <span
446
488
  {...stylex.props(
447
489
  styles.content,
@@ -497,7 +539,9 @@ export function Item({
497
539
 
498
540
  return (
499
541
  <Component
500
- ref={ref as React.Ref<never>}
542
+ ref={
543
+ (isDelegate ? mergeRefs(ref, containerRef) : ref) as React.Ref<never>
544
+ }
501
545
  {...restProps}
502
546
  aria-selected={(allowsAriaSelected && isSelected) || undefined}
503
547
  // aria-selected is invalid on roles that don't permit it (listitem, a
@@ -527,11 +571,13 @@ export function Item({
527
571
  )}
528
572
  role={role}
529
573
  onClick={
530
- hasParentRole
531
- ? onClick
532
- : isInteractive
533
- ? handleContainerClick
534
- : undefined
574
+ isDelegate
575
+ ? delegatedOnClick
576
+ : hasParentRole
577
+ ? onClick
578
+ : isInteractive
579
+ ? handleContainerClick
580
+ : undefined
535
581
  }>
536
582
  {innerContent}
537
583
  </Component>
@@ -61,6 +61,27 @@ const enterStart = stylex.keyframes({
61
61
  to: {opacity: 1, transform: 'translateX(0) scale(1)'},
62
62
  });
63
63
 
64
+ // RTL: the horizontal entrance nudge is a physical translateX, so it must
65
+ // mirror under RTL — a layer on the inline-end/start side must slide in from
66
+ // the correct physical side following the reading flow. Only the horizontal
67
+ // (translateX) keyframes need mirroring; the vertical enterAbove/enterBelow
68
+ // (translateY) entrances are direction-neutral and are left as-is.
69
+ const enterEndRtl = stylex.keyframes({
70
+ from: {
71
+ opacity: 0,
72
+ transform: `translateX(${spacingVars['--spacing-2']}) scale(0.95)`,
73
+ },
74
+ to: {opacity: 1, transform: 'translateX(0) scale(1)'},
75
+ });
76
+
77
+ const enterStartRtl = stylex.keyframes({
78
+ from: {
79
+ opacity: 0,
80
+ transform: `translateX(calc(-1 * ${spacingVars['--spacing-2']})) scale(0.95)`,
81
+ },
82
+ to: {opacity: 1, transform: 'translateX(0) scale(1)'},
83
+ });
84
+
64
85
  const animationBase = {
65
86
  animationDuration: durationVars['--duration-fast-max'],
66
87
  animationTimingFunction: easeVars['--ease-standard'],
@@ -95,6 +116,7 @@ export const layerAnimations = stylex.create({
95
116
  end: {
96
117
  animationName: {
97
118
  default: enterEnd,
119
+ ':is([dir="rtl"] *)': enterEndRtl,
98
120
  '@media (prefers-reduced-motion: reduce)': 'none',
99
121
  },
100
122
  ...animationBase,
@@ -102,6 +124,7 @@ export const layerAnimations = stylex.create({
102
124
  start: {
103
125
  animationName: {
104
126
  default: enterStart,
127
+ ':is([dir="rtl"] *)': enterStartRtl,
105
128
  '@media (prefers-reduced-motion: reduce)': 'none',
106
129
  },
107
130
  ...animationBase,
@@ -443,4 +443,37 @@ describe('Lightbox', () => {
443
443
  );
444
444
  expect(container.querySelector('dialog')).not.toBeInTheDocument();
445
445
  });
446
+
447
+ describe('backdrop dismiss', () => {
448
+ it('calls onOpenChange(false) when the dark area around the media is clicked', () => {
449
+ const onOpenChange = vi.fn();
450
+ render(
451
+ <Lightbox
452
+ isOpen={true}
453
+ onOpenChange={onOpenChange}
454
+ media={{src: '/photo.jpg', alt: 'Photo'}}
455
+ />,
456
+ );
457
+ // The container fills the whole dialog, so a click on the visual
458
+ // backdrop (the dark area around the media) lands on it — not on the
459
+ // dialog element itself.
460
+ const dialog = document.querySelector('dialog')!;
461
+ const container = dialog.firstElementChild!;
462
+ fireEvent.click(container);
463
+ expect(onOpenChange).toHaveBeenCalledWith(false);
464
+ });
465
+
466
+ it('does not close when the media itself is clicked', () => {
467
+ const onOpenChange = vi.fn();
468
+ render(
469
+ <Lightbox
470
+ isOpen={true}
471
+ onOpenChange={onOpenChange}
472
+ media={{src: '/photo.jpg', alt: 'Photo'}}
473
+ />,
474
+ );
475
+ fireEvent.click(screen.getByRole('img', {hidden: true}));
476
+ expect(onOpenChange).not.toHaveBeenCalled();
477
+ });
478
+ });
446
479
  });
@@ -32,7 +32,7 @@ import {IconButton} from '../IconButton';
32
32
  import {useAnnounce} from '../hooks/useAnnounce';
33
33
  import {useScrollLock} from '../hooks/useScrollLock';
34
34
  import {useIsomorphicLayoutEffect} from '../hooks/useIsomorphicLayoutEffect';
35
- import {mergeProps, mergeRefs} from '../utils';
35
+ import {mergeProps, mergeRefs, rtlStyles} from '../utils';
36
36
  import type {BaseProps} from '../BaseProps';
37
37
  import {themeProps} from '../utils/themeProps';
38
38
  import {useTranslator} from '../i18n';
@@ -199,7 +199,7 @@ const styles = stylex.create({
199
199
  closeButton: {
200
200
  position: 'absolute',
201
201
  top: spacingVars['--spacing-3'],
202
- right: spacingVars['--spacing-3'],
202
+ insetInlineEnd: spacingVars['--spacing-3'],
203
203
  zIndex: 1,
204
204
  },
205
205
  navButton: {
@@ -209,15 +209,15 @@ const styles = stylex.create({
209
209
  zIndex: 1,
210
210
  },
211
211
  navPrev: {
212
- left: spacingVars['--spacing-3'],
212
+ insetInlineStart: spacingVars['--spacing-3'],
213
213
  },
214
214
  navNext: {
215
- right: spacingVars['--spacing-3'],
215
+ insetInlineEnd: spacingVars['--spacing-3'],
216
216
  },
217
217
  counter: {
218
218
  position: 'absolute',
219
219
  top: spacingVars['--spacing-3'],
220
- left: spacingVars['--spacing-3'],
220
+ insetInlineStart: spacingVars['--spacing-3'],
221
221
  color: colorVars['--color-on-dark'],
222
222
  fontSize: typeScaleVars['--text-body-size'],
223
223
  lineHeight: typeScaleVars['--text-body-leading'],
@@ -285,6 +285,7 @@ export function Lightbox({
285
285
  }: LightboxProps) {
286
286
  const t = useTranslator();
287
287
  const dialogRef = useRef<HTMLDialogElement>(null);
288
+ const containerRef = useRef<HTMLDivElement>(null);
288
289
  const imageWrapperRef = useRef<HTMLDivElement>(null);
289
290
  const triggerElementRef = useRef<Element | null>(null);
290
291
 
@@ -390,10 +391,19 @@ export function Lightbox({
390
391
  [handleClose],
391
392
  );
392
393
 
393
- // Backdrop click
394
+ // Backdrop click. The layout container fills the whole transparent dialog,
395
+ // so clicks on the visual backdrop (the dark area around the media) land on
396
+ // the container, never on the dialog element itself — treat both as the
397
+ // backdrop. A pan drag that ends over the backdrop still fires a click on
398
+ // the common ancestor; ignore it so releasing a drag doesn't dismiss.
399
+ const didDragRef = useRef(false);
394
400
  const handleBackdropClick = useCallback(
395
401
  (e: ReactMouseEvent<HTMLDialogElement>) => {
396
- if (e.target === e.currentTarget) {
402
+ if (didDragRef.current) {
403
+ didDragRef.current = false;
404
+ return;
405
+ }
406
+ if (e.target === e.currentTarget || e.target === containerRef.current) {
397
407
  handleClose();
398
408
  }
399
409
  },
@@ -448,6 +458,7 @@ export function Lightbox({
448
458
  return;
449
459
  }
450
460
  setIsDragging(true);
461
+ didDragRef.current = false;
451
462
  dragStartRef.current = {
452
463
  x: e.clientX,
453
464
  y: e.clientY,
@@ -464,6 +475,7 @@ export function Lightbox({
464
475
  }
465
476
 
466
477
  const handlePointerMove = (e: PointerEvent) => {
478
+ didDragRef.current = true;
467
479
  const dx = e.clientX - dragStartRef.current.x;
468
480
  const dy = e.clientY - dragStartRef.current.y;
469
481
  setPan({
@@ -514,7 +526,7 @@ export function Lightbox({
514
526
  style,
515
527
  )}
516
528
  {...props}>
517
- <div {...stylex.props(styles.container)}>
529
+ <div ref={containerRef} {...stylex.props(styles.container)}>
518
530
  {/* Close button */}
519
531
  <div {...stylex.props(styles.closeButton)}>
520
532
  <IconButton
@@ -532,7 +544,11 @@ export function Lightbox({
532
544
  {isGallery && (
533
545
  <div {...stylex.props(styles.navButton, styles.navPrev)}>
534
546
  <IconButton
535
- icon={<Icon icon="chevronLeft" size="sm" color="inherit" />}
547
+ icon={
548
+ <span {...stylex.props(rtlStyles.mirror)}>
549
+ <Icon icon="chevronLeft" size="sm" color="inherit" />
550
+ </span>
551
+ }
536
552
  label={t('@astryx.lightbox.previous')}
537
553
  variant="ghost"
538
554
  isDisabled={!canPrev}
@@ -587,7 +603,11 @@ export function Lightbox({
587
603
  {isGallery && (
588
604
  <div {...stylex.props(styles.navButton, styles.navNext)}>
589
605
  <IconButton
590
- icon={<Icon icon="chevronRight" size="sm" color="inherit" />}
606
+ icon={
607
+ <span {...stylex.props(rtlStyles.mirror)}>
608
+ <Icon icon="chevronRight" size="sm" color="inherit" />
609
+ </span>
610
+ }
591
611
  label={t('@astryx.lightbox.next')}
592
612
  variant="ghost"
593
613
  isDisabled={!canNext}