@fabio.caffarello/react-design-system 1.7.0 → 1.8.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 (460) hide show
  1. package/README.md +48 -3
  2. package/dist/docs/components/ComponentStatusTable.d.ts +11 -0
  3. package/dist/ui/atoms/Accordion/Accordion.d.ts +34 -0
  4. package/dist/ui/atoms/Accordion/Accordion.stories.d.ts +11 -0
  5. package/dist/ui/atoms/Accordion/Accordion.test.d.ts +1 -0
  6. package/dist/ui/atoms/Accordion/index.d.ts +2 -0
  7. package/dist/ui/atoms/Avatar/Avatar.d.ts +30 -0
  8. package/dist/ui/atoms/Avatar/Avatar.stories.d.ts +13 -0
  9. package/dist/ui/atoms/Avatar/Avatar.test.d.ts +1 -0
  10. package/dist/ui/atoms/Avatar/AvatarGroup.d.ts +26 -0
  11. package/dist/ui/atoms/Avatar/index.d.ts +9 -0
  12. package/dist/ui/atoms/Badge/Badge.d.ts +14 -6
  13. package/dist/ui/atoms/Badge/Badge.stories.d.ts +8 -9
  14. package/dist/ui/atoms/BoxWrapper/BoxWrapper.d.ts +3 -3
  15. package/dist/ui/atoms/BoxWrapper/BoxWrapper.test.d.ts +1 -0
  16. package/dist/ui/atoms/Button/Button.d.ts +32 -10
  17. package/dist/ui/atoms/Button/Button.stories.d.ts +7 -0
  18. package/dist/ui/atoms/Button/Button.test.d.ts +1 -0
  19. package/dist/ui/atoms/Checkbox/Checkbox.d.ts +2 -1
  20. package/dist/ui/atoms/Collapsible/Collapsible.stories.d.ts +2 -0
  21. package/dist/ui/atoms/Info/Info.d.ts +2 -3
  22. package/dist/ui/atoms/Info/Info.test.d.ts +1 -0
  23. package/dist/ui/atoms/Input/Input.d.ts +14 -4
  24. package/dist/ui/atoms/Input/Input.stories.d.ts +6 -0
  25. package/dist/ui/atoms/Popover/Popover.d.ts +35 -0
  26. package/dist/ui/atoms/Popover/Popover.stories.d.ts +11 -0
  27. package/dist/ui/atoms/Popover/Popover.test.d.ts +1 -0
  28. package/dist/ui/atoms/Popover/index.d.ts +2 -0
  29. package/dist/ui/atoms/Progress/Progress.d.ts +33 -0
  30. package/dist/ui/atoms/Progress/Progress.stories.d.ts +12 -0
  31. package/dist/ui/atoms/Progress/Progress.test.d.ts +1 -0
  32. package/dist/ui/atoms/Select/Select.d.ts +18 -6
  33. package/dist/ui/atoms/Select/Select.stories.d.ts +11 -8
  34. package/dist/ui/atoms/Separator/Separator.d.ts +23 -0
  35. package/dist/ui/atoms/Separator/Separator.stories.d.ts +10 -0
  36. package/dist/ui/atoms/Separator/Separator.test.d.ts +1 -0
  37. package/dist/ui/atoms/Separator/index.d.ts +2 -0
  38. package/dist/ui/atoms/Skeleton/Skeleton.d.ts +1 -1
  39. package/dist/ui/atoms/Skeleton/Skeleton.stories.d.ts +24 -0
  40. package/dist/ui/atoms/Slider/Slider.d.ts +45 -0
  41. package/dist/ui/atoms/Slider/Slider.stories.d.ts +13 -0
  42. package/dist/ui/atoms/Slider/Slider.test.d.ts +1 -0
  43. package/dist/ui/atoms/Slider/index.d.ts +2 -0
  44. package/dist/ui/atoms/Spinner/Spinner.d.ts +22 -0
  45. package/dist/ui/atoms/Spinner/Spinner.stories.d.ts +9 -0
  46. package/dist/ui/atoms/Spinner/Spinner.test.d.ts +1 -0
  47. package/dist/ui/atoms/Switch/Switch.d.ts +28 -0
  48. package/dist/ui/atoms/Switch/Switch.stories.d.ts +11 -0
  49. package/dist/ui/atoms/Switch/Switch.test.d.ts +1 -0
  50. package/dist/ui/atoms/Switch/index.d.ts +2 -0
  51. package/dist/ui/atoms/Tooltip/Tooltip.d.ts +2 -1
  52. package/dist/ui/atoms/Tooltip/Tooltip.stories.d.ts +17 -0
  53. package/dist/ui/atoms/index.d.ts +20 -3
  54. package/dist/ui/index.d.ts +6 -1
  55. package/dist/ui/molecules/Card/Card.d.ts +6 -2
  56. package/dist/ui/molecules/Card/Card.stories.d.ts +2 -0
  57. package/dist/ui/molecules/ColorPicker/ColorPicker.d.ts +28 -0
  58. package/dist/ui/molecules/ColorPicker/ColorPicker.stories.d.ts +12 -0
  59. package/dist/ui/molecules/ColorPicker/ColorPicker.test.d.ts +1 -0
  60. package/dist/ui/molecules/ColorPicker/index.d.ts +2 -0
  61. package/dist/ui/molecules/DatePicker/DatePicker.d.ts +74 -0
  62. package/dist/ui/molecules/DatePicker/DatePicker.stories.d.ts +12 -0
  63. package/dist/ui/molecules/DatePicker/DatePicker.test.d.ts +1 -0
  64. package/dist/ui/molecules/DatePicker/DatePickerCalendar.d.ts +6 -0
  65. package/dist/ui/molecules/DatePicker/DatePickerContext.d.ts +28 -0
  66. package/dist/ui/molecules/DatePicker/DatePickerInput.d.ts +9 -0
  67. package/dist/ui/molecules/DatePicker/DatePickerProvider.d.ts +23 -0
  68. package/dist/ui/molecules/DatePicker/index.d.ts +14 -0
  69. package/dist/ui/molecules/Dropdown/Dropdown.d.ts +2 -1
  70. package/dist/ui/molecules/Dropdown/Dropdown.stories.d.ts +13 -0
  71. package/dist/ui/molecules/EmptyState/EmptyState.stories.d.ts +22 -0
  72. package/dist/ui/molecules/FileUpload/FileUpload.d.ts +37 -0
  73. package/dist/ui/molecules/FileUpload/FileUpload.stories.d.ts +12 -0
  74. package/dist/ui/molecules/FileUpload/FileUpload.test.d.ts +1 -0
  75. package/dist/ui/molecules/FileUpload/index.d.ts +2 -0
  76. package/dist/ui/molecules/Form/Form.d.ts +29 -4
  77. package/dist/ui/molecules/Form/Form.stories.d.ts +2 -0
  78. package/dist/ui/molecules/Form/FormContext.d.ts +17 -0
  79. package/dist/ui/molecules/Form/FormField.d.ts +36 -0
  80. package/dist/ui/molecules/Form/FormProvider.d.ts +14 -0
  81. package/dist/ui/molecules/Form/index.d.ts +13 -0
  82. package/dist/ui/molecules/Form/useFormFieldArray.d.ts +28 -0
  83. package/dist/ui/molecules/InputWithLabel/InputWithLabel.test.d.ts +1 -0
  84. package/dist/ui/molecules/Rating/Rating.d.ts +33 -0
  85. package/dist/ui/molecules/Rating/Rating.stories.d.ts +13 -0
  86. package/dist/ui/molecules/Rating/Rating.test.d.ts +1 -0
  87. package/dist/ui/molecules/Rating/index.d.ts +2 -0
  88. package/dist/ui/molecules/SearchInput/SearchInput.d.ts +24 -0
  89. package/dist/ui/molecules/SearchInput/SearchInput.stories.d.ts +10 -0
  90. package/dist/ui/molecules/SearchInput/SearchInput.test.d.ts +1 -0
  91. package/dist/ui/molecules/SearchInput/index.d.ts +2 -0
  92. package/dist/ui/molecules/SidebarHeader/SidebarHeader.test.d.ts +1 -0
  93. package/dist/ui/molecules/TableActions/TableActions.d.ts +31 -0
  94. package/dist/ui/molecules/TableActions/TableActions.stories.d.ts +7 -0
  95. package/dist/ui/molecules/TableActions/TableActions.test.d.ts +1 -0
  96. package/dist/ui/molecules/TableFilters/TableFilters.d.ts +37 -0
  97. package/dist/ui/molecules/TableFilters/TableFilters.stories.d.ts +7 -0
  98. package/dist/ui/molecules/TableFilters/TableFilters.test.d.ts +1 -0
  99. package/dist/ui/molecules/TablePagination/TablePagination.d.ts +29 -0
  100. package/dist/ui/molecules/TablePagination/TablePagination.stories.d.ts +8 -0
  101. package/dist/ui/molecules/TablePagination/TablePagination.test.d.ts +1 -0
  102. package/dist/ui/molecules/Tabs/Tabs.d.ts +15 -0
  103. package/dist/ui/molecules/Tabs/Tabs.stories.d.ts +10 -0
  104. package/dist/ui/molecules/Tabs/Tabs.test.d.ts +1 -0
  105. package/dist/ui/molecules/Tabs/TabsContent.d.ts +14 -0
  106. package/dist/ui/molecules/Tabs/TabsContext.d.ts +18 -0
  107. package/dist/ui/molecules/Tabs/TabsList.d.ts +12 -0
  108. package/dist/ui/molecules/Tabs/TabsProvider.d.ts +16 -0
  109. package/dist/ui/molecules/Tabs/TabsTrigger.d.ts +13 -0
  110. package/dist/ui/molecules/Tabs/index.d.ts +17 -0
  111. package/dist/ui/molecules/TimePicker/TimePicker.d.ts +29 -0
  112. package/dist/ui/molecules/TimePicker/TimePicker.stories.d.ts +12 -0
  113. package/dist/ui/molecules/TimePicker/TimePicker.test.d.ts +1 -0
  114. package/dist/ui/molecules/TimePicker/index.d.ts +2 -0
  115. package/dist/ui/molecules/index.d.ts +13 -5
  116. package/dist/ui/organisms/CommandPalette/CommandPalette.d.ts +37 -0
  117. package/dist/ui/organisms/CommandPalette/CommandPalette.stories.d.ts +11 -0
  118. package/dist/ui/organisms/CommandPalette/CommandPalette.test.d.ts +1 -0
  119. package/dist/ui/organisms/CommandPalette/index.d.ts +2 -0
  120. package/dist/ui/organisms/DataGrid/DataGrid.d.ts +84 -0
  121. package/dist/ui/organisms/DataGrid/DataGrid.stories.d.ts +14 -0
  122. package/dist/ui/organisms/DataGrid/DataGrid.test.d.ts +1 -0
  123. package/dist/ui/organisms/DataGrid/index.d.ts +2 -0
  124. package/dist/ui/organisms/Dialog/AlertDialog.d.ts +34 -0
  125. package/dist/ui/organisms/Dialog/Dialog.d.ts +58 -0
  126. package/dist/ui/organisms/Dialog/Dialog.stories.d.ts +13 -0
  127. package/dist/ui/organisms/Dialog/Dialog.test.d.ts +1 -0
  128. package/dist/ui/organisms/Dialog/DialogClose.d.ts +8 -0
  129. package/dist/ui/organisms/Dialog/DialogContent.d.ts +8 -0
  130. package/dist/ui/organisms/Dialog/DialogContext.d.ts +10 -0
  131. package/dist/ui/organisms/Dialog/DialogDescription.d.ts +4 -0
  132. package/dist/ui/organisms/Dialog/DialogFooter.d.ts +5 -0
  133. package/dist/ui/organisms/Dialog/DialogHeader.d.ts +5 -0
  134. package/dist/ui/organisms/Dialog/DialogProvider.d.ts +10 -0
  135. package/dist/ui/organisms/Dialog/DialogTitle.d.ts +5 -0
  136. package/dist/ui/organisms/Dialog/DialogTrigger.d.ts +6 -0
  137. package/dist/ui/organisms/Dialog/index.d.ts +22 -0
  138. package/dist/ui/organisms/Sidebar/Sidebar.d.ts +7 -4
  139. package/dist/ui/organisms/Sidebar/SidebarGroup/SidebarGroup.d.ts +27 -0
  140. package/dist/ui/organisms/Sidebar/SidebarGroup/SidebarGroup.stories.d.ts +11 -0
  141. package/dist/ui/organisms/Sidebar/SidebarGroup/SidebarGroup.test.d.ts +1 -0
  142. package/dist/ui/organisms/Sidebar/SidebarHeader/SidebarHeader.d.ts +19 -0
  143. package/dist/ui/organisms/Sidebar/SidebarHeader/SidebarHeader.test.d.ts +1 -0
  144. package/dist/ui/organisms/Sidebar/SidebarItem/SidebarItem.d.ts +23 -0
  145. package/dist/ui/organisms/Sidebar/SidebarItem/SidebarItem.stories.d.ts +10 -0
  146. package/dist/ui/organisms/Sidebar/SidebarItem/SidebarItem.test.d.ts +1 -0
  147. package/dist/ui/organisms/Sidebar/index.d.ts +8 -0
  148. package/dist/ui/organisms/Stepper/Stepper.d.ts +40 -0
  149. package/dist/ui/organisms/Stepper/Stepper.stories.d.ts +12 -0
  150. package/dist/ui/organisms/Stepper/Stepper.test.d.ts +1 -0
  151. package/dist/ui/organisms/Stepper/index.d.ts +2 -0
  152. package/dist/ui/organisms/Table/Table.d.ts +84 -16
  153. package/dist/ui/organisms/Table/Table.stories.d.ts +15 -0
  154. package/dist/ui/organisms/Table/TableActions/TableActions.d.ts +31 -0
  155. package/dist/ui/organisms/Table/TableActions/TableActions.stories.d.ts +7 -0
  156. package/dist/ui/organisms/Table/TableActions/TableActions.test.d.ts +1 -0
  157. package/dist/ui/organisms/Table/TableActions.d.ts +13 -0
  158. package/dist/ui/organisms/Table/TableBody.d.ts +12 -0
  159. package/dist/ui/organisms/Table/TableCell.d.ts +14 -0
  160. package/dist/ui/organisms/Table/TableContext.d.ts +75 -0
  161. package/dist/ui/organisms/Table/TableEmptyState.d.ts +11 -0
  162. package/dist/ui/organisms/Table/TableFilters/TableFilters.d.ts +37 -0
  163. package/dist/ui/organisms/Table/TableFilters/TableFilters.stories.d.ts +7 -0
  164. package/dist/ui/organisms/Table/TableFilters/TableFilters.test.d.ts +1 -0
  165. package/dist/ui/organisms/Table/TableFilters.d.ts +12 -0
  166. package/dist/ui/organisms/Table/TableHeader.d.ts +10 -0
  167. package/dist/ui/organisms/Table/TableHeaderCell.d.ts +18 -0
  168. package/dist/ui/organisms/Table/TableHeaderRow.d.ts +10 -0
  169. package/dist/ui/organisms/Table/TablePagination/TablePagination.d.ts +29 -0
  170. package/dist/ui/organisms/Table/TablePagination/TablePagination.stories.d.ts +8 -0
  171. package/dist/ui/organisms/Table/TablePagination/TablePagination.test.d.ts +1 -0
  172. package/dist/ui/organisms/Table/TablePagination.d.ts +14 -0
  173. package/dist/ui/organisms/Table/TableProvider.d.ts +55 -0
  174. package/dist/ui/organisms/Table/TableRow.d.ts +14 -0
  175. package/dist/ui/organisms/Table/TableTypes.d.ts +8 -0
  176. package/dist/ui/organisms/Table/index.d.ts +30 -0
  177. package/dist/ui/organisms/Table/useColumnResizing.d.ts +39 -0
  178. package/dist/ui/organisms/Table/useVirtualScrolling.d.ts +35 -0
  179. package/dist/ui/organisms/Timeline/Timeline.d.ts +34 -0
  180. package/dist/ui/organisms/Timeline/Timeline.stories.d.ts +12 -0
  181. package/dist/ui/organisms/Timeline/Timeline.test.d.ts +1 -0
  182. package/dist/ui/organisms/Timeline/index.d.ts +2 -0
  183. package/dist/ui/organisms/Toast/Toast.d.ts +8 -0
  184. package/dist/ui/organisms/Toast/Toast.stories.d.ts +14 -0
  185. package/dist/ui/organisms/Toast/Toast.test.d.ts +1 -0
  186. package/dist/ui/organisms/Toast/ToastContainer.d.ts +5 -0
  187. package/dist/ui/organisms/Toast/ToastContext.d.ts +21 -0
  188. package/dist/ui/organisms/Toast/ToastProvider.d.ts +7 -0
  189. package/dist/ui/organisms/Toast/index.d.ts +15 -0
  190. package/dist/ui/organisms/Toast/useToast.d.ts +35 -0
  191. package/dist/ui/organisms/index.d.ts +12 -2
  192. package/dist/ui/providers/AdvancedThemeProvider.d.ts +52 -0
  193. package/dist/ui/providers/index.d.ts +9 -0
  194. package/dist/ui/themes/ThemeBuilder.d.ts +28 -0
  195. package/dist/ui/themes/ThemeRegistry.d.ts +55 -0
  196. package/dist/ui/themes/index.d.ts +9 -0
  197. package/dist/ui/themes/types.d.ts +48 -0
  198. package/dist/ui/themes/utils.d.ts +21 -0
  199. package/dist/ui/tokens/TokenVisualizations.d.ts +41 -0
  200. package/dist/ui/tokens/animations.d.ts +65 -0
  201. package/dist/ui/tokens/borders.d.ts +61 -0
  202. package/dist/ui/tokens/gradients.d.ts +55 -0
  203. package/dist/ui/tokens/index.d.ts +31 -0
  204. package/dist/ui/tokens/opacity.d.ts +51 -0
  205. package/dist/ui/tokens/radius.d.ts +45 -0
  206. package/dist/ui/tokens/shadows.d.ts +42 -0
  207. package/dist/ui/tokens/themes/dark.d.ts +26 -26
  208. package/dist/ui/tokens/themes/light.d.ts +26 -26
  209. package/dist/ui/tokens/tokens.factory.d.ts +42 -0
  210. package/dist/ui/tokens/z-index.d.ts +44 -0
  211. package/dist/ui/utils/index.d.ts +6 -0
  212. package/package.json +50 -6
  213. package/src/docs/Accessibility.mdx +402 -0
  214. package/src/docs/BestPractices.mdx +315 -0
  215. package/src/docs/ComponentComposition.mdx +381 -0
  216. package/src/docs/ComponentStatus.mdx +177 -0
  217. package/src/docs/DesignSystem.mdx +121 -0
  218. package/src/docs/GettingStarted.mdx +284 -0
  219. package/src/docs/MigrationGuide.mdx +297 -0
  220. package/src/docs/Performance.mdx +206 -0
  221. package/src/docs/components/ComponentStatusTable.tsx +184 -0
  222. package/src/setupTests.ts +32 -0
  223. package/src/ui/atoms/Accordion/Accordion.stories.tsx +147 -0
  224. package/src/ui/atoms/Accordion/Accordion.test.tsx +86 -0
  225. package/src/ui/atoms/Accordion/Accordion.tsx +147 -0
  226. package/src/ui/atoms/Accordion/index.ts +2 -0
  227. package/src/ui/atoms/Avatar/Avatar.stories.tsx +226 -0
  228. package/src/ui/atoms/Avatar/Avatar.test.tsx +233 -0
  229. package/src/ui/atoms/Avatar/Avatar.tsx +128 -0
  230. package/src/ui/atoms/Avatar/AvatarGroup.tsx +96 -0
  231. package/src/ui/atoms/Avatar/index.ts +11 -0
  232. package/src/ui/atoms/Badge/Badge.stories.tsx +65 -56
  233. package/src/ui/atoms/Badge/Badge.test.tsx +27 -50
  234. package/src/ui/atoms/Badge/Badge.tsx +70 -27
  235. package/src/ui/atoms/BoxWrapper/BoxWrapper.stories.tsx +1 -1
  236. package/src/ui/atoms/BoxWrapper/BoxWrapper.test.tsx +27 -0
  237. package/src/ui/atoms/BoxWrapper/BoxWrapper.tsx +5 -2
  238. package/src/ui/atoms/Button/Button.stories.tsx +130 -1
  239. package/src/ui/atoms/Button/Button.test.tsx +233 -0
  240. package/src/ui/atoms/Button/Button.tsx +160 -53
  241. package/src/ui/atoms/Checkbox/Checkbox.tsx +14 -1
  242. package/src/ui/atoms/Collapsible/Collapsible.stories.tsx +47 -1
  243. package/src/ui/atoms/Collapsible/Collapsible.test.tsx +36 -24
  244. package/src/ui/atoms/Collapsible/Collapsible.tsx +9 -1
  245. package/src/ui/atoms/ErrorMessage/ErrorMessage.stories.tsx +1 -1
  246. package/src/ui/atoms/Info/Info.stories.tsx +1 -1
  247. package/src/ui/atoms/Info/Info.test.tsx +45 -0
  248. package/src/ui/atoms/Info/Info.tsx +2 -2
  249. package/src/ui/atoms/Input/Input.stories.tsx +80 -0
  250. package/src/ui/atoms/Input/Input.test.tsx +190 -36
  251. package/src/ui/atoms/Input/Input.tsx +144 -25
  252. package/src/ui/atoms/Label/Label.stories.tsx +1 -1
  253. package/src/ui/atoms/NavLink/NavLink.stories.tsx +1 -1
  254. package/src/ui/atoms/Popover/Popover.stories.tsx +157 -0
  255. package/src/ui/atoms/Popover/Popover.test.tsx +80 -0
  256. package/src/ui/atoms/Popover/Popover.tsx +256 -0
  257. package/src/ui/atoms/Popover/index.ts +2 -0
  258. package/src/ui/atoms/Progress/Progress.css +17 -0
  259. package/src/ui/atoms/Progress/Progress.stories.tsx +170 -0
  260. package/src/ui/atoms/Progress/Progress.test.tsx +134 -0
  261. package/src/ui/atoms/Progress/Progress.tsx +138 -0
  262. package/src/ui/atoms/Radio/Radio.tsx +1 -1
  263. package/src/ui/atoms/Select/Select.stories.tsx +93 -58
  264. package/src/ui/atoms/Select/Select.test.tsx +162 -46
  265. package/src/ui/atoms/Select/Select.tsx +142 -44
  266. package/src/ui/atoms/Separator/Separator.stories.tsx +88 -0
  267. package/src/ui/atoms/Separator/Separator.test.tsx +34 -0
  268. package/src/ui/atoms/Separator/Separator.tsx +81 -0
  269. package/src/ui/atoms/Separator/index.ts +2 -0
  270. package/src/ui/atoms/Skeleton/Skeleton.stories.tsx +62 -0
  271. package/src/ui/atoms/Skeleton/Skeleton.tsx +19 -2
  272. package/src/ui/atoms/Slider/Slider.stories.tsx +205 -0
  273. package/src/ui/atoms/Slider/Slider.test.tsx +53 -0
  274. package/src/ui/atoms/Slider/Slider.tsx +307 -0
  275. package/src/ui/atoms/Slider/index.ts +2 -0
  276. package/src/ui/atoms/Spinner/Spinner.stories.tsx +56 -0
  277. package/src/ui/atoms/Spinner/Spinner.test.tsx +35 -0
  278. package/src/ui/atoms/Spinner/Spinner.tsx +88 -0
  279. package/src/ui/atoms/Switch/Switch.stories.tsx +182 -0
  280. package/src/ui/atoms/Switch/Switch.test.tsx +90 -0
  281. package/src/ui/atoms/Switch/Switch.tsx +181 -0
  282. package/src/ui/atoms/Switch/index.ts +2 -0
  283. package/src/ui/atoms/Text/Text.stories.tsx +1 -1
  284. package/src/ui/atoms/Text/Text.test.tsx +48 -32
  285. package/src/ui/atoms/Textarea/Textarea.stories.tsx +1 -1
  286. package/src/ui/atoms/Tooltip/Tooltip.stories.tsx +44 -0
  287. package/src/ui/atoms/Tooltip/Tooltip.tsx +94 -6
  288. package/src/ui/atoms/index.ts +27 -4
  289. package/src/ui/index.ts +6 -1
  290. package/src/ui/molecules/Breadcrumb/Breadcrumb.stories.tsx +1 -1
  291. package/src/ui/molecules/Breadcrumb/Breadcrumb.tsx +1 -1
  292. package/src/ui/molecules/Card/Card.stories.tsx +49 -1
  293. package/src/ui/molecules/Card/Card.tsx +40 -5
  294. package/src/ui/molecules/ColorPicker/ColorPicker.stories.tsx +156 -0
  295. package/src/ui/molecules/ColorPicker/ColorPicker.test.tsx +47 -0
  296. package/src/ui/molecules/ColorPicker/ColorPicker.tsx +271 -0
  297. package/src/ui/molecules/ColorPicker/index.ts +2 -0
  298. package/src/ui/molecules/DatePicker/DatePicker.mdx +150 -0
  299. package/src/ui/molecules/DatePicker/DatePicker.stories.tsx +188 -0
  300. package/src/ui/molecules/DatePicker/DatePicker.test.tsx +381 -0
  301. package/src/ui/molecules/DatePicker/DatePicker.tsx +231 -0
  302. package/src/ui/molecules/DatePicker/DatePickerCalendar.tsx +277 -0
  303. package/src/ui/molecules/DatePicker/DatePickerContext.tsx +39 -0
  304. package/src/ui/molecules/DatePicker/DatePickerInput.tsx +147 -0
  305. package/src/ui/molecules/DatePicker/DatePickerProvider.tsx +100 -0
  306. package/src/ui/molecules/DatePicker/index.ts +16 -0
  307. package/src/ui/molecules/Dropdown/Dropdown.stories.tsx +50 -8
  308. package/src/ui/molecules/Dropdown/Dropdown.test.tsx +272 -12
  309. package/src/ui/molecules/Dropdown/Dropdown.tsx +176 -10
  310. package/src/ui/molecules/EmptyState/EmptyState.stories.tsx +24 -2
  311. package/src/ui/molecules/EmptyState/EmptyState.tsx +9 -3
  312. package/src/ui/molecules/FileUpload/FileUpload.stories.tsx +177 -0
  313. package/src/ui/molecules/FileUpload/FileUpload.test.tsx +114 -0
  314. package/src/ui/molecules/FileUpload/FileUpload.tsx +312 -0
  315. package/src/ui/molecules/FileUpload/index.ts +2 -0
  316. package/src/ui/molecules/Form/Form.mdx +145 -0
  317. package/src/ui/molecules/Form/Form.stories.tsx +121 -1
  318. package/src/ui/molecules/Form/Form.test.tsx +1 -3
  319. package/src/ui/molecules/Form/Form.tsx +95 -15
  320. package/src/ui/molecules/Form/FormContext.tsx +35 -0
  321. package/src/ui/molecules/Form/FormField.tsx +83 -0
  322. package/src/ui/molecules/Form/FormProvider.tsx +34 -0
  323. package/src/ui/molecules/Form/index.ts +21 -0
  324. package/src/ui/molecules/Form/useFormFieldArray.ts +46 -0
  325. package/src/ui/molecules/InputWithLabel/InputWithLabel.stories.tsx +1 -1
  326. package/src/ui/molecules/InputWithLabel/InputWithLabel.test.tsx +44 -0
  327. package/src/ui/molecules/InputWithLabel/InputWithLabel.tsx +3 -1
  328. package/src/ui/molecules/NavbarGroup/NavbarGroup.stories.tsx +1 -1
  329. package/src/ui/molecules/Pagination/Pagination.stories.tsx +1 -1
  330. package/src/ui/molecules/Rating/Rating.stories.tsx +206 -0
  331. package/src/ui/molecules/Rating/Rating.test.tsx +60 -0
  332. package/src/ui/molecules/Rating/Rating.tsx +173 -0
  333. package/src/ui/molecules/Rating/index.ts +2 -0
  334. package/src/ui/molecules/SearchInput/SearchInput.stories.tsx +146 -0
  335. package/src/ui/molecules/SearchInput/SearchInput.test.tsx +82 -0
  336. package/src/ui/molecules/SearchInput/SearchInput.tsx +133 -0
  337. package/src/ui/molecules/SearchInput/index.ts +2 -0
  338. package/src/ui/molecules/Tabs/Tabs.stories.tsx +229 -0
  339. package/src/ui/molecules/Tabs/Tabs.test.tsx +497 -0
  340. package/src/ui/molecules/Tabs/Tabs.tsx +58 -0
  341. package/src/ui/molecules/Tabs/TabsContent.tsx +50 -0
  342. package/src/ui/molecules/Tabs/TabsContext.tsx +36 -0
  343. package/src/ui/molecules/Tabs/TabsList.tsx +98 -0
  344. package/src/ui/molecules/Tabs/TabsProvider.tsx +53 -0
  345. package/src/ui/molecules/Tabs/TabsTrigger.tsx +111 -0
  346. package/src/ui/molecules/Tabs/index.ts +23 -0
  347. package/src/ui/molecules/TimePicker/TimePicker.stories.tsx +145 -0
  348. package/src/ui/molecules/TimePicker/TimePicker.test.tsx +41 -0
  349. package/src/ui/molecules/TimePicker/TimePicker.tsx +264 -0
  350. package/src/ui/molecules/TimePicker/index.ts +2 -0
  351. package/src/ui/molecules/index.ts +20 -7
  352. package/src/ui/organisms/CommandPalette/CommandPalette.stories.tsx +218 -0
  353. package/src/ui/organisms/CommandPalette/CommandPalette.test.tsx +85 -0
  354. package/src/ui/organisms/CommandPalette/CommandPalette.tsx +333 -0
  355. package/src/ui/organisms/CommandPalette/index.ts +2 -0
  356. package/src/ui/organisms/DataGrid/DataGrid.stories.tsx +196 -0
  357. package/src/ui/organisms/DataGrid/DataGrid.test.tsx +53 -0
  358. package/src/ui/organisms/DataGrid/DataGrid.tsx +294 -0
  359. package/src/ui/organisms/DataGrid/index.ts +2 -0
  360. package/src/ui/organisms/Dialog/AlertDialog.tsx +92 -0
  361. package/src/ui/organisms/Dialog/Dialog.mdx +200 -0
  362. package/src/ui/organisms/Dialog/Dialog.stories.tsx +226 -0
  363. package/src/ui/organisms/Dialog/Dialog.test.tsx +435 -0
  364. package/src/ui/organisms/Dialog/Dialog.tsx +79 -0
  365. package/src/ui/organisms/Dialog/DialogClose.tsx +45 -0
  366. package/src/ui/organisms/Dialog/DialogContent.tsx +149 -0
  367. package/src/ui/organisms/Dialog/DialogContext.tsx +25 -0
  368. package/src/ui/organisms/Dialog/DialogDescription.tsx +28 -0
  369. package/src/ui/organisms/Dialog/DialogFooter.tsx +18 -0
  370. package/src/ui/organisms/Dialog/DialogHeader.tsx +18 -0
  371. package/src/ui/organisms/Dialog/DialogProvider.tsx +73 -0
  372. package/src/ui/organisms/Dialog/DialogTitle.tsx +31 -0
  373. package/src/ui/organisms/Dialog/DialogTrigger.tsx +34 -0
  374. package/src/ui/organisms/Dialog/index.ts +24 -0
  375. package/src/ui/organisms/LoginBox/LoginBox.stories.tsx +1 -1
  376. package/src/ui/organisms/Modal/Modal.stories.tsx +2 -2
  377. package/src/ui/organisms/Modal/Modal.test.tsx +1 -1
  378. package/src/ui/organisms/Sidebar/Sidebar.stories.tsx +1 -1
  379. package/src/ui/organisms/Sidebar/Sidebar.test.tsx +5 -3
  380. package/src/ui/organisms/Sidebar/Sidebar.tsx +21 -6
  381. package/src/ui/{molecules → organisms/Sidebar}/SidebarGroup/SidebarGroup.stories.tsx +2 -2
  382. package/src/ui/{molecules → organisms/Sidebar}/SidebarGroup/SidebarGroup.test.tsx +32 -9
  383. package/src/ui/{molecules → organisms/Sidebar}/SidebarGroup/SidebarGroup.tsx +7 -7
  384. package/src/ui/organisms/Sidebar/SidebarHeader/SidebarHeader.test.tsx +66 -0
  385. package/src/ui/{molecules → organisms/Sidebar}/SidebarHeader/SidebarHeader.tsx +1 -2
  386. package/src/ui/{atoms → organisms/Sidebar}/SidebarItem/SidebarItem.stories.tsx +1 -1
  387. package/src/ui/{atoms → organisms/Sidebar}/SidebarItem/SidebarItem.test.tsx +9 -8
  388. package/src/ui/{atoms → organisms/Sidebar}/SidebarItem/SidebarItem.tsx +9 -3
  389. package/src/ui/organisms/Sidebar/index.ts +13 -0
  390. package/src/ui/organisms/Stepper/Stepper.stories.tsx +253 -0
  391. package/src/ui/organisms/Stepper/Stepper.test.tsx +76 -0
  392. package/src/ui/organisms/Stepper/Stepper.tsx +323 -0
  393. package/src/ui/organisms/Stepper/index.ts +2 -0
  394. package/src/ui/organisms/Table/Table.mdx +154 -0
  395. package/src/ui/organisms/Table/Table.stories.tsx +614 -4
  396. package/src/ui/organisms/Table/Table.test.tsx +86 -4
  397. package/src/ui/organisms/Table/Table.tsx +215 -99
  398. package/src/ui/organisms/Table/TableActions/TableActions.stories.tsx +88 -0
  399. package/src/ui/organisms/Table/TableActions/TableActions.test.tsx +64 -0
  400. package/src/ui/organisms/Table/TableActions/TableActions.tsx +71 -0
  401. package/src/ui/organisms/Table/TableActions.tsx +46 -0
  402. package/src/ui/organisms/Table/TableBody.tsx +137 -0
  403. package/src/ui/organisms/Table/TableCell.tsx +36 -0
  404. package/src/ui/organisms/Table/TableContext.tsx +111 -0
  405. package/src/ui/organisms/Table/TableEmptyState.tsx +51 -0
  406. package/src/ui/organisms/Table/TableFilters/TableFilters.stories.tsx +111 -0
  407. package/src/ui/organisms/Table/TableFilters/TableFilters.test.tsx +104 -0
  408. package/src/ui/organisms/Table/TableFilters/TableFilters.tsx +191 -0
  409. package/src/ui/organisms/Table/TableFilters.tsx +39 -0
  410. package/src/ui/organisms/Table/TableHeader.tsx +29 -0
  411. package/src/ui/organisms/Table/TableHeaderCell.tsx +142 -0
  412. package/src/ui/organisms/Table/TableHeaderRow.tsx +72 -0
  413. package/src/ui/organisms/Table/TablePagination/TablePagination.stories.tsx +87 -0
  414. package/src/ui/organisms/Table/TablePagination/TablePagination.test.tsx +90 -0
  415. package/src/ui/organisms/Table/TablePagination/TablePagination.tsx +207 -0
  416. package/src/ui/organisms/Table/TablePagination.tsx +48 -0
  417. package/src/ui/organisms/Table/TableProvider.tsx +429 -0
  418. package/src/ui/organisms/Table/TableRow.tsx +85 -0
  419. package/src/ui/organisms/Table/TableTypes.ts +11 -0
  420. package/src/ui/organisms/Table/index.ts +55 -0
  421. package/src/ui/organisms/Table/useColumnResizing.ts +134 -0
  422. package/src/ui/organisms/Table/useVirtualScrolling.ts +116 -0
  423. package/src/ui/organisms/Timeline/Timeline.stories.tsx +230 -0
  424. package/src/ui/organisms/Timeline/Timeline.test.tsx +47 -0
  425. package/src/ui/organisms/Timeline/Timeline.tsx +179 -0
  426. package/src/ui/organisms/Timeline/index.ts +2 -0
  427. package/src/ui/organisms/Toast/Toast.stories.tsx +169 -0
  428. package/src/ui/organisms/Toast/Toast.test.tsx +537 -0
  429. package/src/ui/organisms/Toast/Toast.tsx +144 -0
  430. package/src/ui/organisms/Toast/ToastContainer.tsx +54 -0
  431. package/src/ui/organisms/Toast/ToastContext.tsx +38 -0
  432. package/src/ui/organisms/Toast/ToastProvider.tsx +56 -0
  433. package/src/ui/organisms/Toast/index.ts +17 -0
  434. package/src/ui/organisms/Toast/useToast.ts +70 -0
  435. package/src/ui/organisms/index.ts +17 -2
  436. package/src/ui/providers/AdvancedThemeProvider.tsx +229 -0
  437. package/src/ui/providers/index.ts +14 -0
  438. package/src/ui/themes/README.md +281 -0
  439. package/src/ui/themes/ThemeBuilder.ts +149 -0
  440. package/src/ui/themes/ThemeRegistry.ts +187 -0
  441. package/src/ui/themes/index.ts +20 -0
  442. package/src/ui/themes/types.ts +53 -0
  443. package/src/ui/themes/utils.ts +70 -0
  444. package/src/ui/tokens/README.md +212 -0
  445. package/src/ui/tokens/TokenVisualizations.tsx +273 -0
  446. package/src/ui/tokens/Tokens.mdx +348 -0
  447. package/src/ui/tokens/animations.ts +157 -0
  448. package/src/ui/tokens/borders.ts +121 -0
  449. package/src/ui/tokens/gradients.ts +154 -0
  450. package/src/ui/tokens/index.ts +57 -0
  451. package/src/ui/tokens/opacity.ts +107 -0
  452. package/src/ui/tokens/radius.ts +107 -0
  453. package/src/ui/tokens/shadows.ts +92 -0
  454. package/src/ui/tokens/tokens.factory.ts +124 -0
  455. package/src/ui/tokens/z-index.ts +113 -0
  456. package/src/ui/utils/index.ts +10 -0
  457. package/src/App.css +0 -42
  458. package/src/App.tsx +0 -35
  459. package/src/index.css +0 -68
  460. package/src/main.tsx +0 -15
@@ -2,7 +2,7 @@ import type { Meta, StoryObj } from "@storybook/react";
2
2
  import NavLink from "./NavLink";
3
3
 
4
4
  const meta: Meta<typeof NavLink> = {
5
- title: "UI/Atoms/NavLink",
5
+ title: "Atoms/NavLink",
6
6
  component: NavLink,
7
7
  parameters: {
8
8
  docs: {
@@ -0,0 +1,157 @@
1
+ import type { Meta, StoryObj } from '@storybook/react';
2
+ import { useState } from 'react';
3
+ import Popover from './Popover';
4
+ import Button from '../Button/Button';
5
+
6
+ const meta: Meta<typeof Popover> = {
7
+ title: 'Atoms/Popover',
8
+ component: Popover,
9
+ tags: ['autodocs'],
10
+ parameters: {
11
+ layout: 'centered',
12
+ },
13
+ argTypes: {
14
+ placement: {
15
+ control: 'select',
16
+ options: [
17
+ 'top',
18
+ 'top-start',
19
+ 'top-end',
20
+ 'bottom',
21
+ 'bottom-start',
22
+ 'bottom-end',
23
+ 'left',
24
+ 'left-start',
25
+ 'left-end',
26
+ 'right',
27
+ 'right-start',
28
+ 'right-end',
29
+ ],
30
+ },
31
+ },
32
+ };
33
+
34
+ export default meta;
35
+ type Story = StoryObj<typeof Popover>;
36
+
37
+ export const Default: Story = {
38
+ render: (args) => (
39
+ <Popover {...args} trigger={<Button>Open Popover</Button>}>
40
+ <p>This is popover content. It can contain any React elements.</p>
41
+ </Popover>
42
+ ),
43
+ };
44
+
45
+ export const WithTitle: Story = {
46
+ render: (args) => (
47
+ <Popover
48
+ {...args}
49
+ trigger={<Button>Open Popover</Button>}
50
+ title="Popover Title"
51
+ >
52
+ <p>This popover has a title and close button.</p>
53
+ </Popover>
54
+ ),
55
+ args: {
56
+ showCloseButton: true,
57
+ },
58
+ };
59
+
60
+ export const Placements: Story = {
61
+ render: () => {
62
+ return (
63
+ <div className="flex flex-col items-center gap-8 p-16">
64
+ <Popover
65
+ trigger={<Button>Top</Button>}
66
+ placement="top"
67
+ title="Top Placement"
68
+ >
69
+ <p>Popover appears above the trigger</p>
70
+ </Popover>
71
+ <div className="flex gap-8">
72
+ <Popover
73
+ trigger={<Button>Left</Button>}
74
+ placement="left"
75
+ title="Left Placement"
76
+ >
77
+ <p>Popover appears to the left</p>
78
+ </Popover>
79
+ <Popover
80
+ trigger={<Button>Right</Button>}
81
+ placement="right"
82
+ title="Right Placement"
83
+ >
84
+ <p>Popover appears to the right</p>
85
+ </Popover>
86
+ </div>
87
+ <Popover
88
+ trigger={<Button>Bottom</Button>}
89
+ placement="bottom"
90
+ title="Bottom Placement"
91
+ >
92
+ <p>Popover appears below the trigger</p>
93
+ </Popover>
94
+ </div>
95
+ );
96
+ },
97
+ };
98
+
99
+ export const RichContent: Story = {
100
+ render: () => (
101
+ <Popover
102
+ trigger={<Button>Open Rich Popover</Button>}
103
+ title="Rich Content Example"
104
+ showCloseButton
105
+ >
106
+ <div className="space-y-2">
107
+ <p className="text-sm">This popover contains rich content:</p>
108
+ <ul className="list-disc list-inside text-sm space-y-1">
109
+ <li>Lists</li>
110
+ <li>Multiple paragraphs</li>
111
+ <li>Any React components</li>
112
+ </ul>
113
+ <div className="mt-4 pt-4 border-t border-gray-200">
114
+ <Button size="sm" variant="primary">
115
+ Action Button
116
+ </Button>
117
+ </div>
118
+ </div>
119
+ </Popover>
120
+ ),
121
+ };
122
+
123
+ export const Controlled: Story = {
124
+ render: () => {
125
+ const [open, setOpen] = useState(false);
126
+ return (
127
+ <div className="space-y-4">
128
+ <Popover
129
+ trigger={<Button>Toggle Popover</Button>}
130
+ open={open}
131
+ onOpenChange={setOpen}
132
+ title="Controlled Popover"
133
+ showCloseButton
134
+ >
135
+ <p>This popover is controlled by external state.</p>
136
+ <p className="mt-2 text-sm text-gray-600">Open: {open ? 'Yes' : 'No'}</p>
137
+ </Popover>
138
+ <Button onClick={() => setOpen(!open)} variant="outline">
139
+ External Toggle
140
+ </Button>
141
+ </div>
142
+ );
143
+ },
144
+ };
145
+
146
+ export const WithoutCloseButton: Story = {
147
+ render: () => (
148
+ <Popover
149
+ trigger={<Button>Open</Button>}
150
+ title="No Close Button"
151
+ showCloseButton={false}
152
+ closeOnClickOutside
153
+ >
154
+ <p>Click outside to close this popover.</p>
155
+ </Popover>
156
+ ),
157
+ };
@@ -0,0 +1,80 @@
1
+ import { describe, it, expect, vi } from 'vitest';
2
+ import { render, screen, fireEvent, waitFor } from '@testing-library/react';
3
+ import Popover from './Popover';
4
+ import Button from '../Button/Button';
5
+
6
+ describe('Popover', () => {
7
+ it('renders trigger correctly', () => {
8
+ render(
9
+ <Popover trigger={<Button>Open</Button>}>
10
+ <p>Content</p>
11
+ </Popover>
12
+ );
13
+ expect(screen.getByText('Open')).toBeInTheDocument();
14
+ });
15
+
16
+ it('opens popover on trigger click', async () => {
17
+ render(
18
+ <Popover trigger={<Button>Open</Button>}>
19
+ <p>Popover Content</p>
20
+ </Popover>
21
+ );
22
+
23
+ const trigger = screen.getByText('Open');
24
+ fireEvent.click(trigger);
25
+
26
+ await waitFor(() => {
27
+ expect(screen.getByText('Popover Content')).toBeInTheDocument();
28
+ });
29
+ });
30
+
31
+ it('closes popover when close button is clicked', async () => {
32
+ render(
33
+ <Popover trigger={<Button>Open</Button>} showCloseButton>
34
+ <p>Popover Content</p>
35
+ </Popover>
36
+ );
37
+
38
+ const trigger = screen.getByText('Open');
39
+ fireEvent.click(trigger);
40
+
41
+ await waitFor(() => {
42
+ expect(screen.getByText('Popover Content')).toBeInTheDocument();
43
+ });
44
+
45
+ const closeButton = screen.getByLabelText('Close popover');
46
+ fireEvent.click(closeButton);
47
+
48
+ await waitFor(() => {
49
+ expect(screen.queryByText('Popover Content')).not.toBeInTheDocument();
50
+ });
51
+ });
52
+
53
+ it('displays title when provided', async () => {
54
+ render(
55
+ <Popover trigger={<Button>Open</Button>} title="Popover Title">
56
+ <p>Content</p>
57
+ </Popover>
58
+ );
59
+
60
+ const trigger = screen.getByText('Open');
61
+ fireEvent.click(trigger);
62
+
63
+ await waitFor(() => {
64
+ expect(screen.getByText('Popover Title')).toBeInTheDocument();
65
+ });
66
+ });
67
+
68
+ it('handles controlled open state', async () => {
69
+ const handleOpenChange = vi.fn();
70
+ render(
71
+ <Popover trigger={<Button>Open</Button>} open={true} onOpenChange={handleOpenChange}>
72
+ <p>Content</p>
73
+ </Popover>
74
+ );
75
+
76
+ await waitFor(() => {
77
+ expect(screen.getByText('Content')).toBeInTheDocument();
78
+ });
79
+ });
80
+ });
@@ -0,0 +1,256 @@
1
+ 'use client';
2
+
3
+ import { useState, useRef, useEffect, type ReactNode } from 'react';
4
+ import { createPortal } from 'react-dom';
5
+ import { X } from 'lucide-react';
6
+ import { getSpacingClass } from '../../tokens/spacing';
7
+ import { getRadiusClass } from '../../tokens/radius';
8
+ import { getShadowClass } from '../../tokens/shadows';
9
+ import { getZIndexClass } from '../../tokens/z-index';
10
+ import { getAnimationClass } from '../../tokens/animations';
11
+ import Button from '../Button/Button';
12
+
13
+ export type PopoverPlacement =
14
+ | 'top'
15
+ | 'top-start'
16
+ | 'top-end'
17
+ | 'bottom'
18
+ | 'bottom-start'
19
+ | 'bottom-end'
20
+ | 'left'
21
+ | 'left-start'
22
+ | 'left-end'
23
+ | 'right'
24
+ | 'right-start'
25
+ | 'right-end';
26
+
27
+ export interface PopoverProps {
28
+ trigger: ReactNode;
29
+ children: ReactNode;
30
+ open?: boolean;
31
+ defaultOpen?: boolean;
32
+ onOpenChange?: (open: boolean) => void;
33
+ placement?: PopoverPlacement;
34
+ showCloseButton?: boolean;
35
+ title?: string;
36
+ closeOnClickOutside?: boolean;
37
+ closeOnEscape?: boolean;
38
+ className?: string;
39
+ triggerClassName?: string;
40
+ contentClassName?: string;
41
+ }
42
+
43
+ /**
44
+ * Popover Component
45
+ *
46
+ * A popover component that displays content in a floating panel.
47
+ * Supports positioning, portal rendering, and keyboard navigation.
48
+ * Follows Atomic Design principles as an Atom component.
49
+ *
50
+ * @example
51
+ * ```tsx
52
+ * <Popover
53
+ * trigger={<Button>Open Popover</Button>}
54
+ * title="Popover Title"
55
+ * >
56
+ * <p>Popover content goes here</p>
57
+ * </Popover>
58
+ * ```
59
+ */
60
+ export default function Popover({
61
+ trigger,
62
+ children,
63
+ open: controlledOpen,
64
+ defaultOpen = false,
65
+ onOpenChange,
66
+ placement = 'bottom',
67
+ showCloseButton = false,
68
+ title,
69
+ closeOnClickOutside = true,
70
+ closeOnEscape = true,
71
+ className = '',
72
+ triggerClassName = '',
73
+ contentClassName = '',
74
+ }: PopoverProps) {
75
+ const [internalOpen, setInternalOpen] = useState(defaultOpen);
76
+ const triggerRef = useRef<HTMLDivElement>(null);
77
+ const popoverRef = useRef<HTMLDivElement>(null);
78
+ const [position, setPosition] = useState({ top: 0, left: 0 });
79
+
80
+ const isControlled = controlledOpen !== undefined;
81
+ const isOpen = isControlled ? controlledOpen : internalOpen;
82
+
83
+ const updatePosition = () => {
84
+ if (!triggerRef.current || !popoverRef.current) return;
85
+
86
+ const triggerRect = triggerRef.current.getBoundingClientRect();
87
+ const popoverRect = popoverRef.current.getBoundingClientRect();
88
+ const scrollY = window.scrollY;
89
+ const scrollX = window.scrollX;
90
+
91
+ let top = 0;
92
+ let left = 0;
93
+
94
+ // Calculate position based on placement
95
+ if (placement.startsWith('top')) {
96
+ top = triggerRect.top + scrollY - popoverRect.height - 8;
97
+ if (placement === 'top-start') left = triggerRect.left + scrollX;
98
+ else if (placement === 'top-end') left = triggerRect.right + scrollX - popoverRect.width;
99
+ else left = triggerRect.left + scrollX + (triggerRect.width - popoverRect.width) / 2;
100
+ } else if (placement.startsWith('bottom')) {
101
+ top = triggerRect.bottom + scrollY + 8;
102
+ if (placement === 'bottom-start') left = triggerRect.left + scrollX;
103
+ else if (placement === 'bottom-end') left = triggerRect.right + scrollX - popoverRect.width;
104
+ else left = triggerRect.left + scrollX + (triggerRect.width - popoverRect.width) / 2;
105
+ } else if (placement.startsWith('left')) {
106
+ left = triggerRect.left + scrollX - popoverRect.width - 8;
107
+ if (placement === 'left-start') top = triggerRect.top + scrollY;
108
+ else if (placement === 'left-end') top = triggerRect.bottom + scrollY - popoverRect.height;
109
+ else top = triggerRect.top + scrollY + (triggerRect.height - popoverRect.height) / 2;
110
+ } else if (placement.startsWith('right')) {
111
+ left = triggerRect.right + scrollX + 8;
112
+ if (placement === 'right-start') top = triggerRect.top + scrollY;
113
+ else if (placement === 'right-end') top = triggerRect.bottom + scrollY - popoverRect.height;
114
+ else top = triggerRect.top + scrollY + (triggerRect.height - popoverRect.height) / 2;
115
+ }
116
+
117
+ // Keep within viewport
118
+ const padding = 8;
119
+ top = Math.max(padding, Math.min(top, window.innerHeight + scrollY - popoverRect.height - padding));
120
+ left = Math.max(padding, Math.min(left, window.innerWidth + scrollX - popoverRect.width - padding));
121
+
122
+ setPosition({ top, left });
123
+ };
124
+
125
+ useEffect(() => {
126
+ if (isOpen) {
127
+ updatePosition();
128
+ const handleResize = () => updatePosition();
129
+ const handleScroll = () => updatePosition();
130
+ window.addEventListener('resize', handleResize);
131
+ window.addEventListener('scroll', handleScroll, true);
132
+ return () => {
133
+ window.removeEventListener('resize', handleResize);
134
+ window.removeEventListener('scroll', handleScroll, true);
135
+ };
136
+ }
137
+ }, [isOpen, placement]);
138
+
139
+ useEffect(() => {
140
+ if (isOpen && popoverRef.current) {
141
+ // Small delay to ensure DOM is ready
142
+ setTimeout(updatePosition, 0);
143
+ }
144
+ }, [isOpen]);
145
+
146
+ const handleOpenChange = (newOpen: boolean) => {
147
+ if (!isControlled) {
148
+ setInternalOpen(newOpen);
149
+ }
150
+ onOpenChange?.(newOpen);
151
+ };
152
+
153
+ const handleClose = () => {
154
+ handleOpenChange(false);
155
+ };
156
+
157
+ useEffect(() => {
158
+ if (isOpen && closeOnEscape) {
159
+ const handleEscape = (e: KeyboardEvent) => {
160
+ if (e.key === 'Escape') {
161
+ handleClose();
162
+ }
163
+ };
164
+ document.addEventListener('keydown', handleEscape);
165
+ return () => document.removeEventListener('keydown', handleEscape);
166
+ }
167
+ }, [isOpen, closeOnEscape]);
168
+
169
+ useEffect(() => {
170
+ if (isOpen && closeOnClickOutside) {
171
+ const handleClickOutside = (e: MouseEvent) => {
172
+ if (
173
+ popoverRef.current &&
174
+ triggerRef.current &&
175
+ !popoverRef.current.contains(e.target as Node) &&
176
+ !triggerRef.current.contains(e.target as Node)
177
+ ) {
178
+ handleClose();
179
+ }
180
+ };
181
+ document.addEventListener('mousedown', handleClickOutside);
182
+ return () => document.removeEventListener('mousedown', handleClickOutside);
183
+ }
184
+ }, [isOpen, closeOnClickOutside]);
185
+
186
+ const popoverContent = isOpen ? (
187
+ <div
188
+ ref={popoverRef}
189
+ className={`
190
+ absolute
191
+ ${getZIndexClass('popover')}
192
+ bg-white
193
+ ${getRadiusClass('lg')}
194
+ ${getShadowClass('lg')}
195
+ border
196
+ border-gray-200
197
+ min-w-[200px]
198
+ max-w-[400px]
199
+ ${getAnimationClass('base')}
200
+ ${contentClassName}
201
+ `}
202
+ style={{
203
+ top: `${position.top}px`,
204
+ left: `${position.left}px`,
205
+ }}
206
+ role="dialog"
207
+ aria-modal="false"
208
+ >
209
+ {(title || showCloseButton) && (
210
+ <div className={`
211
+ flex
212
+ items-center
213
+ justify-between
214
+ ${getSpacingClass('base', 'px')}
215
+ ${getSpacingClass('md', 'py')}
216
+ border-b
217
+ border-gray-200
218
+ `}>
219
+ {title && (
220
+ <h3 className="text-sm font-semibold text-gray-900">{title}</h3>
221
+ )}
222
+ {showCloseButton && (
223
+ <Button
224
+ variant="ghost"
225
+ size="sm"
226
+ onClick={handleClose}
227
+ className="h-auto p-1"
228
+ aria-label="Close popover"
229
+ >
230
+ <X className="h-4 w-4" />
231
+ </Button>
232
+ )}
233
+ </div>
234
+ )}
235
+ <div className={`
236
+ ${getSpacingClass('base', 'p')}
237
+ ${title || showCloseButton ? '' : getSpacingClass('md', 'p')}
238
+ `}>
239
+ {children}
240
+ </div>
241
+ </div>
242
+ ) : null;
243
+
244
+ return (
245
+ <div className={`inline-block ${className}`}>
246
+ <div
247
+ ref={triggerRef}
248
+ className={triggerClassName}
249
+ onClick={() => handleOpenChange(!isOpen)}
250
+ >
251
+ {trigger}
252
+ </div>
253
+ {typeof window !== 'undefined' && createPortal(popoverContent, document.body)}
254
+ </div>
255
+ );
256
+ }
@@ -0,0 +1,2 @@
1
+ export { default } from './Popover';
2
+ export type { PopoverProps, PopoverPlacement } from './Popover';
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Progress Component Styles
3
+ *
4
+ * CSS animations for indeterminate progress bar.
5
+ */
6
+
7
+ @keyframes progress-indeterminate {
8
+ 0% {
9
+ transform: translateX(-100%);
10
+ }
11
+ 50% {
12
+ transform: translateX(0%);
13
+ }
14
+ 100% {
15
+ transform: translateX(300%);
16
+ }
17
+ }
@@ -0,0 +1,170 @@
1
+ import type { Meta, StoryObj } from '@storybook/react';
2
+ import React from 'react';
3
+ import Progress from './Progress';
4
+
5
+ const meta: Meta<typeof Progress> = {
6
+ title: 'Atoms/Progress',
7
+ component: Progress,
8
+ parameters: {
9
+ docs: {
10
+ description: {
11
+ component: 'A progress bar component for displaying progress or loading states. Supports both determinate (with value) and indeterminate (without value) modes. Fully accessible with ARIA attributes.',
12
+ },
13
+ },
14
+ },
15
+ tags: ['autodocs'],
16
+ argTypes: {
17
+ value: {
18
+ control: { type: 'range', min: 0, max: 100, step: 1 },
19
+ description: 'Progress value (0-100). Omit for indeterminate mode.',
20
+ },
21
+ max: {
22
+ control: 'number',
23
+ description: 'Maximum value (default: 100)',
24
+ },
25
+ variant: {
26
+ control: 'select',
27
+ options: ['primary', 'secondary', 'success', 'error', 'warning', 'info'],
28
+ description: 'Color variant of the progress bar',
29
+ },
30
+ size: {
31
+ control: 'select',
32
+ options: ['sm', 'md', 'lg'],
33
+ description: 'Size of the progress bar',
34
+ },
35
+ showLabel: {
36
+ control: 'boolean',
37
+ description: 'Whether to show the label and percentage',
38
+ },
39
+ label: {
40
+ control: 'text',
41
+ description: 'Custom label text',
42
+ },
43
+ },
44
+ };
45
+
46
+ export default meta;
47
+ type Story = StoryObj<typeof Progress>;
48
+
49
+ export const Default: Story = {
50
+ args: {
51
+ value: 50,
52
+ variant: 'primary',
53
+ size: 'md',
54
+ },
55
+ };
56
+
57
+ export const WithLabel: Story = {
58
+ args: {
59
+ value: 75,
60
+ variant: 'primary',
61
+ showLabel: true,
62
+ label: 'Upload Progress',
63
+ },
64
+ };
65
+
66
+ export const Indeterminate: Story = {
67
+ args: {
68
+ variant: 'primary',
69
+ size: 'md',
70
+ },
71
+ parameters: {
72
+ docs: {
73
+ description: {
74
+ story: 'Indeterminate progress bar for loading states where progress cannot be determined.',
75
+ },
76
+ },
77
+ },
78
+ };
79
+
80
+ export const Variants: Story = {
81
+ render: () => (
82
+ <div className="space-y-4 w-full max-w-md">
83
+ <Progress value={60} variant="primary" showLabel label="Primary" />
84
+ <Progress value={60} variant="secondary" showLabel label="Secondary" />
85
+ <Progress value={60} variant="success" showLabel label="Success" />
86
+ <Progress value={60} variant="error" showLabel label="Error" />
87
+ <Progress value={60} variant="warning" showLabel label="Warning" />
88
+ <Progress value={60} variant="info" showLabel label="Info" />
89
+ </div>
90
+ ),
91
+ parameters: {
92
+ docs: {
93
+ description: {
94
+ story: 'All available color variants of the progress bar.',
95
+ },
96
+ },
97
+ },
98
+ };
99
+
100
+ export const Sizes: Story = {
101
+ render: () => (
102
+ <div className="space-y-4 w-full max-w-md">
103
+ <Progress value={50} size="sm" showLabel label="Small" />
104
+ <Progress value={50} size="md" showLabel label="Medium" />
105
+ <Progress value={50} size="lg" showLabel label="Large" />
106
+ </div>
107
+ ),
108
+ parameters: {
109
+ docs: {
110
+ description: {
111
+ story: 'Different sizes of the progress bar.',
112
+ },
113
+ },
114
+ },
115
+ };
116
+
117
+ export const States: Story = {
118
+ render: () => (
119
+ <div className="space-y-4 w-full max-w-md">
120
+ <Progress value={0} showLabel label="Not Started (0%)" />
121
+ <Progress value={25} showLabel label="In Progress (25%)" />
122
+ <Progress value={50} showLabel label="Halfway (50%)" />
123
+ <Progress value={75} showLabel label="Almost Done (75%)" />
124
+ <Progress value={100} showLabel label="Complete (100%)" />
125
+ <Progress variant="primary" showLabel label="Indeterminate" />
126
+ </div>
127
+ ),
128
+ parameters: {
129
+ docs: {
130
+ description: {
131
+ story: 'Different progress states from 0% to 100%, plus indeterminate mode.',
132
+ },
133
+ },
134
+ },
135
+ };
136
+
137
+ export const Animated: Story = {
138
+ render: () => {
139
+ const [progress, setProgress] = React.useState(0);
140
+
141
+ React.useEffect(() => {
142
+ const timer = setInterval(() => {
143
+ setProgress((prev) => {
144
+ if (prev >= 100) {
145
+ return 0;
146
+ }
147
+ return prev + 10;
148
+ });
149
+ }, 500);
150
+
151
+ return () => clearInterval(timer);
152
+ }, []);
153
+
154
+ return (
155
+ <div className="space-y-4 w-full max-w-md">
156
+ <Progress value={progress} showLabel label="Animated Progress" />
157
+ <p className="text-sm text-gray-600">
158
+ Progress automatically updates every 500ms
159
+ </p>
160
+ </div>
161
+ );
162
+ },
163
+ parameters: {
164
+ docs: {
165
+ description: {
166
+ story: 'Animated progress bar that updates automatically.',
167
+ },
168
+ },
169
+ },
170
+ };