@eocrm/design-system 0.0.0-stage → 0.6.17

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 (897) hide show
  1. package/AI-PRIMER.md +341 -0
  2. package/README.md +262 -2
  3. package/docs/components/Accordion.md +114 -0
  4. package/docs/components/AgentAvatar.md +58 -0
  5. package/docs/components/Alert.md +81 -0
  6. package/docs/components/AppLayout.md +70 -0
  7. package/docs/components/Avatar.md +49 -0
  8. package/docs/components/AvatarGroup.md +47 -0
  9. package/docs/components/Badge.md +60 -0
  10. package/docs/components/Banner.md +89 -0
  11. package/docs/components/BrandIcon.md +32 -0
  12. package/docs/components/Breadcrumb.md +72 -0
  13. package/docs/components/Button.md +107 -0
  14. package/docs/components/ButtonGroup.md +78 -0
  15. package/docs/components/Calendar.md +158 -0
  16. package/docs/components/Card.md +165 -0
  17. package/docs/components/CatalogPicker.md +83 -0
  18. package/docs/components/Chart.md +114 -0
  19. package/docs/components/ChatBubble.md +55 -0
  20. package/docs/components/ChatLauncher.md +97 -0
  21. package/docs/components/Checkbox.md +55 -0
  22. package/docs/components/CircularProgress.md +53 -0
  23. package/docs/components/Cluster.md +96 -0
  24. package/docs/components/Code.md +35 -0
  25. package/docs/components/CodeBlock.md +67 -0
  26. package/docs/components/ColorPicker.md +115 -0
  27. package/docs/components/ConfirmationPopover.md +70 -0
  28. package/docs/components/Constrain.md +39 -0
  29. package/docs/components/CurrencySelect.md +57 -0
  30. package/docs/components/CursorPagination.md +43 -0
  31. package/docs/components/DashboardCanvas.md +79 -0
  32. package/docs/components/DashboardWidget.md +131 -0
  33. package/docs/components/DataTable.md +88 -0
  34. package/docs/components/DatePicker.md +68 -0
  35. package/docs/components/DateRangePicker.md +71 -0
  36. package/docs/components/DateStrip.md +56 -0
  37. package/docs/components/DefinitionList.md +82 -0
  38. package/docs/components/Divider.md +57 -0
  39. package/docs/components/Dot.md +26 -0
  40. package/docs/components/Drawer.md +94 -0
  41. package/docs/components/DropdownMenu.md +299 -0
  42. package/docs/components/EmojiPicker.md +84 -0
  43. package/docs/components/EmptyState.md +55 -0
  44. package/docs/components/EntityChip.md +102 -0
  45. package/docs/components/ErrorState.md +72 -0
  46. package/docs/components/Field.md +91 -0
  47. package/docs/components/FileUpload.md +109 -0
  48. package/docs/components/FilterChip.md +88 -0
  49. package/docs/components/FlowCanvas.md +108 -0
  50. package/docs/components/FormRow.md +31 -0
  51. package/docs/components/FormSection.md +37 -0
  52. package/docs/components/Grid.md +103 -0
  53. package/docs/components/Highlight.md +75 -0
  54. package/docs/components/HighlightedText.md +50 -0
  55. package/docs/components/IconPicker.md +134 -0
  56. package/docs/components/IconTile.md +30 -0
  57. package/docs/components/Image.md +84 -0
  58. package/docs/components/ImageCrop.md +163 -0
  59. package/docs/components/Indent.md +31 -0
  60. package/docs/components/InlineDatePicker.md +58 -0
  61. package/docs/components/InlineDateRangePicker.md +57 -0
  62. package/docs/components/Input.md +54 -0
  63. package/docs/components/Kanban.md +122 -0
  64. package/docs/components/Kbd.md +41 -0
  65. package/docs/components/Lightbox.md +105 -0
  66. package/docs/components/Link.md +65 -0
  67. package/docs/components/LinkCard.md +41 -0
  68. package/docs/components/LiquidEditor.md +84 -0
  69. package/docs/components/List.md +68 -0
  70. package/docs/components/LiveRegion.md +29 -0
  71. package/docs/components/LocaleProvider.md +25 -0
  72. package/docs/components/Logo.md +41 -0
  73. package/docs/components/Masonry.md +48 -0
  74. package/docs/components/MediaTile.md +95 -0
  75. package/docs/components/Modal.md +107 -0
  76. package/docs/components/MoneyInput.md +62 -0
  77. package/docs/components/OptionsPicker.md +123 -0
  78. package/docs/components/OtpInput.md +65 -0
  79. package/docs/components/Page.md +35 -0
  80. package/docs/components/PageHeader.md +133 -0
  81. package/docs/components/Pagination.md +44 -0
  82. package/docs/components/Palette.md +32 -0
  83. package/docs/components/PasswordInput.md +45 -0
  84. package/docs/components/PasswordStrengthMeter.md +27 -0
  85. package/docs/components/PersonDisplay.md +153 -0
  86. package/docs/components/PhoneInput.md +54 -0
  87. package/docs/components/PillMenu.md +91 -0
  88. package/docs/components/Popover.md +127 -0
  89. package/docs/components/Progress.md +56 -0
  90. package/docs/components/QrCode.md +34 -0
  91. package/docs/components/Radio.md +37 -0
  92. package/docs/components/RadioGroup.md +56 -0
  93. package/docs/components/Rail.md +191 -0
  94. package/docs/components/RelativeDateInput.md +114 -0
  95. package/docs/components/RichText.md +44 -0
  96. package/docs/components/RichTextEditor.md +112 -0
  97. package/docs/components/Screen.md +37 -0
  98. package/docs/components/ScrollArea.md +39 -0
  99. package/docs/components/Select.md +131 -0
  100. package/docs/components/SettingRow.md +98 -0
  101. package/docs/components/Skeleton.md +68 -0
  102. package/docs/components/Slider.md +92 -0
  103. package/docs/components/SlotGrid.md +55 -0
  104. package/docs/components/SocialButton.md +31 -0
  105. package/docs/components/Sortable.md +127 -0
  106. package/docs/components/SortableGroup.md +52 -0
  107. package/docs/components/Sparkline.md +51 -0
  108. package/docs/components/Split.md +76 -0
  109. package/docs/components/Stack.md +59 -0
  110. package/docs/components/StagePath.md +66 -0
  111. package/docs/components/StatGroup.md +61 -0
  112. package/docs/components/StatTile.md +58 -0
  113. package/docs/components/Sticky.md +69 -0
  114. package/docs/components/Switch.md +89 -0
  115. package/docs/components/Table.md +184 -0
  116. package/docs/components/TableOfContents.md +76 -0
  117. package/docs/components/Tabs.md +94 -0
  118. package/docs/components/Text.md +63 -0
  119. package/docs/components/Textarea.md +59 -0
  120. package/docs/components/Thread.md +52 -0
  121. package/docs/components/TimeField.md +70 -0
  122. package/docs/components/Timeline.md +57 -0
  123. package/docs/components/Title.md +54 -0
  124. package/docs/components/ToastViewport.md +61 -0
  125. package/docs/components/Tooltip.md +63 -0
  126. package/docs/components/TopBar.md +214 -0
  127. package/docs/components/Tour.md +85 -0
  128. package/docs/components/TreeView.md +113 -0
  129. package/docs/components/VisuallyHidden.md +43 -0
  130. package/docs/components/WidgetPreview.md +54 -0
  131. package/docs/components/useBelowBreakpoint.md +11 -0
  132. package/docs/components/useMonth.md +18 -0
  133. package/docs/setup.md +51 -0
  134. package/docs/theming.md +95 -0
  135. package/docs/tokens.md +123 -0
  136. package/docs/transient-state.md +56 -0
  137. package/package.json +82 -4
  138. package/src/_meta/manifest.ts +293 -0
  139. package/src/app/AppProvider.tsx +78 -0
  140. package/src/app/index.ts +3 -0
  141. package/src/app/themeTokens.ts +95 -0
  142. package/src/calendar/dateMath.ts +114 -0
  143. package/src/calendar/formatters.ts +75 -0
  144. package/src/calendar/index.ts +39 -0
  145. package/src/calendar/types.ts +36 -0
  146. package/src/calendar/useAgenda.ts +70 -0
  147. package/src/calendar/useDay.ts +51 -0
  148. package/src/calendar/useMonth.ts +82 -0
  149. package/src/calendar/useWeek.ts +62 -0
  150. package/src/calendar/weekInfo.ts +83 -0
  151. package/src/components/Accordion/Accordion.module.scss +304 -0
  152. package/src/components/Accordion/Accordion.tokens.scss +64 -0
  153. package/src/components/Accordion/Accordion.tsx +272 -0
  154. package/src/components/Accordion/AccordionContent.tsx +36 -0
  155. package/src/components/Accordion/AccordionItem.tsx +66 -0
  156. package/src/components/Accordion/AccordionTrigger.tsx +121 -0
  157. package/src/components/Accordion/context.ts +47 -0
  158. package/src/components/Accordion/index.ts +14 -0
  159. package/src/components/Alert/Alert.module.scss +92 -0
  160. package/src/components/Alert/Alert.tokens.scss +60 -0
  161. package/src/components/Alert/Alert.tsx +136 -0
  162. package/src/components/Alert/index.ts +2 -0
  163. package/src/components/AppLayout/AppLayout.module.scss +130 -0
  164. package/src/components/AppLayout/AppLayout.tokens.scss +27 -0
  165. package/src/components/AppLayout/AppLayout.tsx +211 -0
  166. package/src/components/AppLayout/index.ts +2 -0
  167. package/src/components/Avatar/AgentAvatar.module.scss +117 -0
  168. package/src/components/Avatar/AgentAvatar.tsx +122 -0
  169. package/src/components/Avatar/Avatar.module.scss +181 -0
  170. package/src/components/Avatar/Avatar.tokens.scss +107 -0
  171. package/src/components/Avatar/Avatar.tsx +210 -0
  172. package/src/components/Avatar/AvatarGroup.module.scss +128 -0
  173. package/src/components/Avatar/AvatarGroup.tsx +119 -0
  174. package/src/components/Avatar/AvatarGroupContext.tsx +20 -0
  175. package/src/components/Avatar/index.ts +6 -0
  176. package/src/components/Badge/Badge.module.scss +124 -0
  177. package/src/components/Badge/Badge.tokens.scss +74 -0
  178. package/src/components/Badge/Badge.tsx +164 -0
  179. package/src/components/Badge/index.ts +2 -0
  180. package/src/components/Banner/Banner.module.scss +73 -0
  181. package/src/components/Banner/Banner.tokens.scss +51 -0
  182. package/src/components/Banner/Banner.tsx +138 -0
  183. package/src/components/Banner/index.ts +2 -0
  184. package/src/components/BrandIcon/BrandIcon.module.scss +5 -0
  185. package/src/components/BrandIcon/BrandIcon.tsx +99 -0
  186. package/src/components/BrandIcon/index.ts +2 -0
  187. package/src/components/Breadcrumb/Breadcrumb.module.scss +32 -0
  188. package/src/components/Breadcrumb/Breadcrumb.tokens.scss +9 -0
  189. package/src/components/Breadcrumb/Breadcrumb.tsx +146 -0
  190. package/src/components/Breadcrumb/index.ts +2 -0
  191. package/src/components/Button/Button.module.scss +167 -0
  192. package/src/components/Button/Button.tokens.scss +90 -0
  193. package/src/components/Button/Button.tsx +205 -0
  194. package/src/components/Button/index.ts +2 -0
  195. package/src/components/ButtonGroup/ButtonGroup.module.scss +134 -0
  196. package/src/components/ButtonGroup/ButtonGroup.tokens.scss +42 -0
  197. package/src/components/ButtonGroup/ButtonGroup.tsx +278 -0
  198. package/src/components/ButtonGroup/ButtonGroupItem.tsx +74 -0
  199. package/src/components/ButtonGroup/context.ts +45 -0
  200. package/src/components/ButtonGroup/index.ts +2 -0
  201. package/src/components/Calendar/AgendaView.module.scss +231 -0
  202. package/src/components/Calendar/AgendaView.tsx +214 -0
  203. package/src/components/Calendar/AllDayBand.module.scss +18 -0
  204. package/src/components/Calendar/AllDayBand.tsx +75 -0
  205. package/src/components/Calendar/Calendar.module.scss +23 -0
  206. package/src/components/Calendar/Calendar.tokens.scss +262 -0
  207. package/src/components/Calendar/Calendar.tsx +370 -0
  208. package/src/components/Calendar/DayCell.module.scss +30 -0
  209. package/src/components/Calendar/DayCell.tsx +50 -0
  210. package/src/components/Calendar/DayView.module.scss +10 -0
  211. package/src/components/Calendar/DayView.tsx +163 -0
  212. package/src/components/Calendar/EventChip.module.scss +171 -0
  213. package/src/components/Calendar/EventChip.tsx +115 -0
  214. package/src/components/Calendar/HourGrid.module.scss +123 -0
  215. package/src/components/Calendar/HourGrid.tsx +381 -0
  216. package/src/components/Calendar/MonthView.module.scss +99 -0
  217. package/src/components/Calendar/MonthView.tsx +296 -0
  218. package/src/components/Calendar/TimedEvent.module.scss +205 -0
  219. package/src/components/Calendar/TimedEvent.tsx +247 -0
  220. package/src/components/Calendar/ViewSwitcher.module.scss +3 -0
  221. package/src/components/Calendar/ViewSwitcher.tsx +47 -0
  222. package/src/components/Calendar/WeekView.module.scss +10 -0
  223. package/src/components/Calendar/WeekView.tsx +137 -0
  224. package/src/components/Calendar/eventColor.ts +60 -0
  225. package/src/components/Calendar/index.ts +18 -0
  226. package/src/components/Calendar/types.ts +451 -0
  227. package/src/components/Calendar/useEventDrag.ts +783 -0
  228. package/src/components/Calendar/utils.ts +622 -0
  229. package/src/components/Card/Card.module.scss +264 -0
  230. package/src/components/Card/Card.tokens.scss +55 -0
  231. package/src/components/Card/Card.tsx +170 -0
  232. package/src/components/Card/CardBody.tsx +45 -0
  233. package/src/components/Card/CardHeader.tsx +113 -0
  234. package/src/components/Card/CardList.tsx +24 -0
  235. package/src/components/Card/CardListRow.tsx +24 -0
  236. package/src/components/Card/index.ts +7 -0
  237. package/src/components/CatalogPicker/CatalogPicker.module.scss +193 -0
  238. package/src/components/CatalogPicker/CatalogPicker.tokens.scss +26 -0
  239. package/src/components/CatalogPicker/CatalogPicker.tsx +339 -0
  240. package/src/components/CatalogPicker/index.ts +2 -0
  241. package/src/components/Chart/Chart.module.scss +287 -0
  242. package/src/components/Chart/Chart.tokens.scss +63 -0
  243. package/src/components/Chart/Chart.tsx +607 -0
  244. package/src/components/Chart/ChartLegend.tsx +99 -0
  245. package/src/components/Chart/ChartTable.tsx +62 -0
  246. package/src/components/Chart/ChartTooltip.tsx +91 -0
  247. package/src/components/Chart/chartModel.ts +689 -0
  248. package/src/components/Chart/index.ts +2 -0
  249. package/src/components/ChatBubble/ChatBubble.module.scss +93 -0
  250. package/src/components/ChatBubble/ChatBubble.tokens.scss +17 -0
  251. package/src/components/ChatBubble/ChatBubble.tsx +61 -0
  252. package/src/components/ChatBubble/ChatBubbleList.tsx +27 -0
  253. package/src/components/ChatBubble/index.ts +3 -0
  254. package/src/components/ChatLauncher/ChatLauncher.module.scss +68 -0
  255. package/src/components/ChatLauncher/ChatLauncher.tokens.scss +27 -0
  256. package/src/components/ChatLauncher/ChatLauncher.tsx +202 -0
  257. package/src/components/ChatLauncher/index.ts +2 -0
  258. package/src/components/ChatLauncher/isAtBottom.ts +12 -0
  259. package/src/components/Checkbox/Checkbox.module.scss +147 -0
  260. package/src/components/Checkbox/Checkbox.tokens.scss +44 -0
  261. package/src/components/Checkbox/Checkbox.tsx +188 -0
  262. package/src/components/Checkbox/index.ts +2 -0
  263. package/src/components/CircularProgress/CircularProgress.module.scss +133 -0
  264. package/src/components/CircularProgress/CircularProgress.tokens.scss +40 -0
  265. package/src/components/CircularProgress/CircularProgress.tsx +139 -0
  266. package/src/components/CircularProgress/index.ts +7 -0
  267. package/src/components/Cluster/Cluster.module.scss +145 -0
  268. package/src/components/Cluster/Cluster.tokens.scss +11 -0
  269. package/src/components/Cluster/Cluster.tsx +215 -0
  270. package/src/components/Cluster/index.ts +2 -0
  271. package/src/components/Code/Code.module.scss +28 -0
  272. package/src/components/Code/Code.tokens.scss +15 -0
  273. package/src/components/Code/Code.tsx +44 -0
  274. package/src/components/Code/index.ts +2 -0
  275. package/src/components/CodeBlock/CodeBlock.module.scss +146 -0
  276. package/src/components/CodeBlock/CodeBlock.tokens.scss +27 -0
  277. package/src/components/CodeBlock/CodeBlock.tsx +274 -0
  278. package/src/components/CodeBlock/highlight.ts +179 -0
  279. package/src/components/CodeBlock/index.ts +8 -0
  280. package/src/components/CodeBlock/sampleSync.ts +42 -0
  281. package/src/components/ColorPicker/ColorPicker.module.scss +286 -0
  282. package/src/components/ColorPicker/ColorPicker.tokens.scss +60 -0
  283. package/src/components/ColorPicker/ColorPicker.tsx +367 -0
  284. package/src/components/ColorPicker/ColorPickerPanel.tsx +265 -0
  285. package/src/components/ColorPicker/SVSquare.tsx +189 -0
  286. package/src/components/ColorPicker/colorMath.ts +141 -0
  287. package/src/components/ColorPicker/index.ts +6 -0
  288. package/src/components/ConfirmationPopover/ConfirmationPopover.module.scss +39 -0
  289. package/src/components/ConfirmationPopover/ConfirmationPopover.tokens.scss +13 -0
  290. package/src/components/ConfirmationPopover/ConfirmationPopover.tsx +395 -0
  291. package/src/components/ConfirmationPopover/index.ts +2 -0
  292. package/src/components/Constrain/Constrain.module.scss +99 -0
  293. package/src/components/Constrain/Constrain.tsx +79 -0
  294. package/src/components/Constrain/index.ts +2 -0
  295. package/src/components/CurrencySelect/CurrencySelect.module.scss +7 -0
  296. package/src/components/CurrencySelect/CurrencySelect.tsx +167 -0
  297. package/src/components/CurrencySelect/index.ts +3 -0
  298. package/src/components/CursorPagination/CursorPagination.module.scss +69 -0
  299. package/src/components/CursorPagination/CursorPagination.tokens.scss +32 -0
  300. package/src/components/CursorPagination/CursorPagination.tsx +121 -0
  301. package/src/components/CursorPagination/index.ts +2 -0
  302. package/src/components/DashboardCanvas/DashboardCanvas.module.scss +360 -0
  303. package/src/components/DashboardCanvas/DashboardCanvas.tokens.scss +48 -0
  304. package/src/components/DashboardCanvas/DashboardCanvas.tsx +1270 -0
  305. package/src/components/DashboardCanvas/DashboardCanvasItem.tsx +140 -0
  306. package/src/components/DashboardCanvas/DashboardCanvasSection.tsx +174 -0
  307. package/src/components/DashboardCanvas/engine.ts +363 -0
  308. package/src/components/DashboardCanvas/index.ts +9 -0
  309. package/src/components/DashboardWidget/DashboardWidget.module.scss +100 -0
  310. package/src/components/DashboardWidget/DashboardWidget.tokens.scss +16 -0
  311. package/src/components/DashboardWidget/DashboardWidget.tsx +188 -0
  312. package/src/components/DashboardWidget/index.ts +7 -0
  313. package/src/components/DataTable/BodyRow.tsx +197 -0
  314. package/src/components/DataTable/ColumnVisibilityTrigger.module.scss +7 -0
  315. package/src/components/DataTable/ColumnVisibilityTrigger.tsx +105 -0
  316. package/src/components/DataTable/DataTable.module.scss +511 -0
  317. package/src/components/DataTable/DataTable.tokens.scss +80 -0
  318. package/src/components/DataTable/DataTable.tsx +734 -0
  319. package/src/components/DataTable/HeaderCell.module.scss +215 -0
  320. package/src/components/DataTable/HeaderCell.tsx +440 -0
  321. package/src/components/DataTable/columnShift.ts +117 -0
  322. package/src/components/DataTable/index.ts +23 -0
  323. package/src/components/DataTable/pinStyle.ts +47 -0
  324. package/src/components/DataTable/reorderColumns.ts +66 -0
  325. package/src/components/DataTable/types.ts +289 -0
  326. package/src/components/DataTable/useColumnDragShift.ts +216 -0
  327. package/src/components/DataTable/useDataTable.ts +372 -0
  328. package/src/components/DataTable/useResizeHandle.ts +97 -0
  329. package/src/components/DatePicker/DatePicker.module.scss +180 -0
  330. package/src/components/DatePicker/DatePicker.tokens.scss +152 -0
  331. package/src/components/DatePicker/DatePicker.tsx +664 -0
  332. package/src/components/DatePicker/DatePickerGrid.module.scss +172 -0
  333. package/src/components/DatePicker/DatePickerGrid.tsx +341 -0
  334. package/src/components/DatePicker/InlineDatePicker.module.scss +32 -0
  335. package/src/components/DatePicker/InlineDatePicker.tsx +201 -0
  336. package/src/components/DatePicker/index.ts +4 -0
  337. package/src/components/DatePicker/utils.ts +364 -0
  338. package/src/components/DateRangePicker/DateRangePicker.module.scss +237 -0
  339. package/src/components/DateRangePicker/DateRangePicker.tokens.scss +78 -0
  340. package/src/components/DateRangePicker/DateRangePicker.tsx +720 -0
  341. package/src/components/DateRangePicker/InlineDateRangePicker.module.scss +94 -0
  342. package/src/components/DateRangePicker/InlineDateRangePicker.tsx +376 -0
  343. package/src/components/DateRangePicker/index.ts +5 -0
  344. package/src/components/DateRangePicker/utils.ts +151 -0
  345. package/src/components/DateStrip/DateStrip.module.scss +78 -0
  346. package/src/components/DateStrip/DateStrip.tokens.scss +23 -0
  347. package/src/components/DateStrip/DateStrip.tsx +205 -0
  348. package/src/components/DateStrip/index.ts +2 -0
  349. package/src/components/DefinitionList/DefinitionList.module.scss +102 -0
  350. package/src/components/DefinitionList/DefinitionList.tokens.scss +29 -0
  351. package/src/components/DefinitionList/DefinitionList.tsx +198 -0
  352. package/src/components/DefinitionList/index.ts +9 -0
  353. package/src/components/Divider/Divider.module.scss +144 -0
  354. package/src/components/Divider/Divider.tokens.scss +21 -0
  355. package/src/components/Divider/Divider.tsx +103 -0
  356. package/src/components/Divider/index.ts +2 -0
  357. package/src/components/Dot/Dot.module.scss +40 -0
  358. package/src/components/Dot/Dot.tokens.scss +4 -0
  359. package/src/components/Dot/Dot.tsx +45 -0
  360. package/src/components/Dot/index.ts +2 -0
  361. package/src/components/Drawer/Body.tsx +23 -0
  362. package/src/components/Drawer/Close.tsx +35 -0
  363. package/src/components/Drawer/Content.tsx +93 -0
  364. package/src/components/Drawer/Drawer.module.scss +232 -0
  365. package/src/components/Drawer/Drawer.tokens.scss +38 -0
  366. package/src/components/Drawer/Drawer.tsx +23 -0
  367. package/src/components/Drawer/DrawerRoot.tsx +190 -0
  368. package/src/components/Drawer/Footer.tsx +24 -0
  369. package/src/components/Drawer/Header.tsx +64 -0
  370. package/src/components/Drawer/Overlay.tsx +82 -0
  371. package/src/components/Drawer/context.ts +44 -0
  372. package/src/components/Drawer/index.ts +12 -0
  373. package/src/components/Drawer/useDragToClose.ts +149 -0
  374. package/src/components/DropdownMenu/CheckboxItem.tsx +144 -0
  375. package/src/components/DropdownMenu/Content.tsx +419 -0
  376. package/src/components/DropdownMenu/DropdownMenu.module.scss +280 -0
  377. package/src/components/DropdownMenu/DropdownMenu.tokens.scss +88 -0
  378. package/src/components/DropdownMenu/DropdownMenu.tsx +43 -0
  379. package/src/components/DropdownMenu/Group.tsx +76 -0
  380. package/src/components/DropdownMenu/Item.tsx +148 -0
  381. package/src/components/DropdownMenu/ItemIndicator.tsx +30 -0
  382. package/src/components/DropdownMenu/Radio.tsx +178 -0
  383. package/src/components/DropdownMenu/Root.tsx +100 -0
  384. package/src/components/DropdownMenu/Sub.tsx +332 -0
  385. package/src/components/DropdownMenu/Trigger.tsx +76 -0
  386. package/src/components/DropdownMenu/context.ts +65 -0
  387. package/src/components/DropdownMenu/index.ts +20 -0
  388. package/src/components/EmojiPicker/EmojiPicker.module.scss +84 -0
  389. package/src/components/EmojiPicker/EmojiPicker.tokens.scss +24 -0
  390. package/src/components/EmojiPicker/EmojiPicker.tsx +341 -0
  391. package/src/components/EmojiPicker/emojiData.ts +245 -0
  392. package/src/components/EmojiPicker/index.ts +3 -0
  393. package/src/components/EmptyState/EmptyState.module.scss +102 -0
  394. package/src/components/EmptyState/EmptyState.tokens.scss +28 -0
  395. package/src/components/EmptyState/EmptyState.tsx +112 -0
  396. package/src/components/EmptyState/index.ts +7 -0
  397. package/src/components/EntityChip/EntityChip.module.scss +275 -0
  398. package/src/components/EntityChip/EntityChip.tokens.scss +66 -0
  399. package/src/components/EntityChip/EntityChip.tsx +649 -0
  400. package/src/components/EntityChip/index.ts +10 -0
  401. package/src/components/ErrorState/ErrorState.module.scss +105 -0
  402. package/src/components/ErrorState/ErrorState.tokens.scss +32 -0
  403. package/src/components/ErrorState/ErrorState.tsx +125 -0
  404. package/src/components/ErrorState/index.ts +8 -0
  405. package/src/components/Field/Field.module.scss +46 -0
  406. package/src/components/Field/Field.tsx +185 -0
  407. package/src/components/Field/index.ts +2 -0
  408. package/src/components/FileUpload/FileUpload.module.scss +187 -0
  409. package/src/components/FileUpload/FileUpload.tokens.scss +81 -0
  410. package/src/components/FileUpload/FileUpload.tsx +569 -0
  411. package/src/components/FileUpload/formatBytes.ts +34 -0
  412. package/src/components/FileUpload/iconForFile.ts +40 -0
  413. package/src/components/FileUpload/index.ts +2 -0
  414. package/src/components/FilterChip/FilterChip.module.scss +61 -0
  415. package/src/components/FilterChip/FilterChip.tokens.scss +25 -0
  416. package/src/components/FilterChip/FilterChip.tsx +208 -0
  417. package/src/components/FilterChip/index.ts +5 -0
  418. package/src/components/FlowCanvas/FlowCanvas.module.scss +329 -0
  419. package/src/components/FlowCanvas/FlowCanvas.tokens.scss +45 -0
  420. package/src/components/FlowCanvas/FlowCanvas.tsx +1867 -0
  421. package/src/components/FlowCanvas/FlowControls.tsx +46 -0
  422. package/src/components/FlowCanvas/FlowEdge.tsx +58 -0
  423. package/src/components/FlowCanvas/FlowNode.tsx +76 -0
  424. package/src/components/FlowCanvas/edgePath.ts +85 -0
  425. package/src/components/FlowCanvas/index.ts +4 -0
  426. package/src/components/FlowCanvas/layout.ts +148 -0
  427. package/src/components/FlowCanvas/spatialNav.ts +76 -0
  428. package/src/components/FlowCanvas/types.ts +59 -0
  429. package/src/components/FlowCanvas/useViewport.ts +122 -0
  430. package/src/components/FormRow/FormRow.module.scss +2 -0
  431. package/src/components/FormRow/FormRow.tsx +37 -0
  432. package/src/components/FormRow/index.ts +2 -0
  433. package/src/components/FormSection/FormSection.module.scss +24 -0
  434. package/src/components/FormSection/FormSection.tsx +46 -0
  435. package/src/components/FormSection/index.ts +2 -0
  436. package/src/components/Grid/Grid.module.scss +162 -0
  437. package/src/components/Grid/Grid.tokens.scss +13 -0
  438. package/src/components/Grid/Grid.tsx +226 -0
  439. package/src/components/Grid/GridItem.tsx +77 -0
  440. package/src/components/Grid/index.ts +11 -0
  441. package/src/components/Highlight/Highlight.module.scss +43 -0
  442. package/src/components/Highlight/Highlight.tokens.scss +35 -0
  443. package/src/components/Highlight/Highlight.tsx +164 -0
  444. package/src/components/Highlight/HighlightOverlay.tsx +100 -0
  445. package/src/components/Highlight/index.ts +2 -0
  446. package/src/components/HighlightedText/HighlightedText.module.scss +11 -0
  447. package/src/components/HighlightedText/HighlightedText.tokens.scss +9 -0
  448. package/src/components/HighlightedText/HighlightedText.tsx +50 -0
  449. package/src/components/HighlightedText/highlightRanges.ts +44 -0
  450. package/src/components/HighlightedText/index.ts +2 -0
  451. package/src/components/IconPicker/IconPicker.module.scss +175 -0
  452. package/src/components/IconPicker/IconPicker.tokens.scss +40 -0
  453. package/src/components/IconPicker/IconPicker.tsx +629 -0
  454. package/src/components/IconPicker/index.ts +9 -0
  455. package/src/components/IconTile/IconTile.module.scss +57 -0
  456. package/src/components/IconTile/IconTile.tokens.scss +16 -0
  457. package/src/components/IconTile/IconTile.tsx +91 -0
  458. package/src/components/IconTile/index.ts +2 -0
  459. package/src/components/Image/Image.module.scss +266 -0
  460. package/src/components/Image/Image.tokens.scss +55 -0
  461. package/src/components/Image/Image.tsx +342 -0
  462. package/src/components/Image/index.ts +2 -0
  463. package/src/components/ImageCrop/ImageCrop.module.scss +274 -0
  464. package/src/components/ImageCrop/ImageCrop.tokens.scss +33 -0
  465. package/src/components/ImageCrop/ImageCrop.tsx +542 -0
  466. package/src/components/ImageCrop/cropGeometry.ts +120 -0
  467. package/src/components/ImageCrop/extractCropBlob.ts +140 -0
  468. package/src/components/ImageCrop/index.ts +11 -0
  469. package/src/components/ImageCrop/useCropPreview.ts +161 -0
  470. package/src/components/Indent/Indent.module.scss +33 -0
  471. package/src/components/Indent/Indent.tokens.scss +10 -0
  472. package/src/components/Indent/Indent.tsx +46 -0
  473. package/src/components/Indent/index.ts +2 -0
  474. package/src/components/Input/Input.module.scss +99 -0
  475. package/src/components/Input/Input.tokens.scss +54 -0
  476. package/src/components/Input/Input.tsx +105 -0
  477. package/src/components/Input/Suggestions.tsx +260 -0
  478. package/src/components/Input/index.ts +2 -0
  479. package/src/components/Kanban/Kanban.module.scss +39 -0
  480. package/src/components/Kanban/Kanban.tokens.scss +15 -0
  481. package/src/components/Kanban/Kanban.tsx +951 -0
  482. package/src/components/Kanban/index.ts +7 -0
  483. package/src/components/Kbd/Kbd.module.scss +47 -0
  484. package/src/components/Kbd/Kbd.tokens.scss +26 -0
  485. package/src/components/Kbd/Kbd.tsx +73 -0
  486. package/src/components/Kbd/index.ts +2 -0
  487. package/src/components/Lightbox/Lightbox.module.scss +283 -0
  488. package/src/components/Lightbox/Lightbox.tokens.scss +36 -0
  489. package/src/components/Lightbox/Lightbox.tsx +506 -0
  490. package/src/components/Lightbox/index.ts +2 -0
  491. package/src/components/Link/Link.module.scss +78 -0
  492. package/src/components/Link/Link.tokens.scss +28 -0
  493. package/src/components/Link/Link.tsx +114 -0
  494. package/src/components/Link/index.ts +2 -0
  495. package/src/components/LinkCard/LinkCard.module.scss +92 -0
  496. package/src/components/LinkCard/LinkCard.tokens.scss +9 -0
  497. package/src/components/LinkCard/LinkCard.tsx +72 -0
  498. package/src/components/LinkCard/index.ts +2 -0
  499. package/src/components/LiquidEditor/AutocompleteMenu.tsx +133 -0
  500. package/src/components/LiquidEditor/HighlightLayer.tsx +53 -0
  501. package/src/components/LiquidEditor/InsertVariableMenu.tsx +81 -0
  502. package/src/components/LiquidEditor/LiquidEditor.module.scss +339 -0
  503. package/src/components/LiquidEditor/LiquidEditor.tokens.scss +81 -0
  504. package/src/components/LiquidEditor/LiquidEditor.tsx +412 -0
  505. package/src/components/LiquidEditor/PreviewPane.tsx +29 -0
  506. package/src/components/LiquidEditor/caretCoordinates.ts +97 -0
  507. package/src/components/LiquidEditor/index.ts +7 -0
  508. package/src/components/LiquidEditor/liquidFilters.ts +23 -0
  509. package/src/components/LiquidEditor/liquidTokenizer.ts +235 -0
  510. package/src/components/LiquidEditor/types.ts +101 -0
  511. package/src/components/LiquidEditor/useLiquidAutocomplete.ts +178 -0
  512. package/src/components/List/List.module.scss +105 -0
  513. package/src/components/List/List.tokens.scss +42 -0
  514. package/src/components/List/List.tsx +124 -0
  515. package/src/components/List/index.ts +9 -0
  516. package/src/components/LiveRegion/LiveRegion.module.scss +3 -0
  517. package/src/components/LiveRegion/LiveRegion.tsx +116 -0
  518. package/src/components/LiveRegion/index.ts +2 -0
  519. package/src/components/Logo/Logo.module.scss +139 -0
  520. package/src/components/Logo/Logo.tokens.scss +14 -0
  521. package/src/components/Logo/Logo.tsx +126 -0
  522. package/src/components/Logo/index.ts +2 -0
  523. package/src/components/Masonry/Masonry.module.scss +42 -0
  524. package/src/components/Masonry/Masonry.tokens.scss +8 -0
  525. package/src/components/Masonry/Masonry.tsx +136 -0
  526. package/src/components/Masonry/index.ts +2 -0
  527. package/src/components/Masonry/masonryUtils.ts +42 -0
  528. package/src/components/MediaTile/MediaTile.module.scss +183 -0
  529. package/src/components/MediaTile/MediaTile.tokens.scss +60 -0
  530. package/src/components/MediaTile/MediaTile.tsx +208 -0
  531. package/src/components/MediaTile/index.ts +8 -0
  532. package/src/components/Modal/Body.tsx +27 -0
  533. package/src/components/Modal/Close.tsx +45 -0
  534. package/src/components/Modal/Content.tsx +98 -0
  535. package/src/components/Modal/Footer.tsx +28 -0
  536. package/src/components/Modal/Header.tsx +51 -0
  537. package/src/components/Modal/Modal.module.scss +262 -0
  538. package/src/components/Modal/Modal.tokens.scss +50 -0
  539. package/src/components/Modal/Modal.tsx +23 -0
  540. package/src/components/Modal/ModalRoot.tsx +299 -0
  541. package/src/components/Modal/Overlay.tsx +101 -0
  542. package/src/components/Modal/context.ts +60 -0
  543. package/src/components/Modal/index.ts +11 -0
  544. package/src/components/MoneyInput/MoneyInput.module.scss +57 -0
  545. package/src/components/MoneyInput/MoneyInput.tsx +433 -0
  546. package/src/components/MoneyInput/index.ts +2 -0
  547. package/src/components/OptionsPicker/OptionsPicker.module.scss +216 -0
  548. package/src/components/OptionsPicker/OptionsPicker.tokens.scss +68 -0
  549. package/src/components/OptionsPicker/OptionsPicker.tsx +936 -0
  550. package/src/components/OptionsPicker/index.ts +9 -0
  551. package/src/components/OtpInput/OtpInput.module.scss +69 -0
  552. package/src/components/OtpInput/OtpInput.tokens.scss +45 -0
  553. package/src/components/OtpInput/OtpInput.tsx +368 -0
  554. package/src/components/OtpInput/index.ts +2 -0
  555. package/src/components/Page/Page.module.scss +30 -0
  556. package/src/components/Page/Page.tokens.scss +11 -0
  557. package/src/components/Page/Page.tsx +53 -0
  558. package/src/components/Page/index.ts +2 -0
  559. package/src/components/PageHeader/PageHeader.module.scss +197 -0
  560. package/src/components/PageHeader/PageHeader.tokens.scss +41 -0
  561. package/src/components/PageHeader/PageHeader.tsx +310 -0
  562. package/src/components/PageHeader/index.ts +20 -0
  563. package/src/components/Pagination/Pagination.module.scss +117 -0
  564. package/src/components/Pagination/Pagination.tokens.scss +54 -0
  565. package/src/components/Pagination/Pagination.tsx +165 -0
  566. package/src/components/Pagination/index.ts +4 -0
  567. package/src/components/Pagination/paginationRange.ts +72 -0
  568. package/src/components/PasswordInput/PasswordInput.module.scss +120 -0
  569. package/src/components/PasswordInput/PasswordInput.tokens.scss +44 -0
  570. package/src/components/PasswordInput/PasswordInput.tsx +210 -0
  571. package/src/components/PasswordInput/index.ts +2 -0
  572. package/src/components/PasswordStrengthMeter/PasswordStrengthMeter.module.scss +80 -0
  573. package/src/components/PasswordStrengthMeter/PasswordStrengthMeter.tokens.scss +40 -0
  574. package/src/components/PasswordStrengthMeter/PasswordStrengthMeter.tsx +96 -0
  575. package/src/components/PasswordStrengthMeter/index.ts +2 -0
  576. package/src/components/PersonDisplay/PersonDisplay.module.scss +180 -0
  577. package/src/components/PersonDisplay/PersonDisplay.tokens.scss +35 -0
  578. package/src/components/PersonDisplay/PersonDisplay.tsx +420 -0
  579. package/src/components/PersonDisplay/index.ts +10 -0
  580. package/src/components/PhoneInput/PhoneInput.module.scss +23 -0
  581. package/src/components/PhoneInput/PhoneInput.tsx +271 -0
  582. package/src/components/PhoneInput/index.ts +4 -0
  583. package/src/components/PhoneInput/phone.ts +128 -0
  584. package/src/components/PillMenu/PillMenu.module.scss +117 -0
  585. package/src/components/PillMenu/PillMenu.tokens.scss +22 -0
  586. package/src/components/PillMenu/PillMenu.tsx +324 -0
  587. package/src/components/PillMenu/index.ts +2 -0
  588. package/src/components/Popover/Anchor.tsx +37 -0
  589. package/src/components/Popover/Close.tsx +45 -0
  590. package/src/components/Popover/Content.tsx +213 -0
  591. package/src/components/Popover/Heading.tsx +33 -0
  592. package/src/components/Popover/Popover.module.scss +177 -0
  593. package/src/components/Popover/Popover.tokens.scss +22 -0
  594. package/src/components/Popover/Popover.tsx +23 -0
  595. package/src/components/Popover/PopoverRoot.tsx +75 -0
  596. package/src/components/Popover/Trigger.tsx +86 -0
  597. package/src/components/Popover/context.ts +22 -0
  598. package/src/components/Popover/index.ts +7 -0
  599. package/src/components/Progress/Progress.module.scss +110 -0
  600. package/src/components/Progress/Progress.tokens.scss +44 -0
  601. package/src/components/Progress/Progress.tsx +129 -0
  602. package/src/components/Progress/index.ts +2 -0
  603. package/src/components/QrCode/QrCode.module.scss +97 -0
  604. package/src/components/QrCode/QrCode.tokens.scss +17 -0
  605. package/src/components/QrCode/QrCode.tsx +233 -0
  606. package/src/components/QrCode/index.ts +2 -0
  607. package/src/components/QrCode/qr.ts +161 -0
  608. package/src/components/Radio/Radio.module.scss +175 -0
  609. package/src/components/Radio/Radio.tokens.scss +59 -0
  610. package/src/components/Radio/Radio.tsx +127 -0
  611. package/src/components/Radio/RadioGroup.module.scss +42 -0
  612. package/src/components/Radio/RadioGroup.tsx +120 -0
  613. package/src/components/Radio/RadioGroupContext.tsx +30 -0
  614. package/src/components/Radio/index.ts +4 -0
  615. package/src/components/Rail/Rail.module.scss +510 -0
  616. package/src/components/Rail/Rail.tokens.scss +92 -0
  617. package/src/components/Rail/Rail.tsx +287 -0
  618. package/src/components/Rail/RailCollapseToggle.tsx +57 -0
  619. package/src/components/Rail/RailFooter.tsx +17 -0
  620. package/src/components/Rail/RailGroup.tsx +728 -0
  621. package/src/components/Rail/RailGroupContext.ts +9 -0
  622. package/src/components/Rail/RailHeader.tsx +23 -0
  623. package/src/components/Rail/RailItem.tsx +119 -0
  624. package/src/components/Rail/RailSection.tsx +39 -0
  625. package/src/components/Rail/RailSpacer.tsx +19 -0
  626. package/src/components/Rail/index.ts +9 -0
  627. package/src/components/RelativeDateInput/RelativeDateInput.module.scss +15 -0
  628. package/src/components/RelativeDateInput/RelativeDateInput.tokens.scss +6 -0
  629. package/src/components/RelativeDateInput/RelativeDateInput.tsx +474 -0
  630. package/src/components/RelativeDateInput/index.ts +10 -0
  631. package/src/components/RelativeDateInput/relativeDate.ts +127 -0
  632. package/src/components/RichText/RichText.module.scss +5 -0
  633. package/src/components/RichText/RichText.tsx +70 -0
  634. package/src/components/RichText/RichTextAttachment.module.scss +82 -0
  635. package/src/components/RichText/RichTextAttachment.tsx +122 -0
  636. package/src/components/RichText/_prose.scss +79 -0
  637. package/src/components/RichText/attachmentIcon.tsx +24 -0
  638. package/src/components/RichText/engine/attachment.ts +154 -0
  639. package/src/components/RichText/engine/autolink.ts +64 -0
  640. package/src/components/RichText/engine/blockUnit.ts +174 -0
  641. package/src/components/RichText/engine/colorMarks.ts +85 -0
  642. package/src/components/RichText/engine/escape.ts +11 -0
  643. package/src/components/RichText/engine/fromHtml.ts +353 -0
  644. package/src/components/RichText/engine/fromMarkdown.ts +20 -0
  645. package/src/components/RichText/engine/inlines.ts +82 -0
  646. package/src/components/RichText/engine/listDepths.ts +32 -0
  647. package/src/components/RichText/engine/marks.ts +80 -0
  648. package/src/components/RichText/engine/mdToHtml.ts +178 -0
  649. package/src/components/RichText/engine/model.ts +157 -0
  650. package/src/components/RichText/engine/position.ts +118 -0
  651. package/src/components/RichText/engine/renderDoc.tsx +395 -0
  652. package/src/components/RichText/engine/renderLink.ts +15 -0
  653. package/src/components/RichText/engine/renderMention.ts +16 -0
  654. package/src/components/RichText/engine/safeHref.ts +22 -0
  655. package/src/components/RichText/engine/toHtml.ts +154 -0
  656. package/src/components/RichText/engine/toMarkdown.ts +97 -0
  657. package/src/components/RichText/engine/transforms.ts +434 -0
  658. package/src/components/RichText/imageMaxHeightStyle.ts +10 -0
  659. package/src/components/RichText/index.ts +31 -0
  660. package/src/components/RichTextEditor/RichTextAttachmentConfig.tsx +264 -0
  661. package/src/components/RichTextEditor/RichTextBlockControls.tsx +365 -0
  662. package/src/components/RichTextEditor/RichTextBlockMenu.tsx +162 -0
  663. package/src/components/RichTextEditor/RichTextColorMenu.tsx +115 -0
  664. package/src/components/RichTextEditor/RichTextEditor.module.scss +298 -0
  665. package/src/components/RichTextEditor/RichTextEditor.tsx +1910 -0
  666. package/src/components/RichTextEditor/RichTextImageResizer.tsx +131 -0
  667. package/src/components/RichTextEditor/RichTextLinkEditor.tsx +151 -0
  668. package/src/components/RichTextEditor/RichTextMentionMenu.tsx +99 -0
  669. package/src/components/RichTextEditor/RichTextToolbar.tsx +379 -0
  670. package/src/components/RichTextEditor/autolinkInput.ts +65 -0
  671. package/src/components/RichTextEditor/blockDrop.ts +9 -0
  672. package/src/components/RichTextEditor/blockReflow.ts +62 -0
  673. package/src/components/RichTextEditor/commands.ts +300 -0
  674. package/src/components/RichTextEditor/history.ts +93 -0
  675. package/src/components/RichTextEditor/icons.tsx +152 -0
  676. package/src/components/RichTextEditor/imageSize.ts +70 -0
  677. package/src/components/RichTextEditor/index.ts +5 -0
  678. package/src/components/RichTextEditor/input.ts +209 -0
  679. package/src/components/RichTextEditor/inputRules.ts +71 -0
  680. package/src/components/RichTextEditor/links.ts +103 -0
  681. package/src/components/RichTextEditor/mentionContext.ts +37 -0
  682. package/src/components/RichTextEditor/mentions.ts +28 -0
  683. package/src/components/RichTextEditor/preventSelectionLoss.ts +15 -0
  684. package/src/components/RichTextEditor/selection.ts +415 -0
  685. package/src/components/RichTextEditor/shortcuts.ts +44 -0
  686. package/src/components/RichTextEditor/useAnchoredFloating.ts +50 -0
  687. package/src/components/RichTextEditor/useAttachmentConfig.ts +134 -0
  688. package/src/components/RichTextEditor/useDismissOnOutsidePointerDown.ts +26 -0
  689. package/src/components/RichTextEditor/useLinkEditor.ts +107 -0
  690. package/src/components/RichTextEditor/useMention.ts +226 -0
  691. package/src/components/RichTextEditor/useOverlayRect.ts +73 -0
  692. package/src/components/RichTextEditor/useUpload.ts +246 -0
  693. package/src/components/Screen/Screen.module.scss +46 -0
  694. package/src/components/Screen/Screen.tokens.scss +20 -0
  695. package/src/components/Screen/Screen.tsx +97 -0
  696. package/src/components/Screen/index.ts +2 -0
  697. package/src/components/ScrollArea/ScrollArea.module.scss +39 -0
  698. package/src/components/ScrollArea/ScrollArea.tokens.scss +15 -0
  699. package/src/components/ScrollArea/ScrollArea.tsx +154 -0
  700. package/src/components/ScrollArea/index.ts +2 -0
  701. package/src/components/Select/Chip.tsx +45 -0
  702. package/src/components/Select/Empty.tsx +39 -0
  703. package/src/components/Select/Error.tsx +51 -0
  704. package/src/components/Select/HiddenInputs.tsx +44 -0
  705. package/src/components/Select/Listbox.tsx +557 -0
  706. package/src/components/Select/Loading.tsx +30 -0
  707. package/src/components/Select/Select.module.scss +512 -0
  708. package/src/components/Select/Select.tokens.scss +140 -0
  709. package/src/components/Select/Select.tsx +685 -0
  710. package/src/components/Select/Trigger.tsx +952 -0
  711. package/src/components/Select/context.ts +101 -0
  712. package/src/components/Select/emptyStateText.ts +19 -0
  713. package/src/components/Select/index.ts +9 -0
  714. package/src/components/Select/useSelectState.ts +157 -0
  715. package/src/components/Select/utils-types.ts +7 -0
  716. package/src/components/Select/utils.ts +122 -0
  717. package/src/components/SettingRow/SettingRow.module.scss +166 -0
  718. package/src/components/SettingRow/SettingRow.tokens.scss +37 -0
  719. package/src/components/SettingRow/SettingRow.tsx +242 -0
  720. package/src/components/SettingRow/index.ts +7 -0
  721. package/src/components/Skeleton/Skeleton.module.scss +55 -0
  722. package/src/components/Skeleton/Skeleton.tokens.scss +17 -0
  723. package/src/components/Skeleton/Skeleton.tsx +131 -0
  724. package/src/components/Skeleton/index.ts +4 -0
  725. package/src/components/Skeleton/useSkeletonVisibility.ts +95 -0
  726. package/src/components/Slider/Slider.module.scss +293 -0
  727. package/src/components/Slider/Slider.tokens.scss +98 -0
  728. package/src/components/Slider/Slider.tsx +624 -0
  729. package/src/components/Slider/index.ts +9 -0
  730. package/src/components/SlotGrid/SlotGrid.module.scss +61 -0
  731. package/src/components/SlotGrid/SlotGrid.tokens.scss +21 -0
  732. package/src/components/SlotGrid/SlotGrid.tsx +111 -0
  733. package/src/components/SlotGrid/index.ts +2 -0
  734. package/src/components/SocialButton/SocialButton.module.scss +4 -0
  735. package/src/components/SocialButton/SocialButton.tsx +40 -0
  736. package/src/components/SocialButton/index.ts +2 -0
  737. package/src/components/Sortable/Sortable.module.scss +177 -0
  738. package/src/components/Sortable/Sortable.tokens.scss +27 -0
  739. package/src/components/Sortable/Sortable.tsx +572 -0
  740. package/src/components/Sortable/containerAwareCollision.ts +125 -0
  741. package/src/components/Sortable/index.ts +13 -0
  742. package/src/components/SortableGroup/SortableGroup.module.scss +23 -0
  743. package/src/components/SortableGroup/SortableGroup.tsx +315 -0
  744. package/src/components/SortableGroup/index.ts +4 -0
  745. package/src/components/SortableGroup/moveSortableItem.ts +39 -0
  746. package/src/components/Sparkline/Sparkline.module.scss +28 -0
  747. package/src/components/Sparkline/Sparkline.tokens.scss +7 -0
  748. package/src/components/Sparkline/Sparkline.tsx +133 -0
  749. package/src/components/Sparkline/index.ts +2 -0
  750. package/src/components/Sparkline/sparklineModel.ts +119 -0
  751. package/src/components/Split/Split.module.scss +158 -0
  752. package/src/components/Split/Split.tokens.scss +10 -0
  753. package/src/components/Split/Split.tsx +231 -0
  754. package/src/components/Split/index.ts +2 -0
  755. package/src/components/Stack/Stack.module.scss +67 -0
  756. package/src/components/Stack/Stack.tokens.scss +11 -0
  757. package/src/components/Stack/Stack.tsx +100 -0
  758. package/src/components/Stack/index.ts +2 -0
  759. package/src/components/StagePath/StagePath.module.scss +255 -0
  760. package/src/components/StagePath/StagePath.tokens.scss +43 -0
  761. package/src/components/StagePath/StagePath.tsx +176 -0
  762. package/src/components/StagePath/index.ts +2 -0
  763. package/src/components/StatGroup/StatGroup.module.scss +6 -0
  764. package/src/components/StatGroup/StatGroup.tsx +70 -0
  765. package/src/components/StatGroup/StatGroupContext.ts +10 -0
  766. package/src/components/StatGroup/StatTile.module.scss +99 -0
  767. package/src/components/StatGroup/StatTile.tokens.scss +35 -0
  768. package/src/components/StatGroup/StatTile.tsx +143 -0
  769. package/src/components/StatGroup/index.ts +4 -0
  770. package/src/components/Sticky/Sticky.module.scss +98 -0
  771. package/src/components/Sticky/Sticky.tokens.scss +17 -0
  772. package/src/components/Sticky/Sticky.tsx +103 -0
  773. package/src/components/Sticky/index.ts +2 -0
  774. package/src/components/Switch/Switch.module.scss +182 -0
  775. package/src/components/Switch/Switch.tokens.scss +59 -0
  776. package/src/components/Switch/Switch.tsx +214 -0
  777. package/src/components/Switch/index.ts +2 -0
  778. package/src/components/Table/Table.module.scss +308 -0
  779. package/src/components/Table/Table.tokens.scss +79 -0
  780. package/src/components/Table/Table.tsx +381 -0
  781. package/src/components/Table/index.ts +15 -0
  782. package/src/components/TableOfContents/TableOfContents.module.scss +83 -0
  783. package/src/components/TableOfContents/TableOfContents.tokens.scss +26 -0
  784. package/src/components/TableOfContents/TableOfContents.tsx +192 -0
  785. package/src/components/TableOfContents/activeSection.ts +18 -0
  786. package/src/components/TableOfContents/index.ts +2 -0
  787. package/src/components/Tabs/Tabs.module.scss +359 -0
  788. package/src/components/Tabs/Tabs.tokens.scss +50 -0
  789. package/src/components/Tabs/Tabs.tsx +538 -0
  790. package/src/components/Tabs/index.ts +2 -0
  791. package/src/components/Text/Text.module.scss +115 -0
  792. package/src/components/Text/Text.tokens.scss +55 -0
  793. package/src/components/Text/Text.tsx +197 -0
  794. package/src/components/Text/index.ts +2 -0
  795. package/src/components/Textarea/Textarea.module.scss +94 -0
  796. package/src/components/Textarea/Textarea.tokens.scss +48 -0
  797. package/src/components/Textarea/Textarea.tsx +246 -0
  798. package/src/components/Textarea/index.ts +2 -0
  799. package/src/components/Thread/Thread.module.scss +161 -0
  800. package/src/components/Thread/Thread.tokens.scss +32 -0
  801. package/src/components/Thread/Thread.tsx +176 -0
  802. package/src/components/Thread/index.ts +2 -0
  803. package/src/components/TimeField/TimeField.module.scss +232 -0
  804. package/src/components/TimeField/TimeField.tsx +793 -0
  805. package/src/components/TimeField/index.ts +2 -0
  806. package/src/components/Timeline/Timeline.module.scss +58 -0
  807. package/src/components/Timeline/Timeline.tokens.scss +13 -0
  808. package/src/components/Timeline/Timeline.tsx +53 -0
  809. package/src/components/Timeline/index.ts +2 -0
  810. package/src/components/Title/Title.module.scss +84 -0
  811. package/src/components/Title/Title.tokens.scss +37 -0
  812. package/src/components/Title/Title.tsx +150 -0
  813. package/src/components/Title/index.ts +2 -0
  814. package/src/components/Toast/Toast.module.scss +299 -0
  815. package/src/components/Toast/Toast.tokens.scss +65 -0
  816. package/src/components/Toast/Toast.tsx +122 -0
  817. package/src/components/Toast/ToastViewport.tsx +166 -0
  818. package/src/components/Toast/api.ts +175 -0
  819. package/src/components/Toast/index.ts +5 -0
  820. package/src/components/Toast/store.ts +133 -0
  821. package/src/components/Toast/useToastTimer.ts +94 -0
  822. package/src/components/Tooltip/Tooltip.module.scss +99 -0
  823. package/src/components/Tooltip/Tooltip.tokens.scss +23 -0
  824. package/src/components/Tooltip/Tooltip.tsx +341 -0
  825. package/src/components/Tooltip/index.ts +2 -0
  826. package/src/components/TopBar/TopBar.module.scss +235 -0
  827. package/src/components/TopBar/TopBar.tokens.scss +79 -0
  828. package/src/components/TopBar/TopBar.tsx +87 -0
  829. package/src/components/TopBar/TopBarEnd.tsx +20 -0
  830. package/src/components/TopBar/TopBarIconButton.tsx +86 -0
  831. package/src/components/TopBar/TopBarSearch.tsx +319 -0
  832. package/src/components/TopBar/TopBarSearchPanel.tsx +268 -0
  833. package/src/components/TopBar/TopBarStart.tsx +20 -0
  834. package/src/components/TopBar/index.ts +11 -0
  835. package/src/components/Tour/Spotlight.tsx +121 -0
  836. package/src/components/Tour/Tour.module.scss +210 -0
  837. package/src/components/Tour/Tour.tokens.scss +58 -0
  838. package/src/components/Tour/Tour.tsx +617 -0
  839. package/src/components/Tour/index.ts +2 -0
  840. package/src/components/Tour/useTourTarget.ts +115 -0
  841. package/src/components/TreeView/TreeView.module.scss +268 -0
  842. package/src/components/TreeView/TreeView.tokens.scss +36 -0
  843. package/src/components/TreeView/TreeView.tsx +536 -0
  844. package/src/components/TreeView/index.ts +3 -0
  845. package/src/components/TreeView/treeModel.ts +224 -0
  846. package/src/components/VisuallyHidden/VisuallyHidden.module.scss +7 -0
  847. package/src/components/VisuallyHidden/VisuallyHidden.tsx +29 -0
  848. package/src/components/VisuallyHidden/index.ts +2 -0
  849. package/src/components/WidgetPreview/WidgetPreview.module.scss +11 -0
  850. package/src/components/WidgetPreview/WidgetPreview.tokens.scss +26 -0
  851. package/src/components/WidgetPreview/WidgetPreview.tsx +36 -0
  852. package/src/components/WidgetPreview/WidgetShape.module.scss +140 -0
  853. package/src/components/WidgetPreview/WidgetShape.tsx +159 -0
  854. package/src/components/WidgetPreview/index.ts +2 -0
  855. package/src/components/_internal/Trend.tsx +27 -0
  856. package/src/components/_internal/choiceTile.scss +74 -0
  857. package/src/components/_internal/collapse.scss +10 -0
  858. package/src/components/_internal/collapse.ts +58 -0
  859. package/src/components/_internal/currency.ts +257 -0
  860. package/src/components/_internal/dragAnnouncements.ts +200 -0
  861. package/src/components/_internal/fieldWiring.ts +225 -0
  862. package/src/components/_internal/gridSpan.ts +54 -0
  863. package/src/components/_internal/isoDay.ts +35 -0
  864. package/src/components/_internal/letterKey.ts +26 -0
  865. package/src/components/_internal/overlay/focusRestore.ts +21 -0
  866. package/src/components/_internal/overlay/index.ts +12 -0
  867. package/src/components/_internal/overlay/tourHold.ts +23 -0
  868. package/src/components/_internal/overlay/useFocusTrap.ts +120 -0
  869. package/src/components/_internal/overlay/useInOverlay.ts +81 -0
  870. package/src/components/_internal/overlay/useOverlayStack.ts +232 -0
  871. package/src/components/_internal/overlay/useScrollLock.ts +112 -0
  872. package/src/components/_internal/refs.ts +48 -0
  873. package/src/components/_internal/statusColor.ts +26 -0
  874. package/src/components/_internal/timeUtils.ts +23 -0
  875. package/src/components/_internal/useAsyncOptions.ts +145 -0
  876. package/src/components/_internal/useClippedTooltip.ts +50 -0
  877. package/src/components/_internal/useControllableState.ts +50 -0
  878. package/src/components.manifest.json +1141 -0
  879. package/src/hooks/useBelowBreakpoint.ts +58 -0
  880. package/src/i18n/I18nProvider.tsx +52 -0
  881. package/src/i18n/LocaleProvider.tsx +17 -0
  882. package/src/i18n/en.ts +648 -0
  883. package/src/i18n/format.ts +71 -0
  884. package/src/i18n/index.ts +13 -0
  885. package/src/i18n/messages.ts +1275 -0
  886. package/src/i18n/ru.ts +677 -0
  887. package/src/i18n/useLocale.ts +19 -0
  888. package/src/i18n/useTranslation.ts +58 -0
  889. package/src/index.ts +913 -0
  890. package/src/palette/index.ts +2 -0
  891. package/src/palette/palette.ts +108 -0
  892. package/src/styles/dark.scss +4 -0
  893. package/src/styles/global.scss +7 -0
  894. package/src/styles/mixins.scss +143 -0
  895. package/src/styles/reset.scss +78 -0
  896. package/src/styles/tokens.scss +18 -0
  897. package/src/styles/typography.scss +44 -0
@@ -0,0 +1,45 @@
1
+ # `<PasswordInput>` — password field with eye toggle + optional warnings
2
+
3
+ ```tsx
4
+ <PasswordInput name="password" placeholder="Password" />
5
+ <PasswordInput capsLockWarning wrongLayoutWarning name="password" required />
6
+ <PasswordInput revealable={false} placeholder="Locked-down (no toggle)" />
7
+ ```
8
+
9
+ <!-- props:start -->
10
+
11
+ ## Props
12
+
13
+ <!-- prettier-ignore -->
14
+ | Prop | Type | Required | Description |
15
+ |---|---|---|---|
16
+ | `size` | `'sm' \| 'md' \| 'lg'` | no | Field height + type scale. Same scale as `<Input>`. Defaults to `'md'`. |
17
+ | `invalid` | `boolean` | no | Toggles the error visual + sets `aria-invalid="true"`. |
18
+ | `revealed` | `boolean` | no | Controlled revealed state. Pair with `onRevealChange`. |
19
+ | `defaultRevealed` | `boolean` | no | Initial revealed state for uncontrolled use. Defaults to `false`. |
20
+ | `onRevealChange` | `((revealed: boolean) => void)` | no | Called when the user clicks the eye toggle. Receives the next revealed state. |
21
+ | `revealable` | `boolean` | no | Whether to render the eye toggle button. Defaults to `true`. Set `revealable={false}` for compliance / kiosk screens where revealing is forbidden — the input then behaves like a plain locked-down `<input type='password'>`. |
22
+ | `capsLockWarning` | `boolean` | no | Opt-in caps-lock detection. When `true`, on every keypress the input reads `event.getModifierState('CapsLock')`; when active, a warning icon + polite `aria-live` announce it. Cleared on blur. Defaults to `false`. Opt in on screens where caps-lock matters (login, password creation, password confirmation). |
23
+ | `wrongLayoutWarning` | `boolean` | no | Opt-in wrong-keyboard-layout detection. When `true`, detects keystrokes that produce non-ASCII single characters (e.g., Cyrillic `ф` from a Russian layout). Shows a warning icon + polite live region. Cleared on blur. Heuristic, not deterministic — any non-ASCII keystroke triggers. Only enable when the system expects Latin-only password input. Defaults to `false`. |
24
+ | …native | | | plus native `<input>` attributes |
25
+
26
+ <!-- props:end -->
27
+
28
+ - Renders a real `<input type='password' | 'text'>` underneath — full autofill, RHF/Zod, form-submission integration.
29
+ - Eye toggle (`Eye` / `EyeOff`) flips `type`; `aria-pressed` exposes the state to AT. Toggle aria-labels come from `passwordInput.show` / `passwordInput.hide` in the i18n catalog.
30
+ - Both warnings can stack — they render in separate slots with separate live regions.
31
+ - Sizes: `sm` / `md` (default) / `lg`. Same scale as `<Input>`.
32
+ - `Omit<…, 'size' | 'type'>` — component locks `type` to password/text and shadows native `size`.
33
+
34
+ Pair with `<PasswordStrengthMeter>` for the canonical signup form, and controlled reveal via `revealed` / `onRevealChange`:
35
+
36
+ ```tsx
37
+ <PasswordInput name="password" capsLockWarning wrongLayoutWarning aria-describedby="pw-strength" />
38
+ <PasswordStrengthMeter id="pw-strength" value={password} />
39
+ ```
40
+
41
+ **When NOT to use:** non-secret single-line text — `<Input>`; multi-line secrets (paste-only API tokens) — `<Textarea>` (not shipped); systems that allow non-Latin passwords — do not set `wrongLayoutWarning`.
42
+
43
+ - ❌ `revealable={false}` plus a non-password `<Input>` next to it for "Show in plaintext" UX — use `<Input>` directly.
44
+ - ❌ Wrapping it in another `<label>` outside the component — it already renders the input; an outer label nests poorly.
45
+ - ❌ Treating the default `<PasswordStrengthMeter>` scoring as a security control — it is a UX hint; pass `score` from zxcvbn or server-side validation.
@@ -0,0 +1,27 @@
1
+ # `<PasswordStrengthMeter>` — 4-segment strength visualization
2
+
3
+ ```tsx
4
+ <PasswordStrengthMeter value={password} />
5
+ // or, with a real scorer (zxcvbn / server-side):
6
+ <PasswordStrengthMeter score={zxcvbnScore(password)} />
7
+ ```
8
+
9
+ <!-- props:start -->
10
+
11
+ ## Props
12
+
13
+ <!-- prettier-ignore -->
14
+ | Prop | Type | Required | Description |
15
+ |---|---|---|---|
16
+ | `value` | `string` | no | The password to evaluate. Required UNLESS `score` is provided. Evaluated via the default scoring heuristic or a consumer-supplied `scoreFn`. |
17
+ | `score` | `0 \| 1 \| 2 \| 3 \| 4` | no | Pre-computed score (0–4). Wins over `value` + `scoreFn` when both are present. Use this when scoring is done by zxcvbn or server-side. |
18
+ | `scoreFn` | `((value: string) => PasswordStrengthScore)` | no | Custom scoring fn. Receives the password, returns 0–4. Defaults to a length + character-class heuristic — fine for prototypes, NOT a security control. Production should pass a real scorer via `score`. |
19
+ | `showLabel` | `boolean` | no | Render the textual label next to the segments. Defaults to `true`. |
20
+ | …native | | | plus native `<div>` attributes |
21
+
22
+ <!-- props:end -->
23
+
24
+ - Two driving modes: `value` (uses default heuristic) or `score` (consumer-provided 0–4). `score` wins when both are set.
25
+ - **Default scoring is a UX hint, NOT a security control.** The heuristic flags long+mixed passwords as "Strong" even if they're in a breach corpus. Production deployments should pass `score` from a real scorer.
26
+ - Polite `aria-live` region announces label changes ("Weak" → "Fair" → "Strong") so screen-reader users hear progress as they type.
27
+ - Use `aria-describedby` on the paired `<PasswordInput>` to associate the meter with the field for AT.
@@ -0,0 +1,153 @@
1
+ # `<PersonDisplay>` — Avatar + name (+ optional description lines)
2
+
3
+ ```tsx
4
+ // Canonical: avatar + linked name + email
5
+ <PersonDisplay size="md">
6
+ <PersonDisplay.Avatar name="Sarah Chen" src="/avatars/sarah.png" />
7
+ <PersonDisplay.Name href="/contacts/sarah-chen">Sarah Chen</PersonDisplay.Name>
8
+ <PersonDisplay.Description>sarah@acme.com</PersonDisplay.Description>
9
+ </PersonDisplay>
10
+
11
+ // Multiple description lines (email + role)
12
+ <PersonDisplay size="md">
13
+ <PersonDisplay.Avatar name="Marcus Vega" />
14
+ <PersonDisplay.Name>Marcus Vega</PersonDisplay.Name>
15
+ <PersonDisplay.Description>marcus@acme.com</PersonDisplay.Description>
16
+ <PersonDisplay.Description>Account Executive</PersonDisplay.Description>
17
+ </PersonDisplay>
18
+
19
+ // Tight table cell — sm; name only
20
+ <PersonDisplay size="sm">
21
+ <PersonDisplay.Avatar name="Avery Liu" />
22
+ <PersonDisplay.Name>Avery Liu</PersonDisplay.Name>
23
+ </PersonDisplay>
24
+ ```
25
+
26
+ <!-- props:start -->
27
+
28
+ ## Props
29
+
30
+ ### `PersonDisplayProps`
31
+
32
+ <!-- prettier-ignore -->
33
+ | Prop | Type | Required | Description |
34
+ |---|---|---|---|
35
+ | `size` | `'inline' \| 'sm' \| 'md' \| 'lg'` | no | Visual size of the entire composition. `md` is the default — suits sidebars, members lists, and most card / table contexts. `sm` is the compact density for tight table cells; `lg` is the detail-page hero size. Propagates to the Avatar size and the Name / Description text sizes via context. `inline` fits a person into a text row: the Avatar is one line tall (`1lh`) and the Name inherits the surrounding text's size and weight (and colour, unless it has an `href` — then it's a subtle Link), so a person in a `DefinitionList` value or a table cell is exactly as tall as its plain-text neighbours. Follows the text size; no size decision per call site. Skip Descriptions — a second line defeats it. The root is a `<div>`, so not inside a `<p>`; in a line that also holds something taller than one line it top-aligns rather than sharing the baseline. |
36
+ | `shrink` | `boolean` | no | Force the composition to shrink-wrap to its content (avatar + name) instead of stretching to fill a parent. Default `false`. The root is `inline-flex` and shrink-wraps on its own — but as a child of a *stretching* flex/grid container (a detail/sidebar card column with `align-items: stretch` / `justify-self: stretch`) CSS blockifies it and the parent stretches it to the full column width. The avatar+name then sit in the left portion and the trailing empty space joins the box, so a `Popover.Trigger` / `Tooltip` cloned onto the PersonDisplay anchors to that wide box and centers far to the right of the person. Set `shrink` on such an overlay trigger to keep it content-width (`width: fit-content`) regardless of the parent, so the overlay anchors to the visible avatar+name. |
37
+ | `children` | `ReactNode` | yes | `<PersonDisplay.Avatar>` (or `<PersonDisplay.AgentAvatar>`) + `<PersonDisplay.Name>` (+ optional `<PersonDisplay.OnBehalfOf>` and repeating `<PersonDisplay.Description>`) subcomponents in any order — Root sorts the avatar into its own slot. With an `OnBehalfOf`, Name and OnBehalfOf share one truncating row above the Descriptions. |
38
+ | …native | | | plus native `<div>` attributes |
39
+
40
+ ### `PersonDisplayAgentAvatarProps`
41
+
42
+ <!-- prettier-ignore -->
43
+ | Prop | Type | Required | Description |
44
+ |---|---|---|---|
45
+ | `name` | `string` | yes | Agent label. Not announced here: the avatar is decorative, and the visible `PersonDisplay.Name` (pass the same label) names the agent. |
46
+ | `mark` | `ReactNode` | no | Agent mark, inherits `currentColor` (a neutral foreground), so pass a glyph drawn with `fill`/`stroke="currentColor"`; marks with hard-coded fills keep their colours (the app's responsibility). Defaults to a lucide `Bot`. |
47
+ | `member` | `AgentAvatarMember \| null` | no | The member the agent acts for. Omit for an agent alone (no badge); `null` or an empty name for an erased member (placeholder badge). |
48
+ | …native | | | plus native HTML attributes |
49
+
50
+ ### `PersonDisplayAvatarProps`
51
+
52
+ <!-- prettier-ignore -->
53
+ | Prop | Type | Required | Description |
54
+ |---|---|---|---|
55
+ | `name` | `string` | yes | The person's name. Required — used as the `alt`/`aria-label`, as the source of the initials, and as the seed for the deterministic fallback color. The same name always renders the same color. When `tooltip` is true, also used as the tooltip body. |
56
+ | `src` | `string` | no | Image URL. When provided, the `<img>` is rendered with `alt={name}`. Empty/whitespace strings are treated as missing. If the image fails to load (404, network), the component automatically falls back to initials. |
57
+ | `status` | `'online' \| 'busy' \| 'away' \| 'offline'` | no | Presence dot in the bottom-right. - `'online'` — green. - `'busy'` — red. - `'away'` — amber (the categorical amber, dark enough to read at dot size). - `'offline'` — gray. Omit to render no dot at all. Setting `status` changes the accessible name to `"{name}, {status}"` (localized), because colour alone cannot carry the status (WCAG 1.4.1); query with `getByRole('img', { name: 'Alex, online' })`. Each status also renders a distinct shape (filled / half / barred / hollow), so it survives colour-vision deficiency and greyscale; the dot stays `aria-hidden` so nothing is announced twice. |
58
+ | `tooltip` | `boolean` | no | Whether to wrap the avatar in a `<Tooltip>` showing `name`. Defaults to `false` (back-compat — existing renders don't gain a hover affordance). Inside `<AvatarGroup>`, the group's `tooltip` prop becomes the default (which itself defaults to `true` for grouped avatars); explicit per-child still wins. |
59
+ | …native | | | plus native HTML attributes |
60
+
61
+ ### `PersonDisplayDescriptionProps`
62
+
63
+ <!-- prettier-ignore -->
64
+ | Prop | Type | Required | Description |
65
+ |---|---|---|---|
66
+ | `children` | `ReactNode` | yes | One line of descriptive metadata — email, role, company, etc. Repeat the subcomponent for additional lines; each renders on its own row beneath the name. Accepts arbitrary `ReactNode` children so consumers can inline a `<Badge>` or other small decoration. |
67
+ | …native | | | plus native `<span>` attributes |
68
+
69
+ ### `PersonDisplayNameProps`
70
+
71
+ <!-- prettier-ignore -->
72
+ | Prop | Type | Required | Description |
73
+ |---|---|---|---|
74
+ | `href` | `string` | no | When set, the name renders as a `<Link>` to this URL. Use for navigable people (contacts, members) where the row links to a detail page. Omit for read-only displays (audit actor, activity timeline) where the name is plain text. |
75
+ | `children` | `ReactNode` | yes | The person's display name — usually a plain string. |
76
+ | …native | | | plus native HTML attributes |
77
+
78
+ ### `PersonDisplayOnBehalfOfProps`
79
+
80
+ <!-- prettier-ignore -->
81
+ | Prop | Type | Required | Description |
82
+ |---|---|---|---|
83
+ | `children` | `ReactNode` | no | The member the agent acts for, rendered after a muted "for" prefix. A plain name, or a `<Link>` to the member. Omit (or pass an empty string) when the member was erased: renders "for a former member". Plain-text children (a string, a number, or text-only nodes like `{first} {last}`) give the member box a hover `title` of the full "for {member}" text (the erased copy when erased), which shadows a consumer `title` on OnBehalfOf; a `<Link>` or other element child gets none. The root span is `display: contents` (its prefix and member join the Name's row), so box styles passed via `className`/`style` on it don't paint. |
84
+ | …native | | | plus native `<span>` attributes |
85
+
86
+ <!-- props:end -->
87
+
88
+ - Compound: `<PersonDisplay>` + `<PersonDisplay.Avatar>` (or `<PersonDisplay.AgentAvatar>`) + `<PersonDisplay.Name>` (+ `<PersonDisplay.OnBehalfOf>`) + repeating `<PersonDisplay.Description>`. Inside the agent row, Name always renders before OnBehalfOf whatever the child order.
89
+ - `<PersonDisplay.Name href="...">` renders the name as a `<Link variant="subtle">` (real `<a>`) — `Link`'s `variant="subtle"` is **not** deprecated, unlike `Text`/`Title`'s `tone="subtle"`; do not "fix" it. Omit `href` for read-only displays (audit actor, activity timeline).
90
+ - **A Description clips itself on the inline axis** (`overflow-x: clip`, `white-space: nowrap`), so a long unbroken value cannot paint outside a narrow container such as a DataTable stacked card. Put **interactive** content in `<PersonDisplay.Name href=…>`, which does not clip (except inside the agent row, where the Name clips on the inline axis like the OnBehalfOf next to it): a control flush with the Description line's left or right edge loses those bands of its focus ring, and that residual is recorded in `tests/focus-ring-geometry.baseline.json` rather than hidden. The block axis is deliberately left `visible`, so a ring is never clipped top or bottom.
91
+ - All Avatar props (`name`, `src`, `status`, `tooltip`) flow through `<PersonDisplay.Avatar>` except `size`.
92
+ - **Use for the standard "person row" — Avatar + name + 0–2 muted lines.** Not for Avatar-only badges (use `<Avatar>`), avatar stacks (use `<AvatarGroup>`), or click-anywhere row interactions (wrap PersonDisplay in your own Link).
93
+
94
+ ```tsx
95
+ // Inline — a DefinitionList value, as tall as the text rows around it
96
+ <PersonDisplay size="inline">
97
+ <PersonDisplay.Avatar name="Avery Liu" />
98
+ <PersonDisplay.Name href="/members/avery">Avery Liu</PersonDisplay.Name>
99
+ </PersonDisplay>
100
+ ```
101
+
102
+ `<PersonDisplay.Avatar>` is a thin wrapper around `<Avatar>`; it reads its size from the root and all other Avatar props (`status`, etc.) flow through. `<PersonDisplay.Name>` text size also follows the root `size`.
103
+
104
+ - This is always a horizontal avatar-left layout; for a "profile hero" with a centered avatar above the name, compose by hand.
105
+
106
+ **Anti-patterns**
107
+
108
+ - ❌ Wrapping the whole PersonDisplay in a `<Link>` just to link the person — the Name owns that via `href`. (Wrap it only for click-anywhere row interactions, as above.)
109
+ - ❌ `size="sm"` for a person among text values (a `DefinitionList`, a sentence) — the 24px avatar makes that row taller than its neighbours. Use `size="inline"`.
110
+ - ❌ Descriptions under `size="inline"` — the second line is exactly the extra height `inline` exists to avoid.
111
+ - ❌ Wrapping `<PersonDisplay.Avatar>` in a Fragment or a custom component — the root identifies the Avatar slot by element type, so a wrapped Avatar lands in the text column. Render it as a direct child; use `{shouldShow ? <PersonDisplay.Avatar … /> : null}` for conditional rendering (`null`/`false` are ignored).
112
+
113
+ ## Agent acting for a member
114
+
115
+ ```tsx
116
+ // AI agent acting on behalf of a member
117
+ <PersonDisplay size="md">
118
+ <PersonDisplay.AgentAvatar name="Scout" member={{ name: 'Sarah Chen', src: '/avatars/sarah.png' }} />
119
+ <PersonDisplay.Name>Scout</PersonDisplay.Name>
120
+ <PersonDisplay.OnBehalfOf>Sarah Chen</PersonDisplay.OnBehalfOf>
121
+ <PersonDisplay.Description>Enrichment agent</PersonDisplay.Description>
122
+ </PersonDisplay>
123
+
124
+ // Member erased: placeholder badge + "for a former member"
125
+ <PersonDisplay size="md">
126
+ <PersonDisplay.AgentAvatar name="Scout" member={null} />
127
+ <PersonDisplay.Name>Scout</PersonDisplay.Name>
128
+ <PersonDisplay.OnBehalfOf />
129
+ </PersonDisplay>
130
+
131
+ // Inline: a text row, no member badge; Name + "for Sarah Chen" read as one line
132
+ <PersonDisplay size="inline">
133
+ <PersonDisplay.AgentAvatar name="Scout" member={{ name: 'Sarah Chen' }} />
134
+ <PersonDisplay.Name>Scout</PersonDisplay.Name>
135
+ <PersonDisplay.OnBehalfOf>Sarah Chen</PersonDisplay.OnBehalfOf>
136
+ </PersonDisplay>
137
+ ```
138
+
139
+ - **Three member states** (pass the same state to `AgentAvatar.member` and `OnBehalfOf`): a member (`{ name, src? }` / name child) shows the badge and "for {member}"; `member` omitted = agent alone (no badge, no `OnBehalfOf`); `member={null}` or an empty name = erased, placeholder badge and "for a former member".
140
+ - `PersonDisplay.AgentAvatar` takes the `AgentAvatar` props minus `size` (from the root) and `decorative`. It is **decorative** inside PersonDisplay (`aria-hidden`): the visible Name and `OnBehalfOf` already carry both identities, so nothing is announced twice. The standalone `AgentAvatar` is `role="img"` unless you pass `decorative` (see [AgentAvatar](AgentAvatar.md)).
141
+ - `OnBehalfOf` children: a plain name or a `<Link>` to the member. The "for" prefix is localized.
142
+ - Name and `OnBehalfOf` share one truncating row: the prefix never shrinks, the member ellipsises down to roughly 6ch, then the Name ellipsises. Descriptions sit below.
143
+ - A `<Link>` in `OnBehalfOf` keeps its whole focus ring: the member box pads both inline ends by the ring's extent. Only a member Link that is itself truncated loses its trailing ring band, because the Link runs past the clip edge; its start, top and bottom bands stay.
144
+ - As a flex item (e.g. an activity row `<Cluster wrap={false}>` of IconTile + PersonDisplay + timestamp) the root shrinks (`min-width: 0`) and truncates instead of overflowing. Its siblings shrink too unless you keep them whole: wrap them in `<Constrain flex="none">`.
145
+ - `OnBehalfOf`'s root is `display: contents`, so box styles (background, border, padding) passed via `className` / `style` on it don't paint; style the child you pass. When its children are plain text (a string, a number, or text-only nodes like `{first} {last}`), or the member is erased, the member box gets a hover `title` with the full "for {member}" text (or the erased copy). Over the member box that shadows a consumer `title` passed to `OnBehalfOf`. A `<Link>` or other element child gets no `title`.
146
+ - `inline` hides the member badge and keeps the agent on one text line.
147
+
148
+ **Agent anti-patterns**
149
+
150
+ - ❌ Using the agent parts for a human. Agents only; a person is `PersonDisplay.Avatar`.
151
+ - ❌ Passing a multi-colour brand `mark` and expecting it to come out neutral. The tile only sets `color` (a neutral foreground); draw the glyph with `fill`/`stroke="currentColor"`. Hard-coded fills keep their colours, which is the app's responsibility.
152
+ - ❌ Deriving the brand `mark` from a client-chosen name. Pick the mark from a trusted, server-known agent identity, or an agent can impersonate another product.
153
+ - ❌ Adding a "bot" / "AI" kind chip next to the Name. The tile and "for {member}" already signal it.
@@ -0,0 +1,54 @@
1
+ # `<PhoneInput>`
2
+
3
+ International phone field: searchable country picker (DS `Select`) + national-number `Input`, controlled on a single `value: string | null` (**E.164**), `onChange(e164 | null)`. `defaultCountry` (ISO alpha-2) seeds the picker when empty; `countries` restricts the list; `size`/`invalid`/`disabled` pass through. Country names are localized via `Intl.DisplayNames`; metadata/validation via `libphonenumber-js`. Validate with the exported `isValidPhone(e164)` and drive `invalid` (or wrap in `<Field error>`). `countryDisplay` sets how the SELECTED country shows in the trigger — `"code"` (default, `+1`), `"iso"` (`US +1`), `"name"` (`United States +1`), or `"flag"` (`🇺🇸 +1`; emoji flags don't render on Windows Chrome/Edge). Dropdown rows always show the full name + code (searchable); opening the picker selects the text for instant type-to-search; the country can't be cleared. The picker's accessible name is composed from the group's (`<Field label="Phone">` → "Phone Country"), so it never collides with a form's own Country field; `countryLabel` overrides it. Store the emitted E.164, not the formatted display.
4
+
5
+ ```tsx
6
+ const [phone, setPhone] = useState<string | null>(null);
7
+ <PhoneInput value={phone} onChange={setPhone} defaultCountry="GB" />;
8
+ ```
9
+
10
+ <!-- props:start -->
11
+
12
+ ## Props
13
+
14
+ <!-- prettier-ignore -->
15
+ | Prop | Type | Required | Description |
16
+ |---|---|---|---|
17
+ | `value` | `string \| null` | yes | Controlled E.164 value (e.g. `"+442071838750"`); `null` = empty. |
18
+ | `onChange` | `(e164: string \| null) => void` | yes | Fires with canonical E.164 on every edit; `null` when empty. |
19
+ | `defaultCountry` | `string` | no | ISO 3166-1 alpha-2 country used to seed the picker when `value` is empty. Default `"US"`. |
20
+ | `countries` | `string[]` | no | Restrict the picker to this ISO-code subset. Defaults to all libphonenumber-js countries. An empty array is treated as all countries. |
21
+ | `countryDisplay` | `'flag' \| 'iso' \| 'name' \| 'code'` | no | How the SELECTED country renders in the picker trigger. Default `"code"`. - `"code"` — calling code only (`+1`). - `"iso"` — ISO code + code (`US +1`). - `"name"` — full country name + code (`United States +1`). - `"flag"` — emoji flag + code (`🇺🇸 +1`). Note: emoji flags don't render on Windows Chrome/Edge (they show the letters), so prefer `"iso"` there. The dropdown rows always show the full country name + code (plus a flag in `"flag"` mode) so they stay searchable + identifiable regardless of this. |
22
+ | `countryLabel` | `string` | no | Overrides the country picker's full accessible name. By default the picker is named after the group — "<group label> Country" (e.g. "Phone Country") — so it never collides with a form's own Country field; with no group label it is just "Country". Set this when that composed name reads badly. |
23
+ | `size` | `'sm' \| 'md' \| 'lg'` | no | Control size, forwarded to the Select + Input. Default `"md"`. |
24
+ | `invalid` | `boolean` | no | Error chrome on both controls (host/Field-driven). |
25
+ | `disabled` | `boolean` | no | Disable both controls. |
26
+ | `required` | `boolean` | no | Mark required (forwarded for Field semantics). |
27
+ | `locale` | `string` | no | BCP-47 locale for country-name localization. Defaults to the i18n locale, else `"en"`. |
28
+ | `id` | `string` | no | Stable id; placed on the number field so an external `<label htmlFor>` focuses it. |
29
+ | `aria-label` | `string` | no | Accessible name when used STANDALONE (outside `<Field>`). A standalone PhoneInput MUST be named via `aria-label` or `aria-labelledby`, else the country/number group is unnamed. Inside `<Field>` the label is wired automatically via `aria-labelledby`. |
30
+ | `aria-labelledby` | `string` | no | Ids of elements labelling the group (injected by `<Field>`; takes precedence over `aria-label`). |
31
+ | `aria-describedby` | `string` | no | Ids of description/error elements; forwarded to the number field so it is announced on focus (injected by `<Field>`). |
32
+ | …native | | | plus native `<div>` attributes |
33
+
34
+ <!-- props:end -->
35
+
36
+ Inside a `<Field>` the label and error wiring are injected:
37
+
38
+ ```tsx
39
+ <Field label="Mobile" error={isValidPhone(phone) ? undefined : 'Invalid number'}>
40
+ <PhoneInput value={phone} onChange={setPhone} />
41
+ </Field>
42
+ ```
43
+
44
+ **When NOT to use:** a non-phone numeric field — `<Input type="tel">` or `<Input inputMode="numeric">`.
45
+
46
+ **Anti-patterns**
47
+
48
+ - ❌ Treating it as uncontrolled — feed `onChange`'s E.164 back into `value`.
49
+ - ❌ Storing the formatted national string — persist the emitted E.164; the display is reconstructed from it.
50
+ - ❌ Validating by hand — call `isValidPhone(e164)` and pass `invalid` (or wire it through `<Field error>`).
51
+
52
+ **Known limitations**
53
+
54
+ - Format-as-you-type moves the caret to the end of the number field after each reformat; editing in the middle of the number bounces the caret to the end.
@@ -0,0 +1,91 @@
1
+ # `<PillMenu>` — coloured value menu (status, type, priority…)
2
+
3
+ Renamed from `StatusMenu` — `StatusMenu` / `StatusMenuProps` / `StatusMenuStatus` / `StatusMenuCategory` no longer exist; use `PillMenu` / `PillMenuProps` / `PillMenuOption` / `PillMenuCategory`. Component tokens are `--pill-menu-*`, the i18n namespace is `pillMenu`.
4
+
5
+ ```tsx
6
+ <PillMenu
7
+ current={{ id: 'todo', name: 'To do', category: 'to_do' }}
8
+ options={[
9
+ { id: 'in_progress', name: 'In progress', category: 'in_progress' },
10
+ { id: 'done', name: 'Done', category: 'done' },
11
+ ]}
12
+ onSelect={(id) => updateStatus(task.id, id)}
13
+ />
14
+
15
+ // Read-only chip — omit `options` for a static colored chip, no menu:
16
+ <PillMenu current={{ id: 'won', name: 'Won', category: 'won' }} />
17
+
18
+ // Not a status: label the trigger and add per-value icons:
19
+ <PillMenu
20
+ label="type"
21
+ current={{ id: 'bug', name: 'Bug', color: 'red', icon: <Bug size={14} /> }}
22
+ options={[{ id: 'story', name: 'Story', color: 'green', icon: <BookOpen size={14} /> }]}
23
+ onSelect={setType}
24
+ />
25
+ // → trigger announced "Change type: Bug"
26
+
27
+ // Say what it picks AND the value — visible caption, muted, before a middle dot:
28
+ <PillMenu caption="Pipeline" current={pipeline} options={pipelines} onSelect={setPipeline} />
29
+ // → shows "Pipeline · Faeton", announced "Change Pipeline: Faeton" (a string caption names the trigger when `label` is absent)
30
+
31
+ // Pass `label` too when the name needs another form (e.g. ru accusative) — keep the caption's words in it:
32
+ <PillMenu label="воронку" caption="Воронка" current={pipeline} options={pipelines} onSelect={setPipeline} />
33
+ // → announced "Изменить воронку: Faeton"
34
+ ```
35
+
36
+ <!-- props:start -->
37
+
38
+ ## Props
39
+
40
+ <!-- prettier-ignore -->
41
+ | Prop | Type | Required | Description |
42
+ |---|---|---|---|
43
+ | `current` | `PillMenuOption` | yes | The value currently shown on the trigger (or the read-only chip). |
44
+ | `label` | `string` | no | What the value IS, for the trigger's accessible name: `label="type"` → "Change type: Bug". Default: a string `caption` ("Change Pipeline: …"), else the localized "status" ("Change status: …"). Pass it as it reads right after "Change" / "Изменить", lower-case, in the UI's language — it is data, not a translatable string. In ru that is the accusative: `label="категорию"`, not "категория". Inside a `<Field>`, pass the field's label here (`label="priority"` under "Priority"): the trigger keeps its own name, so the visible field label reaches AT only through this (WCAG 2.5.3). A dev warning fires if it's missing there. |
45
+ | `caption` | `ReactNode` | no | Visible caption rendered inside the pill before the value, separated by a middle dot: `caption="Pipeline"` → "Pipeline · Faeton". For a trigger that must say both what it picks and the current value. Names the trigger only as a fallback: `label` wins ("Change pipeline: Faeton"); with no `label`, a non-blank string caption is used ("Change Pipeline: Faeton") so the visible words stay in the accessible name (WCAG 2.5.3 label-in-name). A non-string caption never names it — pass `label` then, containing the caption's words. In the read-only chip (no accessible name override) the caption text is read along with the value; the dot is `aria-hidden` in both. Muted by weight (regular vs the value's medium), not colour: the palette fills leave no contrast headroom for a dimmer foreground. Omitted or blank → no caption, no dot. |
46
+ | `options` | `PillMenuOption[]` | no | Transition targets, offered in the dropdown. Omitted or empty renders read-only mode: a static colored chip with no button, no menu, no aria-haspopup. |
47
+ | `onSelect` | `((id: string \| number) => void)` | no | Fired with the chosen option's `id` when a transition target is picked. |
48
+ | `disabled` | `boolean` | no | Disables the trigger. Stays colored, dims via opacity. |
49
+ | `busy` | `boolean` | no | Transition in flight: the trigger is non-interactive and keeps its color. Announced from a polite live region the component owns — `aria-busy` is also set but reaches no screen reader on its own. The trigger's accessible name does not change (contrast `EntityChip`): you activated this control, so the change is announced rather than folded into the name. No effect in read-only mode (no `options`), which renders no trigger and so has nothing to mark busy. |
50
+ | `fullWidth` | `boolean` | no | Stretch the trigger (or read-only chip) to its container's width, for a form column of full-width controls (`Input`, `Select`, `DatePicker` in vertical `Field`s). Icon + name stay at the start, the chevron moves to the end edge like a `Select` trigger, and the menu is at least as wide as the trigger. Keeps the full-colour fill. Defaults to `false` (content-width pill). |
51
+ | `invalid` | `boolean` | no | Error state — sets `aria-invalid` on the trigger. `<Field error>` injects it for you. No visual change: the fill IS the value's colour, and the Field's error text carries the error. The read-only chip ignores it (a non-focusable chip isn't a control AT can report invalid). |
52
+ | …native | | | plus native HTML attributes |
53
+
54
+ <!-- props:end -->
55
+
56
+ - A coloured pill trigger that opens a menu of values, each row coloured to its own value — a workflow status, a task type, a priority. Composes `<DropdownMenu>` internally.
57
+ - `icon?: ReactNode` on `current` and on each option renders before the name in the pill and in its row, `aria-hidden` (decorative — the name is announced). Size it to the text (~14px, at most 16px — menu rows use a fixed 16px slot).
58
+ - `current` / each option: `{ id, name, category?, color? }`. `category` (`to_do` / `in_progress` / `open` / `done` / `won` / `lost`) maps to a default palette color (slate / blue / violet / green / green / red); `color` (a `PaletteColor`) overrides it per-status.
59
+ - `attrs` (``Record<`data-${string}`, string>``) on `current` is spread onto the trigger button (or the read-only chip); on an option, onto its menu row. It goes before the component's own attributes, so a key can't override the `id`/`role`/`aria-*`/handlers the component owns (on a menu row, also the row's `data-tone`). A `data-*` passed on `<PillMenu>` itself beats `current.attrs`. **Anti-pattern:** when `current` is the same object as an entry in `options` (`current={options.find(...)}`), its attrs land on both the pill and that menu row, so two elements carry the same `data-tour` while the menu is open. Give `current` its own attrs: `current={{ ...opt, attrs: { 'data-tour': 'stage-pill' } }}`. Use it to target a pill from a `Tour` or to add a test/analytics id: `current={{ id: 1, name: 'Open', attrs: { 'data-tour': 'status-pill' } }}`, then `<Tour steps={[{ target: 'status-pill', title: '...' }]} />`.
60
+ - Not for a plain action menu (use `<DropdownMenu>`), a non-interactive status with no transition (use `<Badge>`), or picking from a long searchable list (use `<Select>`).
61
+
62
+ Per-state colour override (`color` wins over `category`):
63
+
64
+ ```tsx
65
+ <PillMenu
66
+ current={{ id: 'triage', name: 'Triage', color: 'amber' }}
67
+ options={[{ id: 'won', name: 'Won', category: 'won', color: 'emerald' }]}
68
+ onSelect={(id) => setStage(id)}
69
+ />
70
+ ```
71
+
72
+ In a form column beside full-width Selects/Inputs, pass `fullWidth` and `label` (the trigger keeps its own name, "Change priority: High"):
73
+
74
+ ```tsx
75
+ <Field label="Priority" error={errors.priority}>
76
+ <PillMenu
77
+ fullWidth
78
+ label="priority"
79
+ current={priority}
80
+ options={priorities}
81
+ onSelect={setPriority}
82
+ />
83
+ </Field>
84
+ ```
85
+
86
+ **Anti-patterns**
87
+
88
+ - ❌ A small `<Badge>` wrapped inside a neutral `<Button>` to fake a coloured status trigger — that is what `PillMenu` replaces.
89
+ - ❌ Raw hex strings in `color` — it is a `PaletteColor` name (`'amber'`, `'violet'`, …), not a CSS colour value.
90
+ - ❌ A non-string (or blank) `caption` without `label` — only a non-blank string caption falls back as the name; a node leaves "Change status: …", which fails WCAG 2.5.3 label-in-name. Pass `label` containing the caption's words.
91
+ - ❌ Omitting `options` to "disable" the menu — that is read-only mode (no interactivity at all). For a transition that is temporarily blocked, keep `options` and pass `disabled`.
@@ -0,0 +1,127 @@
1
+ # `<Popover>` — non-modal floating panel for interactive content
2
+
3
+ ```tsx
4
+ <Popover>
5
+ <Popover.Trigger>
6
+ <Button variant="secondary">Filters</Button>
7
+ </Popover.Trigger>
8
+ <Popover.Content>
9
+ <Stack gap="sm">
10
+ <Popover.Heading>Filter results</Popover.Heading>
11
+ {/* …form controls… */}
12
+ <Cluster justify="end" gap="sm">
13
+ <Popover.Close>
14
+ <Button variant="secondary" size="sm">
15
+ Cancel
16
+ </Button>
17
+ </Popover.Close>
18
+ <Popover.Close>
19
+ <Button size="sm" onClick={apply}>
20
+ Apply
21
+ </Button>
22
+ </Popover.Close>
23
+ </Cluster>
24
+ </Stack>
25
+ </Popover.Content>
26
+ </Popover>
27
+ ```
28
+
29
+ <!-- props:start -->
30
+
31
+ ## Props
32
+
33
+ ### `PopoverProps`
34
+
35
+ <!-- prettier-ignore -->
36
+ | Prop | Type | Required | Description |
37
+ |---|---|---|---|
38
+ | `children` | `ReactNode` | yes | Must contain exactly one `<Popover.Trigger>` (or `<Popover.Anchor>` for a controlled popover whose anchor owns its own toggle + ARIA) and one `<Popover.Content>`. `<Popover.Heading>` and `<Popover.Close>` are optional and may appear anywhere inside `<Popover.Content>`. |
39
+ | `open` | `boolean` | no | Controlled open state. Provide alongside `onOpenChange` to drive open externally. Omit both to let Popover own its state (the common case). |
40
+ | `onOpenChange` | `((open: boolean) => void)` | no | Fired whenever Popover wants to change open state. Required when `open` is provided. |
41
+ | `defaultOpen` | `boolean` | no | Default open state for uncontrolled usage. Defaults to `false`. |
42
+ | `modal` | `boolean` | no | Reserved future hint. v1 ignores the value and always renders non-modal. Will gate focus-trap + inert-background once `<Modal>` lands. |
43
+
44
+ ### `PopoverAnchorProps`
45
+
46
+ <!-- prettier-ignore -->
47
+ | Prop | Type | Required | Description |
48
+ |---|---|---|---|
49
+ | `children` | `ReactElement<unknown, string \| JSXElementConstructor<any>>` | yes | Exactly one React element that accepts a ref. Unlike `Popover.Trigger`, Anchor injects ONLY the floating-positioning ref — no `onClick`, no keyboard handler, and no `aria-haspopup` / `aria-expanded` / `aria-controls`. Use it when the anchor element already owns its open-toggle and ARIA (e.g. an interactive `FilterChip` whose body `<button>` self-manages `aria-haspopup`/`aria-expanded`), and you drive the popover's open state yourself (controlled `open` + `onOpenChange`). The child must accept a ref (`forwardRef`); raw DOM elements and this library's components qualify, and it should be focusable (a `<button>` or `tabIndex` host) so Escape can return focus to it on close. Wrapping such a chip in `Popover.Trigger` instead would stamp that ARIA onto its `role="group"` root, not the body button. |
50
+
51
+ ### `PopoverCloseProps`
52
+
53
+ <!-- prettier-ignore -->
54
+ | Prop | Type | Required | Description |
55
+ |---|---|---|---|
56
+ | `children` | `ReactElement<unknown, string \| JSXElementConstructor<any>>` | yes | Exactly one React element. The Close clones this element to inject an `onClick` that closes the popover, chained with the child's existing `onClick` (consumer runs first). |
57
+
58
+ ### `PopoverContentProps`
59
+
60
+ <!-- prettier-ignore -->
61
+ | Prop | Type | Required | Description |
62
+ |---|---|---|---|
63
+ | `side` | `'top' \| 'right' \| 'bottom' \| 'left'` | no | Preferred side. Default `'bottom'`. Auto-flips on collision via Floating UI. |
64
+ | `align` | `'start' \| 'center' \| 'end'` | no | Edge alignment. Default `'center'`. |
65
+ | `sideOffset` | `number` | no | Gap in px between trigger and panel. Default `10` (room for the arrow). |
66
+ | `minWidth` | `string \| number` | no | Minimum width in px or any CSS length. Defaults to the token `--size-popover-min-width` (220px) applied via SCSS. |
67
+ | `maxWidth` | `string \| number` | no | Maximum width in px or any CSS length, overriding the default cap (`--popover-max-width`, 360px). Use for wide content — calendars, tables — that would otherwise overflow the panel. Accepts a number (px), `'fit-content'`, `'none'` to remove the cap, or any CSS length. |
68
+ | …native | | | plus native `<div>` attributes |
69
+
70
+ ### `PopoverHeadingProps`
71
+
72
+ <!-- prettier-ignore -->
73
+ | Prop | Type | Required | Description |
74
+ |---|---|---|---|
75
+ | `as` | `'h2' \| 'h3' \| 'h4' \| 'h5' \| 'h6'` | no | Heading level. Defaults to `'h3'`. Pick the level that fits the surrounding document outline (Popover content is usually a level 3 inside a level 2 section). |
76
+ | …native | | | plus native `<h1–h6>` attributes |
77
+
78
+ ### `PopoverTriggerProps`
79
+
80
+ <!-- prettier-ignore -->
81
+ | Prop | Type | Required | Description |
82
+ |---|---|---|---|
83
+ | `children` | `ReactElement<unknown, string \| JSXElementConstructor<any>>` | yes | Exactly one React element that accepts a ref. The Trigger clones this element to inject `aria-haspopup`, `aria-expanded`, `aria-controls`, a click handler that toggles the popover, and a keydown handler that opens on Enter/Space. `<Button>` and raw `<button>` both qualify; a custom component without `forwardRef` does not. |
84
+ | `aria-haspopup` | `'true' \| 'false' \| 'dialog' \| 'grid' \| 'listbox' \| 'menu' \| 'tree'` | no | Override the `aria-haspopup` value injected onto the trigger child. Defaults to `'dialog'` (matching the role of `Popover.Content`). Pass `'listbox'` for picker-style compound usages where the popover surfaces a listbox rather than a generic dialog. |
85
+
86
+ <!-- props:end -->
87
+
88
+ - Compound API: `<Popover>` is the provider; `<Popover.Trigger>` clones its single child to inject ARIA + click; `<Popover.Content>` portals to `document.body` and positions via Floating UI; `<Popover.Heading>` (optional) wires `aria-labelledby`; `<Popover.Close>` clones its child to inject a close-onClick.
89
+ - Trigger child must accept a ref (`forwardRef`). `<Button>` does.
90
+ - **Non-modal**: focus moves to the panel on open; Tab traverses INTO content, then OUT to the page behind. Click-outside or Escape dismisses. Page is NOT inert.
91
+ - Opens with a short scale-fade from the trigger side (140ms). Closes instantly. Respects `prefers-reduced-motion: reduce`.
92
+ - **From a DropdownMenu item.** Wrap a `<DropdownMenu.Item closeOnSelect={false}>` as the `<Popover.Trigger>` child — the Item itself becomes the trigger, so the full highlighted row opens the popover. `closeOnSelect={false}` keeps the menu open while the popover is shown.
93
+ - Z-layer `--z-popover: 1050` — above dropdown, below modal/toast/tooltip.
94
+ - **Overlay host for nested floating surfaces.** A `Popover.Content` (and a `DropdownMenu` content panel) acts as an overlay host: any floating surface (`DropdownMenu` / `Popover` / `ConfirmationPopover` / `Select` / `DatePicker` / `DateRangePicker` / `TimeField` / the `Rail.Group` flyout) whose trigger sits inside it auto-elevates to `--z-overlay-floating` (1190), so a kebab menu, nested popover, or confirm dialog opened from within a Popover panel stacks ABOVE the panel instead of rendering behind it. No prop needed — it keys off the existing `[data-popover-content]` / `[data-dropdown-menu-content]` markers, plus `[data-in-overlay]` itself (elevation is transitive: a surface nested inside an elevated surface elevates too). The Popover also won't dismiss itself when you interact with such a nested surface (its content portals to `document.body`, so a click inside it would otherwise read as "outside") — so a kebab menu item or its confirm dialog stays usable without collapsing the host.
95
+ - **Escape is innermost-first across nested surfaces.** When one floating surface is open inside another — a `Select` listbox inside a `Popover`, a `ConfirmationPopover` opened from a `DropdownMenu` item, etc. — the first `Escape` closes only the **innermost** surface; the outer one (and any host `Modal`/`Drawer`) survives that press. Each press peels exactly one layer. Surfaces coordinate via the shared overlay registry (`isTopFloating`) — the most-recently-opened is innermost — so no per-pair wiring is needed.
96
+ - **Tall content:** a Popover is capped at the viewport only when it holds a `<ScrollArea>`. Wrap the long part (a feed, a list) in `<ScrollArea maxHeight="md">`; the header above it stays put. Without one, a tall popover runs off-screen. Recipe (notification centre): `Popover.Content minWidth={380}` → `Stack` → header `Cluster` (`Popover.Heading` + "Mark all as read" Button) + `ScrollArea maxHeight="md" aria-label="Notifications"`.
97
+ - For passive hover/focus hints → `<Tooltip>`. For lists of actions → `<DropdownMenu>`. For focus-locked dialogs → `<Modal>`.
98
+
99
+ - `<Popover.Content>` is `role="dialog"` with `aria-modal="false"` and `tabIndex={-1}` so it can take focus on open, and renders an `aria-hidden` arrow that tracks the trigger.
100
+ - `<Popover.Close>` wraps exactly one React element child (it throws otherwise); the child's own `onClick` chains and runs first. `<Popover.Heading>` unsubscribes its `aria-labelledby` registration on unmount.
101
+ - **`<ScrollArea>` placement:** keep it a direct child of `<Popover.Content>`, or inside one wrapper element that is a direct child. That wrapper must lay its children out as a column — a `<Stack>`, or a plain element (div/form/Card). A row wrapper such as `<Cluster>` is not supported (the popover caps but the feed overflows it); deeper nesting leaves the popover uncapped. The popover then caps itself at the viewport and only the ScrollArea shrinks.
102
+ - Controlled use is rare — usually let Popover manage state: `<Popover open={open} onOpenChange={setOpen}>…</Popover>`.
103
+ - When you need a focus-locked confirmation, prefer `<Modal>`.
104
+
105
+ `Popover.Anchor` with a controlled popover on an interactive `FilterChip`:
106
+
107
+ ```tsx
108
+ const [open, setOpen] = useState(false);
109
+ <Popover open={open} onOpenChange={setOpen}>
110
+ <Popover.Anchor>
111
+ <FilterChip onActivate={() => setOpen((o) => !o)} expanded={open} onDismiss={remove}>
112
+ <FilterChip.Label>Range</FilterChip.Label>
113
+ <FilterChip.Value>Jun 1 – Jul 31</FilterChip.Value>
114
+ </FilterChip>
115
+ </Popover.Anchor>
116
+ <Popover.Content maxWidth={520}>
117
+ <RangePicker />
118
+ </Popover.Content>
119
+ </Popover>;
120
+ ```
121
+
122
+ **Anti-patterns**
123
+
124
+ - ❌ `<Popover.Trigger><Button disabled>…</Button></Popover.Trigger>` — disabled buttons do not fire click. Use `aria-disabled="true"` and intercept the click, or wrap in `<span>`.
125
+ - ❌ `<Popover.Content>` with no `<Popover.Close>` and content that is not obviously dismissable by clicking outside — keyboard / screen-reader users get no clear close affordance. Rely on outside-click only when the popover is small and obvious.
126
+ - ❌ Multiple `<Popover.Heading>` in one `<Popover.Content>` — the second mount overwrites `aria-labelledby`. One Heading per Popover.
127
+ - ❌ A tall panel with no `<ScrollArea>` — it is not capped at the viewport and runs off-screen.
@@ -0,0 +1,56 @@
1
+ # `<Progress>` — linear progress bar
2
+
3
+ ```tsx
4
+ <Progress value={45} /> // 45% determinate
5
+ <Progress value={67} label /> // shows "67%" on the right
6
+ <Progress value={85} tone="warning" label /> // dark-amber fill (state coding)
7
+ <Progress /> // value omitted = indeterminate slide
8
+ <Progress value={3} max={10} label={`3 of 10`} /> // custom label slot
9
+ ```
10
+
11
+ The track is `--color-border` (as are `CircularProgress` and `Slider` tracks), so it stays visible on white, muted (`bg-muted`) and card surfaces alike — no per-surface `--progress-track-bg` override needed. For a quota meter in a KPI tile use `StatTile`'s `progress` prop.
12
+
13
+ <!-- props:start -->
14
+
15
+ ## Props
16
+
17
+ <!-- prettier-ignore -->
18
+ | Prop | Type | Required | Description |
19
+ |---|---|---|---|
20
+ | `value` | `number` | no | Current progress value. Omit (or pass `undefined`) to render the indeterminate animation. Two-channel behavior for out-of-range and degenerate values: - **Visual fill** is clamped to [0%, 100%]. Values outside [0, max] render at the nearest valid bound. - **ARIA `aria-valuenow`** reports the raw number — this is the right screen-reader behavior so consumer bugs (a value drifting past max) surface in audits and SR announcements. Degenerate inputs fall back to the indeterminate animation: `NaN`, `Infinity`, `-Infinity`, and the case where `max <= 0`. This is the common file-upload race condition (`bytes_uploaded / total_bytes` before `total_bytes` is known produces NaN). |
21
+ | `max` | `number` | no | Upper bound. Defaults to `100`. Consumers using fraction values (0.0–1.0) pass `max={1}`. Consumers tracking a count ("3 of 10") pass `max={10}`. |
22
+ | `size` | `'sm' \| 'md' \| 'lg'` | no | Track height. - `sm` — 4px (compact / inside form rows) - `md` — 8px (default) - `lg` — 12px (page-level emphasis) |
23
+ | `tone` | `'default' \| 'success' \| 'warning' \| 'danger'` | no | Fill color tone. Defaults to `'default'` (accent blue). Tone applies ONLY to determinate mode; indeterminate always uses the accent tone because state-color semantics don't apply to an unknown total. - `default` — `--color-accent` - `success` — `--color-success` - `warning` — `--color-warning-strong` - `danger` — `--color-danger` |
24
+ | `label` | `ProgressLabel` | no | Optional label rendered to the RIGHT of the bar. - `false` (default) — no label - `true` — render `{Math.round((value / max) * 100)}%` when determinate. Auto-suppressed when indeterminate (there's no percentage to show). - `ReactNode` — render the node as-is, in BOTH determinate and indeterminate modes. Consumers wanting "Loading…" text next to an indeterminate bar pass `label="Loading…"`. |
25
+ | …native | | | plus native `<div>` attributes |
26
+
27
+ <!-- props:end -->
28
+
29
+ - `role="progressbar"` is locked — `Omit<HTMLAttributes, 'role'>` prevents the consumer from overriding it.
30
+ - Indeterminate `aria-valuetext` falls back to consumer-passed `aria-label`, then to the translated `progress.indeterminate` — not a hardcoded English string.
31
+
32
+ Use for per-file upload bars, wizard step indicators, form-completion meters and disk-usage gauges — anything with a known total. Storage-usage panel:
33
+
34
+ ```tsx
35
+ <Stack gap="xs">
36
+ <Title order={3} size="md">
37
+ Storage
38
+ </Title>
39
+ <Progress value={85} max={100} tone="warning" label />
40
+ <Text size="sm" tone="muted">
41
+ 85 GB of 100 GB used
42
+ </Text>
43
+ </Stack>
44
+ ```
45
+
46
+ **When NOT to use**
47
+
48
+ - An inline loading affordance next to a button — use indeterminate `<CircularProgress>`.
49
+ - Celebrating completion — a done bar is a done bar; leave the default tone. `tone` communicates state during progress (warning near a threshold, danger when over), not success-on-finish (so no `tone="success"` at `value={100}`).
50
+ - Arbitrary horizontal lines — use `<Divider>`.
51
+
52
+ **Anti-patterns**
53
+
54
+ - ❌ A hand-rolled `<div style={{ width: `${n}%`, … }}>` bar — use the primitive.
55
+ - ❌ `<Progress role="…">` — `role` is locked to `progressbar`; TypeScript rejects the override.
56
+ - ❌ A separate consumer-rendered label element — the `label` slot already handles spacing, font size and tabular-nums for stable digit widths.
@@ -0,0 +1,34 @@
1
+ # `<QrCode>` — scannable QR code
2
+
3
+ ```tsx
4
+ <QrCode value="https://example.com/i/42" aria-label="QR code for invoice 42" />;
5
+ <QrCode value={inviteUrl} logo={brandMark} aria-label="Invite link" />;
6
+ ```
7
+
8
+ <!-- props:start -->
9
+
10
+ ## Props
11
+
12
+ <!-- prettier-ignore -->
13
+ | Prop | Type | Required | Description |
14
+ |---|---|---|---|
15
+ | `value` | `string` | yes | The string to encode — a URL, an ID, a vCard. Encoded as UTF-8, so any script works. An empty string, or one past the largest symbol's capacity at the chosen `level` (~1273 bytes at `'H'`, ~2953 at `'L'`), renders a **disabled** button carrying a localized "unavailable" message instead of a code. It never throws — a long CRM field cannot white-screen a page. |
16
+ | `logo` | `string` | no | URL of a **single-colour** SVG to place in the centre. It is used as a CSS alpha mask and filled with the code's current ink, so it recolours itself in both themes and in the inverted state — the file's own colours are discarded. Full-colour artwork and photographs are not supported. Setting this also raises the default `level` to `'H'`, because the punch-out destroys modules outright. |
17
+ | `level` | `'L' \| 'M' \| 'Q' \| 'H'` | no | Error-correction level — how much damage the symbol survives. `'L'` ~7%, `'M'` ~15%, `'Q'` ~25%, `'H'` ~30%. Higher levels need a larger symbol for the same data. Defaults to `'H'` when `logo` is set, `'M'` otherwise. |
18
+ | …native | | | plus native `<button>` attributes |
19
+
20
+ <!-- props:end -->
21
+
22
+ - Encodes `value` as UTF-8, so Cyrillic and every other script work.
23
+ - **Follows the theme** — dark modules on light paper in light mode, inverted in dark. Clicking the code swaps ink and paper back, for a scanner that refuses an inverted symbol. That click is the component's only interaction.
24
+ - The whole code is a `<button>` with `aria-pressed`. **Never nest it inside another clickable element** — invalid HTML, and it swallows the outer click.
25
+ - **No `size` prop** — it fills its container's width; the parent owns the box. Wrap in `<Constrain>` or a sized element, and keep it above ~100px or a dense symbol stops resolving.
26
+ - The symbol **snaps down to a whole number of device pixels per module and centres itself**, so the painted code can sit up to one module short of the container — measuring the button gives you the box, not the code. Size the container to a whole multiple of the module count and the shortfall disappears. Where snapping would give up more than an eighth of the width, it renders fluid and antialiased instead: a bigger blurry code scans, a smaller pixel-exact one does not. The ~100px floor applies to the painted symbol, not to the box.
27
+ - There is no `label` prop — pass the native `aria-label`. It defaults to a bare localized "QR code", which tells a screen-reader user nothing about what the code points at.
28
+ - An empty `value`, or one over capacity for the level (~1273 bytes at `'H'`), renders a **disabled** button on a muted filled plate — no border — carrying a localized "unavailable" message instead of throwing. A long CRM field cannot white-screen a page. Your `aria-label` is prefixed to that message as visible text, so the name reads "Invoice 42 — QR code unavailable" and a browse-mode user can tell which code failed.
29
+ - Clicking inverts; `title` carries a localized hint describing that, exposed as the accessible description. Pass your own `title` to override it.
30
+ - Always render the underlying URL as selectable text too. The code is unusable to a screen-reader user, and to anyone reading on the device that shows it.
31
+ - Treat the value as public. Anyone who can see the screen can scan it.
32
+
33
+ - `logo` raises `level` to `'H'`, which packs more modules into the same box — each comes out smaller, so size the container up when you use it.
34
+ - Pair the code with a visible caption (e.g. `<Text size="sm" tone="muted">Scan at the door</Text>` in a `<Stack align="center">`) for sighted users.