@borisj74/bv-ds 0.1.0

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 (310) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +94 -0
  3. package/dist/index.cjs +33885 -0
  4. package/dist/index.d.cts +2715 -0
  5. package/dist/index.d.ts +2715 -0
  6. package/dist/index.js +33717 -0
  7. package/package.json +67 -0
  8. package/src/components/ActivityFeed/ActivityFeed.tsx +48 -0
  9. package/src/components/ActivityFeed/index.ts +2 -0
  10. package/src/components/ActivityGauge/ActivityGauge.tsx +155 -0
  11. package/src/components/ActivityGauge/index.ts +7 -0
  12. package/src/components/AdvancedFilterBar/AdvancedFilterBar.tsx +80 -0
  13. package/src/components/AdvancedFilterBar/index.ts +2 -0
  14. package/src/components/Alert/Alert.tsx +210 -0
  15. package/src/components/Alert/index.ts +2 -0
  16. package/src/components/Avatar/Avatar.tsx +111 -0
  17. package/src/components/Avatar/index.ts +2 -0
  18. package/src/components/AvatarAddButton/AvatarAddButton.tsx +65 -0
  19. package/src/components/AvatarAddButton/index.ts +5 -0
  20. package/src/components/AvatarGroup/AvatarGroup.tsx +79 -0
  21. package/src/components/AvatarGroup/index.ts +6 -0
  22. package/src/components/AvatarLabelGroup/AvatarLabelGroup.tsx +62 -0
  23. package/src/components/AvatarLabelGroup/index.ts +5 -0
  24. package/src/components/AvatarProfilePhoto/AvatarProfilePhoto.tsx +117 -0
  25. package/src/components/AvatarProfilePhoto/index.ts +5 -0
  26. package/src/components/Badge/ColorBadge.tsx +36 -0
  27. package/src/components/Badge/ModernBadge.tsx +38 -0
  28. package/src/components/Badge/PillBadge.tsx +36 -0
  29. package/src/components/Badge/badgeShared.tsx +139 -0
  30. package/src/components/Badge/index.ts +7 -0
  31. package/src/components/BadgeCloseX/BadgeCloseX.tsx +64 -0
  32. package/src/components/BadgeCloseX/index.ts +2 -0
  33. package/src/components/BadgeGroup/BadgeGroup.tsx +61 -0
  34. package/src/components/BadgeGroup/index.ts +7 -0
  35. package/src/components/BreadcrumbButtonBase/BreadcrumbButtonBase.tsx +75 -0
  36. package/src/components/BreadcrumbButtonBase/index.ts +5 -0
  37. package/src/components/Breadcrumbs/Breadcrumbs.tsx +62 -0
  38. package/src/components/Breadcrumbs/index.ts +2 -0
  39. package/src/components/Button/Button.tsx +71 -0
  40. package/src/components/Button/index.ts +2 -0
  41. package/src/components/ButtonCloseX/ButtonCloseX.tsx +54 -0
  42. package/src/components/ButtonCloseX/index.ts +2 -0
  43. package/src/components/ButtonDestructive/ButtonDestructive.tsx +67 -0
  44. package/src/components/ButtonDestructive/index.ts +6 -0
  45. package/src/components/ButtonGroup/ButtonGroup.tsx +28 -0
  46. package/src/components/ButtonGroup/index.ts +2 -0
  47. package/src/components/ButtonGroupSegment/ButtonGroupSegment.tsx +54 -0
  48. package/src/components/ButtonGroupSegment/index.ts +5 -0
  49. package/src/components/ButtonUtility/ButtonUtility.tsx +67 -0
  50. package/src/components/ButtonUtility/index.ts +6 -0
  51. package/src/components/CalendarCell/CalendarCell.tsx +82 -0
  52. package/src/components/CalendarCell/index.ts +2 -0
  53. package/src/components/CalendarCellDayWeekView/CalendarCellDayWeekView.tsx +56 -0
  54. package/src/components/CalendarCellDayWeekView/index.ts +2 -0
  55. package/src/components/CalendarColumnHeader/CalendarColumnHeader.tsx +45 -0
  56. package/src/components/CalendarColumnHeader/index.ts +5 -0
  57. package/src/components/CalendarDateIcon/CalendarDateIcon.tsx +25 -0
  58. package/src/components/CalendarDateIcon/index.ts +2 -0
  59. package/src/components/CalendarEvent/CalendarEvent.tsx +76 -0
  60. package/src/components/CalendarEvent/index.ts +2 -0
  61. package/src/components/CalendarEventDayWeekView/CalendarEventDayWeekView.tsx +76 -0
  62. package/src/components/CalendarEventDayWeekView/index.ts +2 -0
  63. package/src/components/CalendarHeader/CalendarHeader.tsx +47 -0
  64. package/src/components/CalendarHeader/index.ts +2 -0
  65. package/src/components/CalendarRowLabel/CalendarRowLabel.tsx +21 -0
  66. package/src/components/CalendarRowLabel/index.ts +2 -0
  67. package/src/components/CalendarTimemarker/CalendarTimemarker.tsx +46 -0
  68. package/src/components/CalendarTimemarker/index.ts +5 -0
  69. package/src/components/CalendarViewDropdown/CalendarViewDropdown.tsx +101 -0
  70. package/src/components/CalendarViewDropdown/index.ts +6 -0
  71. package/src/components/CardHeader/CardHeader.tsx +57 -0
  72. package/src/components/CardHeader/index.ts +2 -0
  73. package/src/components/CarouselArrow/CarouselArrow.tsx +47 -0
  74. package/src/components/CarouselArrow/index.ts +6 -0
  75. package/src/components/CarouselImage/CarouselImage.tsx +60 -0
  76. package/src/components/CarouselImage/index.ts +2 -0
  77. package/src/components/Change/Change.tsx +73 -0
  78. package/src/components/Change/index.ts +2 -0
  79. package/src/components/ChartLegend/ChartLegend.tsx +38 -0
  80. package/src/components/ChartLegend/index.ts +2 -0
  81. package/src/components/ChartMarker/ChartMarker.tsx +54 -0
  82. package/src/components/ChartMarker/index.ts +2 -0
  83. package/src/components/ChartMini/ChartMini.tsx +86 -0
  84. package/src/components/ChartMini/index.ts +2 -0
  85. package/src/components/ChartTooltip/ChartTooltip.tsx +44 -0
  86. package/src/components/ChartTooltip/index.ts +2 -0
  87. package/src/components/Checkbox/Checkbox.tsx +65 -0
  88. package/src/components/Checkbox/checkboxBase.tsx +81 -0
  89. package/src/components/Checkbox/index.ts +3 -0
  90. package/src/components/CodeSnippet/CodeSnippet.tsx +94 -0
  91. package/src/components/CodeSnippet/index.ts +2 -0
  92. package/src/components/CodeSnippetTabs/CodeSnippetTabs.tsx +44 -0
  93. package/src/components/CodeSnippetTabs/index.ts +2 -0
  94. package/src/components/CommandBar/CommandBar.tsx +80 -0
  95. package/src/components/CommandBar/index.ts +2 -0
  96. package/src/components/CommandBarFooter/CommandBarFooter.tsx +125 -0
  97. package/src/components/CommandBarFooter/index.ts +5 -0
  98. package/src/components/CommandBarMenuSection/CommandBarMenuSection.tsx +28 -0
  99. package/src/components/CommandBarMenuSection/index.ts +2 -0
  100. package/src/components/CommandBarNavigationIcon/CommandBarNavigationIcon.tsx +47 -0
  101. package/src/components/CommandBarNavigationIcon/index.ts +2 -0
  102. package/src/components/CommandDropdownMenuItem/CommandDropdownMenuItem.tsx +51 -0
  103. package/src/components/CommandDropdownMenuItem/index.ts +2 -0
  104. package/src/components/CommandInput/CommandInput.tsx +74 -0
  105. package/src/components/CommandInput/index.ts +2 -0
  106. package/src/components/CommandShortcut/CommandShortcut.tsx +26 -0
  107. package/src/components/CommandShortcut/index.ts +2 -0
  108. package/src/components/ContentDivider/ContentDivider.tsx +80 -0
  109. package/src/components/ContentDivider/index.ts +6 -0
  110. package/src/components/ContentFeatureText/ContentFeatureText.tsx +60 -0
  111. package/src/components/ContentFeatureText/index.ts +5 -0
  112. package/src/components/ContentHeading/ContentHeading.tsx +43 -0
  113. package/src/components/ContentHeading/index.ts +5 -0
  114. package/src/components/ContentParagraph/ContentParagraph.tsx +39 -0
  115. package/src/components/ContentParagraph/index.ts +5 -0
  116. package/src/components/ContentQuote/ContentQuote.tsx +114 -0
  117. package/src/components/ContentQuote/index.ts +6 -0
  118. package/src/components/ContentRule/ContentRule.tsx +31 -0
  119. package/src/components/ContentRule/index.ts +2 -0
  120. package/src/components/ContextMenu/ContextMenu.tsx +67 -0
  121. package/src/components/ContextMenu/index.ts +7 -0
  122. package/src/components/ContextMenu/useContextMenu.ts +41 -0
  123. package/src/components/DatePickerCell/DatePickerCell.tsx +77 -0
  124. package/src/components/DatePickerCell/index.ts +2 -0
  125. package/src/components/DatePickerListItem/DatePickerListItem.tsx +39 -0
  126. package/src/components/DatePickerListItem/index.ts +2 -0
  127. package/src/components/DatePickerMenu/DatePickerMenu.tsx +131 -0
  128. package/src/components/DatePickerMenu/index.ts +2 -0
  129. package/src/components/DropdownAccountListItem/DropdownAccountListItem.tsx +69 -0
  130. package/src/components/DropdownAccountListItem/index.ts +2 -0
  131. package/src/components/DropdownMenuFooter/DropdownMenuFooter.tsx +50 -0
  132. package/src/components/DropdownMenuFooter/index.ts +5 -0
  133. package/src/components/DropdownMenuHeader/DropdownMenuHeader.tsx +93 -0
  134. package/src/components/DropdownMenuHeader/index.ts +5 -0
  135. package/src/components/DropdownMenuItemInsetIcon/DropdownMenuItemInsetIcon.tsx +89 -0
  136. package/src/components/DropdownMenuItemInsetIcon/index.ts +5 -0
  137. package/src/components/DropdownMenuListItem/DropdownMenuListItem.tsx +84 -0
  138. package/src/components/DropdownMenuListItem/index.ts +2 -0
  139. package/src/components/EmptyState/EmptyState.tsx +65 -0
  140. package/src/components/EmptyState/index.ts +2 -0
  141. package/src/components/FeedItemBase/FeedItemBase.tsx +135 -0
  142. package/src/components/FeedItemBase/index.ts +2 -0
  143. package/src/components/FileUpload/FileUpload.tsx +112 -0
  144. package/src/components/FileUpload/index.ts +2 -0
  145. package/src/components/FileUploadBase/FileUploadBase.tsx +69 -0
  146. package/src/components/FileUploadBase/index.ts +2 -0
  147. package/src/components/FileUploadItemBase/FileUploadItemBase.tsx +190 -0
  148. package/src/components/FileUploadItemBase/index.ts +7 -0
  149. package/src/components/FilterBar/FilterBar.tsx +62 -0
  150. package/src/components/FilterBar/index.ts +2 -0
  151. package/src/components/FilterTabs/FilterTabs.tsx +41 -0
  152. package/src/components/FilterTabs/index.ts +2 -0
  153. package/src/components/FiltersDropdownMenu/FiltersDropdownMenu.tsx +104 -0
  154. package/src/components/FiltersDropdownMenu/index.ts +2 -0
  155. package/src/components/FiltersSlideoutMenu/FiltersSlideoutMenu.tsx +71 -0
  156. package/src/components/FiltersSlideoutMenu/index.ts +2 -0
  157. package/src/components/HeaderNavigation/HeaderNavigation.tsx +178 -0
  158. package/src/components/HeaderNavigation/index.ts +6 -0
  159. package/src/components/HelpIcon/HelpIcon.tsx +49 -0
  160. package/src/components/HelpIcon/index.ts +2 -0
  161. package/src/components/InputField/InputField.tsx +108 -0
  162. package/src/components/InputField/index.ts +3 -0
  163. package/src/components/InputField/inputFieldShared.tsx +68 -0
  164. package/src/components/LeadingInputField/LeadingInputField.tsx +60 -0
  165. package/src/components/LeadingInputField/index.ts +2 -0
  166. package/src/components/LineAndBarChart/LineAndBarChart.tsx +96 -0
  167. package/src/components/LineAndBarChart/index.ts +2 -0
  168. package/src/components/LinkMessage/LinkMessage.tsx +52 -0
  169. package/src/components/LinkMessage/index.ts +2 -0
  170. package/src/components/LoadingIndicator/LoadingIndicator.tsx +108 -0
  171. package/src/components/LoadingIndicator/index.ts +6 -0
  172. package/src/components/MediaMessage/MediaMessage.tsx +109 -0
  173. package/src/components/MediaMessage/index.ts +2 -0
  174. package/src/components/MegaInputFieldBase/MegaInputFieldBase.tsx +49 -0
  175. package/src/components/MegaInputFieldBase/index.ts +5 -0
  176. package/src/components/Message/Message.tsx +85 -0
  177. package/src/components/Message/index.ts +3 -0
  178. package/src/components/Message/messageShared.tsx +73 -0
  179. package/src/components/MessageAction/MessageAction.tsx +221 -0
  180. package/src/components/MessageAction/index.ts +2 -0
  181. package/src/components/MessageActionButton/MessageActionButton.tsx +36 -0
  182. package/src/components/MessageActionButton/index.ts +2 -0
  183. package/src/components/MessageActionPanel/MessageActionPanel.tsx +36 -0
  184. package/src/components/MessageActionPanel/index.ts +2 -0
  185. package/src/components/MessageReaction/MessageReaction.tsx +37 -0
  186. package/src/components/MessageReaction/index.ts +2 -0
  187. package/src/components/MessageStatusIcon/MessageStatusIcon.tsx +54 -0
  188. package/src/components/MessageStatusIcon/index.ts +2 -0
  189. package/src/components/MetricItem/MetricItem.tsx +147 -0
  190. package/src/components/MetricItem/index.ts +2 -0
  191. package/src/components/ModalActions/ModalActions.tsx +57 -0
  192. package/src/components/ModalActions/index.ts +2 -0
  193. package/src/components/ModalHeader/ModalHeader.tsx +99 -0
  194. package/src/components/ModalHeader/index.ts +2 -0
  195. package/src/components/MultiSelect/MultiSelect.tsx +118 -0
  196. package/src/components/MultiSelect/index.ts +2 -0
  197. package/src/components/NavAccountCard/NavAccountCard.tsx +124 -0
  198. package/src/components/NavAccountCard/index.ts +2 -0
  199. package/src/components/NavAccountCardMenuItem/NavAccountCardMenuItem.tsx +101 -0
  200. package/src/components/NavAccountCardMenuItem/index.ts +5 -0
  201. package/src/components/NavButton/NavButton.tsx +50 -0
  202. package/src/components/NavButton/index.ts +2 -0
  203. package/src/components/NavFeaturedCard/NavFeaturedCard.tsx +82 -0
  204. package/src/components/NavFeaturedCard/index.ts +2 -0
  205. package/src/components/NavItemBase/NavItemBase.tsx +79 -0
  206. package/src/components/NavItemBase/index.ts +2 -0
  207. package/src/components/NavItemDropdownBase/NavItemDropdownBase.tsx +74 -0
  208. package/src/components/NavItemDropdownBase/index.ts +2 -0
  209. package/src/components/NavMenuButton/NavMenuButton.tsx +47 -0
  210. package/src/components/NavMenuButton/index.ts +2 -0
  211. package/src/components/Notification/Notification.tsx +102 -0
  212. package/src/components/Notification/index.ts +2 -0
  213. package/src/components/NumberInput/NumberInput.tsx +114 -0
  214. package/src/components/NumberInput/index.ts +2 -0
  215. package/src/components/PageHeader/PageHeader.tsx +88 -0
  216. package/src/components/PageHeader/index.ts +2 -0
  217. package/src/components/Pagination/Pagination.tsx +124 -0
  218. package/src/components/Pagination/index.ts +2 -0
  219. package/src/components/PaginationButtonGroupBase/PaginationButtonGroupBase.tsx +69 -0
  220. package/src/components/PaginationButtonGroupBase/index.ts +5 -0
  221. package/src/components/PaginationCards/PaginationCards.tsx +72 -0
  222. package/src/components/PaginationCards/index.ts +2 -0
  223. package/src/components/PaginationDotGroup/PaginationDotGroup.tsx +66 -0
  224. package/src/components/PaginationDotGroup/index.ts +2 -0
  225. package/src/components/PaginationDotIndicator/PaginationDotIndicator.tsx +39 -0
  226. package/src/components/PaginationDotIndicator/index.ts +6 -0
  227. package/src/components/PaginationNumberBase/PaginationNumberBase.tsx +42 -0
  228. package/src/components/PaginationNumberBase/index.ts +5 -0
  229. package/src/components/PieChart/PieChart.tsx +73 -0
  230. package/src/components/PieChart/index.ts +2 -0
  231. package/src/components/ProgressBar/ProgressBar.tsx +75 -0
  232. package/src/components/ProgressBar/index.ts +2 -0
  233. package/src/components/ProgressCircle/ProgressCircle.tsx +89 -0
  234. package/src/components/ProgressCircle/index.ts +6 -0
  235. package/src/components/RadarChart/RadarChart.tsx +62 -0
  236. package/src/components/RadarChart/index.ts +2 -0
  237. package/src/components/Radio/Radio.tsx +55 -0
  238. package/src/components/Radio/index.ts +2 -0
  239. package/src/components/RadioGroup/RadioGroup.tsx +54 -0
  240. package/src/components/RadioGroup/index.ts +2 -0
  241. package/src/components/RadioGroupItem/RadioGroupItem.tsx +118 -0
  242. package/src/components/RadioGroupItem/index.ts +6 -0
  243. package/src/components/SectionFooter/SectionFooter.tsx +40 -0
  244. package/src/components/SectionFooter/index.ts +2 -0
  245. package/src/components/SectionHeader/SectionHeader.tsx +44 -0
  246. package/src/components/SectionHeader/index.ts +2 -0
  247. package/src/components/SectionLabel/SectionLabel.tsx +51 -0
  248. package/src/components/SectionLabel/index.ts +2 -0
  249. package/src/components/Select/Select.tsx +121 -0
  250. package/src/components/Select/index.ts +2 -0
  251. package/src/components/SelectMenuItem/SelectMenuItem.tsx +85 -0
  252. package/src/components/SelectMenuItem/index.ts +2 -0
  253. package/src/components/SidebarNavigation/SidebarNavigation.tsx +100 -0
  254. package/src/components/SidebarNavigation/index.ts +2 -0
  255. package/src/components/SlideOutMenuHeader/SlideOutMenuHeader.tsx +56 -0
  256. package/src/components/SlideOutMenuHeader/index.ts +2 -0
  257. package/src/components/Slider/Slider.tsx +125 -0
  258. package/src/components/Slider/index.ts +2 -0
  259. package/src/components/SocialButton/SocialButton.tsx +88 -0
  260. package/src/components/SocialButton/index.ts +2 -0
  261. package/src/components/StatusIcon/StatusIcon.tsx +75 -0
  262. package/src/components/StatusIcon/index.ts +2 -0
  263. package/src/components/StepBase/StepBase.tsx +90 -0
  264. package/src/components/StepBase/index.ts +2 -0
  265. package/src/components/StepIconBase/StepIconBase.tsx +65 -0
  266. package/src/components/StepIconBase/index.ts +7 -0
  267. package/src/components/TabButtonBase/TabButtonBase.tsx +88 -0
  268. package/src/components/TabButtonBase/index.ts +2 -0
  269. package/src/components/TableCell/TableCell.tsx +44 -0
  270. package/src/components/TableCell/index.ts +2 -0
  271. package/src/components/TableHeaderCell/TableHeaderCell.tsx +34 -0
  272. package/src/components/TableHeaderCell/index.ts +2 -0
  273. package/src/components/TableHeaderLabel/TableHeaderLabel.tsx +37 -0
  274. package/src/components/TableHeaderLabel/index.ts +2 -0
  275. package/src/components/Tabs/Tabs.tsx +80 -0
  276. package/src/components/Tabs/index.ts +2 -0
  277. package/src/components/Tag/Tag.tsx +91 -0
  278. package/src/components/Tag/index.ts +2 -0
  279. package/src/components/TagsInputField/TagsInputField.tsx +90 -0
  280. package/src/components/TagsInputField/index.ts +2 -0
  281. package/src/components/TextEditorToolbar/TextEditorToolbar.tsx +33 -0
  282. package/src/components/TextEditorToolbar/index.ts +2 -0
  283. package/src/components/TextEditorTooltip/TextEditorTooltip.tsx +28 -0
  284. package/src/components/TextEditorTooltip/index.ts +2 -0
  285. package/src/components/TextareaInputField/TextareaInputField.tsx +45 -0
  286. package/src/components/TextareaInputField/index.ts +2 -0
  287. package/src/components/Toggle/Toggle.tsx +87 -0
  288. package/src/components/Toggle/index.ts +2 -0
  289. package/src/components/Tooltip/Tooltip.tsx +59 -0
  290. package/src/components/Tooltip/index.ts +2 -0
  291. package/src/components/TrailingInputField/TrailingInputField.tsx +62 -0
  292. package/src/components/TrailingInputField/index.ts +2 -0
  293. package/src/components/TreeView/TreeView.tsx +86 -0
  294. package/src/components/TreeView/index.ts +2 -0
  295. package/src/components/TreeViewConnector/TreeViewConnector.tsx +36 -0
  296. package/src/components/TreeViewConnector/index.ts +2 -0
  297. package/src/components/TreeViewItem/TreeViewItem.tsx +111 -0
  298. package/src/components/TreeViewItem/index.ts +2 -0
  299. package/src/components/VerificationCodeInput/VerificationCodeInput.tsx +114 -0
  300. package/src/components/VerificationCodeInput/index.ts +2 -0
  301. package/src/illustrations/BoxIllustration.tsx +13 -0
  302. package/src/illustrations/CloudIllustration.tsx +18 -0
  303. package/src/illustrations/CreditCardIllustration.tsx +13 -0
  304. package/src/illustrations/DocumentsIllustration.tsx +13 -0
  305. package/src/illustrations/index.ts +4 -0
  306. package/src/index.ts +147 -0
  307. package/src/internal/chartTheme.ts +30 -0
  308. package/src/internal/ringBase.tsx +82 -0
  309. package/src/styles.css +3 -0
  310. package/tailwind-preset.js +295 -0
@@ -0,0 +1,36 @@
1
+ import { type ButtonHTMLAttributes, type ReactNode } from "react";
2
+ import clsx from "clsx";
3
+
4
+ export interface MessageActionButtonProps
5
+ extends ButtonHTMLAttributes<HTMLButtonElement> {
6
+ /** Icon glyph (16px). Use `currentColor` so the button can tint it. */
7
+ icon: ReactNode;
8
+ }
9
+
10
+ /**
11
+ * Single icon button used inside `MessageActionPanel` (the hover toolbar over a
12
+ * message). Sits on the dark panel surface — icon is light, hover lifts it to
13
+ * full white with a translucent backdrop. `rounded-xs` / `p-xxs` per Figma.
14
+ */
15
+ export function MessageActionButton({
16
+ icon,
17
+ className,
18
+ type = "button",
19
+ ...rest
20
+ }: MessageActionButtonProps) {
21
+ return (
22
+ <button
23
+ type={type}
24
+ className={clsx(
25
+ "flex items-center rounded-xs p-xxs",
26
+ "text-text-white/70 transition-colors hover:bg-white/10 hover:text-text-white",
27
+ className,
28
+ )}
29
+ {...rest}
30
+ >
31
+ <span className="flex size-4 items-center justify-center [&>svg]:size-4">
32
+ {icon}
33
+ </span>
34
+ </button>
35
+ );
36
+ }
@@ -0,0 +1,2 @@
1
+ export { MessageActionButton } from "./MessageActionButton";
2
+ export type { MessageActionButtonProps } from "./MessageActionButton";
@@ -0,0 +1,36 @@
1
+ import { type HTMLAttributes, type ReactNode } from "react";
2
+ import clsx from "clsx";
3
+
4
+ export interface MessageActionPanelProps
5
+ extends HTMLAttributes<HTMLDivElement> {
6
+ /** Action buttons — compose `MessageActionButton` elements here. */
7
+ children: ReactNode;
8
+ }
9
+
10
+ /**
11
+ * Floating dark toolbar that appears over a message on hover. Holds a row of
12
+ * `MessageActionButton`s (react / reply / regenerate / copy …). Composition
13
+ * shell only — the buttons are supplied as children, not reimplemented here.
14
+ *
15
+ * Surface uses `bg-bg-primary-solid` (#0a0a0a) for the dark floating panel;
16
+ * Figma's `bg-primary_alt` dark value is #171717 (token gap — see figma-map
17
+ * Pending token verification). `shadow-xl` is the Tailwind-default approximation
18
+ * of Figma's 3-layer xl stack.
19
+ */
20
+ export function MessageActionPanel({
21
+ children,
22
+ className,
23
+ ...rest
24
+ }: MessageActionPanelProps) {
25
+ return (
26
+ <div
27
+ className={clsx(
28
+ "inline-flex items-start gap-sm rounded-md bg-bg-primary-solid px-md py-sm shadow-xl",
29
+ className,
30
+ )}
31
+ {...rest}
32
+ >
33
+ {children}
34
+ </div>
35
+ );
36
+ }
@@ -0,0 +1,2 @@
1
+ export { MessageActionPanel } from "./MessageActionPanel";
2
+ export type { MessageActionPanelProps } from "./MessageActionPanel";
@@ -0,0 +1,37 @@
1
+ import type { ButtonHTMLAttributes, ReactNode } from "react";
2
+ import clsx from "clsx";
3
+
4
+ export interface MessageReactionProps
5
+ extends ButtonHTMLAttributes<HTMLButtonElement> {
6
+ /** Emoji glyph (defaults to a heart). */
7
+ emoji?: ReactNode;
8
+ /** Reaction count — hidden when undefined. */
9
+ count?: number;
10
+ }
11
+
12
+ /** A pill reaction chip shown under a chat message. */
13
+ export function MessageReaction({
14
+ emoji = "❤️",
15
+ count,
16
+ className,
17
+ ...rest
18
+ }: MessageReactionProps) {
19
+ return (
20
+ <button
21
+ type="button"
22
+ className={clsx(
23
+ "flex h-6 items-center justify-center rounded-full border border-border-secondary bg-bg-secondary px-md py-xs font-body",
24
+ count != null ? "gap-xs" : "gap-0",
25
+ className,
26
+ )}
27
+ {...rest}
28
+ >
29
+ <span className="flex size-4 items-center justify-center text-[14px] leading-none">
30
+ {emoji}
31
+ </span>
32
+ {count != null ? (
33
+ <span className="text-sm font-medium text-text-secondary">{count}</span>
34
+ ) : null}
35
+ </button>
36
+ );
37
+ }
@@ -0,0 +1,2 @@
1
+ export { MessageReaction } from "./MessageReaction";
2
+ export type { MessageReactionProps } from "./MessageReaction";
@@ -0,0 +1,54 @@
1
+ import type { ReactNode } from "react";
2
+ import clsx from "clsx";
3
+
4
+ export type MessageStatus = "unread" | "read" | "failed";
5
+
6
+ export interface MessageStatusIconProps {
7
+ /** Delivery status. */
8
+ status?: MessageStatus;
9
+ /** Tooltip shown on hover (e.g. "Read 2:20 PM"). */
10
+ tooltip?: ReactNode;
11
+ className?: string;
12
+ }
13
+
14
+ /**
15
+ * Delivery status glyph for a sent message — single check (unread), double
16
+ * check (read, brand), or an error circle (failed). Optional hover tooltip.
17
+ */
18
+ export function MessageStatusIcon({
19
+ status = "unread",
20
+ tooltip,
21
+ className,
22
+ }: MessageStatusIconProps) {
23
+ let glyph: ReactNode;
24
+ if (status === "read") {
25
+ glyph = (
26
+ <svg viewBox="0 0 16 16" fill="none" className="size-4 text-fg-brand-primary" aria-hidden>
27
+ <path d="M1.5 8.5 4 11l5.5-6M7 11l.5.5 5.5-6" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
28
+ </svg>
29
+ );
30
+ } else if (status === "failed") {
31
+ glyph = (
32
+ <svg viewBox="0 0 16 16" fill="none" className="size-4 text-fg-error-primary" aria-hidden>
33
+ <path d="M8 5.333V8m0 2.667h.007M14.667 8A6.667 6.667 0 1 1 8 1.333 6.667 6.667 0 0 1 14.667 8Z" stroke="currentColor" strokeWidth="1.333" strokeLinecap="round" strokeLinejoin="round" />
34
+ </svg>
35
+ );
36
+ } else {
37
+ glyph = (
38
+ <svg viewBox="0 0 16 16" fill="none" className="size-4 text-fg-quaternary" aria-hidden>
39
+ <path d="m3 8.5 3 3 7-7" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
40
+ </svg>
41
+ );
42
+ }
43
+
44
+ return (
45
+ <span className={clsx("group relative inline-flex size-4 items-center justify-center font-body", className)}>
46
+ {glyph}
47
+ {tooltip ? (
48
+ <span className="pointer-events-none absolute bottom-full left-1/2 mb-1.5 hidden -translate-x-1/2 whitespace-nowrap rounded-md bg-bg-primary-solid px-md py-sm text-xs font-semibold text-text-white shadow-lg group-hover:block">
49
+ {tooltip}
50
+ </span>
51
+ ) : null}
52
+ </span>
53
+ );
54
+ }
@@ -0,0 +1,2 @@
1
+ export { MessageStatusIcon } from "./MessageStatusIcon";
2
+ export type { MessageStatusIconProps, MessageStatus } from "./MessageStatusIcon";
@@ -0,0 +1,147 @@
1
+ import { type HTMLAttributes, type ReactNode } from "react";
2
+ import clsx from "clsx";
3
+
4
+ export interface MetricItemProps extends HTMLAttributes<HTMLDivElement> {
5
+ /** Metric title, e.g. "Views 24 hours". */
6
+ label: ReactNode;
7
+ /** Big number, e.g. "2,000". Rendered in display-sm. */
8
+ value: ReactNode;
9
+ /** Trend chip — compose a `Change` element here. */
10
+ change?: ReactNode;
11
+ /** Caption beside the change, e.g. "vs last month" (chart layout only). */
12
+ changeText?: ReactNode;
13
+ /** Featured-icon slot, rendered top-left (consumer supplies the badge). */
14
+ icon?: ReactNode;
15
+ /** Sparkline slot, rendered right of the number (e.g. a Recharts chart). */
16
+ chart?: ReactNode;
17
+ /** Footer action, e.g. a "View report" button — renders a divided footer. */
18
+ action?: ReactNode;
19
+ /** Top-right options (dots) button — rendered only when handler is given. */
20
+ onMenuClick?: () => void;
21
+ }
22
+
23
+ const DotsVertical = ({ className }: { className?: string }) => (
24
+ <svg className={className} viewBox="0 0 20 20" fill="none" aria-hidden>
25
+ <path
26
+ d="M10 10.83a.83.83 0 1 0 0-1.66.83.83 0 0 0 0 1.66ZM10 5a.83.83 0 1 0 0-1.67A.83.83 0 0 0 10 5ZM10 16.67A.83.83 0 1 0 10 15a.83.83 0 0 0 0 1.67Z"
27
+ stroke="currentColor"
28
+ strokeWidth="1.67"
29
+ strokeLinecap="round"
30
+ strokeLinejoin="round"
31
+ />
32
+ </svg>
33
+ );
34
+
35
+ const Label = ({ children }: { children: ReactNode }) => (
36
+ <p className="w-full text-sm font-medium text-text-tertiary">{children}</p>
37
+ );
38
+
39
+ const Value = ({ children }: { children: ReactNode }) => (
40
+ <span className="flex-1 font-display text-display-sm font-semibold text-text-primary">
41
+ {children}
42
+ </span>
43
+ );
44
+
45
+ /**
46
+ * Metric / stat card. One component covering the Figma Simple / Icon / Chart
47
+ * types via optional slots:
48
+ * - bare → Simple (label + value + inline `change`).
49
+ * - `icon` → Icon (featured-icon badge on top).
50
+ * - `chart` → Chart (value + change/`changeText` left, sparkline right).
51
+ * - `action` → divided footer with the action node.
52
+ * - `onMenuClick` → dots-vertical button top-right.
53
+ *
54
+ * `icon` and `chart` are ReactNode slots, so the missing Figma "Featured icons"
55
+ * family and the deferred `_ChartMini` (Recharts) are non-blocking — consumers
56
+ * fill them. Note: Figma's Chart variant uses a text-md/semibold label; this
57
+ * component standardises on text-sm/medium for all types (see figma-map).
58
+ */
59
+ export function MetricItem({
60
+ label,
61
+ value,
62
+ change,
63
+ changeText,
64
+ icon,
65
+ chart,
66
+ action,
67
+ onMenuClick,
68
+ className,
69
+ ...rest
70
+ }: MetricItemProps) {
71
+ const hasChart = !!chart;
72
+ const hasIcon = !!icon;
73
+
74
+ return (
75
+ <div
76
+ className={clsx(
77
+ "relative flex w-full flex-col rounded-xl border border-border-secondary bg-bg-primary shadow-xs",
78
+ className,
79
+ )}
80
+ {...rest}
81
+ >
82
+ <div
83
+ className={clsx(
84
+ "flex w-full flex-col p-2xl",
85
+ hasIcon || hasChart ? "gap-2xl" : "gap-md",
86
+ )}
87
+ >
88
+ {hasIcon && <div className="shrink-0">{icon}</div>}
89
+
90
+ {hasChart ? (
91
+ <>
92
+ <Label>{label}</Label>
93
+ <div className="flex w-full items-end gap-xl">
94
+ <div className="flex min-w-0 flex-1 flex-col gap-lg">
95
+ <Value>{value}</Value>
96
+ {(change || changeText) && (
97
+ <div className="flex w-full items-center gap-md">
98
+ {change}
99
+ {changeText && (
100
+ <span className="min-w-0 flex-1 truncate text-sm font-medium text-text-tertiary">
101
+ {changeText}
102
+ </span>
103
+ )}
104
+ </div>
105
+ )}
106
+ </div>
107
+ <div className="shrink-0">{chart}</div>
108
+ </div>
109
+ </>
110
+ ) : hasIcon ? (
111
+ <div className="flex w-full flex-col gap-md">
112
+ <Label>{label}</Label>
113
+ <div className="flex w-full items-end gap-xl">
114
+ <Value>{value}</Value>
115
+ {change && <div className="shrink-0">{change}</div>}
116
+ </div>
117
+ </div>
118
+ ) : (
119
+ <>
120
+ <Label>{label}</Label>
121
+ <div className="flex w-full items-end gap-xl">
122
+ <Value>{value}</Value>
123
+ {change && <div className="shrink-0">{change}</div>}
124
+ </div>
125
+ </>
126
+ )}
127
+ </div>
128
+
129
+ {action && (
130
+ <div className="flex w-full items-center justify-end border-t border-border-secondary px-2xl py-xl">
131
+ {action}
132
+ </div>
133
+ )}
134
+
135
+ {onMenuClick && (
136
+ <button
137
+ type="button"
138
+ onClick={onMenuClick}
139
+ aria-label="Options"
140
+ className="absolute right-[19px] top-[19px] text-fg-quaternary transition-colors hover:text-fg-quaternary-hover"
141
+ >
142
+ <DotsVertical className="size-5" />
143
+ </button>
144
+ )}
145
+ </div>
146
+ );
147
+ }
@@ -0,0 +1,2 @@
1
+ export { MetricItem } from "./MetricItem";
2
+ export type { MetricItemProps } from "./MetricItem";
@@ -0,0 +1,57 @@
1
+ import { type HTMLAttributes, type ReactNode } from "react";
2
+ import clsx from "clsx";
3
+
4
+ export type ModalActionsType = "horizontal-fill" | "vertical-fill" | "right-aligned";
5
+
6
+ export interface ModalActionsProps extends HTMLAttributes<HTMLDivElement> {
7
+ /**
8
+ * - `horizontal-fill` — buttons share the row, each flex-1.
9
+ * - `vertical-fill` — buttons stacked full-width.
10
+ * - `right-aligned` — `leading` on the left, buttons pushed right.
11
+ */
12
+ type?: ModalActionsType;
13
+ /** Top divider separating actions from the modal body. */
14
+ divider?: boolean;
15
+ /** Left-side content for `right-aligned` (e.g. a checkbox / tertiary button). */
16
+ leading?: ReactNode;
17
+ /** The action buttons — compose `Button` / `ButtonDestructive` here. */
18
+ children: ReactNode;
19
+ }
20
+
21
+ /**
22
+ * Modal footer button row. Layout shell only — buttons are supplied as children
23
+ * (composed from the library's Button components), laid out per `type`. Fill
24
+ * variants stretch their children; `right-aligned` pairs a `leading` slot with
25
+ * the right-pushed actions.
26
+ */
27
+ export function ModalActions({
28
+ type = "horizontal-fill",
29
+ divider = true,
30
+ leading,
31
+ children,
32
+ className,
33
+ ...rest
34
+ }: ModalActionsProps) {
35
+ return (
36
+ <div className={clsx("flex w-full flex-col", className)} {...rest}>
37
+ {divider && <div className="mt-4xl border-t border-border-secondary" />}
38
+ <div
39
+ className={clsx(
40
+ "flex px-3xl pb-3xl pt-3xl",
41
+ type === "horizontal-fill" && "gap-lg [&>*]:flex-1",
42
+ type === "vertical-fill" && "flex-col gap-lg [&>*]:w-full",
43
+ type === "right-aligned" && "items-center gap-lg",
44
+ )}
45
+ >
46
+ {type === "right-aligned" ? (
47
+ <>
48
+ <div className="flex flex-1 items-center gap-lg">{leading}</div>
49
+ <div className="flex items-center gap-lg">{children}</div>
50
+ </>
51
+ ) : (
52
+ children
53
+ )}
54
+ </div>
55
+ </div>
56
+ );
57
+ }
@@ -0,0 +1,2 @@
1
+ export { ModalActions } from "./ModalActions";
2
+ export type { ModalActionsProps, ModalActionsType } from "./ModalActions";
@@ -0,0 +1,99 @@
1
+ import { type HTMLAttributes, type ReactNode } from "react";
2
+ import clsx from "clsx";
3
+
4
+ export type ModalHeaderType = "left" | "center" | "horizontal";
5
+
6
+ export interface ModalHeaderProps
7
+ extends Omit<HTMLAttributes<HTMLDivElement>, "title"> {
8
+ title: ReactNode;
9
+ description?: ReactNode;
10
+ /** Featured-icon glyph, rendered inside a 40px boxed badge. */
11
+ icon?: ReactNode;
12
+ /**
13
+ * - `left` — icon on top, text left-aligned.
14
+ * - `center` — icon on top, text centred.
15
+ * - `horizontal` — icon to the left of the text.
16
+ */
17
+ type?: ModalHeaderType;
18
+ /** Bottom divider separating the header from the modal body. */
19
+ divider?: boolean;
20
+ /** Renders an x-close button top-right when provided. */
21
+ onClose?: () => void;
22
+ }
23
+
24
+ const FeaturedIcon = ({ children }: { children: ReactNode }) => (
25
+ <div className="flex size-10 shrink-0 items-center justify-center rounded-md border border-border-primary text-fg-secondary shadow-xs">
26
+ {children}
27
+ </div>
28
+ );
29
+
30
+ const XClose = () => (
31
+ <svg viewBox="0 0 20 20" fill="none" className="size-5" aria-hidden>
32
+ <path d="M15 5 5 15M5 5l10 10" stroke="currentColor" strokeWidth="1.67" strokeLinecap="round" strokeLinejoin="round" />
33
+ </svg>
34
+ );
35
+
36
+ /**
37
+ * Modal header — featured-icon badge + title + supporting text, with an optional
38
+ * x-close button and bottom divider. `type` controls alignment (left / centred /
39
+ * icon-beside-text). The `icon` is a slot; consumer supplies the glyph.
40
+ */
41
+ export function ModalHeader({
42
+ title,
43
+ description,
44
+ icon,
45
+ type = "left",
46
+ divider = true,
47
+ onClose,
48
+ className,
49
+ ...rest
50
+ }: ModalHeaderProps) {
51
+ const isCenter = type === "center";
52
+ const isHorizontal = type === "horizontal";
53
+
54
+ return (
55
+ <div
56
+ className={clsx(
57
+ "relative flex w-full flex-col",
58
+ isHorizontal ? "items-start" : isCenter ? "items-center" : "items-start",
59
+ className,
60
+ )}
61
+ {...rest}
62
+ >
63
+ <div
64
+ className={clsx(
65
+ "flex w-full gap-xl px-3xl pt-3xl",
66
+ isHorizontal ? "items-start" : "flex-col",
67
+ isCenter && "items-center",
68
+ )}
69
+ >
70
+ {icon && <FeaturedIcon>{icon}</FeaturedIcon>}
71
+ <div
72
+ className={clsx(
73
+ "flex flex-col gap-xxs",
74
+ isHorizontal ? "flex-1" : "w-full",
75
+ isCenter && "items-center text-center",
76
+ )}
77
+ >
78
+ <p className="w-full text-md font-semibold text-text-primary">{title}</p>
79
+ {description && (
80
+ <p className="w-full text-sm text-text-tertiary">{description}</p>
81
+ )}
82
+ </div>
83
+ </div>
84
+
85
+ {onClose && (
86
+ <button
87
+ type="button"
88
+ onClick={onClose}
89
+ aria-label="Close"
90
+ className="absolute right-4 top-4 flex size-9 items-center justify-center rounded-md text-fg-quaternary transition-colors hover:text-fg-quaternary-hover"
91
+ >
92
+ <XClose />
93
+ </button>
94
+ )}
95
+
96
+ {divider && <div className="mt-2xl w-full border-t border-border-secondary" />}
97
+ </div>
98
+ );
99
+ }
@@ -0,0 +1,2 @@
1
+ export { ModalHeader } from "./ModalHeader";
2
+ export type { ModalHeaderProps, ModalHeaderType } from "./ModalHeader";
@@ -0,0 +1,118 @@
1
+ import { useState, type ReactNode } from "react";
2
+ import clsx from "clsx";
3
+ import { SelectMenuItem } from "../SelectMenuItem";
4
+ import { Tag } from "../Tag";
5
+
6
+ export interface MultiSelectOption {
7
+ value: string;
8
+ label: string;
9
+ supportingText?: ReactNode;
10
+ }
11
+
12
+ export interface MultiSelectProps {
13
+ options: MultiSelectOption[];
14
+ value?: string[];
15
+ onChange?: (value: string[]) => void;
16
+ open?: boolean;
17
+ onToggle?: () => void;
18
+ label?: ReactNode;
19
+ hint?: ReactNode;
20
+ placeholder?: string;
21
+ /** Show the in-trigger search input (default true). */
22
+ searchable?: boolean;
23
+ disabled?: boolean;
24
+ invalid?: boolean;
25
+ className?: string;
26
+ }
27
+
28
+ /**
29
+ * Multi-select — trigger with selected-item `Tag` chips + a search input, over a
30
+ * shared dropdown of `SelectMenuItem` (`multi`) options with a search empty
31
+ * state. Composes the Select-family primitives rather than reimplementing a
32
+ * dropdown. Controlled: `value`/`onChange` (selection) and `open`/`onToggle`.
33
+ */
34
+ export function MultiSelect({
35
+ options,
36
+ value = [],
37
+ onChange,
38
+ open = false,
39
+ onToggle,
40
+ label,
41
+ hint,
42
+ placeholder = "Select...",
43
+ searchable = true,
44
+ disabled = false,
45
+ invalid = false,
46
+ className,
47
+ }: MultiSelectProps) {
48
+ const [query, setQuery] = useState("");
49
+ const selected = options.filter((o) => value.includes(o.value));
50
+ const filtered = options.filter((o) => o.label.toLowerCase().includes(query.toLowerCase()));
51
+
52
+ const toggleValue = (v: string) =>
53
+ onChange?.(value.includes(v) ? value.filter((x) => x !== v) : [...value, v]);
54
+
55
+ return (
56
+ <div className={clsx("flex w-full flex-col gap-sm font-body", className)}>
57
+ {label && <span className="text-sm font-medium text-text-secondary">{label}</span>}
58
+
59
+ <div className="relative">
60
+ <div
61
+ className={clsx(
62
+ "flex min-h-[44px] w-full flex-wrap items-center gap-xs rounded-md border bg-bg-primary px-md py-1.5 shadow-xs",
63
+ invalid ? "border-border-error" : open ? "border-border-brand ring-2 ring-utility-brand-500/40" : "border-border-primary",
64
+ disabled && "cursor-not-allowed bg-bg-secondary opacity-60",
65
+ )}
66
+ onClick={() => !disabled && onToggle?.()}
67
+ >
68
+ {selected.map((o) => (
69
+ <Tag
70
+ key={o.value}
71
+ size="sm"
72
+ onClose={() => toggleValue(o.value)}
73
+ onClick={(e) => e.stopPropagation()}
74
+ >
75
+ {o.label}
76
+ </Tag>
77
+ ))}
78
+ {searchable ? (
79
+ <input
80
+ value={query}
81
+ disabled={disabled}
82
+ placeholder={selected.length ? "" : placeholder}
83
+ onChange={(e) => setQuery(e.target.value)}
84
+ onClick={(e) => e.stopPropagation()}
85
+ className="min-w-[80px] flex-1 bg-transparent py-xxs text-md text-text-primary outline-none placeholder:text-text-placeholder"
86
+ />
87
+ ) : (
88
+ !selected.length && <span className="flex-1 text-md text-text-placeholder">{placeholder}</span>
89
+ )}
90
+ <svg viewBox="0 0 16 16" fill="none" className={clsx("size-4 shrink-0 text-fg-quaternary transition-transform", open && "rotate-180")} aria-hidden>
91
+ <path d="M4 6l4 4 4-4" stroke="currentColor" strokeWidth="1.33" strokeLinecap="round" strokeLinejoin="round" />
92
+ </svg>
93
+ </div>
94
+
95
+ {open && (
96
+ <div className="absolute left-0 right-0 top-full z-50 mt-xs flex max-h-[320px] flex-col gap-px overflow-auto rounded-md border border-border-secondary-alt bg-bg-primary p-xs shadow-lg">
97
+ {filtered.length ? (
98
+ filtered.map((o) => (
99
+ <SelectMenuItem
100
+ key={o.value}
101
+ multi
102
+ label={o.label}
103
+ supportingText={o.supportingText}
104
+ selected={value.includes(o.value)}
105
+ onClick={() => toggleValue(o.value)}
106
+ />
107
+ ))
108
+ ) : (
109
+ <div className="px-md py-lg text-center text-sm text-text-tertiary">No results found</div>
110
+ )}
111
+ </div>
112
+ )}
113
+ </div>
114
+
115
+ {hint && <span className={clsx("text-sm", invalid ? "text-text-error-primary" : "text-text-tertiary")}>{hint}</span>}
116
+ </div>
117
+ );
118
+ }
@@ -0,0 +1,2 @@
1
+ export { MultiSelect } from "./MultiSelect";
2
+ export type { MultiSelectProps, MultiSelectOption } from "./MultiSelect";