@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,65 @@
1
+ import type { ButtonHTMLAttributes } from "react";
2
+ import clsx from "clsx";
3
+
4
+ export type AvatarAddButtonSize = "xs" | "sm" | "md";
5
+
6
+ export interface AvatarAddButtonProps
7
+ extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, "size"> {
8
+ size?: AvatarAddButtonSize;
9
+ /** Tooltip text + accessible label (Figma hover shows "Add user"). */
10
+ label?: string;
11
+ }
12
+
13
+ const sizeClass: Record<AvatarAddButtonSize, string> = {
14
+ xs: "size-6", // 24px
15
+ sm: "size-8", // 32px
16
+ md: "size-10", // 40px
17
+ };
18
+
19
+ function PlusIcon() {
20
+ return (
21
+ <svg viewBox="0 0 20 20" fill="none" className="h-1/2 w-1/2" aria-hidden>
22
+ <path
23
+ d="M10 4.167v11.666M4.167 10h11.666"
24
+ stroke="currentColor"
25
+ strokeWidth="1.667"
26
+ strokeLinecap="round"
27
+ strokeLinejoin="round"
28
+ />
29
+ </svg>
30
+ );
31
+ }
32
+
33
+ export function AvatarAddButton({
34
+ size = "md",
35
+ label,
36
+ className,
37
+ ...rest
38
+ }: AvatarAddButtonProps) {
39
+ return (
40
+ <span className="group relative inline-flex">
41
+ <button
42
+ type="button"
43
+ aria-label={label ?? "Add"}
44
+ className={clsx(
45
+ "flex items-center justify-center rounded-full border border-dashed border-border-primary text-fg-quaternary transition-colors",
46
+ "hover:border-border-brand hover:text-fg-quaternary-hover",
47
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-border-brand focus-visible:ring-offset-2 focus-visible:ring-offset-bg-primary",
48
+ sizeClass[size],
49
+ className,
50
+ )}
51
+ {...rest}
52
+ >
53
+ <PlusIcon />
54
+ </button>
55
+ {label ? (
56
+ <span
57
+ role="tooltip"
58
+ className="pointer-events-none absolute bottom-full left-1/2 mb-xs -translate-x-1/2 whitespace-nowrap rounded-md bg-bg-primary-solid px-md py-xs text-xs font-semibold text-text-white opacity-0 shadow-lg transition-opacity group-hover:opacity-100 group-focus-within:opacity-100"
59
+ >
60
+ {label}
61
+ </span>
62
+ ) : null}
63
+ </span>
64
+ );
65
+ }
@@ -0,0 +1,5 @@
1
+ export { AvatarAddButton } from "./AvatarAddButton";
2
+ export type {
3
+ AvatarAddButtonProps,
4
+ AvatarAddButtonSize,
5
+ } from "./AvatarAddButton";
@@ -0,0 +1,79 @@
1
+ import clsx from "clsx";
2
+ import { Avatar } from "../Avatar";
3
+ import { AvatarAddButton } from "../AvatarAddButton";
4
+
5
+ export type AvatarGroupSize = "xs" | "sm" | "md";
6
+
7
+ export interface AvatarGroupItem {
8
+ src?: string;
9
+ alt?: string;
10
+ initials?: string;
11
+ }
12
+
13
+ export interface AvatarGroupProps {
14
+ size?: AvatarGroupSize;
15
+ avatars: AvatarGroupItem[];
16
+ /** Max avatars shown before collapsing the rest into a "+N" chip. */
17
+ max?: number;
18
+ /** Renders a trailing dashed add button when provided. */
19
+ onAdd?: () => void;
20
+ /** Tooltip/label for the add button. */
21
+ addLabel?: string;
22
+ className?: string;
23
+ }
24
+
25
+ const chipSizeClass: Record<AvatarGroupSize, string> = {
26
+ xs: "size-6", // 24px
27
+ sm: "size-8", // 32px
28
+ md: "size-10", // 40px
29
+ };
30
+
31
+ const chipTextClass: Record<AvatarGroupSize, string> = {
32
+ xs: "text-xs",
33
+ sm: "text-xs",
34
+ md: "text-sm",
35
+ };
36
+
37
+ export function AvatarGroup({
38
+ size = "md",
39
+ avatars,
40
+ max,
41
+ onAdd,
42
+ addLabel,
43
+ className,
44
+ }: AvatarGroupProps) {
45
+ const shown = max ? avatars.slice(0, max) : avatars;
46
+ const surplus = avatars.length - shown.length;
47
+
48
+ return (
49
+ <div className={clsx("flex items-center", className)}>
50
+ {shown.map((a, i) => (
51
+ <span
52
+ key={i}
53
+ className={clsx(
54
+ "rounded-full ring-2 ring-bg-primary",
55
+ i > 0 && "-ml-md",
56
+ )}
57
+ >
58
+ <Avatar size={size} src={a.src} alt={a.alt} initials={a.initials} />
59
+ </span>
60
+ ))}
61
+ {surplus > 0 ? (
62
+ <span
63
+ className={clsx(
64
+ "-ml-md flex items-center justify-center rounded-full border border-border-secondary bg-bg-tertiary font-semibold text-text-quaternary ring-2 ring-bg-primary",
65
+ chipSizeClass[size],
66
+ chipTextClass[size],
67
+ )}
68
+ >
69
+ +{surplus}
70
+ </span>
71
+ ) : null}
72
+ {onAdd ? (
73
+ <span className="ml-md">
74
+ <AvatarAddButton size={size} label={addLabel} onClick={onAdd} />
75
+ </span>
76
+ ) : null}
77
+ </div>
78
+ );
79
+ }
@@ -0,0 +1,6 @@
1
+ export { AvatarGroup } from "./AvatarGroup";
2
+ export type {
3
+ AvatarGroupProps,
4
+ AvatarGroupSize,
5
+ AvatarGroupItem,
6
+ } from "./AvatarGroup";
@@ -0,0 +1,62 @@
1
+ import clsx from "clsx";
2
+ import { Avatar, type AvatarSize } from "../Avatar";
3
+
4
+ export type AvatarLabelGroupSize = "sm" | "md" | "lg";
5
+
6
+ export interface AvatarLabelGroupProps {
7
+ size?: AvatarLabelGroupSize;
8
+ /** Primary line (name). */
9
+ name: string;
10
+ /** Secondary line (email / handle / role). */
11
+ subtitle?: string;
12
+ src?: string;
13
+ alt?: string;
14
+ initials?: string;
15
+ hasStatus?: boolean;
16
+ className?: string;
17
+ }
18
+
19
+ const avatarSize: Record<AvatarLabelGroupSize, AvatarSize> = {
20
+ sm: "sm",
21
+ md: "md",
22
+ lg: "lg",
23
+ };
24
+
25
+ const textClass: Record<AvatarLabelGroupSize, string> = {
26
+ sm: "text-sm",
27
+ md: "text-sm",
28
+ lg: "text-md",
29
+ };
30
+
31
+ export function AvatarLabelGroup({
32
+ size = "md",
33
+ name,
34
+ subtitle,
35
+ src,
36
+ alt,
37
+ initials,
38
+ hasStatus = false,
39
+ className,
40
+ }: AvatarLabelGroupProps) {
41
+ return (
42
+ <div className={clsx("flex items-center gap-md font-body", className)}>
43
+ <Avatar
44
+ size={avatarSize[size]}
45
+ src={src}
46
+ alt={alt ?? name}
47
+ initials={initials}
48
+ hasStatus={hasStatus}
49
+ />
50
+ <div className="flex min-w-0 flex-col">
51
+ <span className={clsx("truncate font-semibold text-text-primary", textClass[size])}>
52
+ {name}
53
+ </span>
54
+ {subtitle ? (
55
+ <span className={clsx("truncate font-normal text-text-tertiary", textClass[size])}>
56
+ {subtitle}
57
+ </span>
58
+ ) : null}
59
+ </div>
60
+ </div>
61
+ );
62
+ }
@@ -0,0 +1,5 @@
1
+ export { AvatarLabelGroup } from "./AvatarLabelGroup";
2
+ export type {
3
+ AvatarLabelGroupProps,
4
+ AvatarLabelGroupSize,
5
+ } from "./AvatarLabelGroup";
@@ -0,0 +1,117 @@
1
+ import clsx from "clsx";
2
+
3
+ export type AvatarProfilePhotoSize = "sm" | "md" | "lg";
4
+
5
+ export interface AvatarProfilePhotoProps {
6
+ size?: AvatarProfilePhotoSize;
7
+ src?: string;
8
+ alt?: string;
9
+ /** Placeholder initials when no image is supplied. */
10
+ initials?: string;
11
+ /** Show the verified (blue tick) badge bottom-right. */
12
+ verified?: boolean;
13
+ className?: string;
14
+ }
15
+
16
+ const sizeClass: Record<AvatarProfilePhotoSize, string> = {
17
+ sm: "size-16", // 64px
18
+ md: "size-24", // 96px
19
+ lg: "size-40", // 160px
20
+ };
21
+
22
+ // Initials typography (display-sm / display-md / display-xl, Semibold).
23
+ const initialsClass: Record<AvatarProfilePhotoSize, string> = {
24
+ sm: "text-display-sm",
25
+ md: "text-display-md",
26
+ lg: "text-display-xl",
27
+ };
28
+
29
+ const shadowClass: Record<AvatarProfilePhotoSize, string> = {
30
+ sm: "shadow-xl",
31
+ md: "shadow-xl",
32
+ lg: "shadow-2xl",
33
+ };
34
+
35
+ const badgeClass: Record<AvatarProfilePhotoSize, string> = {
36
+ sm: "size-4", // 16px
37
+ md: "size-6", // 24px
38
+ lg: "size-9", // 36px
39
+ };
40
+
41
+ function UserIcon() {
42
+ return (
43
+ <svg viewBox="0 0 24 24" fill="none" className="h-1/2 w-1/2" aria-hidden>
44
+ <path
45
+ d="M20 21a8 8 0 0 0-16 0M12 11a4 4 0 1 0 0-8 4 4 0 0 0 0 8Z"
46
+ stroke="currentColor"
47
+ strokeWidth="2"
48
+ strokeLinecap="round"
49
+ strokeLinejoin="round"
50
+ />
51
+ </svg>
52
+ );
53
+ }
54
+
55
+ function VerifiedBadge({ className }: { className?: string }) {
56
+ // Approximated as a filled disc + white check (the source uses a scalloped
57
+ // seal outline); colour is utility-blue-500.
58
+ return (
59
+ <span
60
+ className={clsx(
61
+ "absolute bottom-0 right-0 flex items-center justify-center rounded-full border-2 border-bg-primary bg-utility-blue-500 text-text-white",
62
+ className,
63
+ )}
64
+ aria-label="Verified"
65
+ >
66
+ <svg viewBox="0 0 20 20" fill="none" className="h-1/2 w-1/2" aria-hidden>
67
+ <path
68
+ d="m6 10 2.5 2.5L14 7"
69
+ stroke="currentColor"
70
+ strokeWidth="2"
71
+ strokeLinecap="round"
72
+ strokeLinejoin="round"
73
+ />
74
+ </svg>
75
+ </span>
76
+ );
77
+ }
78
+
79
+ export function AvatarProfilePhoto({
80
+ size = "md",
81
+ src,
82
+ alt = "",
83
+ initials,
84
+ verified = false,
85
+ className,
86
+ }: AvatarProfilePhotoProps) {
87
+ return (
88
+ <span className={clsx("relative inline-flex shrink-0", className)}>
89
+ <span
90
+ className={clsx(
91
+ "flex items-center justify-center overflow-hidden rounded-full bg-bg-tertiary",
92
+ src
93
+ ? "border-[0.5px] border-border-secondary-alt"
94
+ : "text-fg-quaternary",
95
+ shadowClass[size],
96
+ sizeClass[size],
97
+ )}
98
+ >
99
+ {src ? (
100
+ <img src={src} alt={alt} className="size-full object-cover" />
101
+ ) : initials ? (
102
+ <span
103
+ className={clsx(
104
+ "font-display font-semibold text-text-quaternary",
105
+ initialsClass[size],
106
+ )}
107
+ >
108
+ {initials}
109
+ </span>
110
+ ) : (
111
+ <UserIcon />
112
+ )}
113
+ </span>
114
+ {verified ? <VerifiedBadge className={badgeClass[size]} /> : null}
115
+ </span>
116
+ );
117
+ }
@@ -0,0 +1,5 @@
1
+ export { AvatarProfilePhoto } from "./AvatarProfilePhoto";
2
+ export type {
3
+ AvatarProfilePhotoProps,
4
+ AvatarProfilePhotoSize,
5
+ } from "./AvatarProfilePhoto";
@@ -0,0 +1,36 @@
1
+ import clsx from "clsx";
2
+ import {
3
+ BadgeBase,
4
+ colorFillClasses,
5
+ dotColorClasses,
6
+ type BadgeCommonProps,
7
+ } from "./badgeShared";
8
+
9
+ export type ColorBadgeProps = BadgeCommonProps;
10
+
11
+ /** Rounded-rectangle coloured badge (Figma Badge `Type=Badge color`). */
12
+ export function ColorBadge({
13
+ color = "gray",
14
+ size = "md",
15
+ dot,
16
+ children,
17
+ iconLeading,
18
+ iconTrailing,
19
+ onClose,
20
+ className,
21
+ }: ColorBadgeProps) {
22
+ return (
23
+ <BadgeBase
24
+ size={size}
25
+ dot={dot}
26
+ dotClass={dotColorClasses[color]}
27
+ iconLeading={iconLeading}
28
+ iconTrailing={iconTrailing}
29
+ onClose={onClose}
30
+ shapeClass={clsx("rounded-md", colorFillClasses[color])}
31
+ className={className}
32
+ >
33
+ {children}
34
+ </BadgeBase>
35
+ );
36
+ }
@@ -0,0 +1,38 @@
1
+ import {
2
+ BadgeBase,
3
+ dotColorClasses,
4
+ type BadgeCommonProps,
5
+ } from "./badgeShared";
6
+
7
+ export type ModernBadgeProps = BadgeCommonProps;
8
+
9
+ /**
10
+ * Neutral white badge with a coloured leading dot (Figma Badge
11
+ * `Type=Badge modern`). Here `color` drives only the dot — the chrome stays
12
+ * neutral. The dot defaults on (it's the defining trait of this style).
13
+ */
14
+ export function ModernBadge({
15
+ color = "gray",
16
+ size = "md",
17
+ dot = true,
18
+ children,
19
+ iconLeading,
20
+ iconTrailing,
21
+ onClose,
22
+ className,
23
+ }: ModernBadgeProps) {
24
+ return (
25
+ <BadgeBase
26
+ size={size}
27
+ dot={dot}
28
+ dotClass={dotColorClasses[color]}
29
+ iconLeading={iconLeading}
30
+ iconTrailing={iconTrailing}
31
+ onClose={onClose}
32
+ shapeClass="rounded-md bg-bg-primary border-border-primary text-text-secondary shadow-xs"
33
+ className={className}
34
+ >
35
+ {children}
36
+ </BadgeBase>
37
+ );
38
+ }
@@ -0,0 +1,36 @@
1
+ import clsx from "clsx";
2
+ import {
3
+ BadgeBase,
4
+ colorFillClasses,
5
+ dotColorClasses,
6
+ type BadgeCommonProps,
7
+ } from "./badgeShared";
8
+
9
+ export type PillBadgeProps = BadgeCommonProps;
10
+
11
+ /** Fully-rounded coloured badge (Figma Badge `Type=Pill color`). */
12
+ export function PillBadge({
13
+ color = "gray",
14
+ size = "md",
15
+ dot,
16
+ children,
17
+ iconLeading,
18
+ iconTrailing,
19
+ onClose,
20
+ className,
21
+ }: PillBadgeProps) {
22
+ return (
23
+ <BadgeBase
24
+ size={size}
25
+ dot={dot}
26
+ dotClass={dotColorClasses[color]}
27
+ iconLeading={iconLeading}
28
+ iconTrailing={iconTrailing}
29
+ onClose={onClose}
30
+ shapeClass={clsx("rounded-full", colorFillClasses[color])}
31
+ className={className}
32
+ >
33
+ {children}
34
+ </BadgeBase>
35
+ );
36
+ }
@@ -0,0 +1,139 @@
1
+ import type { ReactNode } from "react";
2
+ import clsx from "clsx";
3
+
4
+ // 12 Badge colours. Family names match the Figma utility-* palette; `gray`
5
+ // maps to the `neutral` family.
6
+ export type BadgeColor =
7
+ | "brand"
8
+ | "gray"
9
+ | "red"
10
+ | "yellow"
11
+ | "green"
12
+ | "slate"
13
+ | "sky"
14
+ | "blue"
15
+ | "indigo"
16
+ | "purple"
17
+ | "pink"
18
+ | "orange";
19
+
20
+ export type BadgeSize = "sm" | "md" | "lg";
21
+
22
+ // Static class strings (not constructed) so Tailwind's content scanner keeps
23
+ // them. bg = utility-<c>-50, text = -700, border = -200.
24
+ export const colorFillClasses: Record<BadgeColor, string> = {
25
+ brand: "bg-utility-brand-50 text-utility-brand-700 border-utility-brand-200",
26
+ gray: "bg-utility-neutral-50 text-utility-neutral-700 border-utility-neutral-200",
27
+ red: "bg-utility-red-50 text-utility-red-700 border-utility-red-200",
28
+ yellow: "bg-utility-yellow-50 text-utility-yellow-700 border-utility-yellow-200",
29
+ green: "bg-utility-green-50 text-utility-green-700 border-utility-green-200",
30
+ slate: "bg-utility-slate-50 text-utility-slate-700 border-utility-slate-200",
31
+ sky: "bg-utility-sky-50 text-utility-sky-700 border-utility-sky-200",
32
+ blue: "bg-utility-blue-50 text-utility-blue-700 border-utility-blue-200",
33
+ indigo: "bg-utility-indigo-50 text-utility-indigo-700 border-utility-indigo-200",
34
+ purple: "bg-utility-purple-50 text-utility-purple-700 border-utility-purple-200",
35
+ pink: "bg-utility-pink-50 text-utility-pink-700 border-utility-pink-200",
36
+ orange: "bg-utility-orange-50 text-utility-orange-700 border-utility-orange-200",
37
+ };
38
+
39
+ // Leading-dot colour (utility-<c>-500).
40
+ export const dotColorClasses: Record<BadgeColor, string> = {
41
+ brand: "bg-utility-brand-500",
42
+ gray: "bg-utility-neutral-500",
43
+ red: "bg-utility-red-500",
44
+ yellow: "bg-utility-yellow-500",
45
+ green: "bg-utility-green-500",
46
+ slate: "bg-utility-slate-500",
47
+ sky: "bg-utility-sky-500",
48
+ blue: "bg-utility-blue-500",
49
+ indigo: "bg-utility-indigo-500",
50
+ purple: "bg-utility-purple-500",
51
+ pink: "bg-utility-pink-500",
52
+ orange: "bg-utility-orange-500",
53
+ };
54
+
55
+ const sizeClasses: Record<BadgeSize, string> = {
56
+ sm: "px-md py-xxs text-xs gap-xs",
57
+ md: "px-lg py-xxs text-sm gap-xs",
58
+ lg: "px-lg py-xs text-sm gap-md",
59
+ };
60
+
61
+ /** Props shared by all three Badge types. */
62
+ export interface BadgeCommonProps {
63
+ children: ReactNode;
64
+ color?: BadgeColor;
65
+ size?: BadgeSize;
66
+ /** Leading coloured dot. */
67
+ dot?: boolean;
68
+ iconLeading?: ReactNode;
69
+ iconTrailing?: ReactNode;
70
+ /** Renders a trailing X-close button when provided. */
71
+ onClose?: () => void;
72
+ className?: string;
73
+ }
74
+
75
+ function CloseX() {
76
+ return (
77
+ <svg viewBox="0 0 12 12" fill="none" className="size-3" aria-hidden>
78
+ <path
79
+ d="m9 3-6 6m0-6 6 6"
80
+ stroke="currentColor"
81
+ strokeWidth="1.5"
82
+ strokeLinecap="round"
83
+ strokeLinejoin="round"
84
+ />
85
+ </svg>
86
+ );
87
+ }
88
+
89
+ /** Internal layout shell used by PillBadge / ColorBadge / ModernBadge. */
90
+ export function BadgeBase({
91
+ children,
92
+ size = "md",
93
+ dot,
94
+ dotClass,
95
+ iconLeading,
96
+ iconTrailing,
97
+ onClose,
98
+ shapeClass,
99
+ className,
100
+ }: {
101
+ children: ReactNode;
102
+ size?: BadgeSize;
103
+ dot?: boolean;
104
+ dotClass?: string;
105
+ iconLeading?: ReactNode;
106
+ iconTrailing?: ReactNode;
107
+ onClose?: () => void;
108
+ /** Type-specific shape + colour classes (rounded + bg/text/border). */
109
+ shapeClass: string;
110
+ className?: string;
111
+ }) {
112
+ return (
113
+ <span
114
+ className={clsx(
115
+ "inline-flex items-center whitespace-nowrap border font-medium font-body",
116
+ sizeClasses[size],
117
+ shapeClass,
118
+ className,
119
+ )}
120
+ >
121
+ {dot ? (
122
+ <span className={clsx("size-2 shrink-0 rounded-full", dotClass)} aria-hidden />
123
+ ) : null}
124
+ {iconLeading ? <span className="shrink-0">{iconLeading}</span> : null}
125
+ {children}
126
+ {iconTrailing ? <span className="shrink-0">{iconTrailing}</span> : null}
127
+ {onClose ? (
128
+ <button
129
+ type="button"
130
+ onClick={onClose}
131
+ aria-label="Remove"
132
+ className="-mr-xxs shrink-0 rounded-xs opacity-70 transition-opacity hover:opacity-100"
133
+ >
134
+ <CloseX />
135
+ </button>
136
+ ) : null}
137
+ </span>
138
+ );
139
+ }
@@ -0,0 +1,7 @@
1
+ export { PillBadge } from "./PillBadge";
2
+ export { ColorBadge } from "./ColorBadge";
3
+ export { ModernBadge } from "./ModernBadge";
4
+ export type { PillBadgeProps } from "./PillBadge";
5
+ export type { ColorBadgeProps } from "./ColorBadge";
6
+ export type { ModernBadgeProps } from "./ModernBadge";
7
+ export type { BadgeColor, BadgeSize, BadgeCommonProps } from "./badgeShared";
@@ -0,0 +1,64 @@
1
+ import type { ButtonHTMLAttributes } from "react";
2
+ import clsx from "clsx";
3
+ import type { BadgeColor } from "../Badge";
4
+
5
+ export type BadgeCloseXShape = "square" | "rounded";
6
+
7
+ export interface BadgeCloseXProps
8
+ extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, "color"> {
9
+ /**
10
+ * Tint for the X. Omit to inherit the parent badge's text colour
11
+ * (currentColor) — the usual case when composed inside a Badge.
12
+ */
13
+ color?: BadgeColor;
14
+ shape?: BadgeCloseXShape;
15
+ }
16
+
17
+ // Standalone tint map (utility-<c>-500). Static strings for Tailwind.
18
+ const textColorClasses: Record<BadgeColor, string> = {
19
+ brand: "text-utility-brand-500",
20
+ gray: "text-utility-neutral-500",
21
+ red: "text-utility-red-500",
22
+ yellow: "text-utility-yellow-500",
23
+ green: "text-utility-green-500",
24
+ slate: "text-utility-slate-500",
25
+ sky: "text-utility-sky-500",
26
+ blue: "text-utility-blue-500",
27
+ indigo: "text-utility-indigo-500",
28
+ purple: "text-utility-purple-500",
29
+ pink: "text-utility-pink-500",
30
+ orange: "text-utility-orange-500",
31
+ };
32
+
33
+ export function BadgeCloseX({
34
+ color,
35
+ shape = "rounded",
36
+ className,
37
+ ...rest
38
+ }: BadgeCloseXProps) {
39
+ return (
40
+ <button
41
+ type="button"
42
+ aria-label="Remove"
43
+ className={clsx(
44
+ "inline-flex size-4 items-center justify-center transition-colors",
45
+ shape === "square" ? "rounded-xs" : "rounded-full",
46
+ color ? textColorClasses[color] : undefined,
47
+ "hover:bg-black/10",
48
+ "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-border-brand focus-visible:ring-offset-1 focus-visible:ring-offset-bg-primary",
49
+ className,
50
+ )}
51
+ {...rest}
52
+ >
53
+ <svg viewBox="0 0 12 12" fill="none" className="size-3" aria-hidden>
54
+ <path
55
+ d="m9 3-6 6m0-6 6 6"
56
+ stroke="currentColor"
57
+ strokeWidth="1.5"
58
+ strokeLinecap="round"
59
+ strokeLinejoin="round"
60
+ />
61
+ </svg>
62
+ </button>
63
+ );
64
+ }
@@ -0,0 +1,2 @@
1
+ export { BadgeCloseX } from "./BadgeCloseX";
2
+ export type { BadgeCloseXProps, BadgeCloseXShape } from "./BadgeCloseX";