@astryxdesign/core 0.1.8-canary.fe8657a → 0.1.9-canary.02ef052

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 (570) hide show
  1. package/CHANGELOG.md +100 -0
  2. package/dist/Avatar/Avatar.d.ts +58 -3
  3. package/dist/Avatar/Avatar.d.ts.map +1 -1
  4. package/dist/Avatar/Avatar.js +240 -53
  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.map +1 -1
  11. package/dist/AvatarGroup/AvatarGroupOverflow.js +1 -0
  12. package/dist/Banner/Banner.js +2 -2
  13. package/dist/Breadcrumbs/BreadcrumbItem.d.ts +31 -2
  14. package/dist/Breadcrumbs/BreadcrumbItem.d.ts.map +1 -1
  15. package/dist/Breadcrumbs/BreadcrumbItem.js +215 -6
  16. package/dist/Breadcrumbs/index.d.ts +6 -0
  17. package/dist/Breadcrumbs/index.d.ts.map +1 -1
  18. package/dist/Breadcrumbs/index.js +10 -1
  19. package/dist/Button/Button.js +2 -2
  20. package/dist/Calendar/Calendar.d.ts.map +1 -1
  21. package/dist/Calendar/Calendar.js +50 -9
  22. package/dist/Calendar/dayCellUtils.d.ts +4 -4
  23. package/dist/Calendar/dayCellUtils.js +3 -3
  24. package/dist/Calendar/styles.d.ts +30 -31
  25. package/dist/Calendar/styles.d.ts.map +1 -1
  26. package/dist/Calendar/styles.js +30 -31
  27. package/dist/Carousel/Carousel.d.ts.map +1 -1
  28. package/dist/Carousel/Carousel.js +22 -12
  29. package/dist/Chat/ChatComposer.d.ts.map +1 -1
  30. package/dist/Chat/ChatComposer.js +15 -1
  31. package/dist/Chat/ChatComposerInput.d.ts.map +1 -1
  32. package/dist/Chat/ChatComposerInput.js +17 -1
  33. package/dist/Chat/ChatContext.d.ts +33 -0
  34. package/dist/Chat/ChatContext.d.ts.map +1 -1
  35. package/dist/Chat/ChatContext.js +16 -2
  36. package/dist/Chat/ChatDictationButton.d.ts.map +1 -1
  37. package/dist/Chat/ChatDictationButton.js +4 -2
  38. package/dist/Chat/ChatLayout.js +4 -4
  39. package/dist/Chat/ChatLayoutScrollButton.d.ts.map +1 -1
  40. package/dist/Chat/ChatLayoutScrollButton.js +4 -4
  41. package/dist/Chat/ChatSendButton.d.ts.map +1 -1
  42. package/dist/Chat/ChatSendButton.js +7 -1
  43. package/dist/Chat/ChatToolCalls.d.ts.map +1 -1
  44. package/dist/Chat/ChatToolCalls.js +16 -9
  45. package/dist/Chat/index.d.ts +2 -1
  46. package/dist/Chat/index.d.ts.map +1 -1
  47. package/dist/Chat/index.js +1 -1
  48. package/dist/Chat/useSpeechRecognition.d.ts +0 -1
  49. package/dist/Chat/useSpeechRecognition.d.ts.map +1 -1
  50. package/dist/Chat/useSpeechRecognition.js +1 -1
  51. package/dist/Chat/useTriggerMenu.js +2 -2
  52. package/dist/CheckboxInput/CheckboxInput.js +5 -5
  53. package/dist/CheckboxList/CheckboxListItem.d.ts +20 -1
  54. package/dist/CheckboxList/CheckboxListItem.d.ts.map +1 -1
  55. package/dist/CheckboxList/CheckboxListItem.js +11 -1
  56. package/dist/Citation/Citation.d.ts +22 -1
  57. package/dist/Citation/Citation.d.ts.map +1 -1
  58. package/dist/Citation/Citation.js +20 -6
  59. package/dist/ClickableCard/ClickableCard.js +2 -2
  60. package/dist/CodeBlock/CodeBlock.d.ts.map +1 -1
  61. package/dist/CodeBlock/CodeBlock.js +14 -8
  62. package/dist/Collapsible/Collapsible.d.ts.map +1 -1
  63. package/dist/Collapsible/Collapsible.js +3 -1
  64. package/dist/CommandPalette/CommandPalette.d.ts +2 -2
  65. package/dist/CommandPalette/CommandPalette.d.ts.map +1 -1
  66. package/dist/CommandPalette/CommandPalette.js +45 -4
  67. package/dist/CommandPalette/CommandPaletteGroup.d.ts.map +1 -1
  68. package/dist/CommandPalette/CommandPaletteGroup.js +9 -2
  69. package/dist/CommandPalette/CommandPaletteItem.js +1 -1
  70. package/dist/ContextMenu/ContextMenu.d.ts.map +1 -1
  71. package/dist/ContextMenu/ContextMenu.js +14 -5
  72. package/dist/ContextMenu/index.d.ts +1 -0
  73. package/dist/ContextMenu/index.d.ts.map +1 -1
  74. package/dist/ContextMenu/index.js +3 -1
  75. package/dist/DateInput/DateInput.d.ts +56 -2
  76. package/dist/DateInput/DateInput.d.ts.map +1 -1
  77. package/dist/DateInput/DateInput.js +59 -21
  78. package/dist/DateInput/index.d.ts +1 -1
  79. package/dist/DateInput/index.d.ts.map +1 -1
  80. package/dist/DateRangeInput/DateRangeInput.d.ts +10 -2
  81. package/dist/DateRangeInput/DateRangeInput.d.ts.map +1 -1
  82. package/dist/DateRangeInput/DateRangeInput.js +23 -20
  83. package/dist/DateTimeInput/DateTimeInput.d.ts.map +1 -1
  84. package/dist/DateTimeInput/DateTimeInput.js +23 -18
  85. package/dist/Dialog/Dialog.d.ts +3 -0
  86. package/dist/Dialog/Dialog.d.ts.map +1 -1
  87. package/dist/Dialog/Dialog.js +55 -5
  88. package/dist/Dialog/DialogContext.d.ts +7 -0
  89. package/dist/Dialog/DialogContext.d.ts.map +1 -1
  90. package/dist/Dialog/DialogContext.js +2 -2
  91. package/dist/Dialog/DialogHeader.d.ts +5 -2
  92. package/dist/Dialog/DialogHeader.d.ts.map +1 -1
  93. package/dist/Dialog/DialogHeader.js +6 -1
  94. package/dist/Divider/Divider.js +1 -1
  95. package/dist/DropdownMenu/DropdownMenu.d.ts +6 -0
  96. package/dist/DropdownMenu/DropdownMenu.d.ts.map +1 -1
  97. package/dist/DropdownMenu/DropdownMenu.js +22 -5
  98. package/dist/DropdownMenu/DropdownMenuCheckboxItem.d.ts.map +1 -1
  99. package/dist/DropdownMenu/DropdownMenuCheckboxItem.js +4 -1
  100. package/dist/DropdownMenu/DropdownMenuItem.d.ts.map +1 -1
  101. package/dist/DropdownMenu/DropdownMenuItem.js +5 -2
  102. package/dist/DropdownMenu/DropdownMenuRadioItem.d.ts.map +1 -1
  103. package/dist/DropdownMenu/DropdownMenuRadioItem.js +4 -1
  104. package/dist/DropdownMenu/DropdownMenuSubMenu.d.ts +104 -0
  105. package/dist/DropdownMenu/DropdownMenuSubMenu.d.ts.map +1 -0
  106. package/dist/DropdownMenu/DropdownMenuSubMenu.js +427 -0
  107. package/dist/DropdownMenu/index.d.ts +10 -0
  108. package/dist/DropdownMenu/index.d.ts.map +1 -1
  109. package/dist/DropdownMenu/index.js +13 -0
  110. package/dist/DropdownMenu/menuItemHover.d.ts +23 -0
  111. package/dist/DropdownMenu/menuItemHover.d.ts.map +1 -0
  112. package/dist/DropdownMenu/menuItemHover.js +33 -0
  113. package/dist/DropdownMenu/menuItemRoles.d.ts +8 -0
  114. package/dist/DropdownMenu/menuItemRoles.d.ts.map +1 -1
  115. package/dist/DropdownMenu/menuItemRoles.js +10 -1
  116. package/dist/DropdownMenu/renderDropdownItems.d.ts.map +1 -1
  117. package/dist/DropdownMenu/renderDropdownItems.js +21 -6
  118. package/dist/Field/Field.d.ts +3 -1
  119. package/dist/Field/Field.d.ts.map +1 -1
  120. package/dist/Field/Field.js +6 -4
  121. package/dist/Field/FieldLabel.d.ts +1 -1
  122. package/dist/Field/FieldLabel.d.ts.map +1 -1
  123. package/dist/Field/FieldLabel.js +43 -16
  124. package/dist/Field/inputStyles.stylex.d.ts +1 -0
  125. package/dist/Field/inputStyles.stylex.d.ts.map +1 -1
  126. package/dist/Field/inputStyles.stylex.js +1 -0
  127. package/dist/FieldStatus/FieldStatus.d.ts +10 -0
  128. package/dist/FieldStatus/FieldStatus.d.ts.map +1 -1
  129. package/dist/FieldStatus/FieldStatus.js +39 -3
  130. package/dist/FileInput/FileInput.d.ts +10 -2
  131. package/dist/FileInput/FileInput.d.ts.map +1 -1
  132. package/dist/FileInput/FileInput.js +44 -33
  133. package/dist/HoverCard/useHoverCard.d.ts.map +1 -1
  134. package/dist/HoverCard/useHoverCard.js +10 -4
  135. package/dist/Icon/Icon.d.ts +22 -3
  136. package/dist/Icon/Icon.d.ts.map +1 -1
  137. package/dist/Icon/Icon.js +19 -3
  138. package/dist/Item/Item.d.ts +6 -1
  139. package/dist/Item/Item.d.ts.map +1 -1
  140. package/dist/Item/Item.js +22 -1
  141. package/dist/Lightbox/Lightbox.d.ts.map +1 -1
  142. package/dist/Lightbox/Lightbox.js +19 -13
  143. package/dist/Markdown/Markdown.d.ts.map +1 -1
  144. package/dist/Markdown/Markdown.js +7 -0
  145. package/dist/MultiSelector/MultiSelector.d.ts +9 -1
  146. package/dist/MultiSelector/MultiSelector.d.ts.map +1 -1
  147. package/dist/MultiSelector/MultiSelector.js +67 -40
  148. package/dist/NavMenu/NavHeadingMenuItem.js +1 -1
  149. package/dist/NumberInput/NumberInput.d.ts +10 -2
  150. package/dist/NumberInput/NumberInput.d.ts.map +1 -1
  151. package/dist/NumberInput/NumberInput.js +22 -17
  152. package/dist/Pagination/Pagination.d.ts.map +1 -1
  153. package/dist/Pagination/Pagination.js +11 -3
  154. package/dist/Popover/Popover.d.ts.map +1 -1
  155. package/dist/Popover/Popover.js +3 -2
  156. package/dist/Popover/usePopover.d.ts.map +1 -1
  157. package/dist/Popover/usePopover.js +3 -9
  158. package/dist/PowerSearch/PowerSearch.d.ts +9 -2
  159. package/dist/PowerSearch/PowerSearch.d.ts.map +1 -1
  160. package/dist/PowerSearch/PowerSearch.js +2 -0
  161. package/dist/RadioList/RadioList.d.ts +2 -2
  162. package/dist/RadioList/RadioListItem.js +4 -4
  163. package/dist/SegmentedControl/SegmentedControlItem.d.ts +1 -1
  164. package/dist/SegmentedControl/SegmentedControlItem.d.ts.map +1 -1
  165. package/dist/SegmentedControl/SegmentedControlItem.js +2 -1
  166. package/dist/SelectableCard/SelectableCard.js +2 -2
  167. package/dist/Selector/Selector.d.ts +8 -0
  168. package/dist/Selector/Selector.d.ts.map +1 -1
  169. package/dist/Selector/Selector.js +61 -17
  170. package/dist/SideNav/SideNav.d.ts.map +1 -1
  171. package/dist/SideNav/SideNav.js +5 -5
  172. package/dist/SideNav/SideNavCollapseButton.d.ts.map +1 -1
  173. package/dist/SideNav/SideNavCollapseButton.js +13 -10
  174. package/dist/SideNav/SideNavItem.d.ts +1 -1
  175. package/dist/SideNav/SideNavItem.d.ts.map +1 -1
  176. package/dist/SideNav/SideNavItem.js +12 -10
  177. package/dist/Slider/Slider.d.ts.map +1 -1
  178. package/dist/Slider/Slider.js +91 -35
  179. package/dist/Stack/stack.stylex.d.ts +9 -9
  180. package/dist/Switch/Switch.d.ts +8 -1
  181. package/dist/Switch/Switch.d.ts.map +1 -1
  182. package/dist/Switch/Switch.js +160 -91
  183. package/dist/TabList/Tab.js +2 -2
  184. package/dist/TabList/TabMenu.js +1 -1
  185. package/dist/Table/BaseTable.d.ts.map +1 -1
  186. package/dist/Table/BaseTable.js +33 -6
  187. package/dist/Table/TableCell.js +3 -3
  188. package/dist/Table/TableHeaderCell.js +3 -3
  189. package/dist/Table/plugins/groupedRows/useTableGroupedRows.d.ts.map +1 -1
  190. package/dist/Table/plugins/groupedRows/useTableGroupedRows.js +15 -11
  191. package/dist/Table/plugins/rowExpansion/useTableRowExpansion.d.ts.map +1 -1
  192. package/dist/Table/plugins/rowExpansion/useTableRowExpansion.js +36 -26
  193. package/dist/Table/plugins/selection/useTableSelection.d.ts +2 -1
  194. package/dist/Table/plugins/selection/useTableSelection.d.ts.map +1 -1
  195. package/dist/Table/plugins/selection/useTableSelection.js +3 -0
  196. package/dist/Table/plugins/stickyColumns/useTableStickyColumns.js +1 -1
  197. package/dist/Table/plugins/tree/useTableTreeData.d.ts +16 -0
  198. package/dist/Table/plugins/tree/useTableTreeData.d.ts.map +1 -1
  199. package/dist/Table/plugins/tree/useTableTreeData.js +105 -12
  200. package/dist/Table/plugins/tree/useTableTreeState.d.ts +6 -0
  201. package/dist/Table/plugins/tree/useTableTreeState.d.ts.map +1 -1
  202. package/dist/Table/plugins/tree/useTableTreeState.js +22 -1
  203. package/dist/Table/types.d.ts +32 -0
  204. package/dist/Table/types.d.ts.map +1 -1
  205. package/dist/Table/useBaseTablePlugins.d.ts.map +1 -1
  206. package/dist/Table/useBaseTablePlugins.js +5 -3
  207. package/dist/TextArea/TextArea.d.ts +10 -1
  208. package/dist/TextArea/TextArea.d.ts.map +1 -1
  209. package/dist/TextArea/TextArea.js +18 -19
  210. package/dist/TextInput/TextInput.d.ts +10 -2
  211. package/dist/TextInput/TextInput.d.ts.map +1 -1
  212. package/dist/TextInput/TextInput.js +20 -17
  213. package/dist/Thumbnail/Thumbnail.d.ts +24 -10
  214. package/dist/Thumbnail/Thumbnail.d.ts.map +1 -1
  215. package/dist/Thumbnail/Thumbnail.js +82 -77
  216. package/dist/Thumbnail/thumbnail.markers.stylex.d.ts +9 -0
  217. package/dist/Thumbnail/thumbnail.markers.stylex.d.ts.map +1 -0
  218. package/dist/Thumbnail/thumbnail.markers.stylex.js +14 -0
  219. package/dist/TimeInput/TimeInput.d.ts +10 -2
  220. package/dist/TimeInput/TimeInput.d.ts.map +1 -1
  221. package/dist/TimeInput/TimeInput.js +17 -17
  222. package/dist/Timestamp/Timestamp.d.ts +3 -1
  223. package/dist/Timestamp/Timestamp.d.ts.map +1 -1
  224. package/dist/Timestamp/Timestamp.js +8 -6
  225. package/dist/Toast/useToast.d.ts.map +1 -1
  226. package/dist/Toast/useToast.js +2 -5
  227. package/dist/ToggleButton/ToggleButtonGroup.d.ts +0 -1
  228. package/dist/ToggleButton/ToggleButtonGroup.d.ts.map +1 -1
  229. package/dist/ToggleButton/ToggleButtonGroup.js +1 -1
  230. package/dist/Token/Token.d.ts +30 -3
  231. package/dist/Token/Token.d.ts.map +1 -1
  232. package/dist/Token/Token.js +17 -2
  233. package/dist/Token/index.d.ts +1 -1
  234. package/dist/Token/index.d.ts.map +1 -1
  235. package/dist/Tokenizer/Tokenizer.d.ts +9 -2
  236. package/dist/Tokenizer/Tokenizer.d.ts.map +1 -1
  237. package/dist/Tokenizer/Tokenizer.js +4 -2
  238. package/dist/Tooltip/useTooltip.d.ts.map +1 -1
  239. package/dist/Tooltip/useTooltip.js +17 -1
  240. package/dist/TopNav/TopNavMegaMenuFeaturedCard.d.ts +9 -1
  241. package/dist/TopNav/TopNavMegaMenuFeaturedCard.d.ts.map +1 -1
  242. package/dist/TopNav/TopNavMegaMenuFeaturedCard.js +8 -1
  243. package/dist/TreeList/TreeList.d.ts +12 -3
  244. package/dist/TreeList/TreeList.d.ts.map +1 -1
  245. package/dist/TreeList/TreeList.js +3 -0
  246. package/dist/TreeList/TreeListBranches.d.ts +5 -0
  247. package/dist/TreeList/TreeListBranches.d.ts.map +1 -1
  248. package/dist/TreeList/TreeListBranches.js +18 -10
  249. package/dist/TreeList/TreeListItem.d.ts +8 -2
  250. package/dist/TreeList/TreeListItem.d.ts.map +1 -1
  251. package/dist/TreeList/TreeListItem.js +59 -21
  252. package/dist/TreeList/TreeListTypes.d.ts +25 -1
  253. package/dist/TreeList/TreeListTypes.d.ts.map +1 -1
  254. package/dist/TreeList/index.d.ts +2 -2
  255. package/dist/TreeList/index.d.ts.map +1 -1
  256. package/dist/Typeahead/BaseTypeahead.d.ts.map +1 -1
  257. package/dist/Typeahead/BaseTypeahead.js +20 -11
  258. package/dist/Typeahead/Typeahead.d.ts +9 -2
  259. package/dist/Typeahead/Typeahead.d.ts.map +1 -1
  260. package/dist/Typeahead/Typeahead.js +3 -1
  261. package/dist/Typeahead/TypeaheadItem.d.ts +1 -1
  262. package/dist/Typeahead/TypeaheadItem.d.ts.map +1 -1
  263. package/dist/Typeahead/TypeaheadItem.js +20 -10
  264. package/dist/astryx.css +39 -31
  265. package/dist/astryx.umd.js +53 -53
  266. package/dist/astryx.umd.js.map +4 -4
  267. package/dist/docs-types.d.ts +8 -0
  268. package/dist/docs-types.d.ts.map +1 -1
  269. package/dist/hooks/index.d.ts +3 -0
  270. package/dist/hooks/index.d.ts.map +1 -1
  271. package/dist/hooks/index.js +3 -1
  272. package/dist/hooks/isRtlElement.d.ts +18 -0
  273. package/dist/hooks/isRtlElement.d.ts.map +1 -0
  274. package/dist/hooks/isRtlElement.js +27 -0
  275. package/dist/hooks/useDevWarning.d.ts +18 -0
  276. package/dist/hooks/useDevWarning.d.ts.map +1 -0
  277. package/dist/hooks/useDevWarning.js +49 -0
  278. package/dist/hooks/useGridFocus.d.ts +6 -1
  279. package/dist/hooks/useGridFocus.d.ts.map +1 -1
  280. package/dist/hooks/useGridFocus.js +12 -9
  281. package/dist/hooks/useInputStatusIcon.d.ts +38 -0
  282. package/dist/hooks/useInputStatusIcon.d.ts.map +1 -0
  283. package/dist/hooks/useInputStatusIcon.js +158 -0
  284. package/dist/hooks/useListFocus.d.ts +39 -1
  285. package/dist/hooks/useListFocus.d.ts.map +1 -1
  286. package/dist/hooks/useListFocus.js +54 -9
  287. package/dist/hooks/useOverflow.d.ts.map +1 -1
  288. package/dist/hooks/useOverflow.js +2 -3
  289. package/dist/i18n/InternationalizationContext.d.ts +1 -0
  290. package/dist/i18n/InternationalizationContext.d.ts.map +1 -1
  291. package/dist/i18n/InternationalizationContext.js +3 -0
  292. package/dist/i18n/InternationalizationProvider.d.ts +8 -1
  293. package/dist/i18n/InternationalizationProvider.d.ts.map +1 -1
  294. package/dist/i18n/InternationalizationProvider.js +5 -1
  295. package/dist/i18n/getLocaleDirection.d.ts +18 -0
  296. package/dist/i18n/getLocaleDirection.d.ts.map +1 -0
  297. package/dist/i18n/getLocaleDirection.js +29 -0
  298. package/dist/i18n/index.d.ts +6 -0
  299. package/dist/i18n/index.d.ts.map +1 -1
  300. package/dist/i18n/index.js +7 -1
  301. package/dist/i18n/resolve.d.ts.map +1 -1
  302. package/dist/i18n/resolve.js +7 -18
  303. package/dist/i18n/useDirection.d.ts +2 -0
  304. package/dist/i18n/useDirection.d.ts.map +1 -0
  305. package/dist/i18n/useDirection.js +27 -0
  306. package/dist/theme/Theme.d.ts.map +1 -1
  307. package/dist/theme/Theme.js +2 -7
  308. package/dist/theme/derivedVarRegistry.d.ts.map +1 -1
  309. package/dist/theme/derivedVarRegistry.js +13 -0
  310. package/dist/theme/hct.d.ts +0 -1
  311. package/dist/theme/hct.d.ts.map +1 -1
  312. package/dist/theme/hct.js +1 -1
  313. package/dist/theme/syntax/defineSyntaxTheme.d.ts.map +1 -1
  314. package/dist/theme/syntax/defineSyntaxTheme.js +2 -1
  315. package/dist/utils/devWarning.d.ts +42 -0
  316. package/dist/utils/devWarning.d.ts.map +1 -0
  317. package/dist/utils/devWarning.js +88 -0
  318. package/dist/utils/index.d.ts +4 -1
  319. package/dist/utils/index.d.ts.map +1 -1
  320. package/dist/utils/index.js +4 -2
  321. package/dist/utils/plainDate.d.ts +30 -0
  322. package/dist/utils/plainDate.d.ts.map +1 -1
  323. package/dist/utils/plainDate.js +65 -3
  324. package/dist/utils/rtlStyles.d.ts +24 -0
  325. package/dist/utils/rtlStyles.d.ts.map +1 -0
  326. package/dist/utils/rtlStyles.js +27 -0
  327. package/locales/en.json +92 -0
  328. package/locales/fr-FR.json +4 -0
  329. package/locales/pseudo.json +69 -0
  330. package/package.json +6 -1
  331. package/src/Avatar/Avatar.doc.mjs +59 -2
  332. package/src/Avatar/Avatar.test.tsx +374 -1
  333. package/src/Avatar/Avatar.tsx +367 -69
  334. package/src/Avatar/AvatarStatusDot.doc.mjs +4 -4
  335. package/src/Avatar/AvatarStatusDot.tsx +6 -4
  336. package/src/AvatarGroup/AvatarGroup.doc.mjs +2 -0
  337. package/src/AvatarGroup/AvatarGroup.test.tsx +141 -1
  338. package/src/AvatarGroup/AvatarGroup.tsx +58 -3
  339. package/src/AvatarGroup/AvatarGroupOverflow.tsx +1 -0
  340. package/src/Banner/Banner.tsx +6 -6
  341. package/src/Breadcrumbs/BreadcrumbItem.doc.mjs +26 -0
  342. package/src/Breadcrumbs/BreadcrumbItem.tsx +333 -14
  343. package/src/Breadcrumbs/Breadcrumbs.doc.mjs +2 -0
  344. package/src/Breadcrumbs/Breadcrumbs.test.tsx +335 -2
  345. package/src/Breadcrumbs/index.ts +31 -0
  346. package/src/Button/Button.doc.mjs +0 -4
  347. package/src/Button/Button.tsx +2 -2
  348. package/src/Calendar/Calendar.test.tsx +170 -20
  349. package/src/Calendar/Calendar.tsx +73 -16
  350. package/src/Calendar/dayCellUtils.test.ts +23 -18
  351. package/src/Calendar/dayCellUtils.ts +3 -3
  352. package/src/Calendar/styles.ts +33 -39
  353. package/src/Carousel/Carousel.doc.mjs +1 -0
  354. package/src/Carousel/Carousel.tsx +25 -6
  355. package/src/Chat/ChatComposer.doc.mjs +4 -4
  356. package/src/Chat/ChatComposer.test.tsx +82 -2
  357. package/src/Chat/ChatComposer.tsx +15 -0
  358. package/src/Chat/ChatComposerInput.doc.mjs +1 -1
  359. package/src/Chat/ChatComposerInput.test.tsx +16 -0
  360. package/src/Chat/ChatComposerInput.tsx +16 -2
  361. package/src/Chat/ChatContext.tsx +37 -10
  362. package/src/Chat/ChatDictationButton.tsx +11 -2
  363. package/src/Chat/ChatLayout.tsx +4 -4
  364. package/src/Chat/ChatLayoutScrollButton.tsx +4 -1
  365. package/src/Chat/ChatSendButton.tsx +6 -0
  366. package/src/Chat/ChatToolCalls.tsx +21 -5
  367. package/src/Chat/index.ts +5 -1
  368. package/src/Chat/useSpeechRecognition.ts +1 -1
  369. package/src/Chat/useTriggerMenu.tsx +1 -1
  370. package/src/CheckboxInput/CheckboxInput.doc.mjs +6 -0
  371. package/src/CheckboxInput/CheckboxInput.tsx +5 -5
  372. package/src/CheckboxList/CheckboxList.doc.mjs +6 -0
  373. package/src/CheckboxList/CheckboxList.test.tsx +72 -2
  374. package/src/CheckboxList/CheckboxListItem.doc.mjs +33 -5
  375. package/src/CheckboxList/CheckboxListItem.tsx +41 -5
  376. package/src/Citation/Citation.doc.mjs +4 -3
  377. package/src/Citation/Citation.test.tsx +97 -0
  378. package/src/Citation/Citation.tsx +43 -11
  379. package/src/ClickableCard/ClickableCard.tsx +2 -2
  380. package/src/CodeBlock/CodeBlock.tsx +36 -9
  381. package/src/Collapsible/Collapsible.doc.mjs +1 -0
  382. package/src/Collapsible/Collapsible.test.tsx +7 -0
  383. package/src/Collapsible/Collapsible.tsx +16 -6
  384. package/src/CommandPalette/CommandPalette.doc.mjs +1 -0
  385. package/src/CommandPalette/CommandPalette.test.tsx +95 -1
  386. package/src/CommandPalette/CommandPalette.tsx +44 -3
  387. package/src/CommandPalette/CommandPaletteGroup.test.tsx +71 -0
  388. package/src/CommandPalette/CommandPaletteGroup.tsx +12 -1
  389. package/src/CommandPalette/CommandPaletteItem.tsx +1 -1
  390. package/src/ContextMenu/ContextMenu.test.tsx +235 -0
  391. package/src/ContextMenu/ContextMenu.tsx +13 -11
  392. package/src/ContextMenu/index.ts +5 -0
  393. package/src/DateInput/DateInput.doc.mjs +41 -0
  394. package/src/DateInput/DateInput.test.tsx +338 -0
  395. package/src/DateInput/DateInput.tsx +119 -32
  396. package/src/DateInput/index.ts +1 -0
  397. package/src/DateRangeInput/DateRangeInput.doc.mjs +16 -0
  398. package/src/DateRangeInput/DateRangeInput.test.tsx +140 -0
  399. package/src/DateRangeInput/DateRangeInput.tsx +42 -30
  400. package/src/DateTimeInput/DateTimeInput.doc.mjs +22 -1
  401. package/src/DateTimeInput/DateTimeInput.test.tsx +112 -0
  402. package/src/DateTimeInput/DateTimeInput.tsx +44 -39
  403. package/src/Dialog/Dialog.doc.mjs +2 -2
  404. package/src/Dialog/Dialog.test.tsx +77 -4
  405. package/src/Dialog/Dialog.tsx +77 -3
  406. package/src/Dialog/DialogContext.ts +9 -2
  407. package/src/Dialog/DialogHeader.doc.mjs +2 -2
  408. package/src/Dialog/DialogHeader.tsx +9 -2
  409. package/src/Divider/Divider.tsx +2 -2
  410. package/src/DropdownMenu/DropdownMenu.test.tsx +229 -0
  411. package/src/DropdownMenu/DropdownMenu.tsx +31 -12
  412. package/src/DropdownMenu/DropdownMenuCheckboxItem.tsx +8 -2
  413. package/src/DropdownMenu/DropdownMenuItem.tsx +9 -3
  414. package/src/DropdownMenu/DropdownMenuRadioItem.tsx +8 -2
  415. package/src/DropdownMenu/DropdownMenuSubMenu.doc.mjs +88 -0
  416. package/src/DropdownMenu/DropdownMenuSubMenu.test.tsx +635 -0
  417. package/src/DropdownMenu/DropdownMenuSubMenu.tsx +553 -0
  418. package/src/DropdownMenu/index.ts +16 -0
  419. package/src/DropdownMenu/menuItemHover.ts +39 -0
  420. package/src/DropdownMenu/menuItemRoles.ts +9 -0
  421. package/src/DropdownMenu/renderDropdownItems.tsx +29 -15
  422. package/src/Field/Field.tsx +20 -14
  423. package/src/Field/FieldLabel.tsx +9 -1
  424. package/src/Field/inputStyles.stylex.ts +2 -0
  425. package/src/FieldStatus/FieldStatus.test.tsx +72 -0
  426. package/src/FieldStatus/FieldStatus.tsx +48 -2
  427. package/src/FileInput/FileInput.doc.mjs +23 -2
  428. package/src/FileInput/FileInput.test.tsx +83 -9
  429. package/src/FileInput/FileInput.tsx +52 -49
  430. package/src/HoverCard/useHoverCard.tsx +15 -3
  431. package/src/Icon/Icon.doc.mjs +16 -2
  432. package/src/Icon/Icon.test.tsx +89 -0
  433. package/src/Icon/Icon.tsx +58 -5
  434. package/src/Item/Item.test.tsx +40 -18
  435. package/src/Item/Item.tsx +38 -2
  436. package/src/Lightbox/Lightbox.tsx +15 -7
  437. package/src/List/List.test.tsx +9 -8
  438. package/src/Markdown/Markdown.test.tsx +21 -0
  439. package/src/Markdown/Markdown.tsx +4 -0
  440. package/src/MultiSelector/MultiSelector.doc.mjs +20 -0
  441. package/src/MultiSelector/MultiSelector.test.tsx +336 -2
  442. package/src/MultiSelector/MultiSelector.tsx +98 -57
  443. package/src/NavMenu/NavHeadingMenuItem.tsx +1 -1
  444. package/src/NumberInput/NumberInput.doc.mjs +21 -0
  445. package/src/NumberInput/NumberInput.test.tsx +71 -0
  446. package/src/NumberInput/NumberInput.tsx +35 -26
  447. package/src/Pagination/Pagination.tsx +11 -3
  448. package/src/Popover/Popover.tsx +7 -4
  449. package/src/Popover/usePopover.tsx +9 -13
  450. package/src/PowerSearch/PowerSearch.doc.mjs +29 -0
  451. package/src/PowerSearch/PowerSearch.test.tsx +43 -0
  452. package/src/PowerSearch/PowerSearch.tsx +10 -1
  453. package/src/RadioList/RadioList.doc.mjs +6 -0
  454. package/src/RadioList/RadioList.tsx +2 -2
  455. package/src/RadioList/RadioListItem.tsx +4 -4
  456. package/src/SegmentedControl/SegmentedControlItem.tsx +2 -0
  457. package/src/SelectableCard/SelectableCard.tsx +2 -2
  458. package/src/Selector/Selector.doc.mjs +15 -0
  459. package/src/Selector/Selector.test.tsx +348 -0
  460. package/src/Selector/Selector.tsx +81 -20
  461. package/src/SideNav/SideNav.tsx +1 -8
  462. package/src/SideNav/SideNavCollapseButton.tsx +9 -7
  463. package/src/SideNav/SideNavItem.tsx +5 -3
  464. package/src/Slider/Slider.doc.mjs +6 -0
  465. package/src/Slider/Slider.test.tsx +252 -11
  466. package/src/Slider/Slider.tsx +102 -27
  467. package/src/Switch/Switch.doc.mjs +142 -42
  468. package/src/Switch/Switch.test.tsx +22 -0
  469. package/src/Switch/Switch.tsx +90 -33
  470. package/src/TabList/Tab.tsx +2 -2
  471. package/src/TabList/TabMenu.tsx +2 -2
  472. package/src/Table/BaseTable.tsx +37 -7
  473. package/src/Table/Table.doc.mjs +11 -0
  474. package/src/Table/Table.test.tsx +85 -0
  475. package/src/Table/TableCell.tsx +3 -3
  476. package/src/Table/TableHeaderCell.tsx +3 -3
  477. package/src/Table/plugins/groupedRows/useTableGroupedRows.tsx +9 -6
  478. package/src/Table/plugins/rowExpansion/useTableRowExpansion.tsx +24 -17
  479. package/src/Table/plugins/selection/useTableSelection.test.tsx +61 -3
  480. package/src/Table/plugins/selection/useTableSelection.tsx +5 -1
  481. package/src/Table/plugins/stickyColumns/useTableStickyColumns.tsx +1 -1
  482. package/src/Table/plugins/tree/useTableTreeData.test.tsx +135 -3
  483. package/src/Table/plugins/tree/useTableTreeData.tsx +139 -8
  484. package/src/Table/plugins/tree/useTableTreeState.test.tsx +104 -0
  485. package/src/Table/plugins/tree/useTableTreeState.tsx +46 -2
  486. package/src/Table/types.ts +33 -0
  487. package/src/Table/useBaseTablePlugins.ts +10 -6
  488. package/src/Table/useTableRowStatus.doc.mjs +1 -1
  489. package/src/Table/useTableTreeData.doc.mjs +29 -0
  490. package/src/Table/useTableTreeState.doc.mjs +2 -2
  491. package/src/TextArea/TextArea.doc.mjs +21 -0
  492. package/src/TextArea/TextArea.test.tsx +23 -0
  493. package/src/TextArea/TextArea.tsx +27 -26
  494. package/src/TextInput/TextInput.doc.mjs +21 -0
  495. package/src/TextInput/TextInput.test.tsx +150 -0
  496. package/src/TextInput/TextInput.tsx +28 -25
  497. package/src/Thumbnail/Thumbnail.doc.mjs +16 -16
  498. package/src/Thumbnail/Thumbnail.test.tsx +82 -21
  499. package/src/Thumbnail/Thumbnail.tsx +140 -67
  500. package/src/Thumbnail/thumbnail.markers.stylex.ts +12 -0
  501. package/src/TimeInput/TimeInput.doc.mjs +21 -0
  502. package/src/TimeInput/TimeInput.test.tsx +23 -0
  503. package/src/TimeInput/TimeInput.tsx +24 -25
  504. package/src/Timestamp/Timestamp.doc.mjs +4 -4
  505. package/src/Timestamp/Timestamp.test.tsx +32 -0
  506. package/src/Timestamp/Timestamp.tsx +28 -8
  507. package/src/Toast/useToast.tsx +7 -8
  508. package/src/ToggleButton/ToggleButtonGroup.tsx +1 -1
  509. package/src/Token/Token.test.tsx +21 -15
  510. package/src/Token/Token.tsx +31 -14
  511. package/src/Token/index.ts +1 -1
  512. package/src/Tokenizer/Tokenizer.doc.mjs +37 -1
  513. package/src/Tokenizer/Tokenizer.test.tsx +69 -0
  514. package/src/Tokenizer/Tokenizer.tsx +14 -2
  515. package/src/Tooltip/Tooltip.test.tsx +46 -0
  516. package/src/Tooltip/useTooltip.tsx +20 -0
  517. package/src/TopNav/TopNav.test.tsx +45 -0
  518. package/src/TopNav/TopNavMegaMenuFeaturedCard.doc.mjs +3 -3
  519. package/src/TopNav/TopNavMegaMenuFeaturedCard.tsx +19 -2
  520. package/src/TreeList/TreeList.doc.mjs +28 -0
  521. package/src/TreeList/TreeList.test.tsx +272 -0
  522. package/src/TreeList/TreeList.tsx +23 -2
  523. package/src/TreeList/TreeListBranches.tsx +24 -8
  524. package/src/TreeList/TreeListItem.tsx +84 -22
  525. package/src/TreeList/TreeListTypes.ts +27 -1
  526. package/src/TreeList/index.ts +2 -2
  527. package/src/Typeahead/BaseTypeahead.tsx +30 -15
  528. package/src/Typeahead/Typeahead.doc.mjs +13 -0
  529. package/src/Typeahead/Typeahead.test.tsx +50 -0
  530. package/src/Typeahead/Typeahead.tsx +11 -1
  531. package/src/Typeahead/TypeaheadItem.tsx +2 -1
  532. package/src/__tests__/inputWidthContract.test.tsx +62 -0
  533. package/src/doc-mjs.d.ts +19 -0
  534. package/src/docs-types.ts +5 -0
  535. package/src/hooks/index.ts +8 -0
  536. package/src/hooks/isRtlElement.ts +27 -0
  537. package/src/hooks/useDevWarning.test.tsx +45 -0
  538. package/src/hooks/useDevWarning.ts +54 -0
  539. package/src/hooks/useGridFocus.doc.mjs +3 -3
  540. package/src/hooks/useGridFocus.test.tsx +41 -0
  541. package/src/hooks/useGridFocus.ts +21 -10
  542. package/src/hooks/useInputStatusIcon.test.tsx +162 -0
  543. package/src/hooks/useInputStatusIcon.tsx +224 -0
  544. package/src/hooks/useListFocus.doc.mjs +25 -3
  545. package/src/hooks/useListFocus.test.tsx +153 -1
  546. package/src/hooks/useListFocus.ts +102 -9
  547. package/src/hooks/useOverflow.ts +8 -11
  548. package/src/i18n/InternationalizationContext.ts +4 -0
  549. package/src/i18n/InternationalizationProvider.doc.mjs +99 -2
  550. package/src/i18n/InternationalizationProvider.tsx +12 -2
  551. package/src/i18n/__tests__/getLocaleDirection.test.ts +40 -0
  552. package/src/i18n/__tests__/useDirection.test.tsx +66 -0
  553. package/src/i18n/getLocaleDirection.ts +29 -0
  554. package/src/i18n/index.ts +6 -0
  555. package/src/i18n/resolve.ts +9 -21
  556. package/src/i18n/useDirection.ts +29 -0
  557. package/src/reset.css +0 -26
  558. package/src/reset.test.ts +60 -0
  559. package/src/theme/Theme.tsx +11 -14
  560. package/src/theme/derivedVarRegistry.test.ts +1 -0
  561. package/src/theme/derivedVarRegistry.ts +6 -0
  562. package/src/theme/generateThemeRules.test.ts +42 -0
  563. package/src/theme/hct.ts +1 -1
  564. package/src/theme/syntax/defineSyntaxTheme.ts +5 -6
  565. package/src/utils/devWarning.test.ts +56 -0
  566. package/src/utils/devWarning.ts +102 -0
  567. package/src/utils/index.ts +8 -0
  568. package/src/utils/plainDate.test.ts +46 -6
  569. package/src/utils/plainDate.ts +69 -3
  570. package/src/utils/rtlStyles.ts +27 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,105 @@
1
1
  # @xds/core
2
2
 
3
+ # 0.1.9
4
+
5
+ #### New Features
6
+
7
+ - Avatar: add a `tooltip?: string | boolean` prop for a name-on-hover tooltip. Omitting it (or `true`) shows the avatar's `name` on hover and keyboard focus; a string shows that text instead (no need to wrap in `Tooltip`); `false` disables it. Avatar owns the tooltip via the existing Tooltip hook, so there's no extra wrapper DOM. Because this adds a default tooltip to every existing named Avatar, set `tooltip={false}` when you supply your own `Tooltip`/`HoverCard` overlay. The root `aria-label` (`alt || name`) is unchanged; the default name tooltip is visual-only (no `aria-describedby` double-announce), while a custom string tooltip is exposed as a description. Decorative avatars (no `name`/`alt`) get no tooltip. (#4164)
8
+ - BreadcrumbItem gains a `menu` prop that turns a crumb into a menu trigger for switching between sibling destinations. It accepts the same item API as DropdownMenu/MoreMenu/ContextMenu (a `DropdownMenuOption[]` array or composed item children), so existing menu-item definitions drop into a breadcrumb with no rewrite. The item components are also re-exported under `Breadcrumb*` aliases.
9
+ - Calendar: make the today/selected day-cell ring precisely themeable. The day cell now reflects a compound `marker` state (`today-only` / `today-in-range`) that maps 1:1 to the treatment actually drawn, so `defineTheme({components: {'calendar-day': {'marker:today-only': {...}}}})` targets exactly those states without over-matching or needing a `:not()` exclusion. Default rendering is unchanged.
10
+ - Calendar: add a dedicated `astryx-calendar-nav` theme target for the prev/next month-nav buttons, so consumers can theme the nav controls (color, radius, per-direction, disabled edge) without reaching every Button via the global `astryx-button` handle. Reflects `nav` (prev/next) and the `disabled` state as data attributes.
11
+ - ChatComposer: make custom inputs first-class. `useChatComposerContext()` and its types are now public, so any input in the `input` slot can read `value`/`onChange`/`onSubmit`/`canSend`/`placeholder`/`isDisabled` and drive the shell's send button. Inputs can register a focus control on `inputControlRef` so click-to-focus works for any input shape (not just `contenteditable`/`textarea`); the shell keeps a DOM-query fallback for uninstrumented inputs.
12
+ - ChatComposerInput: add an `onKeyDown` seam so consumers can host platform- or app-specific key handling — e.g. `preventDefault()` Enter to insert a newline on a touch keyboard, or submit on Cmd/Ctrl+Enter. Enter also no longer submits mid-IME-composition.
13
+ - CommandPalette: add a dedicated `astryx-command-palette-group-heading` theme target on the group heading, so consumers can theme just the heading (e.g. its padding or typography) via `defineTheme` instead of a fragile structural selector. The group root keeps its own `astryx-command-palette-group` target.
14
+ - DateInput gains a `format` prop for the committed date value, reusing Timestamp's `format` vocabulary so the same literal renders the same date shape in both components. Named values are `date_long` (the default, "March 21, 2026"), `date` ("Mar 21, 2026"), `date_weekday` ("Wed, Mar 21, 2026"), and `system_date` ("2026-03-21"); a `(value) => string` function is also accepted for custom output. The `date_long` default is byte-identical to DateInput's previous long-month rendering, so existing usage is unchanged. This also extends Timestamp with two new shared members, `date_long` and `date_weekday`, giving the two components full value parity on the date-only formats. Formatting applies only to the committed value, never to text being typed.
15
+ - Add an `elevation` prop to configurable surfaces — Card, ClickableCard, SelectableCard, Button, IconButton, ButtonGroup, and Banner take the full `'none' | 'low' | 'med' | 'high'` scale; ChatComposer takes `'none' | 'low'`. Defaults preserve today's appearance (`none` everywhere except ChatComposer's `low`), so nothing changes unless you opt in. (#4146)
16
+ - OverflowList: add `maxVisibleItems` to cap the number of visible items (the ceiling partner to `minVisibleItems`) and `maxRows` for bounded multi-row wrapping — items wrap onto up to N rows, then collapse into the overflow indicator. Both props are optional and default to off, so single-line behavior is unchanged. See #4176.
17
+ - Add `useTableRowStatus`, a plugin that prepends a narrow column
18
+ signaling per-row status.
19
+ - Thumbnail: add `showRemoveOn` prop — `'hover'` (default) reveals the remove button on hover or keyboard focus and keeps it visible on touch; `'always'` shows it at rest.
20
+ - Table tree: add an optional expand-all/collapse-all header control (#4142)
21
+ `useTableTreeState` now returns an aggregate `isAllExpanded` state (`true` / `false` / `'indeterminate'`) and threads `expandAll` / `collapseAll` into `treeConfig`. `useTableTreeData` gains a `hasExpandAllControl` prop: when set, it renders an expand-all/collapse-all toggle in the tree column header, wired to that state, so consumers no longer need to hand-roll external buttons. Flat data stays a full no-op. This is the first affordance folded in from `useTableRowExpansion` as part of converging the two tree plugins.
22
+ - TreeList: add a dedicated `astryx-tree-list-chevron` theme target for the expand/collapse toggle, so consumers can theme the chevron (color, per open/closed state) via `defineTheme` instead of reaching it through the functional `[data-tree-toggle]` attribute. Reflects the open/closed state as a `data-state` attribute (`expanded`/`collapsed`); the functional `data-tree-toggle` hook is unchanged.
23
+ - TreeList: add a stable `astryx-tree-list-guide` theme target on the hierarchy guide (connector) line elements, so consumers can recolor or hide the guides through `defineTheme` (e.g. `backgroundColor`, or `display: 'none'` to hide them) instead of hiding the built-in connectors and reimplementing them with unlayered CSS.
24
+ - TreeList: add a dedicated `astryx-tree-list-item-label` theme target on the item's label text, so consumers can theme just the label (e.g. bold the selected item's label) via `defineTheme` instead of a fragile `button:not([data-tree-toggle]) > span` structural selector. Reflects the row's `selected` state as a `data-selected` attribute on the label.
25
+
26
+ #### Fixes
27
+
28
+ - AvatarStatusDot: pair each variant with a distinct built-in shape — success stays a filled dot, neutral renders as a ring, error gets a minus bar — so status no longer relies on colour alone (WCAG 2.1 SC 1.4.1, #4143). A rendered `icon` replaces the shape glyph at sizes where icons fit; themes can target the new stable `astryx-avatar-status-dot-glyph` class and its `data-shape` attribute — a stroked inline `<svg>` painted from the dot's `currentColor`.
29
+ - Button: link-rendered buttons (`href`) now expose `aria-busy` while loading, matching the `<button>` branch. Previously an interruptible loading link showed the spinner and announced "Loading" but carried no machine-readable busy state.
30
+ - Calendar only marks in-month date cells as today, preventing duplicate today indicators in multi-month views.
31
+ - Carousel: slides now expose APG slide semantics (role=group, aria-roledescription="slide", "Slide N of M" labels) instead of anonymous divs.
32
+ - Honor `prefers-reduced-motion` in ChatToolCalls (chevron rotation, expand/collapse), ChatLayoutScrollButton (pill show/hide), and ChatDictationButton (equalizer bars).
33
+ - Chat/useChatStreamScroll: the scroll-follow spring now respects `prefers-reduced-motion` — locked following, `scrollToBottom()`, and `lock()` fall back to the existing instant jump, so the transcript still tracks the bottom without animated travel. Follow-up promised in #3800.
34
+ - Chat: the composer drawer toggle now references its disclosed content via aria-controls, so assistive tech can navigate from the toggle to the drawer.
35
+ - ChatSendButton now forwards `className`, `style`, and pass-through attributes (`data-*`, `aria-*`, and other rest props) to the rendered button. Previously these were silently dropped. (#4190)
36
+ - Chat: tool-call error details are now exposed to screen readers and keyboard users instead of living only in a hover-only title attribute.
37
+ - CheckboxInput: the indeterminate mark now uses the `--radius-full` token instead of a hardcoded radius, for token consistency. No visual change.
38
+ - CheckboxList: items with rich (non-string) labels can now provide an accessibleLabel so their checkbox no longer announces as the literal "Checkbox".
39
+ - CodeBlock: collapsed code regions are now inert, so keyboard focus can no longer land on the invisible scroll container while collapsed.
40
+ - CommandPalette: forward BaseProps pass-through attributes (className, style, xstyle, data-_, aria-_) to the underlying Dialog. Previously these were silently dropped.
41
+ - CommandPalette: the search input (role=combobox) now has an accessible name by default, from the new label prop or the visible placeholder. Previously screen readers announced a nameless combobox.
42
+ - DateTimeInput: ArrowDown (and Alt+ArrowDown) in the date field now opens the calendar popover from the keyboard, matching DateInput and the advertised combobox pattern.
43
+ - Dialog: modals are now automatically labelled by their DialogHeader title via aria-labelledby, matching AlertDialog. Unnamed open dialogs warn in development.
44
+ - Dialog: the entry animation is disabled under prefers-reduced-motion, matching the Layer animation guards.
45
+ - Fix Divider rest-prop spread order so consumer-passed HTML attributes cannot overwrite the component's `role="separator"` or `aria-orientation`.
46
+ - FieldLabel now forwards className, style, xstyle, and pass-through attributes (data-_, aria-_, event handlers) to the rendered element. Previously these were accepted by the type but silently dropped.
47
+ - Field/FieldStatus: status and error messages are now announced through persistent live regions, so they are reliably read by screen readers regardless of when they appear.
48
+ - FileInput: the trigger's accessible name now includes the selected filenames, so screen-reader users can review what is attached when refocusing the control.
49
+ - Prevent PowerSearch edit popover from closing when selecting multi-select options via Enter (#4245)
50
+ - Selector/MultiSelector: PageUp/PageDown now jump the active option to the first/last match while searching, complementing Home/End which stay on text-caret movement.
51
+ - HoverCard: popups now expose a named dialog when the new label prop is set, and honest group semantics otherwise. Previously every hover card announced as an unnamed dialog.
52
+ - Item: aria-selected is now emitted only when the item's role permits it (option, tab, treeitem, grid cells), removing invalid ARIA from plain list items.
53
+ - MobileNav: the toggle button now exposes `aria-expanded` and references the nav drawer via `aria-controls`, so screen-reader users can tell whether the drawer is open and what the button controls. (#3721)
54
+ - MultiSelector: searching within the options popover now announces the number of matching results ("3 results" / "No results found") to screen readers, mirroring Selector and Typeahead. Previously filtering happened silently.
55
+ - SideNav/TopNav: collapsed heading popovers no longer wrap their menus in a modal dialog, and the heading button is no longer an invalid child of the menu.
56
+ - Slider now clamps controlled values to its minimum and maximum before positioning the thumb and exposing ARIA values.
57
+ - Slider: required sliders now convey the required state to screen readers through the thumb's accessible description (aria-required is invalid on the slider role).
58
+ - Make the CLI's `.mjs` sources fully strict-typecheckable (checkJs + JSDoc)
59
+ Annotated the entire CLI package so `tsconfig.strict.json` (full `strict` `checkJs` over `src`, `bin`, `scripts`, `docs`, and the emitted `templates`) reports zero errors — down from 1717. Fixes are JSDoc-only: no runtime logic changed, `.mjs` stays `.mjs`. Strict checking also surfaced and corrected several type-contract drifts: the `upgrade.run` response type (declared a `depsUpdated` field the command never emits, and omitted the real `integrations`/`filesChanged`/`transformsApplied`/`errors`), registered the emitted `theme.list`/`theme.add`/`layout.*` response types in the `--json` envelope union, and added `category?` to `ReferenceSection` in core's docs types (reference docs already emit it).
60
+ - Table: the selection plugin accepts getRowLabel so row checkboxes announce which row they select, instead of an undifferentiated "Select row".
61
+ - Text: an explicit `size` now overrides the font-size of a themed `type`. The `size` class lived in a lower cascade layer (`astryx-base`) than a theme's per-type font-size rule (`astryx-theme`), so `<Text type="supporting" size="xsm">` silently kept the type's size. Themes now re-emit the size classes in the theme layer so `size` wins as documented.
62
+ - Thumbnail: replace the hover box-shadow on interactive tiles with the same `::after` overlay treatment ClickableCard and SelectableCard use. All three now tint on hover with `--color-overlay-hover` (and `--color-overlay-pressed` on press), so interactive feedback is consistent across the card family.
63
+ - Thumbnail/TopNavMegaMenuFeaturedCard: images without alt text are now explicitly decorative instead of silently empty-alt, matching Avatar's handling.
64
+ - Thumbnail: the overlaid remove button now uses a fixed `--color-overlay` scrim with an `--color-on-dark` icon instead of adapting to the image's luminance, so it has reliable contrast on any image.
65
+ - Tokenizer: adding and removing tokens (including Backspace on an empty input) is now announced to screen readers. Previously tokens appeared and disappeared silently.
66
+ - TopNav: TopNavMegaMenu triggers now expose aria-controls, and the panel is a labeled group instead of an invalid modal-dialog-wrapped menu.
67
+ - TopNav: TopNavMenu popups now expose proper menu semantics (no modal dialog wrapper) with the full APG keyboard pattern (roving tabindex, arrow keys, typeahead).
68
+
69
+ #### Documentation
70
+
71
+ - docs(Tokenizer, PowerSearch): document and test the existing startIcon prop
72
+ Both components have shipped a working `startIcon?: ReactNode | IconType` prop for a while (`PowerSearch` forwards it verbatim to the internal `Tokenizer`, and it's already exercised in Storybook), but neither's `.doc.mjs` documented it and neither had test coverage — so it was invisible to `astryx component <Name> --dense`, the docsite props table, and anyone (human or AI) relying on those as the source of truth. No behavior change; adds the missing props-table entries (en/zh/dense) and colocated tests confirming the icon renders and forwards correctly.
73
+
74
+ #### Other Changes
75
+
76
+ - Compact per-row status signal (error, warning, unread, etc.) without a
77
+ dedicated status column: a colored status dot by default, or an icon when provided.
78
+ - `getStatus(item)` maps a row to `{color, icon?, label?}`, or `null` for no
79
+ indicator. `color` accepts a semantic status name (`success`/`error`/`warning`/`accent`/`red`/`green`/etc.) mapped to a theme token, or a raw CSS color as an escape hatch.
80
+ - `icon` renders the status as a shape signifier instead of the dot, which is
81
+ more accessible than color alone when multiple statuses coexist. `label` supplies the accessible name.
82
+ - Memoize `getStatus` with `useCallback` for a stable plugin identity.
83
+
84
+ #### Contributors
85
+
86
+ Thanks to everyone who contributed to this release:
87
+
88
+ - @AKnassa
89
+ - @bhamodi
90
+ - @cixzhang
91
+ - @ejc3
92
+ - @freddymeta
93
+ - @HelloOjasMutreja
94
+ - @humbertovirtudes
95
+ - @josephfarina
96
+ - @kentonquatman
97
+ - @Kevinjohn
98
+ - @saadpocalypse
99
+ - @yyq1025
100
+
101
+ ---
102
+
3
103
  # 0.1.8
4
104
 
5
105
  #### Breaking Changes
@@ -1,6 +1,7 @@
1
1
  /**
2
2
  * @file Avatar.tsx
3
- * @input Uses React, HTMLAttributes, ReactNode, useState
3
+ * @input Uses React, HTMLAttributes, ReactNode, useState; useTooltip
4
+ * (Tooltip hook) for the optional name-on-hover tooltip; useTranslator (i18n)
4
5
  * @output Exports Avatar component, AvatarProps, AvatarSize types
5
6
  * @position Core implementation; consumed by index.ts
6
7
  *
@@ -9,15 +10,18 @@
9
10
  * - /packages/core/src/Avatar/index.ts (exports if types change)
10
11
  * - /apps/storybook/stories/Avatar.stories.tsx (storybook stories)
11
12
  * - /packages/cli/templates/blocks/components/Avatar/ (showcase blocks)
13
+ *
14
+ * Last synced props: alt, fallbackSrc, name, size, src, status, href, as, target, rel, onClick
12
15
  */
13
16
  import { type ReactNode } from 'react';
14
17
  import type { BaseProps } from '../BaseProps';
18
+ import type { LinkComponentType } from '../Link/types';
15
19
  /**
16
20
  * Named size options.
17
21
  *
18
22
  * Avatar uses the same abbreviated scale as Icon (`xsm`/`sm`/`md`/`lg`/`xl`),
19
23
  * but the values are larger because avatars align with media rather than
20
- * glyphs. The tiers match EPS's avatar sizes.
24
+ * glyphs. The tiers follow the standard avatar size scale.
21
25
  */
22
26
  type AvatarNamedSize = 'xsm' | 'sm' | 'md' | 'lg' | 'xl';
23
27
  /**
@@ -68,8 +72,55 @@ export interface AvatarProps extends BaseProps<HTMLDivElement> {
68
72
  /**
69
73
  * Content displayed in the corner of the avatar.
70
74
  * Typically used for status indicators or badges.
75
+ *
76
+ * When the element carries a string `label` prop (as `AvatarStatusDot`
77
+ * does), the label is composed into the avatar's accessible name
78
+ * (e.g. "Jane Doe, Online") so assistive tech can reach the status —
79
+ * the `role="img"` root prunes descendant semantics (WCAG 4.1.2).
71
80
  */
72
81
  status?: ReactNode;
82
+ /**
83
+ * Tooltip shown on hover (and keyboard focus).
84
+ * - omitted / `true`: show the avatar's `name`
85
+ * - a string: show that text instead
86
+ * - `false`: no tooltip
87
+ *
88
+ * The avatar owns this tooltip. It is NOT auto-disabled when wrapped in your
89
+ * own Tooltip/HoverCard — set `tooltip={false}` if you provide your own
90
+ * overlay. No tooltip is shown if `tooltip` is `true`/omitted and there is
91
+ * no (non-whitespace) `name`.
92
+ * @default true
93
+ */
94
+ tooltip?: string | boolean;
95
+ /**
96
+ * When provided, the avatar becomes an interactive link (`<a>` or custom
97
+ * link component) pointing at `href`. Follows the same element-swap rules as
98
+ * Button: `href` renders a link, otherwise `onClick` renders a
99
+ * `<button type="button">`, otherwise the avatar stays a static (non-focusable)
100
+ * element. An interactive avatar requires a meaningful accessible name via
101
+ * `alt` or `name`.
102
+ */
103
+ href?: string;
104
+ /**
105
+ * Custom link component to use when `href` is provided. Overrides the
106
+ * provider-level default set by LinkProvider. Useful for Next.js `<Link>` or
107
+ * other router-aware components. Only applies when `href` is provided.
108
+ */
109
+ as?: LinkComponentType;
110
+ /**
111
+ * HTML target attribute for the link. Only applies when `href` is provided.
112
+ */
113
+ target?: string;
114
+ /**
115
+ * HTML rel attribute for the link. Only applies when `href` is provided.
116
+ */
117
+ rel?: string;
118
+ /**
119
+ * Click handler. When provided without `href`, renders the avatar as a
120
+ * focusable `<button type="button">`. An interactive avatar requires a
121
+ * meaningful accessible name via `alt` or `name`.
122
+ */
123
+ onClick?: React.MouseEventHandler<HTMLElement>;
73
124
  }
74
125
  /**
75
126
  * Avatar component for displaying user profile pictures.
@@ -82,9 +133,13 @@ export interface AvatarProps extends BaseProps<HTMLDivElement> {
82
133
  * <Avatar src="/user.jpg" name="John Doe" />
83
134
  * <Avatar name="Jane Smith" size="xl" />
84
135
  * <Avatar src="/user.jpg" status={<OnlineIndicator />} />
136
+ * <Avatar name="jsmith" tooltip="Jane Smith, Staff Engineer" />
137
+ * <Avatar name="Jane" tooltip={false} />
138
+ * <Avatar src="/user.jpg" name="John Doe" href="/users/john" />
139
+ * <Avatar src="/user.jpg" name="John Doe" onClick={() => openProfile()} />
85
140
  * ```
86
141
  */
87
- export declare function Avatar({ alt, 'data-testid': testId, fallbackSrc, name, size, src, status, xstyle, className, style, ref, ...props }: AvatarProps): import("react").JSX.Element;
142
+ export declare function Avatar({ alt, 'data-testid': testId, fallbackSrc, name, size, src, status, tooltip, href, as, target, rel, onClick, xstyle, className, style, ref, ...props }: AvatarProps): import("react").JSX.Element;
88
143
  export declare namespace Avatar {
89
144
  var displayName: string;
90
145
  }
@@ -1 +1 @@
1
- {"version":3,"file":"Avatar.d.ts","sourceRoot":"","sources":["../../src/Avatar/Avatar.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAoB,KAAK,SAAS,EAAC,MAAM,OAAO,CAAC;AACxD,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAsC5C;;;;;;GAMG;AACH,KAAK,eAAe,GAAG,KAAK,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAEzD;;GAEG;AACH,KAAK,iBAAiB,GACpB,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;AAEzE;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG,eAAe,GAAG,iBAAiB,CAAC;AAE7D;;GAEG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CAgBpD;AAqFD,MAAM,WAAW,WAAY,SAAQ,SAAS,CAAC,cAAc,CAAC;IAC5D,wCAAwC;IACxC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAChC;;;OAGG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB;;OAEG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;;OAGG;IACH,MAAM,CAAC,EAAE,SAAS,CAAC;CACpB;AAsCD;;;;;;;;;;;;GAYG;AACH,wBAAgB,MAAM,CAAC,EACrB,GAAG,EACH,aAAa,EAAE,MAAM,EACrB,WAAW,EACX,IAAI,EACJ,IAAW,EACX,GAAG,EACH,MAAM,EACN,MAAM,EACN,SAAS,EACT,KAAK,EACL,GAAG,EACH,GAAG,KAAK,EACT,EAAE,WAAW,+BAwFb;yBArGe,MAAM"}
1
+ {"version":3,"file":"Avatar.d.ts","sourceRoot":"","sources":["../../src/Avatar/Avatar.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAoC,KAAK,SAAS,EAAC,MAAM,OAAO,CAAC;AACxE,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAc5C,OAAO,KAAK,EAAC,iBAAiB,EAAC,MAAM,eAAe,CAAC;AA4BrD;;;;;;GAMG;AACH,KAAK,eAAe,GAAG,KAAK,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;AAEzD;;GAEG;AACH,KAAK,iBAAiB,GACpB,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;AAEzE;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG,eAAe,GAAG,iBAAiB,CAAC;AAE7D;;GAEG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,UAAU,GAAG,MAAM,CAgBpD;AAiJD,MAAM,WAAW,WAAY,SAAQ,SAAS,CAAC,cAAc,CAAC;IAC5D,wCAAwC;IACxC,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAChC;;;OAGG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;OAGG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;OAIG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB;;OAEG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;;;;;;;OAQG;IACH,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAC3B;;;;;;;OAOG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,EAAE,CAAC,EAAE,iBAAiB,CAAC;IACvB;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB;;OAEG;IACH,GAAG,CAAC,EAAE,MAAM,CAAC;IACb;;;;OAIG;IACH,OAAO,CAAC,EAAE,KAAK,CAAC,iBAAiB,CAAC,WAAW,CAAC,CAAC;CAChD;AAwDD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,MAAM,CAAC,EACrB,GAAG,EACH,aAAa,EAAE,MAAM,EACrB,WAAW,EACX,IAAI,EACJ,IAAW,EACX,GAAG,EACH,MAAM,EACN,OAAc,EACd,IAAI,EACJ,EAAE,EACF,MAAM,EACN,GAAG,EACH,OAAO,EACP,MAAM,EACN,SAAS,EACT,KAAK,EACL,GAAG,EACH,GAAG,KAAK,EACT,EAAE,WAAW,+BAoPb;yBAvQe,MAAM"}
@@ -4,7 +4,8 @@
4
4
 
5
5
  /**
6
6
  * @file Avatar.tsx
7
- * @input Uses React, HTMLAttributes, ReactNode, useState
7
+ * @input Uses React, HTMLAttributes, ReactNode, useState; useTooltip
8
+ * (Tooltip hook) for the optional name-on-hover tooltip; useTranslator (i18n)
8
9
  * @output Exports Avatar component, AvatarProps, AvatarSize types
9
10
  * @position Core implementation; consumed by index.ts
10
11
  *
@@ -13,15 +14,20 @@
13
14
  * - /packages/core/src/Avatar/index.ts (exports if types change)
14
15
  * - /apps/storybook/stories/Avatar.stories.tsx (storybook stories)
15
16
  * - /packages/cli/templates/blocks/components/Avatar/ (showcase blocks)
17
+ *
18
+ * Last synced props: alt, fallbackSrc, name, size, src, status, href, as, target, rel, onClick
16
19
  */
17
- import { useMemo, useState } from 'react';
20
+ import { isValidElement, useMemo, useState } from 'react';
18
21
  import * as stylex from '@stylexjs/stylex';
19
22
  import "../theme/tokens.stylex.js";
20
23
  import { colorVars, typographyVars, fontWeightVars, radiusVars } from "../theme/tokens.stylex.js";
21
24
  import { AvatarSizeContext } from "./AvatarSizeContext.js";
22
25
  import { useAvatarGroup } from "../AvatarGroup/AvatarGroupContext.js";
23
- import { mergeProps } from "../utils/index.js";
26
+ import { mergeProps, mergeRefs } from "../utils/index.js";
24
27
  import { themeProps } from "../utils/themeProps.js";
28
+ import { useTooltip } from "../Tooltip/useTooltip.js";
29
+ import { useLinkComponent } from "../Link/useLinkComponent.js";
30
+ import { useTranslator } from "../i18n/index.js";
25
31
 
26
32
  /**
27
33
  * The offset ratio for positioning elements on a circle's edge at 45°.
@@ -35,7 +41,7 @@ import { themeProps } from "../utils/themeProps.js";
35
41
  *
36
42
  * This constant represents that ratio: (1 - 1/√2) / 2 ≈ 0.146
37
43
  */
38
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
44
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
39
45
  const CIRCLE_EDGE_OFFSET_RATIO = (1 - 1 / Math.SQRT2) / 2;
40
46
 
41
47
  /**
@@ -54,7 +60,7 @@ const INITIALS_FONT_SIZE_RATIO = 0.4;
54
60
  *
55
61
  * Avatar uses the same abbreviated scale as Icon (`xsm`/`sm`/`md`/`lg`/`xl`),
56
62
  * but the values are larger because avatars align with media rather than
57
- * glyphs. The tiers match EPS's avatar sizes.
63
+ * glyphs. The tiers follow the standard avatar size scale.
58
64
  */
59
65
 
60
66
  /**
@@ -95,6 +101,7 @@ const styles = {
95
101
  kVAEAm: "x1n2onr6",
96
102
  k1xSpc: "x3nfvp2",
97
103
  kmuXW: "x2lah0s",
104
+ kaIpWk: "xjspbzw",
98
105
  $$css: true
99
106
  },
100
107
  content: {
@@ -112,16 +119,39 @@ const styles = {
112
119
  kjj79g: "xl56j7k",
113
120
  kzqmXN: "xh8yej3",
114
121
  kZKoxP: "x5yr21d",
115
- kWkggS: "x17x4s8c",
116
- kMwMTN: "xv1l7n4",
122
+ kWkggS: "xelv01g",
123
+ kMwMTN: "xicfil",
117
124
  kMv6JI: "x9ynric",
118
- k63SB2: "x1e4wzip",
125
+ k63SB2: "xi08x9w",
119
126
  kP9fke: "xtvhhri",
120
127
  $$css: true
121
128
  },
122
129
  status: {
123
130
  kVAEAm: "x10l6tqk",
124
131
  $$css: true
132
+ },
133
+ focusable: {
134
+ kI3sdo: "x17nn4n9",
135
+ kInvED: "x1wfwxd8 x7s97pk",
136
+ $$css: true
137
+ },
138
+ interactive: {
139
+ kysU6D: "xjyslct",
140
+ kmVPX3: "x1717udv",
141
+ kogj98: "x1ghz6dp",
142
+ kMzoRj: "xc342km",
143
+ ksu8eU: "xng3xce",
144
+ kWkggS: "xjbqb8w",
145
+ kMwMTN: "x1heor9g",
146
+ kVVagm: "xln7xf2",
147
+ kybGjl: "x1hl2dhg",
148
+ kkrTdU: "x1ypdohk",
149
+ kaIpWk: "xjspbzw",
150
+ kMeerF: "x1k57tk5 x784prv",
151
+ k3XXqK: "x1t137rt x9v5kkp",
152
+ kjBf7l: "xzunyri",
153
+ kInvED: "x1wfwxd8 x7s97pk",
154
+ $$css: true
125
155
  }
126
156
  };
127
157
 
@@ -148,7 +178,7 @@ const dynamicStyles = {
148
178
  "--x-height": (val => typeof val === "number" ? val + "px" : val != null ? val : undefined)(size)
149
179
  }],
150
180
  fontSize: size => [_temp, {
151
- "--x-fontSize": (val => typeof val === "number" ? val + "px" : val != null ? val : undefined)(size * INITIALS_FONT_SIZE_RATIO)
181
+ "--x-fontSize": (val => typeof val === "number" ? val + "px" : val != null ? val : undefined)(`var(--_avatar-fallback-font-size, ${size * INITIALS_FONT_SIZE_RATIO}px)`)
152
182
  }],
153
183
  statusPosition: size => [_temp2, {
154
184
  "--x-bottom": (val => typeof val === "number" ? val + "px" : val != null ? val : undefined)(size * CIRCLE_EDGE_OFFSET_RATIO),
@@ -200,6 +230,26 @@ function getInitials(name) {
200
230
  return (words[0].charAt(0) + words[words.length - 1].charAt(0)).toUpperCase();
201
231
  }
202
232
 
233
+ /**
234
+ * Reads the accessible status label off the `status` element, when it
235
+ * exposes one. `AvatarStatusDot`'s `label` prop is the canonical source,
236
+ * but any custom status element with a string `label` prop participates.
237
+ *
238
+ * The avatar root is `role="img"`, which prunes ALL descendant semantics
239
+ * from the accessibility tree — a label inside the status subtree is never
240
+ * announced on its own. Composing it into the avatar's own accessible name
241
+ * is the only way the status reaches assistive tech (WCAG 4.1.2).
242
+ */
243
+ function getStatusLabel(status) {
244
+ if (! /*#__PURE__*/isValidElement(status)) {
245
+ return undefined;
246
+ }
247
+ const {
248
+ label
249
+ } = status.props;
250
+ return typeof label === 'string' && label !== '' ? label : undefined;
251
+ }
252
+
203
253
  /**
204
254
  * Default person icon SVG for when no image or name is provided
205
255
  */
@@ -229,6 +279,10 @@ function DefaultIcon({
229
279
  * <Avatar src="/user.jpg" name="John Doe" />
230
280
  * <Avatar name="Jane Smith" size="xl" />
231
281
  * <Avatar src="/user.jpg" status={<OnlineIndicator />} />
282
+ * <Avatar name="jsmith" tooltip="Jane Smith, Staff Engineer" />
283
+ * <Avatar name="Jane" tooltip={false} />
284
+ * <Avatar src="/user.jpg" name="John Doe" href="/users/john" />
285
+ * <Avatar src="/user.jpg" name="John Doe" onClick={() => openProfile()} />
232
286
  * ```
233
287
  */
234
288
  export function Avatar({
@@ -239,6 +293,12 @@ export function Avatar({
239
293
  size = 'md',
240
294
  src,
241
295
  status,
296
+ tooltip = true,
297
+ href,
298
+ as,
299
+ target,
300
+ rel,
301
+ onClick,
242
302
  xstyle,
243
303
  className,
244
304
  style,
@@ -254,58 +314,185 @@ export function Avatar({
254
314
  const showInitials = !showImage && !showFallbackImage && name;
255
315
  const showIcon = !showImage && !showFallbackImage && !name;
256
316
 
257
- // A meaningful accessible name comes from `alt` or `name`. With neither, the
258
- // avatar is decorative — expose it as `presentation`/`aria-hidden` rather than
259
- // announcing a meaningless generic "Avatar" (obs-9).
260
- const accessibleName = alt || name;
317
+ // A meaningful accessible name comes from `alt`/`name`, composed with the
318
+ // status element's `label` when one is present ("Jane Doe, Online") — the
319
+ // `role="img"` root prunes descendant semantics, so surfacing the label in
320
+ // the avatar's own name is the only way assistive tech can reach the
321
+ // status (WCAG 4.1.2). A labelled status alone is also meaningful. With
322
+ // neither a name nor a labelled status, the avatar is decorative — expose
323
+ // it as `presentation`/`aria-hidden` rather than announcing a meaningless
324
+ // generic "Avatar" (obs-9).
325
+ const t = useTranslator();
326
+ const nameLabel = alt || name;
327
+ const statusLabel = getStatusLabel(status);
328
+ const accessibleName = nameLabel && statusLabel ? t('@astryx.avatar.nameWithStatus', {
329
+ name: nameLabel,
330
+ status: statusLabel
331
+ }) : nameLabel || statusLabel;
261
332
  const isDecorative = !accessibleName;
262
333
  const avatarGroup = useAvatarGroup();
263
334
  const resolvedSize = avatarGroup?.size ?? size;
264
335
  const numericSize = useMemo(() => resolveSize(resolvedSize), [resolvedSize]);
265
- return /*#__PURE__*/_jsx(AvatarSizeContext, {
266
- value: numericSize,
267
- children: /*#__PURE__*/_jsxs("div", {
336
+
337
+ // Resolve the tooltip content:
338
+ // - `false` → no tooltip
339
+ // - a string → that string
340
+ // - `true` / omitted → the `name` (a whitespace-only name yields nothing)
341
+ // Note: the *visible* tooltip prefers `name` (not `alt`); the *accessible
342
+ // name* on the root still uses `alt || name` above, independent of this.
343
+ const tooltipContent = tooltip === false ? undefined : typeof tooltip === 'string' ? tooltip : name;
344
+ const trimmedTooltip = tooltipContent?.trim();
345
+ const showTooltip = trimmedTooltip != null && trimmedTooltip !== '';
346
+ // Whether the tooltip text is a consumer-authored override (a custom string)
347
+ // rather than the default name. A custom description is worth wiring to
348
+ // `aria-describedby` (it adds information, matching Button); the default name
349
+ // tooltip is visual-only — its text duplicates the root `aria-label`, so
350
+ // describing it too would double-announce the same name (OQ-4).
351
+ const isCustomTooltip = typeof tooltip === 'string';
352
+
353
+ // Own the name tooltip via the Tooltip hook (the Button pattern), which
354
+ // returns `describedBy` as a value we choose whether to apply — the only way
355
+ // to satisfy the per-case aria-describedby rule (default name: none; custom
356
+ // string: describe) without editing Tooltip. `focusTrigger: 'auto'` shows the
357
+ // tooltip on keyboard focus once the root is focusable (natively for the
358
+ // interactive <a>/<button>, or via an explicit tab stop on the static div).
359
+ const tooltipHook = useTooltip({
360
+ placement: 'above',
361
+ isEnabled: showTooltip
362
+ });
363
+ // The tooltip ref attaches to whichever root element renders (static or
364
+ // interactive), so the tooltip works for link/button avatars too.
365
+ const rootRef = mergeRefs(ref, showTooltip ? tooltipHook.ref : undefined);
366
+ const describedByProp = showTooltip && isCustomTooltip ? {
367
+ 'aria-describedby': [props['aria-describedby'], tooltipHook.describedBy].filter(Boolean).join(' ') || undefined
368
+ } : null;
369
+
370
+ // Element-swap trichotomy, copied from Button: `href` renders a link,
371
+ // otherwise `onClick` renders a `<button>`, otherwise today's static element
372
+ // is unchanged (the non-breaking default).
373
+ const renderAsLink = href != null;
374
+ const renderAsButton = !renderAsLink && onClick != null;
375
+ const isInteractive = renderAsLink || renderAsButton;
376
+ const LinkComponent = useLinkComponent(as);
377
+
378
+ // An interactive control with no accessible name is an unacceptable control
379
+ // name. Warn in the same client-safe way sibling components do (Field,
380
+ // Timestamp, Popover) — a plain `console.warn`, never gated on `process.env`
381
+ // (which is not available on the client in this codebase).
382
+ if (isInteractive && !accessibleName) {
383
+ console.warn('Avatar: an interactive avatar (with `href` or `onClick`) needs a ' + 'meaningful accessible name. Pass `alt` or `name`.');
384
+ }
385
+
386
+ // The inner visuals are identical across the static and interactive variants.
387
+ const visualContent = /*#__PURE__*/_jsxs(_Fragment, {
388
+ children: [/*#__PURE__*/_jsxs("div", {
389
+ ...stylex.props(styles.content, dynamicStyles.size(numericSize)),
390
+ children: [showImage && /*#__PURE__*/_jsx("img", {
391
+ src: src,
392
+ alt: "",
393
+ onError: () => setErroredSrc(src),
394
+ ...{
395
+ className: "xh8yej3 x5yr21d xl1xv1r"
396
+ }
397
+ }), showFallbackImage && /*#__PURE__*/_jsx("img", {
398
+ src: fallbackSrc,
399
+ alt: "",
400
+ onError: () => setErroredFallbackSrc(fallbackSrc),
401
+ ...{
402
+ className: "xh8yej3 x5yr21d xl1xv1r"
403
+ }
404
+ }), showInitials && /*#__PURE__*/_jsx("div", {
405
+ ...stylex.props(styles.fallback, dynamicStyles.fontSize(numericSize)),
406
+ children: getInitials(name)
407
+ }), showIcon && /*#__PURE__*/_jsx("div", {
408
+ ...{
409
+ className: "x78zum5 x6s0dn4 xl56j7k xh8yej3 x5yr21d xelv01g xicfil x9ynric xi08x9w xtvhhri"
410
+ },
411
+ children: /*#__PURE__*/_jsx(DefaultIcon, {
412
+ size: numericSize
413
+ })
414
+ })]
415
+ }), status && /*#__PURE__*/_jsx("div", {
416
+ ...stylex.props(styles.status, dynamicStyles.statusPosition(numericSize)),
417
+ children: status
418
+ })]
419
+ });
420
+
421
+ // Shared StyleX + theme props for the root element in every variant. The
422
+ // group ring/overlap, the interactive focus-visible ring, and the
423
+ // tooltip tab-stop focus ring all live here so the interactive
424
+ // `<a>`/`<button>` and the static `<div>` carry the exact same box.
425
+ const rootStylexProps = mergeProps(themeProps('avatar', {
426
+ size: resolvedSize
427
+ }), stylex.props(styles.wrapper, isInteractive && styles.interactive, !isInteractive && showTooltip && !avatarGroup && styles.focusable, avatarGroup && groupStyles.ring, avatarGroup && groupStyles.overlap, avatarGroup && groupDynamicStyles.overlap(-avatarGroup.overlap), xstyle), className, style);
428
+ let rootElement;
429
+
430
+ // `props` is typed for the default `<div>` root (its event handlers are
431
+ // HTMLDivElement-typed). The interactive branches render an `<a>`/`<button>`,
432
+ // so the passthrough props are re-typed to the generic element here — the
433
+ // avatar's own handlers (onClick) are declared on HTMLElement and stay typed.
434
+ const interactivePassthrough = props;
435
+ if (renderAsLink) {
436
+ // The rendered link carries the `data-avatar-item` marker so AvatarGroup's
437
+ // roving focus (which selects on `[data-avatar-item]`, not a tag/role) picks
438
+ // it up while ignoring nested buttons in a custom status/badge slot.
439
+ rootElement = /*#__PURE__*/_jsx(LinkComponent, {
440
+ ...interactivePassthrough,
441
+ ...describedByProp,
442
+ ref: rootRef,
443
+ href: href,
444
+ target: target,
445
+ rel: rel,
446
+ "aria-label": accessibleName,
447
+ "data-avatar-item": "",
448
+ "data-testid": testId,
449
+ onClick: onClick,
450
+ ...rootStylexProps,
451
+ children: visualContent
452
+ });
453
+ } else if (renderAsButton) {
454
+ rootElement = /*#__PURE__*/_jsx("button", {
455
+ ...interactivePassthrough,
456
+ ...describedByProp,
457
+ ref: rootRef,
458
+ type: "button",
459
+ "aria-label": accessibleName,
460
+ "data-avatar-item": "",
461
+ "data-testid": testId,
462
+ onClick: onClick,
463
+ ...rootStylexProps,
464
+ children: visualContent
465
+ });
466
+ } else {
467
+ rootElement = /*#__PURE__*/_jsx("div", {
268
468
  ...props,
269
- ref: ref,
469
+ ref: rootRef,
270
470
  role: isDecorative ? 'presentation' : 'img',
271
471
  "aria-label": isDecorative ? undefined : accessibleName,
272
- "aria-hidden": isDecorative || undefined,
472
+ "aria-hidden": isDecorative || undefined
473
+ // The root is a div[role="img"], not natively focusable. When a name
474
+ // tooltip is active, add a tab stop so keyboard users can reveal it
475
+ // (WCAG 1.4.13 / 2.1.1) — matching Timestamp/Button. Suppressed inside
476
+ // an AvatarGroup, which owns a single roving tab stop for its members.
477
+ ,
478
+ tabIndex: showTooltip && !avatarGroup ? 0 : undefined,
273
479
  "data-testid": testId,
274
- ...mergeProps(themeProps('avatar', {
275
- size: resolvedSize
276
- }), stylex.props(styles.wrapper, avatarGroup && groupStyles.ring, avatarGroup && groupStyles.overlap, avatarGroup && groupDynamicStyles.overlap(-avatarGroup.overlap), xstyle), className, style),
277
- children: [/*#__PURE__*/_jsxs("div", {
278
- ...stylex.props(styles.content, dynamicStyles.size(numericSize)),
279
- children: [showImage && /*#__PURE__*/_jsx("img", {
280
- src: src,
281
- alt: "",
282
- onError: () => setErroredSrc(src),
283
- ...{
284
- className: "xh8yej3 x5yr21d xl1xv1r"
285
- }
286
- }), showFallbackImage && /*#__PURE__*/_jsx("img", {
287
- src: fallbackSrc,
288
- alt: "",
289
- onError: () => setErroredFallbackSrc(fallbackSrc),
290
- ...{
291
- className: "xh8yej3 x5yr21d xl1xv1r"
292
- }
293
- }), showInitials && /*#__PURE__*/_jsx("div", {
294
- ...stylex.props(styles.fallback, dynamicStyles.fontSize(numericSize)),
295
- children: getInitials(name)
296
- }), showIcon && /*#__PURE__*/_jsx("div", {
297
- ...{
298
- className: "x78zum5 x6s0dn4 xl56j7k xh8yej3 x5yr21d x17x4s8c xv1l7n4 x9ynric x1e4wzip xtvhhri"
299
- },
300
- children: /*#__PURE__*/_jsx(DefaultIcon, {
301
- size: numericSize
302
- })
303
- })]
304
- }), status && /*#__PURE__*/_jsx("div", {
305
- ...stylex.props(styles.status, dynamicStyles.statusPosition(numericSize)),
306
- children: status
307
- })]
308
- })
480
+ ...describedByProp,
481
+ ...rootStylexProps,
482
+ children: visualContent
483
+ });
484
+ }
485
+ const avatarElement = /*#__PURE__*/_jsx(AvatarSizeContext, {
486
+ value: numericSize,
487
+ children: rootElement
488
+ });
489
+
490
+ // Always return the same structure so the avatar keeps its position in the
491
+ // React tree regardless of the tooltip flag — toggling it must not remount
492
+ // the avatar subtree (and lose image-load state). The tooltip is a sibling
493
+ // (no wrapper DOM); the hook's ref is already on the root via `rootRef`.
494
+ return /*#__PURE__*/_jsxs(_Fragment, {
495
+ children: [avatarElement, showTooltip ? tooltipHook.renderTooltip(trimmedTooltip) : null]
309
496
  });
310
497
  }
311
498
  Avatar.displayName = 'Avatar';
@@ -60,10 +60,12 @@ export interface AvatarStatusDotProps extends BaseProps<HTMLDivElement> {
60
60
  * Describes the meaning of the indicator for screen readers
61
61
  * (e.g. "Online", "Accepted", "John Doe is busy").
62
62
  *
63
- * Note: inside an Avatar the label is currently not announced — the
64
- * Avatar root is `role="img"`, which prunes descendant semantics.
65
- * Pass it anyway; composing status into the avatar's accessible name
66
- * is a planned Avatar-level fix.
63
+ * Note: inside an Avatar the dot sits in the avatar's `role="img"`
64
+ * subtree, where descendant semantics are pruned — the dot is never its
65
+ * own stop there. Instead, Avatar reads this `label` and composes it into
66
+ * its own accessible name (e.g. "Jane Doe, Online"), which is how the
67
+ * status reaches assistive tech (WCAG 4.1.2). Standalone dots (outside an
68
+ * Avatar) expose `role="img"` with this label directly.
67
69
  */
68
70
  label?: string;
69
71
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"AvatarStatusDot.d.ts","sourceRoot":"","sources":["../../src/Avatar/AvatarStatusDot.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,EAAM,KAAK,SAAS,EAAC,MAAM,OAAO,CAAC;AACjD,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAiD5C;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,WAAW,yBAAyB;IACxC,OAAO,EAAE,IAAI,CAAC;IACd,OAAO,EAAE,IAAI,CAAC;IACd,KAAK,EAAE,IAAI,CAAC;CACb;AAED;;GAEG;AACH,MAAM,MAAM,sBAAsB,GAAG,MAAM,yBAAyB,CAAC;AAErE,MAAM,WAAW,oBAAqB,SAAQ,SAAS,CAAC,cAAc,CAAC;IACrE,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAChC;;;;;;;;;;OAUG;IACH,OAAO,CAAC,EAAE,sBAAsB,CAAC;IACjC;;;;;;;;;OASG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;;;;;;;;;;;;;;;OAkBG;IACH,IAAI,CAAC,EAAE,SAAS,CAAC;CAClB;AA2JD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,eAAe,CAAC,EAC9B,GAAG,EACH,OAAmB,EACnB,KAAK,EACL,IAAI,EACJ,MAAM,EACN,SAAS,EACT,KAAK,EACL,GAAG,KAAK,EACT,EAAE,oBAAoB,qBAyCtB;yBAlDe,eAAe"}
1
+ {"version":3,"file":"AvatarStatusDot.d.ts","sourceRoot":"","sources":["../../src/Avatar/AvatarStatusDot.tsx"],"names":[],"mappings":"AAIA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,EAAM,KAAK,SAAS,EAAC,MAAM,OAAO,CAAC;AACjD,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,cAAc,CAAC;AAiD5C;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,WAAW,yBAAyB;IACxC,OAAO,EAAE,IAAI,CAAC;IACd,OAAO,EAAE,IAAI,CAAC;IACd,KAAK,EAAE,IAAI,CAAC;CACb;AAED;;GAEG;AACH,MAAM,MAAM,sBAAsB,GAAG,MAAM,yBAAyB,CAAC;AAErE,MAAM,WAAW,oBAAqB,SAAQ,SAAS,CAAC,cAAc,CAAC;IACrE,GAAG,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAChC;;;;;;;;;;OAUG;IACH,OAAO,CAAC,EAAE,sBAAsB,CAAC;IACjC;;;;;;;;;;;OAWG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;;;;;;;;;;;;;;;OAkBG;IACH,IAAI,CAAC,EAAE,SAAS,CAAC;CAClB;AA2JD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,eAAe,CAAC,EAC9B,GAAG,EACH,OAAmB,EACnB,KAAK,EACL,IAAI,EACJ,MAAM,EACN,SAAS,EACT,KAAK,EACL,GAAG,KAAK,EACT,EAAE,oBAAoB,qBAyCtB;yBAlDe,eAAe"}