@eocrm/design-system 0.0.0-stage → 0.6.18

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 (898) hide show
  1. package/AI-PRIMER.md +341 -0
  2. package/LICENSE +202 -0
  3. package/README.md +266 -2
  4. package/docs/components/Accordion.md +114 -0
  5. package/docs/components/AgentAvatar.md +58 -0
  6. package/docs/components/Alert.md +81 -0
  7. package/docs/components/AppLayout.md +70 -0
  8. package/docs/components/Avatar.md +49 -0
  9. package/docs/components/AvatarGroup.md +47 -0
  10. package/docs/components/Badge.md +60 -0
  11. package/docs/components/Banner.md +89 -0
  12. package/docs/components/BrandIcon.md +32 -0
  13. package/docs/components/Breadcrumb.md +72 -0
  14. package/docs/components/Button.md +107 -0
  15. package/docs/components/ButtonGroup.md +78 -0
  16. package/docs/components/Calendar.md +158 -0
  17. package/docs/components/Card.md +165 -0
  18. package/docs/components/CatalogPicker.md +83 -0
  19. package/docs/components/Chart.md +114 -0
  20. package/docs/components/ChatBubble.md +55 -0
  21. package/docs/components/ChatLauncher.md +97 -0
  22. package/docs/components/Checkbox.md +55 -0
  23. package/docs/components/CircularProgress.md +53 -0
  24. package/docs/components/Cluster.md +96 -0
  25. package/docs/components/Code.md +35 -0
  26. package/docs/components/CodeBlock.md +67 -0
  27. package/docs/components/ColorPicker.md +115 -0
  28. package/docs/components/ConfirmationPopover.md +70 -0
  29. package/docs/components/Constrain.md +39 -0
  30. package/docs/components/CurrencySelect.md +57 -0
  31. package/docs/components/CursorPagination.md +43 -0
  32. package/docs/components/DashboardCanvas.md +79 -0
  33. package/docs/components/DashboardWidget.md +131 -0
  34. package/docs/components/DataTable.md +88 -0
  35. package/docs/components/DatePicker.md +68 -0
  36. package/docs/components/DateRangePicker.md +71 -0
  37. package/docs/components/DateStrip.md +56 -0
  38. package/docs/components/DefinitionList.md +82 -0
  39. package/docs/components/Divider.md +57 -0
  40. package/docs/components/Dot.md +26 -0
  41. package/docs/components/Drawer.md +94 -0
  42. package/docs/components/DropdownMenu.md +299 -0
  43. package/docs/components/EmojiPicker.md +84 -0
  44. package/docs/components/EmptyState.md +55 -0
  45. package/docs/components/EntityChip.md +102 -0
  46. package/docs/components/ErrorState.md +72 -0
  47. package/docs/components/Field.md +91 -0
  48. package/docs/components/FileUpload.md +109 -0
  49. package/docs/components/FilterChip.md +88 -0
  50. package/docs/components/FlowCanvas.md +108 -0
  51. package/docs/components/FormRow.md +31 -0
  52. package/docs/components/FormSection.md +37 -0
  53. package/docs/components/Grid.md +103 -0
  54. package/docs/components/Highlight.md +75 -0
  55. package/docs/components/HighlightedText.md +50 -0
  56. package/docs/components/IconPicker.md +134 -0
  57. package/docs/components/IconTile.md +30 -0
  58. package/docs/components/Image.md +84 -0
  59. package/docs/components/ImageCrop.md +163 -0
  60. package/docs/components/Indent.md +31 -0
  61. package/docs/components/InlineDatePicker.md +58 -0
  62. package/docs/components/InlineDateRangePicker.md +57 -0
  63. package/docs/components/Input.md +54 -0
  64. package/docs/components/Kanban.md +122 -0
  65. package/docs/components/Kbd.md +41 -0
  66. package/docs/components/Lightbox.md +105 -0
  67. package/docs/components/Link.md +65 -0
  68. package/docs/components/LinkCard.md +41 -0
  69. package/docs/components/LiquidEditor.md +84 -0
  70. package/docs/components/List.md +68 -0
  71. package/docs/components/LiveRegion.md +29 -0
  72. package/docs/components/LocaleProvider.md +25 -0
  73. package/docs/components/Logo.md +41 -0
  74. package/docs/components/Masonry.md +48 -0
  75. package/docs/components/MediaTile.md +95 -0
  76. package/docs/components/Modal.md +107 -0
  77. package/docs/components/MoneyInput.md +62 -0
  78. package/docs/components/OptionsPicker.md +123 -0
  79. package/docs/components/OtpInput.md +65 -0
  80. package/docs/components/Page.md +35 -0
  81. package/docs/components/PageHeader.md +133 -0
  82. package/docs/components/Pagination.md +44 -0
  83. package/docs/components/Palette.md +32 -0
  84. package/docs/components/PasswordInput.md +45 -0
  85. package/docs/components/PasswordStrengthMeter.md +27 -0
  86. package/docs/components/PersonDisplay.md +153 -0
  87. package/docs/components/PhoneInput.md +54 -0
  88. package/docs/components/PillMenu.md +91 -0
  89. package/docs/components/Popover.md +127 -0
  90. package/docs/components/Progress.md +56 -0
  91. package/docs/components/QrCode.md +34 -0
  92. package/docs/components/Radio.md +37 -0
  93. package/docs/components/RadioGroup.md +56 -0
  94. package/docs/components/Rail.md +191 -0
  95. package/docs/components/RelativeDateInput.md +114 -0
  96. package/docs/components/RichText.md +44 -0
  97. package/docs/components/RichTextEditor.md +112 -0
  98. package/docs/components/Screen.md +37 -0
  99. package/docs/components/ScrollArea.md +39 -0
  100. package/docs/components/Select.md +131 -0
  101. package/docs/components/SettingRow.md +98 -0
  102. package/docs/components/Skeleton.md +68 -0
  103. package/docs/components/Slider.md +92 -0
  104. package/docs/components/SlotGrid.md +55 -0
  105. package/docs/components/SocialButton.md +31 -0
  106. package/docs/components/Sortable.md +127 -0
  107. package/docs/components/SortableGroup.md +52 -0
  108. package/docs/components/Sparkline.md +51 -0
  109. package/docs/components/Split.md +76 -0
  110. package/docs/components/Stack.md +59 -0
  111. package/docs/components/StagePath.md +66 -0
  112. package/docs/components/StatGroup.md +61 -0
  113. package/docs/components/StatTile.md +58 -0
  114. package/docs/components/Sticky.md +69 -0
  115. package/docs/components/Switch.md +89 -0
  116. package/docs/components/Table.md +184 -0
  117. package/docs/components/TableOfContents.md +76 -0
  118. package/docs/components/Tabs.md +94 -0
  119. package/docs/components/Text.md +63 -0
  120. package/docs/components/Textarea.md +59 -0
  121. package/docs/components/Thread.md +52 -0
  122. package/docs/components/TimeField.md +70 -0
  123. package/docs/components/Timeline.md +57 -0
  124. package/docs/components/Title.md +54 -0
  125. package/docs/components/ToastViewport.md +61 -0
  126. package/docs/components/Tooltip.md +63 -0
  127. package/docs/components/TopBar.md +214 -0
  128. package/docs/components/Tour.md +85 -0
  129. package/docs/components/TreeView.md +113 -0
  130. package/docs/components/VisuallyHidden.md +43 -0
  131. package/docs/components/WidgetPreview.md +54 -0
  132. package/docs/components/useBelowBreakpoint.md +11 -0
  133. package/docs/components/useMonth.md +18 -0
  134. package/docs/setup.md +51 -0
  135. package/docs/theming.md +95 -0
  136. package/docs/tokens.md +123 -0
  137. package/docs/transient-state.md +56 -0
  138. package/package.json +86 -4
  139. package/src/_meta/manifest.ts +293 -0
  140. package/src/app/AppProvider.tsx +78 -0
  141. package/src/app/index.ts +3 -0
  142. package/src/app/themeTokens.ts +95 -0
  143. package/src/calendar/dateMath.ts +114 -0
  144. package/src/calendar/formatters.ts +75 -0
  145. package/src/calendar/index.ts +39 -0
  146. package/src/calendar/types.ts +36 -0
  147. package/src/calendar/useAgenda.ts +70 -0
  148. package/src/calendar/useDay.ts +51 -0
  149. package/src/calendar/useMonth.ts +82 -0
  150. package/src/calendar/useWeek.ts +62 -0
  151. package/src/calendar/weekInfo.ts +83 -0
  152. package/src/components/Accordion/Accordion.module.scss +304 -0
  153. package/src/components/Accordion/Accordion.tokens.scss +64 -0
  154. package/src/components/Accordion/Accordion.tsx +272 -0
  155. package/src/components/Accordion/AccordionContent.tsx +36 -0
  156. package/src/components/Accordion/AccordionItem.tsx +66 -0
  157. package/src/components/Accordion/AccordionTrigger.tsx +121 -0
  158. package/src/components/Accordion/context.ts +47 -0
  159. package/src/components/Accordion/index.ts +14 -0
  160. package/src/components/Alert/Alert.module.scss +92 -0
  161. package/src/components/Alert/Alert.tokens.scss +60 -0
  162. package/src/components/Alert/Alert.tsx +136 -0
  163. package/src/components/Alert/index.ts +2 -0
  164. package/src/components/AppLayout/AppLayout.module.scss +130 -0
  165. package/src/components/AppLayout/AppLayout.tokens.scss +27 -0
  166. package/src/components/AppLayout/AppLayout.tsx +211 -0
  167. package/src/components/AppLayout/index.ts +2 -0
  168. package/src/components/Avatar/AgentAvatar.module.scss +117 -0
  169. package/src/components/Avatar/AgentAvatar.tsx +122 -0
  170. package/src/components/Avatar/Avatar.module.scss +181 -0
  171. package/src/components/Avatar/Avatar.tokens.scss +107 -0
  172. package/src/components/Avatar/Avatar.tsx +210 -0
  173. package/src/components/Avatar/AvatarGroup.module.scss +128 -0
  174. package/src/components/Avatar/AvatarGroup.tsx +119 -0
  175. package/src/components/Avatar/AvatarGroupContext.tsx +20 -0
  176. package/src/components/Avatar/index.ts +6 -0
  177. package/src/components/Badge/Badge.module.scss +124 -0
  178. package/src/components/Badge/Badge.tokens.scss +74 -0
  179. package/src/components/Badge/Badge.tsx +164 -0
  180. package/src/components/Badge/index.ts +2 -0
  181. package/src/components/Banner/Banner.module.scss +73 -0
  182. package/src/components/Banner/Banner.tokens.scss +51 -0
  183. package/src/components/Banner/Banner.tsx +138 -0
  184. package/src/components/Banner/index.ts +2 -0
  185. package/src/components/BrandIcon/BrandIcon.module.scss +5 -0
  186. package/src/components/BrandIcon/BrandIcon.tsx +99 -0
  187. package/src/components/BrandIcon/index.ts +2 -0
  188. package/src/components/Breadcrumb/Breadcrumb.module.scss +32 -0
  189. package/src/components/Breadcrumb/Breadcrumb.tokens.scss +9 -0
  190. package/src/components/Breadcrumb/Breadcrumb.tsx +146 -0
  191. package/src/components/Breadcrumb/index.ts +2 -0
  192. package/src/components/Button/Button.module.scss +167 -0
  193. package/src/components/Button/Button.tokens.scss +90 -0
  194. package/src/components/Button/Button.tsx +205 -0
  195. package/src/components/Button/index.ts +2 -0
  196. package/src/components/ButtonGroup/ButtonGroup.module.scss +134 -0
  197. package/src/components/ButtonGroup/ButtonGroup.tokens.scss +42 -0
  198. package/src/components/ButtonGroup/ButtonGroup.tsx +278 -0
  199. package/src/components/ButtonGroup/ButtonGroupItem.tsx +74 -0
  200. package/src/components/ButtonGroup/context.ts +45 -0
  201. package/src/components/ButtonGroup/index.ts +2 -0
  202. package/src/components/Calendar/AgendaView.module.scss +231 -0
  203. package/src/components/Calendar/AgendaView.tsx +214 -0
  204. package/src/components/Calendar/AllDayBand.module.scss +18 -0
  205. package/src/components/Calendar/AllDayBand.tsx +75 -0
  206. package/src/components/Calendar/Calendar.module.scss +23 -0
  207. package/src/components/Calendar/Calendar.tokens.scss +262 -0
  208. package/src/components/Calendar/Calendar.tsx +370 -0
  209. package/src/components/Calendar/DayCell.module.scss +30 -0
  210. package/src/components/Calendar/DayCell.tsx +50 -0
  211. package/src/components/Calendar/DayView.module.scss +10 -0
  212. package/src/components/Calendar/DayView.tsx +163 -0
  213. package/src/components/Calendar/EventChip.module.scss +171 -0
  214. package/src/components/Calendar/EventChip.tsx +115 -0
  215. package/src/components/Calendar/HourGrid.module.scss +123 -0
  216. package/src/components/Calendar/HourGrid.tsx +381 -0
  217. package/src/components/Calendar/MonthView.module.scss +99 -0
  218. package/src/components/Calendar/MonthView.tsx +296 -0
  219. package/src/components/Calendar/TimedEvent.module.scss +205 -0
  220. package/src/components/Calendar/TimedEvent.tsx +247 -0
  221. package/src/components/Calendar/ViewSwitcher.module.scss +3 -0
  222. package/src/components/Calendar/ViewSwitcher.tsx +47 -0
  223. package/src/components/Calendar/WeekView.module.scss +10 -0
  224. package/src/components/Calendar/WeekView.tsx +137 -0
  225. package/src/components/Calendar/eventColor.ts +60 -0
  226. package/src/components/Calendar/index.ts +18 -0
  227. package/src/components/Calendar/types.ts +451 -0
  228. package/src/components/Calendar/useEventDrag.ts +783 -0
  229. package/src/components/Calendar/utils.ts +622 -0
  230. package/src/components/Card/Card.module.scss +264 -0
  231. package/src/components/Card/Card.tokens.scss +55 -0
  232. package/src/components/Card/Card.tsx +170 -0
  233. package/src/components/Card/CardBody.tsx +45 -0
  234. package/src/components/Card/CardHeader.tsx +113 -0
  235. package/src/components/Card/CardList.tsx +24 -0
  236. package/src/components/Card/CardListRow.tsx +24 -0
  237. package/src/components/Card/index.ts +7 -0
  238. package/src/components/CatalogPicker/CatalogPicker.module.scss +193 -0
  239. package/src/components/CatalogPicker/CatalogPicker.tokens.scss +26 -0
  240. package/src/components/CatalogPicker/CatalogPicker.tsx +339 -0
  241. package/src/components/CatalogPicker/index.ts +2 -0
  242. package/src/components/Chart/Chart.module.scss +287 -0
  243. package/src/components/Chart/Chart.tokens.scss +63 -0
  244. package/src/components/Chart/Chart.tsx +607 -0
  245. package/src/components/Chart/ChartLegend.tsx +99 -0
  246. package/src/components/Chart/ChartTable.tsx +62 -0
  247. package/src/components/Chart/ChartTooltip.tsx +91 -0
  248. package/src/components/Chart/chartModel.ts +689 -0
  249. package/src/components/Chart/index.ts +2 -0
  250. package/src/components/ChatBubble/ChatBubble.module.scss +93 -0
  251. package/src/components/ChatBubble/ChatBubble.tokens.scss +17 -0
  252. package/src/components/ChatBubble/ChatBubble.tsx +61 -0
  253. package/src/components/ChatBubble/ChatBubbleList.tsx +27 -0
  254. package/src/components/ChatBubble/index.ts +3 -0
  255. package/src/components/ChatLauncher/ChatLauncher.module.scss +68 -0
  256. package/src/components/ChatLauncher/ChatLauncher.tokens.scss +27 -0
  257. package/src/components/ChatLauncher/ChatLauncher.tsx +202 -0
  258. package/src/components/ChatLauncher/index.ts +2 -0
  259. package/src/components/ChatLauncher/isAtBottom.ts +12 -0
  260. package/src/components/Checkbox/Checkbox.module.scss +147 -0
  261. package/src/components/Checkbox/Checkbox.tokens.scss +44 -0
  262. package/src/components/Checkbox/Checkbox.tsx +188 -0
  263. package/src/components/Checkbox/index.ts +2 -0
  264. package/src/components/CircularProgress/CircularProgress.module.scss +133 -0
  265. package/src/components/CircularProgress/CircularProgress.tokens.scss +40 -0
  266. package/src/components/CircularProgress/CircularProgress.tsx +139 -0
  267. package/src/components/CircularProgress/index.ts +7 -0
  268. package/src/components/Cluster/Cluster.module.scss +145 -0
  269. package/src/components/Cluster/Cluster.tokens.scss +11 -0
  270. package/src/components/Cluster/Cluster.tsx +215 -0
  271. package/src/components/Cluster/index.ts +2 -0
  272. package/src/components/Code/Code.module.scss +28 -0
  273. package/src/components/Code/Code.tokens.scss +15 -0
  274. package/src/components/Code/Code.tsx +44 -0
  275. package/src/components/Code/index.ts +2 -0
  276. package/src/components/CodeBlock/CodeBlock.module.scss +146 -0
  277. package/src/components/CodeBlock/CodeBlock.tokens.scss +27 -0
  278. package/src/components/CodeBlock/CodeBlock.tsx +274 -0
  279. package/src/components/CodeBlock/highlight.ts +179 -0
  280. package/src/components/CodeBlock/index.ts +8 -0
  281. package/src/components/CodeBlock/sampleSync.ts +42 -0
  282. package/src/components/ColorPicker/ColorPicker.module.scss +286 -0
  283. package/src/components/ColorPicker/ColorPicker.tokens.scss +60 -0
  284. package/src/components/ColorPicker/ColorPicker.tsx +367 -0
  285. package/src/components/ColorPicker/ColorPickerPanel.tsx +265 -0
  286. package/src/components/ColorPicker/SVSquare.tsx +189 -0
  287. package/src/components/ColorPicker/colorMath.ts +141 -0
  288. package/src/components/ColorPicker/index.ts +6 -0
  289. package/src/components/ConfirmationPopover/ConfirmationPopover.module.scss +39 -0
  290. package/src/components/ConfirmationPopover/ConfirmationPopover.tokens.scss +13 -0
  291. package/src/components/ConfirmationPopover/ConfirmationPopover.tsx +395 -0
  292. package/src/components/ConfirmationPopover/index.ts +2 -0
  293. package/src/components/Constrain/Constrain.module.scss +99 -0
  294. package/src/components/Constrain/Constrain.tsx +79 -0
  295. package/src/components/Constrain/index.ts +2 -0
  296. package/src/components/CurrencySelect/CurrencySelect.module.scss +7 -0
  297. package/src/components/CurrencySelect/CurrencySelect.tsx +167 -0
  298. package/src/components/CurrencySelect/index.ts +3 -0
  299. package/src/components/CursorPagination/CursorPagination.module.scss +69 -0
  300. package/src/components/CursorPagination/CursorPagination.tokens.scss +32 -0
  301. package/src/components/CursorPagination/CursorPagination.tsx +121 -0
  302. package/src/components/CursorPagination/index.ts +2 -0
  303. package/src/components/DashboardCanvas/DashboardCanvas.module.scss +360 -0
  304. package/src/components/DashboardCanvas/DashboardCanvas.tokens.scss +48 -0
  305. package/src/components/DashboardCanvas/DashboardCanvas.tsx +1270 -0
  306. package/src/components/DashboardCanvas/DashboardCanvasItem.tsx +140 -0
  307. package/src/components/DashboardCanvas/DashboardCanvasSection.tsx +174 -0
  308. package/src/components/DashboardCanvas/engine.ts +363 -0
  309. package/src/components/DashboardCanvas/index.ts +9 -0
  310. package/src/components/DashboardWidget/DashboardWidget.module.scss +100 -0
  311. package/src/components/DashboardWidget/DashboardWidget.tokens.scss +16 -0
  312. package/src/components/DashboardWidget/DashboardWidget.tsx +188 -0
  313. package/src/components/DashboardWidget/index.ts +7 -0
  314. package/src/components/DataTable/BodyRow.tsx +197 -0
  315. package/src/components/DataTable/ColumnVisibilityTrigger.module.scss +7 -0
  316. package/src/components/DataTable/ColumnVisibilityTrigger.tsx +105 -0
  317. package/src/components/DataTable/DataTable.module.scss +511 -0
  318. package/src/components/DataTable/DataTable.tokens.scss +80 -0
  319. package/src/components/DataTable/DataTable.tsx +734 -0
  320. package/src/components/DataTable/HeaderCell.module.scss +215 -0
  321. package/src/components/DataTable/HeaderCell.tsx +440 -0
  322. package/src/components/DataTable/columnShift.ts +117 -0
  323. package/src/components/DataTable/index.ts +23 -0
  324. package/src/components/DataTable/pinStyle.ts +47 -0
  325. package/src/components/DataTable/reorderColumns.ts +66 -0
  326. package/src/components/DataTable/types.ts +289 -0
  327. package/src/components/DataTable/useColumnDragShift.ts +216 -0
  328. package/src/components/DataTable/useDataTable.ts +372 -0
  329. package/src/components/DataTable/useResizeHandle.ts +97 -0
  330. package/src/components/DatePicker/DatePicker.module.scss +180 -0
  331. package/src/components/DatePicker/DatePicker.tokens.scss +152 -0
  332. package/src/components/DatePicker/DatePicker.tsx +664 -0
  333. package/src/components/DatePicker/DatePickerGrid.module.scss +172 -0
  334. package/src/components/DatePicker/DatePickerGrid.tsx +341 -0
  335. package/src/components/DatePicker/InlineDatePicker.module.scss +32 -0
  336. package/src/components/DatePicker/InlineDatePicker.tsx +201 -0
  337. package/src/components/DatePicker/index.ts +4 -0
  338. package/src/components/DatePicker/utils.ts +364 -0
  339. package/src/components/DateRangePicker/DateRangePicker.module.scss +237 -0
  340. package/src/components/DateRangePicker/DateRangePicker.tokens.scss +78 -0
  341. package/src/components/DateRangePicker/DateRangePicker.tsx +720 -0
  342. package/src/components/DateRangePicker/InlineDateRangePicker.module.scss +94 -0
  343. package/src/components/DateRangePicker/InlineDateRangePicker.tsx +376 -0
  344. package/src/components/DateRangePicker/index.ts +5 -0
  345. package/src/components/DateRangePicker/utils.ts +151 -0
  346. package/src/components/DateStrip/DateStrip.module.scss +78 -0
  347. package/src/components/DateStrip/DateStrip.tokens.scss +23 -0
  348. package/src/components/DateStrip/DateStrip.tsx +205 -0
  349. package/src/components/DateStrip/index.ts +2 -0
  350. package/src/components/DefinitionList/DefinitionList.module.scss +102 -0
  351. package/src/components/DefinitionList/DefinitionList.tokens.scss +29 -0
  352. package/src/components/DefinitionList/DefinitionList.tsx +198 -0
  353. package/src/components/DefinitionList/index.ts +9 -0
  354. package/src/components/Divider/Divider.module.scss +144 -0
  355. package/src/components/Divider/Divider.tokens.scss +21 -0
  356. package/src/components/Divider/Divider.tsx +103 -0
  357. package/src/components/Divider/index.ts +2 -0
  358. package/src/components/Dot/Dot.module.scss +40 -0
  359. package/src/components/Dot/Dot.tokens.scss +4 -0
  360. package/src/components/Dot/Dot.tsx +45 -0
  361. package/src/components/Dot/index.ts +2 -0
  362. package/src/components/Drawer/Body.tsx +23 -0
  363. package/src/components/Drawer/Close.tsx +35 -0
  364. package/src/components/Drawer/Content.tsx +93 -0
  365. package/src/components/Drawer/Drawer.module.scss +232 -0
  366. package/src/components/Drawer/Drawer.tokens.scss +38 -0
  367. package/src/components/Drawer/Drawer.tsx +23 -0
  368. package/src/components/Drawer/DrawerRoot.tsx +190 -0
  369. package/src/components/Drawer/Footer.tsx +24 -0
  370. package/src/components/Drawer/Header.tsx +64 -0
  371. package/src/components/Drawer/Overlay.tsx +82 -0
  372. package/src/components/Drawer/context.ts +44 -0
  373. package/src/components/Drawer/index.ts +12 -0
  374. package/src/components/Drawer/useDragToClose.ts +149 -0
  375. package/src/components/DropdownMenu/CheckboxItem.tsx +144 -0
  376. package/src/components/DropdownMenu/Content.tsx +419 -0
  377. package/src/components/DropdownMenu/DropdownMenu.module.scss +280 -0
  378. package/src/components/DropdownMenu/DropdownMenu.tokens.scss +88 -0
  379. package/src/components/DropdownMenu/DropdownMenu.tsx +43 -0
  380. package/src/components/DropdownMenu/Group.tsx +76 -0
  381. package/src/components/DropdownMenu/Item.tsx +148 -0
  382. package/src/components/DropdownMenu/ItemIndicator.tsx +30 -0
  383. package/src/components/DropdownMenu/Radio.tsx +178 -0
  384. package/src/components/DropdownMenu/Root.tsx +100 -0
  385. package/src/components/DropdownMenu/Sub.tsx +332 -0
  386. package/src/components/DropdownMenu/Trigger.tsx +76 -0
  387. package/src/components/DropdownMenu/context.ts +65 -0
  388. package/src/components/DropdownMenu/index.ts +20 -0
  389. package/src/components/EmojiPicker/EmojiPicker.module.scss +84 -0
  390. package/src/components/EmojiPicker/EmojiPicker.tokens.scss +24 -0
  391. package/src/components/EmojiPicker/EmojiPicker.tsx +341 -0
  392. package/src/components/EmojiPicker/emojiData.ts +245 -0
  393. package/src/components/EmojiPicker/index.ts +3 -0
  394. package/src/components/EmptyState/EmptyState.module.scss +102 -0
  395. package/src/components/EmptyState/EmptyState.tokens.scss +28 -0
  396. package/src/components/EmptyState/EmptyState.tsx +112 -0
  397. package/src/components/EmptyState/index.ts +7 -0
  398. package/src/components/EntityChip/EntityChip.module.scss +275 -0
  399. package/src/components/EntityChip/EntityChip.tokens.scss +66 -0
  400. package/src/components/EntityChip/EntityChip.tsx +649 -0
  401. package/src/components/EntityChip/index.ts +10 -0
  402. package/src/components/ErrorState/ErrorState.module.scss +105 -0
  403. package/src/components/ErrorState/ErrorState.tokens.scss +32 -0
  404. package/src/components/ErrorState/ErrorState.tsx +125 -0
  405. package/src/components/ErrorState/index.ts +8 -0
  406. package/src/components/Field/Field.module.scss +46 -0
  407. package/src/components/Field/Field.tsx +185 -0
  408. package/src/components/Field/index.ts +2 -0
  409. package/src/components/FileUpload/FileUpload.module.scss +187 -0
  410. package/src/components/FileUpload/FileUpload.tokens.scss +81 -0
  411. package/src/components/FileUpload/FileUpload.tsx +569 -0
  412. package/src/components/FileUpload/formatBytes.ts +34 -0
  413. package/src/components/FileUpload/iconForFile.ts +40 -0
  414. package/src/components/FileUpload/index.ts +2 -0
  415. package/src/components/FilterChip/FilterChip.module.scss +61 -0
  416. package/src/components/FilterChip/FilterChip.tokens.scss +25 -0
  417. package/src/components/FilterChip/FilterChip.tsx +208 -0
  418. package/src/components/FilterChip/index.ts +5 -0
  419. package/src/components/FlowCanvas/FlowCanvas.module.scss +329 -0
  420. package/src/components/FlowCanvas/FlowCanvas.tokens.scss +45 -0
  421. package/src/components/FlowCanvas/FlowCanvas.tsx +1867 -0
  422. package/src/components/FlowCanvas/FlowControls.tsx +46 -0
  423. package/src/components/FlowCanvas/FlowEdge.tsx +58 -0
  424. package/src/components/FlowCanvas/FlowNode.tsx +76 -0
  425. package/src/components/FlowCanvas/edgePath.ts +85 -0
  426. package/src/components/FlowCanvas/index.ts +4 -0
  427. package/src/components/FlowCanvas/layout.ts +148 -0
  428. package/src/components/FlowCanvas/spatialNav.ts +76 -0
  429. package/src/components/FlowCanvas/types.ts +59 -0
  430. package/src/components/FlowCanvas/useViewport.ts +122 -0
  431. package/src/components/FormRow/FormRow.module.scss +2 -0
  432. package/src/components/FormRow/FormRow.tsx +37 -0
  433. package/src/components/FormRow/index.ts +2 -0
  434. package/src/components/FormSection/FormSection.module.scss +24 -0
  435. package/src/components/FormSection/FormSection.tsx +46 -0
  436. package/src/components/FormSection/index.ts +2 -0
  437. package/src/components/Grid/Grid.module.scss +162 -0
  438. package/src/components/Grid/Grid.tokens.scss +13 -0
  439. package/src/components/Grid/Grid.tsx +226 -0
  440. package/src/components/Grid/GridItem.tsx +77 -0
  441. package/src/components/Grid/index.ts +11 -0
  442. package/src/components/Highlight/Highlight.module.scss +43 -0
  443. package/src/components/Highlight/Highlight.tokens.scss +35 -0
  444. package/src/components/Highlight/Highlight.tsx +164 -0
  445. package/src/components/Highlight/HighlightOverlay.tsx +100 -0
  446. package/src/components/Highlight/index.ts +2 -0
  447. package/src/components/HighlightedText/HighlightedText.module.scss +11 -0
  448. package/src/components/HighlightedText/HighlightedText.tokens.scss +9 -0
  449. package/src/components/HighlightedText/HighlightedText.tsx +50 -0
  450. package/src/components/HighlightedText/highlightRanges.ts +44 -0
  451. package/src/components/HighlightedText/index.ts +2 -0
  452. package/src/components/IconPicker/IconPicker.module.scss +175 -0
  453. package/src/components/IconPicker/IconPicker.tokens.scss +40 -0
  454. package/src/components/IconPicker/IconPicker.tsx +629 -0
  455. package/src/components/IconPicker/index.ts +9 -0
  456. package/src/components/IconTile/IconTile.module.scss +57 -0
  457. package/src/components/IconTile/IconTile.tokens.scss +16 -0
  458. package/src/components/IconTile/IconTile.tsx +91 -0
  459. package/src/components/IconTile/index.ts +2 -0
  460. package/src/components/Image/Image.module.scss +266 -0
  461. package/src/components/Image/Image.tokens.scss +55 -0
  462. package/src/components/Image/Image.tsx +342 -0
  463. package/src/components/Image/index.ts +2 -0
  464. package/src/components/ImageCrop/ImageCrop.module.scss +274 -0
  465. package/src/components/ImageCrop/ImageCrop.tokens.scss +33 -0
  466. package/src/components/ImageCrop/ImageCrop.tsx +542 -0
  467. package/src/components/ImageCrop/cropGeometry.ts +120 -0
  468. package/src/components/ImageCrop/extractCropBlob.ts +140 -0
  469. package/src/components/ImageCrop/index.ts +11 -0
  470. package/src/components/ImageCrop/useCropPreview.ts +161 -0
  471. package/src/components/Indent/Indent.module.scss +33 -0
  472. package/src/components/Indent/Indent.tokens.scss +10 -0
  473. package/src/components/Indent/Indent.tsx +46 -0
  474. package/src/components/Indent/index.ts +2 -0
  475. package/src/components/Input/Input.module.scss +99 -0
  476. package/src/components/Input/Input.tokens.scss +54 -0
  477. package/src/components/Input/Input.tsx +105 -0
  478. package/src/components/Input/Suggestions.tsx +260 -0
  479. package/src/components/Input/index.ts +2 -0
  480. package/src/components/Kanban/Kanban.module.scss +39 -0
  481. package/src/components/Kanban/Kanban.tokens.scss +15 -0
  482. package/src/components/Kanban/Kanban.tsx +951 -0
  483. package/src/components/Kanban/index.ts +7 -0
  484. package/src/components/Kbd/Kbd.module.scss +47 -0
  485. package/src/components/Kbd/Kbd.tokens.scss +26 -0
  486. package/src/components/Kbd/Kbd.tsx +73 -0
  487. package/src/components/Kbd/index.ts +2 -0
  488. package/src/components/Lightbox/Lightbox.module.scss +283 -0
  489. package/src/components/Lightbox/Lightbox.tokens.scss +36 -0
  490. package/src/components/Lightbox/Lightbox.tsx +506 -0
  491. package/src/components/Lightbox/index.ts +2 -0
  492. package/src/components/Link/Link.module.scss +78 -0
  493. package/src/components/Link/Link.tokens.scss +28 -0
  494. package/src/components/Link/Link.tsx +114 -0
  495. package/src/components/Link/index.ts +2 -0
  496. package/src/components/LinkCard/LinkCard.module.scss +92 -0
  497. package/src/components/LinkCard/LinkCard.tokens.scss +9 -0
  498. package/src/components/LinkCard/LinkCard.tsx +72 -0
  499. package/src/components/LinkCard/index.ts +2 -0
  500. package/src/components/LiquidEditor/AutocompleteMenu.tsx +133 -0
  501. package/src/components/LiquidEditor/HighlightLayer.tsx +53 -0
  502. package/src/components/LiquidEditor/InsertVariableMenu.tsx +81 -0
  503. package/src/components/LiquidEditor/LiquidEditor.module.scss +339 -0
  504. package/src/components/LiquidEditor/LiquidEditor.tokens.scss +81 -0
  505. package/src/components/LiquidEditor/LiquidEditor.tsx +412 -0
  506. package/src/components/LiquidEditor/PreviewPane.tsx +29 -0
  507. package/src/components/LiquidEditor/caretCoordinates.ts +97 -0
  508. package/src/components/LiquidEditor/index.ts +7 -0
  509. package/src/components/LiquidEditor/liquidFilters.ts +23 -0
  510. package/src/components/LiquidEditor/liquidTokenizer.ts +235 -0
  511. package/src/components/LiquidEditor/types.ts +101 -0
  512. package/src/components/LiquidEditor/useLiquidAutocomplete.ts +178 -0
  513. package/src/components/List/List.module.scss +105 -0
  514. package/src/components/List/List.tokens.scss +42 -0
  515. package/src/components/List/List.tsx +124 -0
  516. package/src/components/List/index.ts +9 -0
  517. package/src/components/LiveRegion/LiveRegion.module.scss +3 -0
  518. package/src/components/LiveRegion/LiveRegion.tsx +116 -0
  519. package/src/components/LiveRegion/index.ts +2 -0
  520. package/src/components/Logo/Logo.module.scss +139 -0
  521. package/src/components/Logo/Logo.tokens.scss +14 -0
  522. package/src/components/Logo/Logo.tsx +126 -0
  523. package/src/components/Logo/index.ts +2 -0
  524. package/src/components/Masonry/Masonry.module.scss +42 -0
  525. package/src/components/Masonry/Masonry.tokens.scss +8 -0
  526. package/src/components/Masonry/Masonry.tsx +136 -0
  527. package/src/components/Masonry/index.ts +2 -0
  528. package/src/components/Masonry/masonryUtils.ts +42 -0
  529. package/src/components/MediaTile/MediaTile.module.scss +183 -0
  530. package/src/components/MediaTile/MediaTile.tokens.scss +60 -0
  531. package/src/components/MediaTile/MediaTile.tsx +208 -0
  532. package/src/components/MediaTile/index.ts +8 -0
  533. package/src/components/Modal/Body.tsx +27 -0
  534. package/src/components/Modal/Close.tsx +45 -0
  535. package/src/components/Modal/Content.tsx +98 -0
  536. package/src/components/Modal/Footer.tsx +28 -0
  537. package/src/components/Modal/Header.tsx +51 -0
  538. package/src/components/Modal/Modal.module.scss +262 -0
  539. package/src/components/Modal/Modal.tokens.scss +50 -0
  540. package/src/components/Modal/Modal.tsx +23 -0
  541. package/src/components/Modal/ModalRoot.tsx +299 -0
  542. package/src/components/Modal/Overlay.tsx +101 -0
  543. package/src/components/Modal/context.ts +60 -0
  544. package/src/components/Modal/index.ts +11 -0
  545. package/src/components/MoneyInput/MoneyInput.module.scss +57 -0
  546. package/src/components/MoneyInput/MoneyInput.tsx +433 -0
  547. package/src/components/MoneyInput/index.ts +2 -0
  548. package/src/components/OptionsPicker/OptionsPicker.module.scss +216 -0
  549. package/src/components/OptionsPicker/OptionsPicker.tokens.scss +68 -0
  550. package/src/components/OptionsPicker/OptionsPicker.tsx +936 -0
  551. package/src/components/OptionsPicker/index.ts +9 -0
  552. package/src/components/OtpInput/OtpInput.module.scss +69 -0
  553. package/src/components/OtpInput/OtpInput.tokens.scss +45 -0
  554. package/src/components/OtpInput/OtpInput.tsx +368 -0
  555. package/src/components/OtpInput/index.ts +2 -0
  556. package/src/components/Page/Page.module.scss +30 -0
  557. package/src/components/Page/Page.tokens.scss +11 -0
  558. package/src/components/Page/Page.tsx +53 -0
  559. package/src/components/Page/index.ts +2 -0
  560. package/src/components/PageHeader/PageHeader.module.scss +197 -0
  561. package/src/components/PageHeader/PageHeader.tokens.scss +41 -0
  562. package/src/components/PageHeader/PageHeader.tsx +310 -0
  563. package/src/components/PageHeader/index.ts +20 -0
  564. package/src/components/Pagination/Pagination.module.scss +117 -0
  565. package/src/components/Pagination/Pagination.tokens.scss +54 -0
  566. package/src/components/Pagination/Pagination.tsx +165 -0
  567. package/src/components/Pagination/index.ts +4 -0
  568. package/src/components/Pagination/paginationRange.ts +72 -0
  569. package/src/components/PasswordInput/PasswordInput.module.scss +120 -0
  570. package/src/components/PasswordInput/PasswordInput.tokens.scss +44 -0
  571. package/src/components/PasswordInput/PasswordInput.tsx +210 -0
  572. package/src/components/PasswordInput/index.ts +2 -0
  573. package/src/components/PasswordStrengthMeter/PasswordStrengthMeter.module.scss +80 -0
  574. package/src/components/PasswordStrengthMeter/PasswordStrengthMeter.tokens.scss +40 -0
  575. package/src/components/PasswordStrengthMeter/PasswordStrengthMeter.tsx +96 -0
  576. package/src/components/PasswordStrengthMeter/index.ts +2 -0
  577. package/src/components/PersonDisplay/PersonDisplay.module.scss +180 -0
  578. package/src/components/PersonDisplay/PersonDisplay.tokens.scss +35 -0
  579. package/src/components/PersonDisplay/PersonDisplay.tsx +420 -0
  580. package/src/components/PersonDisplay/index.ts +10 -0
  581. package/src/components/PhoneInput/PhoneInput.module.scss +23 -0
  582. package/src/components/PhoneInput/PhoneInput.tsx +271 -0
  583. package/src/components/PhoneInput/index.ts +4 -0
  584. package/src/components/PhoneInput/phone.ts +128 -0
  585. package/src/components/PillMenu/PillMenu.module.scss +117 -0
  586. package/src/components/PillMenu/PillMenu.tokens.scss +22 -0
  587. package/src/components/PillMenu/PillMenu.tsx +324 -0
  588. package/src/components/PillMenu/index.ts +2 -0
  589. package/src/components/Popover/Anchor.tsx +37 -0
  590. package/src/components/Popover/Close.tsx +45 -0
  591. package/src/components/Popover/Content.tsx +213 -0
  592. package/src/components/Popover/Heading.tsx +33 -0
  593. package/src/components/Popover/Popover.module.scss +177 -0
  594. package/src/components/Popover/Popover.tokens.scss +22 -0
  595. package/src/components/Popover/Popover.tsx +23 -0
  596. package/src/components/Popover/PopoverRoot.tsx +75 -0
  597. package/src/components/Popover/Trigger.tsx +86 -0
  598. package/src/components/Popover/context.ts +22 -0
  599. package/src/components/Popover/index.ts +7 -0
  600. package/src/components/Progress/Progress.module.scss +110 -0
  601. package/src/components/Progress/Progress.tokens.scss +44 -0
  602. package/src/components/Progress/Progress.tsx +129 -0
  603. package/src/components/Progress/index.ts +2 -0
  604. package/src/components/QrCode/QrCode.module.scss +97 -0
  605. package/src/components/QrCode/QrCode.tokens.scss +17 -0
  606. package/src/components/QrCode/QrCode.tsx +233 -0
  607. package/src/components/QrCode/index.ts +2 -0
  608. package/src/components/QrCode/qr.ts +161 -0
  609. package/src/components/Radio/Radio.module.scss +175 -0
  610. package/src/components/Radio/Radio.tokens.scss +59 -0
  611. package/src/components/Radio/Radio.tsx +127 -0
  612. package/src/components/Radio/RadioGroup.module.scss +42 -0
  613. package/src/components/Radio/RadioGroup.tsx +120 -0
  614. package/src/components/Radio/RadioGroupContext.tsx +30 -0
  615. package/src/components/Radio/index.ts +4 -0
  616. package/src/components/Rail/Rail.module.scss +510 -0
  617. package/src/components/Rail/Rail.tokens.scss +92 -0
  618. package/src/components/Rail/Rail.tsx +287 -0
  619. package/src/components/Rail/RailCollapseToggle.tsx +57 -0
  620. package/src/components/Rail/RailFooter.tsx +17 -0
  621. package/src/components/Rail/RailGroup.tsx +728 -0
  622. package/src/components/Rail/RailGroupContext.ts +9 -0
  623. package/src/components/Rail/RailHeader.tsx +23 -0
  624. package/src/components/Rail/RailItem.tsx +119 -0
  625. package/src/components/Rail/RailSection.tsx +39 -0
  626. package/src/components/Rail/RailSpacer.tsx +19 -0
  627. package/src/components/Rail/index.ts +9 -0
  628. package/src/components/RelativeDateInput/RelativeDateInput.module.scss +15 -0
  629. package/src/components/RelativeDateInput/RelativeDateInput.tokens.scss +6 -0
  630. package/src/components/RelativeDateInput/RelativeDateInput.tsx +474 -0
  631. package/src/components/RelativeDateInput/index.ts +10 -0
  632. package/src/components/RelativeDateInput/relativeDate.ts +127 -0
  633. package/src/components/RichText/RichText.module.scss +5 -0
  634. package/src/components/RichText/RichText.tsx +70 -0
  635. package/src/components/RichText/RichTextAttachment.module.scss +82 -0
  636. package/src/components/RichText/RichTextAttachment.tsx +122 -0
  637. package/src/components/RichText/_prose.scss +79 -0
  638. package/src/components/RichText/attachmentIcon.tsx +24 -0
  639. package/src/components/RichText/engine/attachment.ts +154 -0
  640. package/src/components/RichText/engine/autolink.ts +64 -0
  641. package/src/components/RichText/engine/blockUnit.ts +174 -0
  642. package/src/components/RichText/engine/colorMarks.ts +85 -0
  643. package/src/components/RichText/engine/escape.ts +11 -0
  644. package/src/components/RichText/engine/fromHtml.ts +353 -0
  645. package/src/components/RichText/engine/fromMarkdown.ts +20 -0
  646. package/src/components/RichText/engine/inlines.ts +82 -0
  647. package/src/components/RichText/engine/listDepths.ts +32 -0
  648. package/src/components/RichText/engine/marks.ts +80 -0
  649. package/src/components/RichText/engine/mdToHtml.ts +178 -0
  650. package/src/components/RichText/engine/model.ts +157 -0
  651. package/src/components/RichText/engine/position.ts +118 -0
  652. package/src/components/RichText/engine/renderDoc.tsx +395 -0
  653. package/src/components/RichText/engine/renderLink.ts +15 -0
  654. package/src/components/RichText/engine/renderMention.ts +16 -0
  655. package/src/components/RichText/engine/safeHref.ts +22 -0
  656. package/src/components/RichText/engine/toHtml.ts +154 -0
  657. package/src/components/RichText/engine/toMarkdown.ts +97 -0
  658. package/src/components/RichText/engine/transforms.ts +434 -0
  659. package/src/components/RichText/imageMaxHeightStyle.ts +10 -0
  660. package/src/components/RichText/index.ts +31 -0
  661. package/src/components/RichTextEditor/RichTextAttachmentConfig.tsx +264 -0
  662. package/src/components/RichTextEditor/RichTextBlockControls.tsx +365 -0
  663. package/src/components/RichTextEditor/RichTextBlockMenu.tsx +162 -0
  664. package/src/components/RichTextEditor/RichTextColorMenu.tsx +115 -0
  665. package/src/components/RichTextEditor/RichTextEditor.module.scss +298 -0
  666. package/src/components/RichTextEditor/RichTextEditor.tsx +1910 -0
  667. package/src/components/RichTextEditor/RichTextImageResizer.tsx +131 -0
  668. package/src/components/RichTextEditor/RichTextLinkEditor.tsx +151 -0
  669. package/src/components/RichTextEditor/RichTextMentionMenu.tsx +99 -0
  670. package/src/components/RichTextEditor/RichTextToolbar.tsx +379 -0
  671. package/src/components/RichTextEditor/autolinkInput.ts +65 -0
  672. package/src/components/RichTextEditor/blockDrop.ts +9 -0
  673. package/src/components/RichTextEditor/blockReflow.ts +62 -0
  674. package/src/components/RichTextEditor/commands.ts +300 -0
  675. package/src/components/RichTextEditor/history.ts +93 -0
  676. package/src/components/RichTextEditor/icons.tsx +152 -0
  677. package/src/components/RichTextEditor/imageSize.ts +70 -0
  678. package/src/components/RichTextEditor/index.ts +5 -0
  679. package/src/components/RichTextEditor/input.ts +209 -0
  680. package/src/components/RichTextEditor/inputRules.ts +71 -0
  681. package/src/components/RichTextEditor/links.ts +103 -0
  682. package/src/components/RichTextEditor/mentionContext.ts +37 -0
  683. package/src/components/RichTextEditor/mentions.ts +28 -0
  684. package/src/components/RichTextEditor/preventSelectionLoss.ts +15 -0
  685. package/src/components/RichTextEditor/selection.ts +415 -0
  686. package/src/components/RichTextEditor/shortcuts.ts +44 -0
  687. package/src/components/RichTextEditor/useAnchoredFloating.ts +50 -0
  688. package/src/components/RichTextEditor/useAttachmentConfig.ts +134 -0
  689. package/src/components/RichTextEditor/useDismissOnOutsidePointerDown.ts +26 -0
  690. package/src/components/RichTextEditor/useLinkEditor.ts +107 -0
  691. package/src/components/RichTextEditor/useMention.ts +226 -0
  692. package/src/components/RichTextEditor/useOverlayRect.ts +73 -0
  693. package/src/components/RichTextEditor/useUpload.ts +246 -0
  694. package/src/components/Screen/Screen.module.scss +46 -0
  695. package/src/components/Screen/Screen.tokens.scss +20 -0
  696. package/src/components/Screen/Screen.tsx +97 -0
  697. package/src/components/Screen/index.ts +2 -0
  698. package/src/components/ScrollArea/ScrollArea.module.scss +39 -0
  699. package/src/components/ScrollArea/ScrollArea.tokens.scss +15 -0
  700. package/src/components/ScrollArea/ScrollArea.tsx +154 -0
  701. package/src/components/ScrollArea/index.ts +2 -0
  702. package/src/components/Select/Chip.tsx +45 -0
  703. package/src/components/Select/Empty.tsx +39 -0
  704. package/src/components/Select/Error.tsx +51 -0
  705. package/src/components/Select/HiddenInputs.tsx +44 -0
  706. package/src/components/Select/Listbox.tsx +557 -0
  707. package/src/components/Select/Loading.tsx +30 -0
  708. package/src/components/Select/Select.module.scss +512 -0
  709. package/src/components/Select/Select.tokens.scss +140 -0
  710. package/src/components/Select/Select.tsx +685 -0
  711. package/src/components/Select/Trigger.tsx +952 -0
  712. package/src/components/Select/context.ts +101 -0
  713. package/src/components/Select/emptyStateText.ts +19 -0
  714. package/src/components/Select/index.ts +9 -0
  715. package/src/components/Select/useSelectState.ts +157 -0
  716. package/src/components/Select/utils-types.ts +7 -0
  717. package/src/components/Select/utils.ts +122 -0
  718. package/src/components/SettingRow/SettingRow.module.scss +166 -0
  719. package/src/components/SettingRow/SettingRow.tokens.scss +37 -0
  720. package/src/components/SettingRow/SettingRow.tsx +242 -0
  721. package/src/components/SettingRow/index.ts +7 -0
  722. package/src/components/Skeleton/Skeleton.module.scss +55 -0
  723. package/src/components/Skeleton/Skeleton.tokens.scss +17 -0
  724. package/src/components/Skeleton/Skeleton.tsx +131 -0
  725. package/src/components/Skeleton/index.ts +4 -0
  726. package/src/components/Skeleton/useSkeletonVisibility.ts +95 -0
  727. package/src/components/Slider/Slider.module.scss +293 -0
  728. package/src/components/Slider/Slider.tokens.scss +98 -0
  729. package/src/components/Slider/Slider.tsx +624 -0
  730. package/src/components/Slider/index.ts +9 -0
  731. package/src/components/SlotGrid/SlotGrid.module.scss +61 -0
  732. package/src/components/SlotGrid/SlotGrid.tokens.scss +21 -0
  733. package/src/components/SlotGrid/SlotGrid.tsx +111 -0
  734. package/src/components/SlotGrid/index.ts +2 -0
  735. package/src/components/SocialButton/SocialButton.module.scss +4 -0
  736. package/src/components/SocialButton/SocialButton.tsx +40 -0
  737. package/src/components/SocialButton/index.ts +2 -0
  738. package/src/components/Sortable/Sortable.module.scss +177 -0
  739. package/src/components/Sortable/Sortable.tokens.scss +27 -0
  740. package/src/components/Sortable/Sortable.tsx +572 -0
  741. package/src/components/Sortable/containerAwareCollision.ts +125 -0
  742. package/src/components/Sortable/index.ts +13 -0
  743. package/src/components/SortableGroup/SortableGroup.module.scss +23 -0
  744. package/src/components/SortableGroup/SortableGroup.tsx +315 -0
  745. package/src/components/SortableGroup/index.ts +4 -0
  746. package/src/components/SortableGroup/moveSortableItem.ts +39 -0
  747. package/src/components/Sparkline/Sparkline.module.scss +28 -0
  748. package/src/components/Sparkline/Sparkline.tokens.scss +7 -0
  749. package/src/components/Sparkline/Sparkline.tsx +133 -0
  750. package/src/components/Sparkline/index.ts +2 -0
  751. package/src/components/Sparkline/sparklineModel.ts +119 -0
  752. package/src/components/Split/Split.module.scss +158 -0
  753. package/src/components/Split/Split.tokens.scss +10 -0
  754. package/src/components/Split/Split.tsx +231 -0
  755. package/src/components/Split/index.ts +2 -0
  756. package/src/components/Stack/Stack.module.scss +67 -0
  757. package/src/components/Stack/Stack.tokens.scss +11 -0
  758. package/src/components/Stack/Stack.tsx +100 -0
  759. package/src/components/Stack/index.ts +2 -0
  760. package/src/components/StagePath/StagePath.module.scss +255 -0
  761. package/src/components/StagePath/StagePath.tokens.scss +43 -0
  762. package/src/components/StagePath/StagePath.tsx +176 -0
  763. package/src/components/StagePath/index.ts +2 -0
  764. package/src/components/StatGroup/StatGroup.module.scss +6 -0
  765. package/src/components/StatGroup/StatGroup.tsx +70 -0
  766. package/src/components/StatGroup/StatGroupContext.ts +10 -0
  767. package/src/components/StatGroup/StatTile.module.scss +99 -0
  768. package/src/components/StatGroup/StatTile.tokens.scss +35 -0
  769. package/src/components/StatGroup/StatTile.tsx +143 -0
  770. package/src/components/StatGroup/index.ts +4 -0
  771. package/src/components/Sticky/Sticky.module.scss +98 -0
  772. package/src/components/Sticky/Sticky.tokens.scss +17 -0
  773. package/src/components/Sticky/Sticky.tsx +103 -0
  774. package/src/components/Sticky/index.ts +2 -0
  775. package/src/components/Switch/Switch.module.scss +182 -0
  776. package/src/components/Switch/Switch.tokens.scss +59 -0
  777. package/src/components/Switch/Switch.tsx +214 -0
  778. package/src/components/Switch/index.ts +2 -0
  779. package/src/components/Table/Table.module.scss +308 -0
  780. package/src/components/Table/Table.tokens.scss +79 -0
  781. package/src/components/Table/Table.tsx +381 -0
  782. package/src/components/Table/index.ts +15 -0
  783. package/src/components/TableOfContents/TableOfContents.module.scss +83 -0
  784. package/src/components/TableOfContents/TableOfContents.tokens.scss +26 -0
  785. package/src/components/TableOfContents/TableOfContents.tsx +192 -0
  786. package/src/components/TableOfContents/activeSection.ts +18 -0
  787. package/src/components/TableOfContents/index.ts +2 -0
  788. package/src/components/Tabs/Tabs.module.scss +359 -0
  789. package/src/components/Tabs/Tabs.tokens.scss +50 -0
  790. package/src/components/Tabs/Tabs.tsx +538 -0
  791. package/src/components/Tabs/index.ts +2 -0
  792. package/src/components/Text/Text.module.scss +115 -0
  793. package/src/components/Text/Text.tokens.scss +55 -0
  794. package/src/components/Text/Text.tsx +197 -0
  795. package/src/components/Text/index.ts +2 -0
  796. package/src/components/Textarea/Textarea.module.scss +94 -0
  797. package/src/components/Textarea/Textarea.tokens.scss +48 -0
  798. package/src/components/Textarea/Textarea.tsx +246 -0
  799. package/src/components/Textarea/index.ts +2 -0
  800. package/src/components/Thread/Thread.module.scss +161 -0
  801. package/src/components/Thread/Thread.tokens.scss +32 -0
  802. package/src/components/Thread/Thread.tsx +176 -0
  803. package/src/components/Thread/index.ts +2 -0
  804. package/src/components/TimeField/TimeField.module.scss +232 -0
  805. package/src/components/TimeField/TimeField.tsx +793 -0
  806. package/src/components/TimeField/index.ts +2 -0
  807. package/src/components/Timeline/Timeline.module.scss +58 -0
  808. package/src/components/Timeline/Timeline.tokens.scss +13 -0
  809. package/src/components/Timeline/Timeline.tsx +53 -0
  810. package/src/components/Timeline/index.ts +2 -0
  811. package/src/components/Title/Title.module.scss +84 -0
  812. package/src/components/Title/Title.tokens.scss +37 -0
  813. package/src/components/Title/Title.tsx +150 -0
  814. package/src/components/Title/index.ts +2 -0
  815. package/src/components/Toast/Toast.module.scss +299 -0
  816. package/src/components/Toast/Toast.tokens.scss +65 -0
  817. package/src/components/Toast/Toast.tsx +122 -0
  818. package/src/components/Toast/ToastViewport.tsx +166 -0
  819. package/src/components/Toast/api.ts +175 -0
  820. package/src/components/Toast/index.ts +5 -0
  821. package/src/components/Toast/store.ts +133 -0
  822. package/src/components/Toast/useToastTimer.ts +94 -0
  823. package/src/components/Tooltip/Tooltip.module.scss +99 -0
  824. package/src/components/Tooltip/Tooltip.tokens.scss +23 -0
  825. package/src/components/Tooltip/Tooltip.tsx +341 -0
  826. package/src/components/Tooltip/index.ts +2 -0
  827. package/src/components/TopBar/TopBar.module.scss +235 -0
  828. package/src/components/TopBar/TopBar.tokens.scss +79 -0
  829. package/src/components/TopBar/TopBar.tsx +87 -0
  830. package/src/components/TopBar/TopBarEnd.tsx +20 -0
  831. package/src/components/TopBar/TopBarIconButton.tsx +86 -0
  832. package/src/components/TopBar/TopBarSearch.tsx +319 -0
  833. package/src/components/TopBar/TopBarSearchPanel.tsx +268 -0
  834. package/src/components/TopBar/TopBarStart.tsx +20 -0
  835. package/src/components/TopBar/index.ts +11 -0
  836. package/src/components/Tour/Spotlight.tsx +121 -0
  837. package/src/components/Tour/Tour.module.scss +210 -0
  838. package/src/components/Tour/Tour.tokens.scss +58 -0
  839. package/src/components/Tour/Tour.tsx +617 -0
  840. package/src/components/Tour/index.ts +2 -0
  841. package/src/components/Tour/useTourTarget.ts +115 -0
  842. package/src/components/TreeView/TreeView.module.scss +268 -0
  843. package/src/components/TreeView/TreeView.tokens.scss +36 -0
  844. package/src/components/TreeView/TreeView.tsx +536 -0
  845. package/src/components/TreeView/index.ts +3 -0
  846. package/src/components/TreeView/treeModel.ts +224 -0
  847. package/src/components/VisuallyHidden/VisuallyHidden.module.scss +7 -0
  848. package/src/components/VisuallyHidden/VisuallyHidden.tsx +29 -0
  849. package/src/components/VisuallyHidden/index.ts +2 -0
  850. package/src/components/WidgetPreview/WidgetPreview.module.scss +11 -0
  851. package/src/components/WidgetPreview/WidgetPreview.tokens.scss +26 -0
  852. package/src/components/WidgetPreview/WidgetPreview.tsx +36 -0
  853. package/src/components/WidgetPreview/WidgetShape.module.scss +140 -0
  854. package/src/components/WidgetPreview/WidgetShape.tsx +159 -0
  855. package/src/components/WidgetPreview/index.ts +2 -0
  856. package/src/components/_internal/Trend.tsx +27 -0
  857. package/src/components/_internal/choiceTile.scss +74 -0
  858. package/src/components/_internal/collapse.scss +10 -0
  859. package/src/components/_internal/collapse.ts +58 -0
  860. package/src/components/_internal/currency.ts +257 -0
  861. package/src/components/_internal/dragAnnouncements.ts +200 -0
  862. package/src/components/_internal/fieldWiring.ts +225 -0
  863. package/src/components/_internal/gridSpan.ts +54 -0
  864. package/src/components/_internal/isoDay.ts +35 -0
  865. package/src/components/_internal/letterKey.ts +26 -0
  866. package/src/components/_internal/overlay/focusRestore.ts +21 -0
  867. package/src/components/_internal/overlay/index.ts +12 -0
  868. package/src/components/_internal/overlay/tourHold.ts +23 -0
  869. package/src/components/_internal/overlay/useFocusTrap.ts +120 -0
  870. package/src/components/_internal/overlay/useInOverlay.ts +81 -0
  871. package/src/components/_internal/overlay/useOverlayStack.ts +232 -0
  872. package/src/components/_internal/overlay/useScrollLock.ts +112 -0
  873. package/src/components/_internal/refs.ts +48 -0
  874. package/src/components/_internal/statusColor.ts +26 -0
  875. package/src/components/_internal/timeUtils.ts +23 -0
  876. package/src/components/_internal/useAsyncOptions.ts +145 -0
  877. package/src/components/_internal/useClippedTooltip.ts +50 -0
  878. package/src/components/_internal/useControllableState.ts +50 -0
  879. package/src/components.manifest.json +1141 -0
  880. package/src/hooks/useBelowBreakpoint.ts +58 -0
  881. package/src/i18n/I18nProvider.tsx +52 -0
  882. package/src/i18n/LocaleProvider.tsx +17 -0
  883. package/src/i18n/en.ts +648 -0
  884. package/src/i18n/format.ts +71 -0
  885. package/src/i18n/index.ts +13 -0
  886. package/src/i18n/messages.ts +1275 -0
  887. package/src/i18n/ru.ts +677 -0
  888. package/src/i18n/useLocale.ts +19 -0
  889. package/src/i18n/useTranslation.ts +58 -0
  890. package/src/index.ts +913 -0
  891. package/src/palette/index.ts +2 -0
  892. package/src/palette/palette.ts +108 -0
  893. package/src/styles/dark.scss +4 -0
  894. package/src/styles/global.scss +7 -0
  895. package/src/styles/mixins.scss +143 -0
  896. package/src/styles/reset.scss +78 -0
  897. package/src/styles/tokens.scss +18 -0
  898. package/src/styles/typography.scss +44 -0
@@ -0,0 +1,49 @@
1
+ # `<Avatar>` — profile circle
2
+
3
+ ```tsx
4
+ <Avatar name="Alex Rivera" />
5
+ <Avatar name="Alex Rivera" src="https://example.com/alex.jpg" size="lg" status="online" />
6
+
7
+ // Hover-discoverable name (off by default; opt in)
8
+ <Avatar name="Alex Rivera" tooltip />
9
+
10
+ // In a table row
11
+ <Cluster gap="sm" align="center">
12
+ <Avatar name={contact.name} size="sm" />
13
+ <span>{contact.name}</span>
14
+ </Cluster>
15
+ ```
16
+
17
+ <!-- props:start -->
18
+
19
+ ## Props
20
+
21
+ <!-- prettier-ignore -->
22
+ | Prop | Type | Required | Description |
23
+ |---|---|---|---|
24
+ | `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. |
25
+ | `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. |
26
+ | `size` | `'inline' \| 'sm' \| 'md' \| 'lg' \| 'xl'` | no | Diameter. - `sm` (24px) — table rows, dense lists. - `md` (32px, default) — most uses. - `lg` (40px) — detail-page headers. - `xl` (80px) — member-card popovers / profile headers. - `inline` — one line of the surrounding text tall (`1lh`), initials scaled to match, so an avatar in a text row (a `DefinitionList` value, a table cell, a line of text) doesn't make it taller. Follows the text size; no size decision per call site. Not available on `<AvatarGroup>` — and don't set it per child inside one: the group's overlaps are sized for its fixed steps. Inside `<AvatarGroup>`, defaults to the group's `size`. |
27
+ | `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. |
28
+ | `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. |
29
+ | …native | | | plus native `<span>` attributes |
30
+
31
+ <!-- props:end -->
32
+
33
+ - Inside `<AvatarGroup>`, the group's `size` and `tooltip` become defaults — explicit per-child props still win. The avatar also picks up a `--color-bg` ring so stacked siblings read as distinct.
34
+ - Use `avatarColorIndex(name)` if you need to match an avatar's color elsewhere (e.g. a chart segment).
35
+
36
+ #### When NOT to use
37
+
38
+ - Company logos: Avatars are for people. Use a `Logo` component (not yet shipped) or an `<img>` with rounded corners.
39
+ - As a clickable button. If clicking opens a profile, wrap the Avatar in a `<button>` or `<Link>`; don't make the Avatar itself interactive.
40
+
41
+ #### Anti-patterns
42
+
43
+ - ❌ `<Avatar name="" />`: `name` is required and is the accessible label.
44
+ - ❌ Relying on the status dot's colour, or re-tinting it. The distinct shape is the channel that survives colour-vision deficiency, and `away` vs `busy` collapses without it.
45
+ - ❌ Adding your own visually-hidden status text next to the avatar. It is announced twice, and inside the no-`src` branch (a `role="img"`) ARIA prunes children as presentational, so it would be silent there anyway.
46
+ - ❌ Using Avatar for a non-person icon. Use an icon component.
47
+ - ❌ Wrapping the result in `role="img"` again. With `src`, the inner `<img>` is the labeled image; without it, the wrapper has `role="img" aria-label={name}`, plus the localized `status` when set (`"Alex, online"`).
48
+
49
+ For an AI agent acting on behalf of a member, see [`AgentAvatar`](AgentAvatar.md).
@@ -0,0 +1,47 @@
1
+ # `<AvatarGroup>` — Slack-style stacked row of avatars
2
+
3
+ ```tsx
4
+ <AvatarGroup max={4} size="md" onOverflowClick={(_e, n) => openMembersPopover(n)}>
5
+ {team.map((m) => (
6
+ <Avatar key={m.id} name={m.name} src={m.avatarUrl} status={m.presence} />
7
+ ))}
8
+ </AvatarGroup>
9
+
10
+ // Static: without onOverflowClick the +N is non-interactive
11
+ <AvatarGroup max={3}>
12
+ <Avatar name="Alex Rivera" />
13
+ <Avatar name="Priya Patel" />
14
+ <Avatar name="Tom Kim" />
15
+ <Avatar name="Sara Chen" />
16
+ </AvatarGroup>
17
+ ```
18
+
19
+ <!-- props:start -->
20
+
21
+ ## Props
22
+
23
+ <!-- prettier-ignore -->
24
+ | Prop | Type | Required | Description |
25
+ |---|---|---|---|
26
+ | `children` | `ReactNode` | yes | Avatar children. |
27
+ | `size` | `'sm' \| 'md' \| 'lg' \| 'xl'` | no | Diameter default for child avatars. Defaults to `'md'`. Each child can still override via its own `size` prop (idiomatic React composition — explicit prop wins). For a strictly uniform group, don't set `size` on individual children. - `sm` (24px) — table rows, dense lists. - `md` (32px, default) — most uses. - `lg` (40px) — detail-page headers. - `xl` (80px) — member-card popovers / profile headers. |
28
+ | `max` | `number` | no | Maximum number of visible avatars. Children beyond this count collapse into a single `+N` button at the tail. Defaults to `4`. The `+N` only appears when there are STRICTLY more children than `max`. |
29
+ | `tooltip` | `boolean` | no | Whether to render a name tooltip on each child avatar. Defaults to `true` inside the group (a standalone `<Avatar tooltip>` is opt-in; group context flips that default). Set `false` on the group to suppress all tooltips; overridable per-child by setting `tooltip` on the Avatar. |
30
+ | `onOverflowClick` | `((event: MouseEvent<HTMLButtonElement, MouseEvent>, hiddenCount: number) => void)` | no | Fires when the user clicks the `+N` overflow button. The library does NOT render a popover — apps decide what happens (open a modal, navigate, etc.). When omitted, the `+N` is rendered as a non-interactive `<span>` (still labelled for AT). |
31
+ | …native | | | plus native `<div>` attributes |
32
+
33
+ <!-- props:end -->
34
+
35
+ - Horizontal row of overlapping `<Avatar>`s with a `+N` overflow control when child count exceeds `max` (default `4`).
36
+ - The group wrapper is `role="list"` and each visible avatar is wrapped in a `role="listitem"` div; the +N (button or span) is the last list item.
37
+ - forwardRef to the outer `<div>`. `className` is merged.
38
+
39
+ #### When NOT to use
40
+
41
+ - A single avatar: use `<Avatar>` directly.
42
+ - Showing member counts but not faces: use a `Badge` next to a label.
43
+
44
+ #### Anti-patterns
45
+
46
+ - ❌ Wrapping `<AvatarGroup>` in a `<button>` as one click target. The `+N` is the click affordance; the visible avatars are deliberately not interactive. Wrap individual avatars in `<button>` / `<Link>` if needed.
47
+ - ❌ Mixing avatar sizes inside one group on purpose. Per-child `size` wins, which is useful for emphasising one member but visually noisy if used carelessly.
@@ -0,0 +1,60 @@
1
+ # `<Badge>` — status / category pill
2
+
3
+ ```tsx
4
+ <Badge tone="success">Active</Badge>
5
+ <Badge tone="danger">Churned</Badge>
6
+
7
+ // Stripe variant — rectangular category marker with left stripe:
8
+ <Badge variant="stripe" tone="info">Lead</Badge>
9
+ <Badge variant="stripe" tone="warning">Renewal due</Badge>
10
+
11
+ // Categorical palette color (non-semantic) — for tag-like labels:
12
+ <Badge color="amber">Marketing</Badge>
13
+ <Badge color="teal">Engineering</Badge>
14
+ <Badge variant="stripe" color="violet">Design</Badge>
15
+
16
+ // Tag list
17
+ <Cluster gap="xs">
18
+ <Badge tone="purple">Enterprise</Badge>
19
+ <Badge tone="info">Pipeline 2026</Badge>
20
+ </Cluster>
21
+
22
+ // Inside a heading line: align="middle" so the badge doesn't ride the heading's baseline
23
+ <Title order={1}>
24
+ <Text as="span" size="inherit" tone="muted">ENG-5</Text> Fix login flow{' '}
25
+ <Badge align="middle" tone="warning">In progress</Badge>
26
+ </Title>
27
+ ```
28
+
29
+ <!-- props:start -->
30
+
31
+ ## Props
32
+
33
+ <!-- prettier-ignore -->
34
+ | Prop | Type | Required | Description |
35
+ |---|---|---|---|
36
+ | `tone` | `'neutral' \| 'info' \| 'success' \| 'warning' \| 'danger' \| 'purple'` | no | Semantic tone. - `neutral` (default) — generic tag, no semantic meaning. - `info` — new / in-progress / informational states ("Lead", "Pipeline 2026"). - `success` — positive states ("Active", "Won", "Healthy"). - `warning` — at-risk / pending states ("Renewal due", "Pending review"). - `danger` — negative states ("Churned", "Lost", "Blocked"). - `purple` — special / highlighted categories ("Enterprise", "VIP"). |
37
+ | `size` | `'sm' \| 'md'` | no | Pill height and emphasis. - `md` (20px, default) — the standard "loud label" pill. Uppercase, tracked, semibold. Reads as a deliberate status marker. - `sm` (16px) — quieter inline tag for tight table cells, compact toolbars, or anywhere a 20px uppercase pill visually crowds adjacent text. Drops the uppercase transform and caps tracking so it sits next to body copy without shouting; case is preserved as-typed (write `Active`, get `Active`). Same 11px size and semibold weight as `md`. |
38
+ | `dot` | `'start' \| 'end'` | no | Render a small filled circle in the badge's text color alongside the content. Useful when the dot is the primary status signal and the label is supporting context ("● Active", "Failed ●"). - `start` — dot before the content. - `end` — dot after the content. Omit for no dot. The dot is purely decorative (`aria-hidden`) — the badge text remains the accessible label. |
39
+ | `variant` | `'filled' \| 'stripe'` | no | Visual variant. - `'filled'` (default) — solid tone-tinted pill. The standard "loud status" look. - `'stripe'` — rectangular block with a tone-colored left stripe + soft tinted body. Use for category markers or sidebar labels where pill emphasis is too loud. |
40
+ | `color` | `PaletteColor` | no | Optional categorical palette color. When set, takes precedence over `tone`: the badge fills with the matching `--color-palette-<name>-bg/fg` tokens. Use for non-semantic categorical labels (e.g., audit event namespaces, tag colors) where the 6 semantic tones aren't enough. Both filled and stripe variants are supported; for stripe the left-border picks up the palette `fg` token. |
41
+ | `align` | `'baseline' \| 'middle'` | no | Vertical alignment within the surrounding line of text. - `baseline` (default) — rides the text baseline; right for body-size text. - `middle` — centers the badge on the line box; use for a badge inside a heading line (`<Title>` / `<PageHeader.Title>`), where baseline riding makes the badge look sunken next to large text. |
42
+ | …native | | | plus native `<span>` attributes |
43
+
44
+ <!-- props:end -->
45
+
46
+ - **Non-interactive.** If it's clickable, use `<Button>` instead.
47
+ - Doesn't auto-add `role="status"`. Wrap the badge (or a parent region) in `aria-live="polite"` if a state change should be announced. **This is not an inconsistency with `EntityChip`, which announces its own state** — a Badge tone is a durable property of the row you are looking at, not a change that happens while you are elsewhere, so there is nothing for the component to announce. See [Transient state and screen readers](../transient-state.md) for the rule both follow.
48
+
49
+ #### When NOT to use
50
+
51
+ - ❌ As a button. Badges are non-interactive labels; if it's clickable use a `Button` or `Link`.
52
+ - ❌ For long-form text. Badges are 1-2 words max.
53
+ - ❌ `align="middle"` outside a heading line. It fixes the baseline-vs-line-box mismatch next to large text; keep the default `baseline` next to body-size text.
54
+
55
+ #### Anti-patterns
56
+
57
+ - ❌ Mixing tone meanings across pages. `success` may mean "Won" on Deals and "Active" on Contacts, but never use `success` for anything negative.
58
+ - ❌ Stacking 4+ badges on a single row. If you have that many tags, the design problem is information density, not the badge.
59
+ - ❌ Wrapping a Badge in a `<button>` to make it clickable. Use a `Button` with an appropriate variant.
60
+ - ❌ Using `color` (palette) for status. Use `tone` (semantic); palette colors carry no built-in meaning and the mapping may shift over time.
@@ -0,0 +1,89 @@
1
+ # `<Banner>` — full-width system / app message bar
2
+
3
+ Tinted, full-width bar for messages about the system or account, not the page: maintenance, "Email sending suspended", "Sending restored". Mount it ONLY in `<AppLayout>`'s `banner` (system-wide, above everything) or `contextBanner` (module/route-scoped, under the top bar) slot. For page content use `<Alert>`.
4
+
5
+ ```tsx
6
+ import { AppLayout, Banner, Link } from '@eocrm/design-system';
7
+
8
+ <AppLayout
9
+ banner={
10
+ <Banner
11
+ tone="warning"
12
+ title="Scheduled maintenance"
13
+ action={<Link href="/status">Details</Link>}
14
+ >
15
+ Sat 4 Oct, 22:00–23:00 CET. CRM will be read-only.
16
+ </Banner>
17
+ }
18
+ contextBanner={
19
+ inEmail &&
20
+ suspended && (
21
+ <Banner tone="danger" title="Email sending suspended.">
22
+ Bounce rate 7.2% (limit 5%).
23
+ </Banner>
24
+ )
25
+ }
26
+ topBar={<TopBar />}
27
+ sidebar={<Rail>{nav}</Rail>}
28
+ >
29
+ {routes}
30
+ </AppLayout>;
31
+
32
+ // Module-scoped banner that appeared mid-session: danger + live is announced on insertion (role="alert")
33
+ <Banner
34
+ tone="danger"
35
+ live
36
+ title="Email sending suspended."
37
+ action={
38
+ <Button size="xs" variant="secondary">
39
+ Review bounces
40
+ </Button>
41
+ }
42
+ >
43
+ Bounce rate 7.2% (limit 5%).
44
+ </Banner>;
45
+
46
+ // Dismissible: the app persists the dismissal
47
+ {
48
+ !dismissed && (
49
+ <Banner tone="success" onDismiss={() => setDismissed(true)}>
50
+ Email sending restored.
51
+ </Banner>
52
+ );
53
+ }
54
+ ```
55
+
56
+ <!-- props:start -->
57
+
58
+ ## Props
59
+
60
+ <!-- prettier-ignore -->
61
+ | Prop | Type | Required | Description |
62
+ |---|---|---|---|
63
+ | `tone` | `'info' \| 'success' \| 'warning' \| 'danger'` | no | Tone. Defaults to `'info'`. `info` — advance notice; `success` — condition resolved; `warning` — imminent or degrading; `danger` — broken or blocked now. See `BannerTone`. |
64
+ | `title` | `ReactNode` | no | Optional bold lead-in, rendered INLINE before `children` in the same text flow ("**Scheduled maintenance** Sat 22:00–23:00."). Keep it short — the banner is one line on desktop. Collapses the native HTML `title` (tooltip) attribute. |
65
+ | `children` | `ReactNode` | no | Message text. Wraps with the title. Keep to one sentence. |
66
+ | `icon` | `ReactNode` | no | Override the tone's default icon (any ReactNode, typically a 16px lucide icon with `aria-hidden`). `null` hides it. Defaults: `info` → `Info`, `success` → `CheckCircle2`, `warning` → `AlertTriangle`, `danger` → `XCircle`. |
67
+ | `action` | `ReactNode` | no | One action pinned to the end of the row — typically a `<Link>` ("Details") or a `<Button size="xs">` ("Review bounces"). Banner doesn't lay out multiple actions; pass one. |
68
+ | `live` | `boolean` | no | Whether the Banner is a live region. Defaults to `false`: `role="note"`, right for a banner that is present when the app loads. Pass `live` for a banner that APPEARS mid-session. Caveat: a mid-session Banner mounts together with its text, and a `role="status"` region that mounts with its text is not reliably announced. Only `tone="danger"` + `live` (`role="alert"`) is announced on insertion. For a must-hear non-danger message, pair the banner with a `<LiveRegion>` or a toast. Decide it at mount — flipping it on a mounted Banner announces nothing. |
69
+ | `onDismiss` | `(() => void)` | no | Called when the × is clicked. When set, the × renders. **Controlled** — Banner keeps no hidden state and persists nothing; the app decides what "dismissed" means (per session, per incident, per user) and stops rendering it. |
70
+ | …native | | | plus native `<div>` attributes |
71
+
72
+ <!-- props:end -->
73
+
74
+ - **The tone is spoken.** A visually hidden, localised prefix ("Warning: ") comes before the text.
75
+ - The tone is `danger`, not Alert's `error`.
76
+ - **`live` defaults to `false`** (`role="note"`), because banners are usually present at load. Pass `live` for one that appears mid-session — but a Banner mounts together with its text, so `role="status"` is not reliably announced; only `tone="danger"` + `live` (`role="alert"`) is. For a must-hear non-danger message, add a `<LiveRegion>` or a toast alongside the banner.
77
+ - Neither slot is sticky; only the TopBar pins.
78
+
79
+ **Anti-patterns**
80
+
81
+ - ❌ A Banner inside page content. Use `<Alert>`.
82
+ - ❌ `onDismiss` on a `danger` banner while the condition still holds.
83
+ - ❌ Routine stacks of banners in one slot. Show the most severe first.
84
+ - ❌ A system-wide message in `contextBanner`, or a route-specific one in `banner`.
85
+ - ❌ `live` on a banner that is present when the app loads.
86
+ - ❌ Relying on `live` for a non-danger banner to be announced on appearing. Add a `<LiveRegion>` or a toast.
87
+ - ❌ Multiple actions or a paragraph of text. Link to a details page.
88
+
89
+ **When NOT to use:** content about the current page or a section of it → `<Alert>`; a transient confirmation ("Saved") → `toast.success(...)`; anywhere other than `AppLayout`'s `banner` / `contextBanner` slots (inside page content it is just a borderless Alert).
@@ -0,0 +1,32 @@
1
+ # `<BrandIcon>` — third-party brand marks
2
+
3
+ ```tsx
4
+ <Button variant="secondary">
5
+ <BrandIcon name="google" size={16} /> Continue with Google
6
+ </Button>
7
+
8
+ // Standalone, labeled
9
+ <BrandIcon name="yandex" title="Yandex" size={24} />
10
+ ```
11
+
12
+ <!-- props:start -->
13
+
14
+ ## Props
15
+
16
+ <!-- prettier-ignore -->
17
+ | Prop | Type | Required | Description |
18
+ |---|---|---|---|
19
+ | `name` | `'google' \| 'yandex'` | yes | Which brand mark to render. |
20
+ | `size` | `number` | no | Square pixel size (width = height). Defaults to `20`. |
21
+ | `title` | `string` | no | Accessible name. Omit (default) for a decorative icon beside a text label — the icon renders `aria-hidden`. Set it for a standalone icon (e.g. an icon-only button) → `role="img"` + `aria-label`. |
22
+ | …native | | | plus native HTML attributes |
23
+
24
+ <!-- props:end -->
25
+
26
+ Full-color official brand marks for SSO buttons. Ships `google` + `yandex`.
27
+
28
+ - Decorative by default (`aria-hidden`); pass `title` for a labeled standalone icon (`role="img"`).
29
+
30
+ **When NOT to use:** generic UI glyphs → `lucide-react`. Don't recolor brand marks.
31
+
32
+ **Anti-pattern:** ❌ a decorative `BrandIcon` next to visible brand text AND a `title` double-announces ("Google Continue with Google"). Keep it `aria-hidden` (the default) beside a label.
@@ -0,0 +1,72 @@
1
+ # `<Breadcrumb>` — navigation trail
2
+
3
+ Compound (Breadcrumb.Item) navigation breadcrumb. Last child is auto-marked as the current page (`<span aria-current="page">`); non-last items are muted Links. Default separator is a ChevronRight icon.
4
+
5
+ ```tsx
6
+ import { Breadcrumb, Link } from '@eocrm/design-system';
7
+ import { Link as RouterLink } from 'react-router-dom';
8
+
9
+ <Breadcrumb>
10
+ <Breadcrumb.Item as={RouterLink} to="/mockups">Mockups</Breadcrumb.Item>
11
+ <Breadcrumb.Item as={RouterLink} to="/mockups/contacts">Contacts</Breadcrumb.Item>
12
+ <Breadcrumb.Item>Acme Corp</Breadcrumb.Item> {/* auto-current */}
13
+ </Breadcrumb>
14
+
15
+ // Custom separator
16
+ <Breadcrumb separator={<Slash size={12} />}>
17
+ <Breadcrumb.Item as={RouterLink} to="/a">A</Breadcrumb.Item>
18
+ <Breadcrumb.Item>B</Breadcrumb.Item>
19
+ </Breadcrumb>
20
+
21
+ // External crumb (default <a>)
22
+ <Breadcrumb>
23
+ <Breadcrumb.Item href="https://docs.example.com">Docs</Breadcrumb.Item>
24
+ <Breadcrumb.Item>This page</Breadcrumb.Item>
25
+ </Breadcrumb>
26
+ ```
27
+
28
+ <!-- props:start -->
29
+
30
+ ## Props
31
+
32
+ ### `BreadcrumbProps`
33
+
34
+ <!-- prettier-ignore -->
35
+ | Prop | Type | Required | Description |
36
+ |---|---|---|---|
37
+ | `children` | `ReactNode` | yes | One or more `<Breadcrumb.Item>` children. The component injects the separator between items and auto-marks the last child as current (renders as `<span aria-current="page">` instead of a link). |
38
+ | `separator` | `ReactNode` | no | Custom separator between items. Defaults to a small `<ChevronRight>` lucide icon. The separator renders inside a `<span aria-hidden="true">` wrapper automatically. |
39
+ | `ariaLabel` | `string` | no | Visible label for the `<nav>` element. Defaults to the i18n value at `breadcrumb.ariaLabel` (`'Breadcrumb'` in English) when omitted OR empty — an empty string is not an explicit name, so it takes the default too. Override when multiple breadcrumb instances coexist on the same page. |
40
+ | `className` | `string` | no | Pass-through className applied to the `<nav>` wrapper. |
41
+
42
+ ### `BreadcrumbItemProps`
43
+
44
+ <!-- prettier-ignore -->
45
+ | Prop | Type | Required | Description |
46
+ |---|---|---|---|
47
+ | `as` | `ElementType` | no | |
48
+ | `current` | `boolean` | no | Mark this item as the current page. Forced to `true` automatically for the last child of `<Breadcrumb>` (auto-current). When `true`, the item renders as `<span aria-current="page">` and ignores all link-related props (`as`, `to`, `href`, etc.). |
49
+ | `children` | `ReactNode` | no | |
50
+ | `className` | `string` | no | |
51
+ | …native | | | plus native attributes of the `as` element (default `<a>`) |
52
+
53
+ <!-- props:end -->
54
+
55
+ - **Compound API** — wrap each crumb in `<Breadcrumb.Item>`.
56
+ - **Auto-current** — last child gets `aria-current="page"` and renders as `<span>`. Override with explicit `current` prop.
57
+ - **Item is polymorphic** — same `as` pattern as Link. It is not `forwardRef`-wrapped because the return shape varies (`<span>` for current, `<Link>` for non-current); for a ref to a specific crumb, render the underlying link manually inside an Item, or use Link directly.
58
+ - Separated by a customizable icon in an `<ol>` inside the `<nav>`.
59
+ - **Default separator** is `<ChevronRight size={14} />`. Override via the `separator` prop.
60
+ - **`<nav aria-label="Breadcrumb">` wrapper** — semantic landmark, AT-friendly.
61
+
62
+ #### When NOT to use
63
+
64
+ - ❌ Horizontal nav of equal-importance siblings → `<Tabs>` or `<ButtonGroup>`.
65
+ - ❌ Step-by-step progress → a dedicated Stepper (not shipped).
66
+ - ❌ Single-page apps with no parent hierarchy — omit Breadcrumb entirely.
67
+
68
+ #### Anti-patterns
69
+
70
+ - ❌ Making the current page clickable. Current items are non-link by design.
71
+ - ❌ Long trails (5+ levels) — wrap and become illegible.
72
+ - ❌ Building your own `<nav>` + chevron pattern. Use Breadcrumb.
@@ -0,0 +1,107 @@
1
+ # `<Button>` — action triggers
2
+
3
+ ```tsx
4
+ <Button onClick={save}>Save</Button>
5
+ <Button variant="danger" size="sm">Delete</Button>
6
+ <Button variant="secondary" disabled>Cancel</Button>
7
+ <Button
8
+ variant="secondary"
9
+ size="sm"
10
+ selected={ownerApplied}
11
+ aria-pressed={ownerApplied}
12
+ onClick={() => setOwnerApplied((value) => !value)}
13
+ >
14
+ Owner: {ownerLabel}
15
+ </Button>
16
+
17
+ // Icon-only square button (20×20 at xs, 32×32 at md); aria-label is the accessible name
18
+ <Button size="xs" variant="ghost" iconOnly aria-label="Remove">
19
+ <X size={12} />
20
+ </Button>
21
+
22
+ // Destination that must look like a button: a real <a>; rel="noreferrer" belongs with target="_blank"
23
+ <Button as="a" href={idpConsoleUrl} target="_blank" rel="noreferrer" variant="secondary">
24
+ Open identity console
25
+ </Button>
26
+
27
+ // Form footer
28
+ <Cluster justify="end" gap="sm">
29
+ <Button variant="secondary">Cancel</Button>
30
+ <Button type="submit">Save</Button>
31
+ </Cluster>
32
+
33
+ // Status quick actions painted like the status pill they set. `noShow` / `completed`
34
+ // are your status records, each with a `color: PaletteColor` that also feeds the
35
+ // PillMenuOption, so a tenant recolouring a status recolours its button too.
36
+ <Cluster gap="sm">
37
+ <PillMenu current={current} options={statuses} onSelect={setStatusId} />
38
+ <Button size="sm" color={noShow.color} onClick={() => setStatusId(noShow.id)}>No show</Button>
39
+ <Button size="sm" color={completed.color} onClick={() => setStatusId(completed.id)}>Completed</Button>
40
+ </Cluster>
41
+ ```
42
+
43
+ <!-- props:start -->
44
+
45
+ ## Props
46
+
47
+ <!-- prettier-ignore -->
48
+ | Prop | Type | Required | Description |
49
+ |---|---|---|---|
50
+ | `variant` | `'primary' \| 'secondary' \| 'ghost' \| 'danger' \| 'danger-outline' \| 'success'` | no | Visual variant. - `primary` (default) — the section's main action. Use **one** per page section. - `secondary` — supporting actions like "Cancel", "Export", "Filter". - `ghost` — tertiary actions in dense UIs (toolbar buttons, row actions). - `danger` — destructive operations only (Delete, Revoke, Remove). Pair with a confirmation if irreversible. - `danger-outline` — a destructive action that must not dominate: surface fill, danger text and border. For a Remove repeated on every row, or a destructive action beside a primary one. Use filled `danger` for the confirm step itself. - `success` — **transient confirmation only**, not an initial state. Flip to `success` for ~1.5s after an action resolves (Save → "Saved!"), then flip back. Never render a button as `success` on mount — it has no action-intent meaning, only post-action feedback. See the `@example` below for the timer pattern. |
51
+ | `size` | `'xs' \| 'sm' \| 'md' \| 'lg'` | no | Control height (matches the shared `--size-*` scale used by Input and Avatar). - `xs` (20px) — icon-only or very dense inline actions (row controls, chip-adjacent buttons). Pass `aria-label` when icon-only. Below WCAG 2.5.5 Level AAA touch-target guidance; reserve for desktop-first surfaces. - `sm` (24px) — dense toolbars, tables, inline actions. - `md` (32px, default) — most contexts. - `lg` (40px) — marketing-style empty states or emphasized primary actions. |
52
+ | `iconOnly` | `boolean` | no | Render the button as a square icon-only target — `aspect-ratio` is forced to 1 so width tracks the size's `height` token (`xs` → 20×20, `sm` → 24×24, `md` → 32×32, `lg` → 40×40) and `padding` is tightened to a small inset (4px) so the icon has breathing room without changing the outer shape. **Always pass `aria-label`** when `iconOnly` is set, otherwise the button has no accessible name. Pass a single icon as `children`. Use for inline density (row controls, chip-adjacent actions, toolbar affordances). For an icon + short text label, leave `iconOnly` off — the button will lay out as a normal rectangle with the existing gap. |
53
+ | `selected` | `boolean` | no | Controlled persistent paint for an applied filter or toolbar value. Selected paint applies only to `secondary` and `ghost` Buttons; `primary`, `danger`, and `success` retain their intent paint. This prop is visual only and does not add toggle-button semantics. Pass native `aria-pressed` explicitly only when activating the Button itself toggles the selected state; menu and disclosure triggers keep their own semantics. The consumer owns the state. Not for transient success feedback or for mutually exclusive `<ButtonGroup>` choices. Defaults to `undefined` (not selected). |
54
+ | `color` | `PaletteColor` | no | Paint the button with a palette color's soft pair (`--color-palette-<color>-bg` fill, `-fg` text) — the same pair a palette-colored `<PillMenu>` or `<Badge color>` uses, in both themes. For a quick action that moves a record to a status and must look like that status's pill (amber "No show" beside an amber status PillMenu). Not a decorative stand-in for `danger`/`success`: palette colors carry no meaning. When set it wins over `variant` and `selected` (like `<Badge color>` over `tone`). Hover/pressed darken via `filter: brightness()`. Defaults to `undefined` (use `variant`). |
55
+ | `as` | `ElementType` | no | Render a different element — the case that matters is `as="a"` with `href`, for a link that must LOOK like a button (an external console, a download, an IdP hand-off). The element named here is what actually renders, and its own attributes are typed: `href` is REQUIRED when `as="a"` (an anchor without one is neither focusable nor a link) and rejected otherwise; `target`/`rel`/`download` come through. Never navigate from `onClick`. Reach for `<Link>` first. `<Link>` is link-SHAPED navigation — inline text in a sentence, a table cell, a breadcrumb. `<Button as="a">` is for a destination that sits in a row of buttons and must carry their weight. Either way the element is a real anchor, so assistive tech announces a link and the browser gives middle-click, "open in new tab", and the status bar preview — none of which a `<button onClick={() => navigate()}>` has. `type="button"` is emitted only for a real `<button>`; an anchor never gets it. Everything else — variant, size, `iconOnly`, `selected`, the focus ring — is unchanged. Default: `'button'`. |
56
+ | …native | | | plus native attributes of the `as` element (default `<button>`) |
57
+
58
+ <!-- props:end -->
59
+
60
+ - Always renders `<button type="button">` unless you pass `type="submit"` — or unless you pass `as`. It won't submit ancestor forms by default.
61
+ - `aria-disabled="true"` keeps an unavailable action focusable (so keyboard users can discover it and its explanation) with the unavailable visual treatment, but does not set native `disabled` or prevent events: the consumer's handler must suppress activation while it is unavailable.
62
+ - `variant="success"` is a **transient confirmation state**, not an action intent. Flip to it for ~1.5s after the action resolves, then flip back to `primary`. The timer is the consumer's responsibility — Button stays stateless. Never render a button as `success` on initial mount. Track the timer in a `useRef` and clear on unmount + on rapid re-clicks so the flash doesn't outlive the component or get cut short.
63
+
64
+ ```tsx
65
+ const [saved, setSaved] = useState(false);
66
+ const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
67
+ useEffect(
68
+ () => () => {
69
+ if (timerRef.current) clearTimeout(timerRef.current);
70
+ },
71
+ [],
72
+ );
73
+ const handleSave = async () => {
74
+ await save();
75
+ if (timerRef.current) clearTimeout(timerRef.current);
76
+ setSaved(true);
77
+ timerRef.current = setTimeout(() => setSaved(false), 1500);
78
+ };
79
+ <Button variant={saved ? 'success' : 'primary'} onClick={handleSave}>
80
+ {saved ? 'Saved!' : 'Save'}
81
+ </Button>;
82
+ ```
83
+
84
+ #### When NOT to use
85
+
86
+ - ❌ Navigation in running text, a table cell, or a breadcrumb → `<Link>`.
87
+ - ❌ Toggle state (on/off) → `Switch` or `Checkbox`, not a Button with internal state.
88
+ - ❌ Mutually exclusive choices → `<ButtonGroup>`, which supplies the group-level selection semantics.
89
+ - ❌ A clickable table row → make the row itself the interactive surface; don't nest a button.
90
+ - ❌ Decorative color for an ordinary action → `variant`. `color` is only for an action that must match a palette-colored `<PillMenu>` / `<Badge color>` (a status or category it sets); resolve it from the same source as that pill so a recolored status carries its button along.
91
+ - On touch-first surfaces prefer `size="sm"` or larger: `xs` (20px×~28px, or 20×20 with `iconOnly`) is below WCAG 2.5.5 Level AAA touch-target guidance (24×24); acceptable here because the CRM is desktop-first.
92
+
93
+ #### Anti-patterns
94
+
95
+ - ❌ Two `variant="primary"` Buttons in the same section. Pick one; others are `secondary`.
96
+ - ❌ `<Button style={{ marginLeft: 'auto' }}>` — wrap in `<Cluster justify="end">` (or `justify="between"` with a sibling) instead.
97
+ - ❌ Overriding padding/height via `className`. A different visual size is a missing variant: request it.
98
+ - ❌ `variant="ghost"` for the page's primary action. Users won't discover it.
99
+ - ❌ `<Button variant="success">Save</Button>` on initial mount. Start as `primary` and flip to `success` after the action resolves.
100
+ - ❌ `<Button color="red">Delete</Button>` or `color="green"` for a confirm. Palette colors carry no meaning; destructive is `variant="danger"`, post-action feedback is `variant="success"`.
101
+ - ❌ `<Button color="amber" variant="secondary">`. `color` wins over `variant` (and `selected`), so the `variant` is dead code — pass one or the other.
102
+ - ❌ `size="xs"` for the primary or most prominent action. `xs` is for inline density, not emphasis; reach for `md` or `lg`.
103
+ - ❌ `<Button iconOnly><X /></Button>` without `aria-label`: screen readers announce nothing.
104
+ - ❌ Assuming `selected` adds toggle semantics. It is paint only; pass `aria-pressed` explicitly when activating the Button toggles that state, and not on menu or disclosure triggers.
105
+ - ❌ Assuming `aria-disabled="true"` blocks activation. It preserves native focusability and pointer events; guard your handler.
106
+ - ❌ `<Button onClick={() => (window.location.href = url)}>` for navigation: it announces as a button, with no middle-click, no open-in-new-tab and no status-bar preview. Use `<Button as="a" href={url}>`.
107
+ - ❌ `<Button as="a">` with no `href`, for a click handler you wanted to look like a link. An anchor without one is neither focusable nor activatable; the type requires `href` whenever `as="a"`, so this does not compile.
@@ -0,0 +1,78 @@
1
+ # `<ButtonGroup>` — joined Buttons + segmented control
2
+
3
+ ```tsx
4
+ // Visual mode — joined Buttons, no shared state.
5
+ <ButtonGroup aria-label="Edit actions">
6
+ <Button>Cut</Button>
7
+ <Button>Copy</Button>
8
+ <Button>Paste</Button>
9
+ </ButtonGroup>
10
+
11
+ // Segmented mode — single-select toggle group.
12
+ <ButtonGroup value={view} onValueChange={setView} aria-label="View mode">
13
+ <ButtonGroup.Item value="grid">Grid</ButtonGroup.Item>
14
+ <ButtonGroup.Item value="list">List</ButtonGroup.Item>
15
+ <ButtonGroup.Item value="calendar">Calendar</ButtonGroup.Item>
16
+ </ButtonGroup>
17
+
18
+ // Size propagation: group-level size flows to children, per-child override wins
19
+ <ButtonGroup size="sm">
20
+ <Button>Cut</Button>
21
+ <Button>Copy</Button>
22
+ <Button size="md">Paste</Button>
23
+ </ButtonGroup>
24
+ ```
25
+
26
+ <!-- props:start -->
27
+
28
+ ## Props
29
+
30
+ ### `ButtonGroupProps`
31
+
32
+ <!-- prettier-ignore -->
33
+ | Prop | Type | Required | Description |
34
+ |---|---|---|---|
35
+ | `size` | `'xs' \| 'sm' \| 'md' \| 'lg'` | no | Size propagated to children. Per-child `size` (Button or Item) wins when explicitly set. In visual mode this happens via cloneElement on Button children. In segmented mode, `<ButtonGroup.Item>` reads from context. |
36
+ | `disabled` | `boolean` | no | Disabled state for the whole group. In segmented mode this is authoritative (all items become aria-disabled, clicks no-op). In visual mode this is a no-op — pass `disabled` per `<Button>` instead. |
37
+ | `invalid` | `boolean` | no | Segmented mode: `aria-invalid` on the radiogroup. Visual mode: consumed and ignored. Field / SettingRow inject it — it used to leak onto the group div as a stray attribute. Default: `false`. |
38
+ | `required` | `boolean` | no | Segmented mode: `aria-required` on the radiogroup. Visual mode: consumed and ignored. Field / SettingRow inject it. Default: `false`. |
39
+ | `className` | `string` | no | |
40
+ | `style` | `CSSProperties` | no | |
41
+ | `value` | `string` | no | Visual mode marker. Never set; absence flips to visual. |
42
+ | `onValueChange` | `(next: string) => void` | no | Fired when a different Item is selected. Consumers wanting literal-union narrowing can cast the setter: `onValueChange={(v) => setView(v as 'grid' \| 'list')}`. |
43
+ | `aria-label` | `string` | no | Accessible name for the group landmark. Optional but recommended. |
44
+ | …native | | | plus native HTML attributes |
45
+
46
+ ### `ButtonGroupItemProps`
47
+
48
+ <!-- prettier-ignore -->
49
+ | Prop | Type | Required | Description |
50
+ |---|---|---|---|
51
+ | `value` | `string` | yes | Value emitted to `onValueChange` when this item is selected. |
52
+ | `disabled` | `boolean` | no | Per-item disabled. Group-level disabled is OR-merged. |
53
+ | `className` | `string` | no | className merges onto the rendered <button>. |
54
+ | `aria-label` | `string` | no | Accessible name for the radio, when the visible text is an abbreviation (`S` / `M` / `L` → "Small tiles"). Start it with the visible text where you can ("S, small tiles") so voice-control users can say what they see (WCAG 2.5.3). Omit it when `children` already reads as a full name. |
55
+ | `aria-describedby` | `string` | no | id(s) of element(s) describing the option — forwarded to the radio. |
56
+ | `children` | `ReactNode` | yes | |
57
+
58
+ <!-- props:end -->
59
+
60
+ - **Mode detection** is by props: with `value` + `onValueChange` you get segmented; without, you get visual joining. Visual mode joins `<Button>` children with shared borders and outer-only rounded corners (toolbar action groups); segmented mode is a single-select radiogroup (view-mode toggles, timeframe filters). A discriminated union enforces "`value` AND `onValueChange` together OR neither".
61
+ - **`<ButtonGroup.Item>`** (segmented only) renders `<button role="radio">` with roving tabindex and `aria-checked` driven by the parent's `value`. Using it in visual mode (no `value` on the parent) throws at render time: it has no group to belong to, by design.
62
+ - **Abbreviated options** (`S` / `M` / `L`) take `aria-label` on the Item, forwarded to the radio: `<ButtonGroup.Item value="s" aria-label="S, small tiles">S</ButtonGroup.Item>`. Start the name with the visible text (WCAG 2.5.3); don't hide the letter and add visually-hidden text instead. `aria-describedby` is forwarded too.
63
+ - **Children differ by mode.** Visual: `<Button>` children. Segmented: `<ButtonGroup.Item>` children. Mixing the two is undefined behavior.
64
+ - **Size propagation** — `size` on the group propagates to children. Per-child override wins.
65
+ - **Segmented height = Button height** — the segmented TRACK (not each item) is the `--size-*` height, so a `size="md"` segmented control lines up with a `size="md"` Button. Items render at that height minus the track padding on both sides.
66
+ - **Keyboard nav (segmented only)** — Arrow keys move selection + focus; Home / End jump to ends; Tab moves IN/OUT of the group on the currently-selected item. Disabled items are skipped.
67
+ - **ARIA** — visual mode is `role="group"`; segmented mode is `role="radiogroup"` (requires `aria-label`).
68
+
69
+ **Anti-patterns:**
70
+
71
+ - ❌ Mixing visual `<Button>` children with `<ButtonGroup.Item>` in the same ButtonGroup — undefined behavior.
72
+ - ❌ Using ButtonGroup as a routing tab strip. That's what `<Tabs>` is for.
73
+ - ❌ Passing only `value` (no `onValueChange`) or only `onValueChange` (no `value`) — a type error, and broken at runtime too.
74
+ - ❌ Wrapping a `<ButtonGroup.Item>` in a user component. The parent focuses items on Arrow nav, which depends on them being direct children.
75
+ - ❌ Using it for non-button content groupings. Use `<Cluster>` or `<Stack>`.
76
+ - ❌ Multi-select via clever workarounds. Compose Checkboxes for that.
77
+
78
+ **See also:** `<Tabs>` for routing-style content switching, `<Radio>` for vertical radio lists.