lerelais-front-library 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 (359) hide show
  1. package/.cursor/skills/project-structure/SKILL.md +51 -0
  2. package/.cursor/skills/storybook-react/SKILL.md +60 -0
  3. package/.cursor/skills/testing-react/SKILL.md +52 -0
  4. package/README.md +93 -0
  5. package/index.html +18 -0
  6. package/package.json +34 -0
  7. package/src/App.css +49 -0
  8. package/src/App.tsx +366 -0
  9. package/src/assets/icons/alert-triangle.svg +7 -0
  10. package/src/assets/icons/arrow-right.svg +5 -0
  11. package/src/assets/icons/bell.svg +6 -0
  12. package/src/assets/icons/chevron-down.svg +5 -0
  13. package/src/assets/icons/chevron-right.svg +5 -0
  14. package/src/assets/icons/clock-muted.svg +10 -0
  15. package/src/assets/icons/clock.svg +11 -0
  16. package/src/assets/icons/close.svg +5 -0
  17. package/src/assets/icons/core-camera.svg +5 -0
  18. package/src/assets/icons/core-check-sm.svg +5 -0
  19. package/src/assets/icons/core-check-white.svg +5 -0
  20. package/src/assets/icons/core-check.svg +5 -0
  21. package/src/assets/icons/core-chevron.svg +5 -0
  22. package/src/assets/icons/core-dot.svg +3 -0
  23. package/src/assets/icons/core-lock-form.svg +5 -0
  24. package/src/assets/icons/core-lock.svg +5 -0
  25. package/src/assets/icons/core-map-pin.svg +5 -0
  26. package/src/assets/icons/core-package-lg.svg +5 -0
  27. package/src/assets/icons/core-package.svg +5 -0
  28. package/src/assets/icons/core-pin-info.svg +6 -0
  29. package/src/assets/icons/core-pin-value.svg +5 -0
  30. package/src/assets/icons/core-pin-white.svg +5 -0
  31. package/src/assets/icons/core-plus.svg +5 -0
  32. package/src/assets/icons/core-search-dark.svg +5 -0
  33. package/src/assets/icons/core-search.svg +5 -0
  34. package/src/assets/icons/core-store.svg +9 -0
  35. package/src/assets/icons/core-x.svg +5 -0
  36. package/src/assets/icons/heart.svg +5 -0
  37. package/src/assets/icons/logout.svg +7 -0
  38. package/src/assets/icons/map-pin.svg +5 -0
  39. package/src/assets/icons/package-read.svg +8 -0
  40. package/src/assets/icons/package-white.svg +8 -0
  41. package/src/assets/icons/package.svg +8 -0
  42. package/src/assets/icons/plus.svg +6 -0
  43. package/src/assets/icons/settings.svg +6 -0
  44. package/src/assets/icons/switch-off.svg +19 -0
  45. package/src/assets/icons/switch-on.svg +19 -0
  46. package/src/assets/icons/unread-dot.svg +3 -0
  47. package/src/assets/icons/upload-cloud.svg +5 -0
  48. package/src/assets/icons/user.svg +6 -0
  49. package/src/assets/icons.ts +41 -0
  50. package/src/components/Accordion/Accordion.module.css +34 -0
  51. package/src/components/Accordion/Accordion.test.tsx +20 -0
  52. package/src/components/Accordion/Accordion.tsx +38 -0
  53. package/src/components/Accordion/index.ts +1 -0
  54. package/src/components/ActionCard/ActionCard.module.css +50 -0
  55. package/src/components/ActionCard/ActionCard.test.tsx +15 -0
  56. package/src/components/ActionCard/ActionCard.tsx +33 -0
  57. package/src/components/ActionCard/index.ts +1 -0
  58. package/src/components/Alert/Alert.module.css +47 -0
  59. package/src/components/Alert/Alert.test.tsx +14 -0
  60. package/src/components/Alert/Alert.tsx +27 -0
  61. package/src/components/Alert/index.ts +1 -0
  62. package/src/components/Avatar/Avatar.module.css +37 -0
  63. package/src/components/Avatar/Avatar.test.tsx +9 -0
  64. package/src/components/Avatar/Avatar.tsx +18 -0
  65. package/src/components/Avatar/index.ts +1 -0
  66. package/src/components/Badge/Badge.module.css +37 -0
  67. package/src/components/Badge/Badge.test.tsx +14 -0
  68. package/src/components/Badge/Badge.tsx +21 -0
  69. package/src/components/Badge/index.ts +1 -0
  70. package/src/components/BarChart/BarChart.module.css +57 -0
  71. package/src/components/BarChart/BarChart.test.tsx +18 -0
  72. package/src/components/BarChart/BarChart.tsx +47 -0
  73. package/src/components/BarChart/index.ts +1 -0
  74. package/src/components/BenefitsCard/BenefitsCard.module.css +44 -0
  75. package/src/components/BenefitsCard/BenefitsCard.test.tsx +10 -0
  76. package/src/components/BenefitsCard/BenefitsCard.tsx +33 -0
  77. package/src/components/BenefitsCard/index.ts +1 -0
  78. package/src/components/BottomNavItem/BottomNavItem.module.css +24 -0
  79. package/src/components/BottomNavItem/BottomNavItem.test.tsx +20 -0
  80. package/src/components/BottomNavItem/BottomNavItem.tsx +23 -0
  81. package/src/components/BottomNavItem/index.ts +1 -0
  82. package/src/components/Breadcrumb/Breadcrumb.module.css +31 -0
  83. package/src/components/Breadcrumb/Breadcrumb.test.tsx +29 -0
  84. package/src/components/Breadcrumb/Breadcrumb.tsx +36 -0
  85. package/src/components/Breadcrumb/index.ts +1 -0
  86. package/src/components/Button/Button.module.css +61 -0
  87. package/src/components/Button/Button.test.tsx +34 -0
  88. package/src/components/Button/Button.tsx +24 -0
  89. package/src/components/Button/index.ts +1 -0
  90. package/src/components/Checkbox/Checkbox.module.css +53 -0
  91. package/src/components/Checkbox/Checkbox.test.tsx +20 -0
  92. package/src/components/Checkbox/Checkbox.tsx +20 -0
  93. package/src/components/Checkbox/index.ts +1 -0
  94. package/src/components/ConfirmModal/ConfirmModal.module.css +69 -0
  95. package/src/components/ConfirmModal/ConfirmModal.test.tsx +25 -0
  96. package/src/components/ConfirmModal/ConfirmModal.tsx +50 -0
  97. package/src/components/ConfirmModal/index.ts +1 -0
  98. package/src/components/CoreButton/CoreButton.module.css +71 -0
  99. package/src/components/CoreButton/CoreButton.test.tsx +24 -0
  100. package/src/components/CoreButton/CoreButton.tsx +27 -0
  101. package/src/components/CoreButton/index.ts +1 -0
  102. package/src/components/CoreField/CoreField.module.css +31 -0
  103. package/src/components/CoreField/CoreField.test.tsx +15 -0
  104. package/src/components/CoreField/CoreField.tsx +18 -0
  105. package/src/components/CoreField/index.ts +1 -0
  106. package/src/components/CoreSelect/CoreSelect.module.css +37 -0
  107. package/src/components/CoreSelect/CoreSelect.test.tsx +22 -0
  108. package/src/components/CoreSelect/CoreSelect.tsx +29 -0
  109. package/src/components/CoreSelect/index.ts +1 -0
  110. package/src/components/CoreTabs/CoreTabs.module.css +41 -0
  111. package/src/components/CoreTabs/CoreTabs.test.tsx +18 -0
  112. package/src/components/CoreTabs/CoreTabs.tsx +67 -0
  113. package/src/components/CoreTabs/index.ts +1 -0
  114. package/src/components/DashboardParcelRow/DashboardParcelRow.module.css +61 -0
  115. package/src/components/DashboardParcelRow/DashboardParcelRow.test.tsx +37 -0
  116. package/src/components/DashboardParcelRow/DashboardParcelRow.tsx +41 -0
  117. package/src/components/DashboardParcelRow/index.ts +1 -0
  118. package/src/components/DataFiltersToolbar/DataFiltersToolbar.module.css +29 -0
  119. package/src/components/DataFiltersToolbar/DataFiltersToolbar.test.tsx +15 -0
  120. package/src/components/DataFiltersToolbar/DataFiltersToolbar.tsx +22 -0
  121. package/src/components/DataFiltersToolbar/index.ts +1 -0
  122. package/src/components/DataSearchBar/DataSearchBar.module.css +28 -0
  123. package/src/components/DataSearchBar/DataSearchBar.test.tsx +15 -0
  124. package/src/components/DataSearchBar/DataSearchBar.tsx +15 -0
  125. package/src/components/DataSearchBar/index.ts +1 -0
  126. package/src/components/DataTable/DataTable.module.css +57 -0
  127. package/src/components/DataTable/DataTable.test.tsx +12 -0
  128. package/src/components/DataTable/DataTable.tsx +67 -0
  129. package/src/components/DataTable/index.ts +1 -0
  130. package/src/components/Divider/Divider.module.css +29 -0
  131. package/src/components/Divider/Divider.test.tsx +9 -0
  132. package/src/components/Divider/Divider.tsx +21 -0
  133. package/src/components/Divider/index.ts +1 -0
  134. package/src/components/DropdownMenu/DropdownMenu.module.css +45 -0
  135. package/src/components/DropdownMenu/DropdownMenu.test.tsx +21 -0
  136. package/src/components/DropdownMenu/DropdownMenu.tsx +45 -0
  137. package/src/components/DropdownMenu/index.ts +1 -0
  138. package/src/components/EmptyState/EmptyState.module.css +52 -0
  139. package/src/components/EmptyState/EmptyState.test.tsx +20 -0
  140. package/src/components/EmptyState/EmptyState.tsx +33 -0
  141. package/src/components/EmptyState/index.ts +1 -0
  142. package/src/components/FaqItem/FaqItem.module.css +47 -0
  143. package/src/components/FaqItem/FaqItem.test.tsx +14 -0
  144. package/src/components/FaqItem/FaqItem.tsx +28 -0
  145. package/src/components/FaqItem/index.ts +1 -0
  146. package/src/components/FavoriteRelayCard/FavoriteRelayCard.module.css +83 -0
  147. package/src/components/FavoriteRelayCard/FavoriteRelayCard.test.tsx +37 -0
  148. package/src/components/FavoriteRelayCard/FavoriteRelayCard.tsx +58 -0
  149. package/src/components/FavoriteRelayCard/index.ts +1 -0
  150. package/src/components/FeatureCard/FeatureCard.module.css +62 -0
  151. package/src/components/FeatureCard/FeatureCard.test.tsx +10 -0
  152. package/src/components/FeatureCard/FeatureCard.tsx +30 -0
  153. package/src/components/FeatureCard/index.ts +1 -0
  154. package/src/components/FileUpload/FileUpload.module.css +41 -0
  155. package/src/components/FileUpload/FileUpload.test.tsx +22 -0
  156. package/src/components/FileUpload/FileUpload.tsx +26 -0
  157. package/src/components/FileUpload/index.ts +1 -0
  158. package/src/components/FilterPill/FilterPill.module.css +18 -0
  159. package/src/components/FilterPill/FilterPill.test.tsx +19 -0
  160. package/src/components/FilterPill/FilterPill.tsx +20 -0
  161. package/src/components/FilterPill/index.ts +1 -0
  162. package/src/components/Footer/Footer.module.css +57 -0
  163. package/src/components/Footer/Footer.test.tsx +10 -0
  164. package/src/components/Footer/Footer.tsx +63 -0
  165. package/src/components/Footer/index.ts +1 -0
  166. package/src/components/Icon/Icon.tsx +20 -0
  167. package/src/components/Icon/index.ts +1 -0
  168. package/src/components/InfoRow/InfoRow.module.css +33 -0
  169. package/src/components/InfoRow/InfoRow.test.tsx +9 -0
  170. package/src/components/InfoRow/InfoRow.tsx +21 -0
  171. package/src/components/InfoRow/index.ts +1 -0
  172. package/src/components/LinkButton/LinkButton.module.css +22 -0
  173. package/src/components/LinkButton/LinkButton.test.tsx +9 -0
  174. package/src/components/LinkButton/LinkButton.tsx +17 -0
  175. package/src/components/LinkButton/index.ts +1 -0
  176. package/src/components/LocationCard/LocationCard.module.css +61 -0
  177. package/src/components/LocationCard/LocationCard.test.tsx +9 -0
  178. package/src/components/LocationCard/LocationCard.tsx +27 -0
  179. package/src/components/LocationCard/index.ts +1 -0
  180. package/src/components/Logo/Logo.module.css +30 -0
  181. package/src/components/Logo/Logo.tsx +18 -0
  182. package/src/components/Logo/index.ts +1 -0
  183. package/src/components/MetricCard/MetricCard.module.css +27 -0
  184. package/src/components/MetricCard/MetricCard.test.tsx +10 -0
  185. package/src/components/MetricCard/MetricCard.tsx +19 -0
  186. package/src/components/MetricCard/index.ts +1 -0
  187. package/src/components/Navbar/Navbar.module.css +87 -0
  188. package/src/components/Navbar/Navbar.test.tsx +21 -0
  189. package/src/components/Navbar/Navbar.tsx +77 -0
  190. package/src/components/Navbar/index.ts +1 -0
  191. package/src/components/NotificationItem/NotificationItem.module.css +73 -0
  192. package/src/components/NotificationItem/NotificationItem.test.tsx +22 -0
  193. package/src/components/NotificationItem/NotificationItem.tsx +30 -0
  194. package/src/components/NotificationItem/index.ts +1 -0
  195. package/src/components/NotificationRow/NotificationRow.module.css +49 -0
  196. package/src/components/NotificationRow/NotificationRow.test.tsx +15 -0
  197. package/src/components/NotificationRow/NotificationRow.tsx +26 -0
  198. package/src/components/NotificationRow/index.ts +1 -0
  199. package/src/components/OutcomeModal/OutcomeModal.module.css +101 -0
  200. package/src/components/OutcomeModal/OutcomeModal.test.tsx +15 -0
  201. package/src/components/OutcomeModal/OutcomeModal.tsx +45 -0
  202. package/src/components/OutcomeModal/index.ts +1 -0
  203. package/src/components/Pagination/Pagination.module.css +27 -0
  204. package/src/components/Pagination/Pagination.test.tsx +25 -0
  205. package/src/components/Pagination/Pagination.tsx +41 -0
  206. package/src/components/Pagination/index.ts +1 -0
  207. package/src/components/ParcelCard/ParcelCard.module.css +34 -0
  208. package/src/components/ParcelCard/ParcelCard.test.tsx +17 -0
  209. package/src/components/ParcelCard/ParcelCard.tsx +21 -0
  210. package/src/components/ParcelCard/index.ts +1 -0
  211. package/src/components/ParcelRow/ParcelRow.module.css +25 -0
  212. package/src/components/ParcelRow/ParcelRow.test.tsx +18 -0
  213. package/src/components/ParcelRow/ParcelRow.tsx +31 -0
  214. package/src/components/ParcelRow/index.ts +1 -0
  215. package/src/components/ParcelTimeline/ParcelTimeline.module.css +68 -0
  216. package/src/components/ParcelTimeline/ParcelTimeline.test.tsx +17 -0
  217. package/src/components/ParcelTimeline/ParcelTimeline.tsx +33 -0
  218. package/src/components/ParcelTimeline/index.ts +1 -0
  219. package/src/components/PhotoUpload/PhotoUpload.module.css +39 -0
  220. package/src/components/PhotoUpload/PhotoUpload.test.tsx +16 -0
  221. package/src/components/PhotoUpload/PhotoUpload.tsx +29 -0
  222. package/src/components/PhotoUpload/index.ts +1 -0
  223. package/src/components/ProcessBadge/ProcessBadge.module.css +29 -0
  224. package/src/components/ProcessBadge/ProcessBadge.test.tsx +9 -0
  225. package/src/components/ProcessBadge/ProcessBadge.tsx +19 -0
  226. package/src/components/ProcessBadge/index.ts +1 -0
  227. package/src/components/ProgressBar/ProgressBar.module.css +56 -0
  228. package/src/components/ProgressBar/ProgressBar.test.tsx +18 -0
  229. package/src/components/ProgressBar/ProgressBar.tsx +33 -0
  230. package/src/components/ProgressBar/index.ts +1 -0
  231. package/src/components/QrScanner/QrScanner.module.css +50 -0
  232. package/src/components/QrScanner/QrScanner.test.tsx +20 -0
  233. package/src/components/QrScanner/QrScanner.tsx +27 -0
  234. package/src/components/QrScanner/index.ts +1 -0
  235. package/src/components/QuestionSearch/QuestionSearch.module.css +28 -0
  236. package/src/components/QuestionSearch/QuestionSearch.test.tsx +15 -0
  237. package/src/components/QuestionSearch/QuestionSearch.tsx +26 -0
  238. package/src/components/QuestionSearch/index.ts +1 -0
  239. package/src/components/QuickActionCard/QuickActionCard.module.css +31 -0
  240. package/src/components/QuickActionCard/QuickActionCard.test.tsx +20 -0
  241. package/src/components/QuickActionCard/QuickActionCard.tsx +22 -0
  242. package/src/components/QuickActionCard/index.ts +1 -0
  243. package/src/components/Radio/Radio.module.css +53 -0
  244. package/src/components/Radio/Radio.test.tsx +20 -0
  245. package/src/components/Radio/Radio.tsx +20 -0
  246. package/src/components/Radio/index.ts +1 -0
  247. package/src/components/RelayCard/RelayCard.module.css +38 -0
  248. package/src/components/RelayCard/RelayCard.test.tsx +22 -0
  249. package/src/components/RelayCard/RelayCard.tsx +31 -0
  250. package/src/components/RelayCard/index.ts +1 -0
  251. package/src/components/RelayResultCard/RelayResultCard.module.css +82 -0
  252. package/src/components/RelayResultCard/RelayResultCard.test.tsx +10 -0
  253. package/src/components/RelayResultCard/RelayResultCard.tsx +34 -0
  254. package/src/components/RelayResultCard/index.ts +1 -0
  255. package/src/components/ResetPasswordCard/ResetPasswordCard.module.css +102 -0
  256. package/src/components/ResetPasswordCard/ResetPasswordCard.test.tsx +16 -0
  257. package/src/components/ResetPasswordCard/ResetPasswordCard.tsx +45 -0
  258. package/src/components/ResetPasswordCard/index.ts +1 -0
  259. package/src/components/SearchBar/SearchBar.module.css +33 -0
  260. package/src/components/SearchBar/SearchBar.test.tsx +19 -0
  261. package/src/components/SearchBar/SearchBar.tsx +18 -0
  262. package/src/components/SearchBar/index.ts +1 -0
  263. package/src/components/Select/Select.module.css +64 -0
  264. package/src/components/Select/Select.test.tsx +24 -0
  265. package/src/components/Select/Select.tsx +60 -0
  266. package/src/components/Select/index.ts +1 -0
  267. package/src/components/ShipmentStatus/ShipmentStatus.module.css +41 -0
  268. package/src/components/ShipmentStatus/ShipmentStatus.test.tsx +14 -0
  269. package/src/components/ShipmentStatus/ShipmentStatus.tsx +52 -0
  270. package/src/components/ShipmentStatus/index.ts +1 -0
  271. package/src/components/Sidebar/Sidebar.module.css +79 -0
  272. package/src/components/Sidebar/Sidebar.test.tsx +21 -0
  273. package/src/components/Sidebar/Sidebar.tsx +98 -0
  274. package/src/components/Sidebar/index.ts +1 -0
  275. package/src/components/SidebarNavItem/SidebarNavItem.module.css +21 -0
  276. package/src/components/SidebarNavItem/SidebarNavItem.test.tsx +20 -0
  277. package/src/components/SidebarNavItem/SidebarNavItem.tsx +22 -0
  278. package/src/components/SidebarNavItem/index.ts +1 -0
  279. package/src/components/Skeleton/Skeleton.module.css +22 -0
  280. package/src/components/Skeleton/Skeleton.test.tsx +9 -0
  281. package/src/components/Skeleton/Skeleton.tsx +13 -0
  282. package/src/components/Skeleton/index.ts +1 -0
  283. package/src/components/StatCard/StatCard.module.css +22 -0
  284. package/src/components/StatCard/StatCard.test.tsx +9 -0
  285. package/src/components/StatCard/StatCard.tsx +19 -0
  286. package/src/components/StatCard/index.ts +1 -0
  287. package/src/components/StatusSummary/StatusSummary.module.css +43 -0
  288. package/src/components/StatusSummary/StatusSummary.test.tsx +9 -0
  289. package/src/components/StatusSummary/StatusSummary.tsx +32 -0
  290. package/src/components/StatusSummary/index.ts +1 -0
  291. package/src/components/StepCard/StepCard.module.css +48 -0
  292. package/src/components/StepCard/StepCard.test.tsx +9 -0
  293. package/src/components/StepCard/StepCard.tsx +27 -0
  294. package/src/components/StepCard/index.ts +1 -0
  295. package/src/components/Stepper/Stepper.module.css +66 -0
  296. package/src/components/Stepper/Stepper.test.tsx +20 -0
  297. package/src/components/Stepper/Stepper.tsx +39 -0
  298. package/src/components/Stepper/index.ts +1 -0
  299. package/src/components/StepsList/StepsList.module.css +35 -0
  300. package/src/components/StepsList/StepsList.test.tsx +10 -0
  301. package/src/components/StepsList/StepsList.tsx +24 -0
  302. package/src/components/StepsList/index.ts +1 -0
  303. package/src/components/SuccessFeedback/SuccessFeedback.module.css +42 -0
  304. package/src/components/SuccessFeedback/SuccessFeedback.test.tsx +9 -0
  305. package/src/components/SuccessFeedback/SuccessFeedback.tsx +21 -0
  306. package/src/components/SuccessFeedback/index.ts +1 -0
  307. package/src/components/Switch/Switch.module.css +57 -0
  308. package/src/components/Switch/Switch.test.tsx +20 -0
  309. package/src/components/Switch/Switch.tsx +22 -0
  310. package/src/components/Switch/index.ts +1 -0
  311. package/src/components/Tabs/Tabs.module.css +26 -0
  312. package/src/components/Tabs/Tabs.test.tsx +34 -0
  313. package/src/components/Tabs/Tabs.tsx +38 -0
  314. package/src/components/Tabs/index.ts +1 -0
  315. package/src/components/Tag/Tag.module.css +39 -0
  316. package/src/components/Tag/Tag.test.tsx +24 -0
  317. package/src/components/Tag/Tag.tsx +25 -0
  318. package/src/components/Tag/index.ts +1 -0
  319. package/src/components/TextField/TextField.module.css +55 -0
  320. package/src/components/TextField/TextField.test.tsx +24 -0
  321. package/src/components/TextField/TextField.tsx +37 -0
  322. package/src/components/TextField/index.ts +1 -0
  323. package/src/components/Toast/Toast.module.css +72 -0
  324. package/src/components/Toast/Toast.test.tsx +20 -0
  325. package/src/components/Toast/Toast.tsx +32 -0
  326. package/src/components/Toast/index.ts +1 -0
  327. package/src/components/Tooltip/Tooltip.module.css +37 -0
  328. package/src/components/Tooltip/Tooltip.test.tsx +22 -0
  329. package/src/components/Tooltip/Tooltip.tsx +20 -0
  330. package/src/components/Tooltip/index.ts +1 -0
  331. package/src/components/TrackingBadge/TrackingBadge.module.css +10 -0
  332. package/src/components/TrackingBadge/TrackingBadge.test.tsx +9 -0
  333. package/src/components/TrackingBadge/TrackingBadge.tsx +9 -0
  334. package/src/components/TrackingBadge/index.ts +1 -0
  335. package/src/components/TrackingCard/TrackingCard.module.css +128 -0
  336. package/src/components/TrackingCard/TrackingCard.test.tsx +10 -0
  337. package/src/components/TrackingCard/TrackingCard.tsx +58 -0
  338. package/src/components/TrackingCard/index.ts +1 -0
  339. package/src/components/TrackingSearch/TrackingSearch.module.css +35 -0
  340. package/src/components/TrackingSearch/TrackingSearch.test.tsx +15 -0
  341. package/src/components/TrackingSearch/TrackingSearch.tsx +24 -0
  342. package/src/components/TrackingSearch/index.ts +1 -0
  343. package/src/components/ValueCard/ValueCard.module.css +38 -0
  344. package/src/components/ValueCard/ValueCard.test.tsx +9 -0
  345. package/src/components/ValueCard/ValueCard.tsx +24 -0
  346. package/src/components/ValueCard/index.ts +1 -0
  347. package/src/lib/cn.ts +3 -0
  348. package/src/main.tsx +10 -0
  349. package/src/styles/global.css +36 -0
  350. package/src/styles/tokens.css +61 -0
  351. package/src/test/setup.ts +9 -0
  352. package/src/vite-env.d.ts +1 -0
  353. package/tsconfig.app.json +25 -0
  354. package/tsconfig.app.tsbuildinfo +1 -0
  355. package/tsconfig.json +7 -0
  356. package/tsconfig.node.json +18 -0
  357. package/tsconfig.node.tsbuildinfo +1 -0
  358. package/vite.config.ts +12 -0
  359. package/vitest.config.ts +22 -0
@@ -0,0 +1,8 @@
1
+ <svg preserveAspectRatio="none" overflow="visible" style="display: block;" width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <g id="icon-package">
3
+ <path id="Vector" d="M5.625 3.2025L12.375 7.065" stroke="white" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
4
+ <path id="Vector_2" d="M15.75 6C15.7497 5.73696 15.6803 5.47861 15.5487 5.25087C15.417 5.02314 15.2278 4.83402 15 4.7025L9.75 1.7025C9.52197 1.57085 9.2633 1.50154 9 1.50154C8.7367 1.50154 8.47803 1.57085 8.25 1.7025L3 4.7025C2.7722 4.83402 2.58299 5.02314 2.45135 5.25087C2.31971 5.47861 2.25027 5.73696 2.25 6V12C2.25027 12.263 2.31971 12.5214 2.45135 12.7491C2.58299 12.9769 2.7722 13.166 3 13.2975L8.25 16.2975C8.47803 16.4292 8.7367 16.4985 9 16.4985C9.2633 16.4985 9.52197 16.4292 9.75 16.2975L15 13.2975C15.2278 13.166 15.417 12.9769 15.5487 12.7491C15.6803 12.5214 15.7497 12.263 15.75 12V6Z" stroke="white" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
5
+ <path id="Vector_3" d="M2.475 5.25L9 9L15.525 5.25" stroke="white" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
6
+ <path id="Vector_4" d="M9 16.5V9" stroke="white" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
7
+ </g>
8
+ </svg>
@@ -0,0 +1,8 @@
1
+ <svg preserveAspectRatio="none" overflow="visible" style="display: block;" width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <g id="icon-package">
3
+ <path id="Vector" d="M10 5.69333L22 12.56" stroke="#D34860" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
4
+ <path id="Vector_2" d="M28 10.6667C27.9995 10.199 27.8761 9.73975 27.6421 9.33488C27.408 8.93002 27.0717 8.59382 26.6667 8.36L17.3333 3.02667C16.9279 2.79262 16.4681 2.6694 16 2.6694C15.5319 2.6694 15.0721 2.79262 14.6667 3.02667L5.33333 8.36C4.92835 8.59382 4.59197 8.93002 4.35795 9.33488C4.12392 9.73975 4.00048 10.199 4 10.6667V21.3333C4.00048 21.801 4.12392 22.2603 4.35795 22.6651C4.59197 23.07 4.92835 23.4062 5.33333 23.64L14.6667 28.9733C15.0721 29.2074 15.5319 29.3306 16 29.3306C16.4681 29.3306 16.9279 29.2074 17.3333 28.9733L26.6667 23.64C27.0717 23.4062 27.408 23.07 27.6421 22.6651C27.8761 22.2603 27.9995 21.801 28 21.3333V10.6667Z" stroke="#D34860" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
5
+ <path id="Vector_3" d="M4.4 9.33333L16 16L27.6 9.33333" stroke="#D34860" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
6
+ <path id="Vector_4" d="M16 29.3333V16" stroke="#D34860" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
7
+ </g>
8
+ </svg>
@@ -0,0 +1,6 @@
1
+ <svg preserveAspectRatio="none" overflow="visible" style="display: block;" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <g id="icon-plus">
3
+ <path id="Vector" d="M3.33333 8H12.6667" stroke="white" stroke-width="1.66667" stroke-linecap="round" stroke-linejoin="round"/>
4
+ <path id="Vector_2" d="M8 3.33333V12.6667" stroke="white" stroke-width="1.66667" stroke-linecap="round" stroke-linejoin="round"/>
5
+ </g>
6
+ </svg>
@@ -0,0 +1,6 @@
1
+ <svg preserveAspectRatio="none" overflow="visible" style="display: block;" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <g id="icon-settings">
3
+ <path id="Vector" d="M8.14667 1.33333H7.85333C7.49971 1.33333 7.16057 1.47381 6.91052 1.72386C6.66048 1.97391 6.52 2.31304 6.52 2.66667V2.78667C6.51976 3.02048 6.45804 3.25013 6.34103 3.45256C6.22401 3.65499 6.05582 3.82309 5.85333 3.94L5.56667 4.10667C5.36397 4.22369 5.13405 4.2853 4.9 4.2853C4.66595 4.2853 4.43603 4.22369 4.23333 4.10667L4.13333 4.05333C3.82738 3.87684 3.46389 3.82896 3.12267 3.92021C2.78144 4.01145 2.49037 4.23436 2.31333 4.54L2.16667 4.79333C1.99018 5.09929 1.9423 5.46278 2.03354 5.804C2.12478 6.14522 2.34769 6.4363 2.65333 6.61333L2.75333 6.68C2.95485 6.79634 3.12241 6.96339 3.23937 7.16455C3.35632 7.36572 3.4186 7.59398 3.42 7.82667V8.16667C3.42093 8.40161 3.35977 8.63264 3.2427 8.83634C3.12562 9.04004 2.95681 9.20919 2.75333 9.32667L2.65333 9.38667C2.34769 9.5637 2.12478 9.85478 2.03354 10.196C1.9423 10.5372 1.99018 10.9007 2.16667 11.2067L2.31333 11.46C2.49037 11.7656 2.78144 11.9886 3.12267 12.0798C3.46389 12.171 3.82738 12.1232 4.13333 11.9467L4.23333 11.8933C4.43603 11.7763 4.66595 11.7147 4.9 11.7147C5.13405 11.7147 5.36397 11.7763 5.56667 11.8933L5.85333 12.06C6.05582 12.1769 6.22401 12.345 6.34103 12.5474C6.45804 12.7499 6.51976 12.9795 6.52 13.2133V13.3333C6.52 13.687 6.66048 14.0261 6.91052 14.2761C7.16057 14.5262 7.49971 14.6667 7.85333 14.6667H8.14667C8.50029 14.6667 8.83943 14.5262 9.08948 14.2761C9.33952 14.0261 9.48 13.687 9.48 13.3333V13.2133C9.48024 12.9795 9.54196 12.7499 9.65897 12.5474C9.77599 12.345 9.94418 12.1769 10.1467 12.06L10.4333 11.8933C10.636 11.7763 10.866 11.7147 11.1 11.7147C11.334 11.7147 11.564 11.7763 11.7667 11.8933L11.8667 11.9467C12.1726 12.1232 12.5361 12.171 12.8773 12.0798C13.2186 11.9886 13.5096 11.7656 13.6867 11.46L13.8333 11.2C14.0098 10.894 14.0577 10.5306 13.9665 10.1893C13.8752 9.84811 13.6523 9.55703 13.3467 9.38L13.2467 9.32667C13.0432 9.20919 12.8744 9.04004 12.7573 8.83634C12.6402 8.63264 12.5791 8.40161 12.58 8.16667V7.83333C12.5791 7.59839 12.6402 7.36736 12.7573 7.16366C12.8744 6.95996 13.0432 6.79081 13.2467 6.67333L13.3467 6.61333C13.6523 6.4363 13.8752 6.14522 13.9665 5.804C14.0577 5.46278 14.0098 5.09929 13.8333 4.79333L13.6867 4.54C13.5096 4.23436 13.2186 4.01145 12.8773 3.92021C12.5361 3.82896 12.1726 3.87684 11.8667 4.05333L11.7667 4.10667C11.564 4.22369 11.334 4.2853 11.1 4.2853C10.866 4.2853 10.636 4.22369 10.4333 4.10667L10.1467 3.94C9.94418 3.82309 9.77599 3.65499 9.65897 3.45256C9.54196 3.25013 9.48024 3.02048 9.48 2.78667V2.66667C9.48 2.31304 9.33952 1.97391 9.08948 1.72386C8.83943 1.47381 8.50029 1.33333 8.14667 1.33333Z" stroke="#606978" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/>
4
+ <path id="Vector_2" d="M8 10C9.10457 10 10 9.10457 10 8C10 6.89543 9.10457 6 8 6C6.89543 6 6 6.89543 6 8C6 9.10457 6.89543 10 8 10Z" stroke="#606978" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/>
5
+ </g>
6
+ </svg>
@@ -0,0 +1,19 @@
1
+ <svg preserveAspectRatio="none" overflow="visible" style="display: block;" width="45" height="26" viewBox="0 0 45 26" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <g id="Switch">
3
+ <rect x="1" width="44" height="24" rx="12" fill="#D0D5DD"/>
4
+ <g id="Knob" filter="url(#filter0_d_0_6)">
5
+ <circle cx="13" cy="12" r="10" fill="white"/>
6
+ </g>
7
+ </g>
8
+ <defs>
9
+ <filter id="filter0_d_0_6" x="0" y="0" width="26" height="26" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
10
+ <feFlood flood-opacity="0" result="BackgroundImageFix"/>
11
+ <feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
12
+ <feOffset dy="1"/>
13
+ <feGaussianBlur stdDeviation="1.5"/>
14
+ <feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.15 0"/>
15
+ <feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_0_6"/>
16
+ <feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_0_6" result="shape"/>
17
+ </filter>
18
+ </defs>
19
+ </svg>
@@ -0,0 +1,19 @@
1
+ <svg preserveAspectRatio="none" overflow="visible" style="display: block;" width="45" height="26" viewBox="0 0 45 26" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <g id="Switch">
3
+ <rect width="44" height="24" rx="12" fill="#D34860"/>
4
+ <g id="Knob" filter="url(#filter0_d_0_10)">
5
+ <circle cx="32" cy="12" r="10" fill="white"/>
6
+ </g>
7
+ </g>
8
+ <defs>
9
+ <filter id="filter0_d_0_10" x="19" y="0" width="26" height="26" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
10
+ <feFlood flood-opacity="0" result="BackgroundImageFix"/>
11
+ <feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
12
+ <feOffset dy="1"/>
13
+ <feGaussianBlur stdDeviation="1.5"/>
14
+ <feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.15 0"/>
15
+ <feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_0_10"/>
16
+ <feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_0_10" result="shape"/>
17
+ </filter>
18
+ </defs>
19
+ </svg>
@@ -0,0 +1,3 @@
1
+ <svg preserveAspectRatio="none" overflow="visible" style="display: block;" width="8" height="8" viewBox="0 0 8 8" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <circle id="Unread dot" cx="4" cy="4" r="4" fill="#D34860"/>
3
+ </svg>
@@ -0,0 +1,5 @@
1
+ <svg preserveAspectRatio="none" overflow="visible" style="display: block;" width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <g id="upload-cloud">
3
+ <path id="Vector" d="M16.0007 17.333V28M21.3337 22.6665L16.0007 17.333L10.6676 22.6665M5.33506 19.8654C4.34451 18.8533 3.59725 17.629 3.1499 16.2853C2.70255 14.9415 2.56683 13.5136 2.75302 12.1096C2.93922 10.7057 3.44244 9.36247 4.22458 8.18182C5.00673 7.00116 6.04727 6.01399 7.2674 5.29509C8.48753 4.57618 9.85524 4.14439 11.267 4.03242C12.6787 3.92045 14.0973 4.13123 15.4155 4.64881C16.7337 5.16639 17.9168 5.97719 18.8753 7.01978C19.8337 8.06238 20.5424 9.30944 20.9475 10.6665H23.3341C24.6213 10.6664 25.8745 11.0803 26.9085 11.8471C27.9425 12.614 28.7024 13.6931 29.0761 14.925C29.4497 16.157 29.4173 17.4765 28.9835 18.6886C28.5497 19.9007 27.7376 20.9411 26.6672 21.6562" stroke="#606978" stroke-width="2" stroke-linecap="round"/>
4
+ </g>
5
+ </svg>
@@ -0,0 +1,6 @@
1
+ <svg preserveAspectRatio="none" overflow="visible" style="display: block;" width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <g id="icon-user">
3
+ <path id="Vector" d="M12.6667 14V12.6667C12.6667 11.9594 12.3857 11.2811 11.8856 10.781C11.3855 10.281 10.7072 10 10 10H6C5.29276 10 4.61448 10.281 4.11438 10.781C3.61428 11.2811 3.33333 11.9594 3.33333 12.6667V14" stroke="#606978" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/>
4
+ <path id="Vector_2" d="M8 7.33333C9.47276 7.33333 10.6667 6.13943 10.6667 4.66667C10.6667 3.19391 9.47276 2 8 2C6.52724 2 5.33333 3.19391 5.33333 4.66667C5.33333 6.13943 6.52724 7.33333 8 7.33333Z" stroke="#606978" stroke-width="1.33333" stroke-linecap="round" stroke-linejoin="round"/>
5
+ </g>
6
+ </svg>
@@ -0,0 +1,41 @@
1
+ import alertTriangle from './icons/alert-triangle.svg';
2
+ import arrowRight from './icons/arrow-right.svg';
3
+ import bell from './icons/bell.svg';
4
+ import chevronDown from './icons/chevron-down.svg';
5
+ import chevronRight from './icons/chevron-right.svg';
6
+ import clock from './icons/clock.svg';
7
+ import clockMuted from './icons/clock-muted.svg';
8
+ import close from './icons/close.svg';
9
+ import heart from './icons/heart.svg';
10
+ import logout from './icons/logout.svg';
11
+ import mapPin from './icons/map-pin.svg';
12
+ import packageIcon from './icons/package.svg';
13
+ import packageRead from './icons/package-read.svg';
14
+ import packageWhite from './icons/package-white.svg';
15
+ import plus from './icons/plus.svg';
16
+ import settings from './icons/settings.svg';
17
+ import uploadCloud from './icons/upload-cloud.svg';
18
+ import user from './icons/user.svg';
19
+
20
+ export const icons = {
21
+ alertTriangle,
22
+ arrowRight,
23
+ bell,
24
+ chevronDown,
25
+ chevronRight,
26
+ clock,
27
+ clockMuted,
28
+ close,
29
+ heart,
30
+ logout,
31
+ mapPin,
32
+ package: packageIcon,
33
+ packageRead,
34
+ packageWhite,
35
+ plus,
36
+ settings,
37
+ uploadCloud,
38
+ user,
39
+ } as const;
40
+
41
+ export type IconName = keyof typeof icons;
@@ -0,0 +1,34 @@
1
+ .item {
2
+ width: 100%;
3
+ border: 1px solid var(--color-border);
4
+ background: #fff;
5
+ }
6
+
7
+ .heading {
8
+ margin: 0;
9
+ font-size: inherit;
10
+ font-weight: inherit;
11
+ }
12
+
13
+ .trigger {
14
+ display: flex;
15
+ align-items: center;
16
+ justify-content: space-between;
17
+ gap: 16px;
18
+ width: 100%;
19
+ padding: 16px;
20
+ border: 0;
21
+ background: transparent;
22
+ color: var(--color-text);
23
+ font-size: 16px;
24
+ font-weight: 500;
25
+ text-align: left;
26
+ cursor: pointer;
27
+ }
28
+
29
+ .panel {
30
+ padding: 0 16px 20px;
31
+ color: var(--color-text-secondary);
32
+ font-size: 14px;
33
+ line-height: 1.5;
34
+ }
@@ -0,0 +1,20 @@
1
+ import { render, screen } from '@testing-library/react';
2
+ import userEvent from '@testing-library/user-event';
3
+ import { Accordion } from './Accordion';
4
+
5
+ describe('<Accordion>', () => {
6
+ it('should render the title collapsed', () => {
7
+ render(<Accordion title="Comment suivre mon colis LeRelais ?">Détail</Accordion>);
8
+ expect(screen.getByRole('button', { name: /Comment suivre/ })).toHaveAttribute('aria-expanded', 'false');
9
+ expect(screen.queryByText('Détail')).not.toBeInTheDocument();
10
+ });
11
+
12
+ it('should reveal the content when activated', async () => {
13
+ const user = userEvent.setup();
14
+ render(<Accordion title="Délais">Les délais varient de 24h à 72h.</Accordion>);
15
+
16
+ await user.click(screen.getByRole('button', { name: 'Délais' }));
17
+
18
+ expect(screen.getByText('Les délais varient de 24h à 72h.')).toBeInTheDocument();
19
+ });
20
+ });
@@ -0,0 +1,38 @@
1
+ import { useId, useState, type ReactNode } from 'react';
2
+ import { cn } from '@/lib/cn';
3
+ import { Icon } from '@/components/Icon';
4
+ import styles from './Accordion.module.css';
5
+
6
+ export interface AccordionProps {
7
+ title: string;
8
+ children: ReactNode;
9
+ defaultOpen?: boolean;
10
+ className?: string;
11
+ }
12
+
13
+ export function Accordion({ title, children, defaultOpen = false, className }: AccordionProps) {
14
+ const [open, setOpen] = useState(defaultOpen);
15
+ const panelId = useId();
16
+
17
+ return (
18
+ <div className={cn(styles.item, className)}>
19
+ <h3 className={styles.heading}>
20
+ <button
21
+ type="button"
22
+ className={styles.trigger}
23
+ aria-expanded={open}
24
+ aria-controls={panelId}
25
+ onClick={() => setOpen((current) => !current)}
26
+ >
27
+ <span>{title}</span>
28
+ <Icon name={open ? 'chevronDown' : 'chevronRight'} size={16} />
29
+ </button>
30
+ </h3>
31
+ {open ? (
32
+ <div id={panelId} className={styles.panel}>
33
+ {children}
34
+ </div>
35
+ ) : null}
36
+ </div>
37
+ );
38
+ }
@@ -0,0 +1 @@
1
+ export { Accordion, type AccordionProps } from './Accordion';
@@ -0,0 +1,50 @@
1
+ .card {
2
+ display: flex;
3
+ flex-direction: column;
4
+ gap: 16px;
5
+ width: 100%;
6
+ max-width: 450px;
7
+ padding: 24px;
8
+ overflow: hidden;
9
+ border: 1px solid #e5e7eb;
10
+ border-radius: 16px;
11
+ background: #fff;
12
+ box-shadow: 0 8px 24px rgb(16 24 40 / 8%);
13
+ }
14
+
15
+ .primary,
16
+ .secondary {
17
+ width: 100%;
18
+ padding: 16px 20px;
19
+ border-radius: 14px;
20
+ font-family: inherit;
21
+ font-size: 16px;
22
+ font-weight: 600;
23
+ line-height: 1.3;
24
+ text-align: left;
25
+ cursor: pointer;
26
+ }
27
+
28
+ .primary {
29
+ border: 0;
30
+ background: #d34860;
31
+ color: #fff;
32
+ box-shadow: 0 8px 18px rgb(211 72 96 / 20%);
33
+ }
34
+
35
+ .secondary {
36
+ border: 1px solid #d34860;
37
+ background: #fff;
38
+ color: #d34860;
39
+ }
40
+
41
+ .trust {
42
+ display: flex;
43
+ align-items: center;
44
+ gap: 8px;
45
+ margin: 0;
46
+ color: #606978;
47
+ font-size: 13px;
48
+ font-weight: 500;
49
+ line-height: 1.3;
50
+ }
@@ -0,0 +1,15 @@
1
+ import { render, screen } from '@testing-library/react';
2
+ import userEvent from '@testing-library/user-event';
3
+ import { ActionCard } from './ActionCard';
4
+
5
+ describe('<ActionCard>', () => {
6
+ it('should call the primary action', async () => {
7
+ const user = userEvent.setup();
8
+ const onPrimary = vi.fn();
9
+ render(<ActionCard onPrimary={onPrimary} />);
10
+
11
+ await user.click(screen.getByRole('button', { name: 'Choisir ce point relais' }));
12
+
13
+ expect(onPrimary).toHaveBeenCalledOnce();
14
+ });
15
+ });
@@ -0,0 +1,33 @@
1
+ import check from '@/assets/icons/core-check.svg';
2
+ import styles from './ActionCard.module.css';
3
+
4
+ export interface ActionCardProps {
5
+ primaryLabel?: string;
6
+ secondaryLabel?: string;
7
+ trust?: string;
8
+ onPrimary?: () => void;
9
+ onSecondary?: () => void;
10
+ }
11
+
12
+ export function ActionCard({
13
+ primaryLabel = 'Choisir ce point relais',
14
+ secondaryLabel = 'Voir les relais à proximité',
15
+ trust = 'Plus de 120 colis traités ce mois',
16
+ onPrimary,
17
+ onSecondary,
18
+ }: ActionCardProps) {
19
+ return (
20
+ <article className={styles.card}>
21
+ <button type="button" className={styles.primary} onClick={onPrimary}>
22
+ {primaryLabel}
23
+ </button>
24
+ <button type="button" className={styles.secondary} onClick={onSecondary}>
25
+ {secondaryLabel}
26
+ </button>
27
+ <p className={styles.trust}>
28
+ <img src={check} alt="" width={16} height={16} />
29
+ {trust}
30
+ </p>
31
+ </article>
32
+ );
33
+ }
@@ -0,0 +1 @@
1
+ export { ActionCard, type ActionCardProps } from './ActionCard';
@@ -0,0 +1,47 @@
1
+ .alert {
2
+ display: flex;
3
+ flex-direction: column;
4
+ gap: 5px;
5
+ width: 360px;
6
+ max-width: 100%;
7
+ padding: 13px 16px;
8
+ border-radius: var(--radius-md);
9
+ }
10
+
11
+ .title {
12
+ font-size: 12px;
13
+ font-weight: 600;
14
+ }
15
+
16
+ .message {
17
+ font-size: 11px;
18
+ color: var(--color-text);
19
+ }
20
+
21
+ .info {
22
+ background: var(--color-info-bg);
23
+ }
24
+ .info .title {
25
+ color: var(--color-info);
26
+ }
27
+
28
+ .success {
29
+ background: var(--color-success-bg);
30
+ }
31
+ .success .title {
32
+ color: var(--color-success);
33
+ }
34
+
35
+ .warning {
36
+ background: var(--color-warning-bg);
37
+ }
38
+ .warning .title {
39
+ color: var(--color-warning);
40
+ }
41
+
42
+ .error {
43
+ background: var(--color-error-bg);
44
+ }
45
+ .error .title {
46
+ color: var(--color-error);
47
+ }
@@ -0,0 +1,14 @@
1
+ import { render, screen } from '@testing-library/react';
2
+ import { Alert } from './Alert';
3
+
4
+ describe('<Alert>', () => {
5
+ it('should render the message', () => {
6
+ render(<Alert>Information utile pour continuer.</Alert>);
7
+ expect(screen.getByText('Information utile pour continuer.')).toBeInTheDocument();
8
+ });
9
+
10
+ it('should expose an error as an alert', () => {
11
+ render(<Alert type="error">Une erreur empêche de continuer.</Alert>);
12
+ expect(screen.getByRole('alert')).toHaveTextContent('Une erreur empêche de continuer.');
13
+ });
14
+ });
@@ -0,0 +1,27 @@
1
+ import { cn } from '@/lib/cn';
2
+ import styles from './Alert.module.css';
3
+
4
+ export type AlertType = 'info' | 'success' | 'warning' | 'error';
5
+
6
+ const TITLES: Record<AlertType, string> = {
7
+ info: 'Info',
8
+ success: 'Success',
9
+ warning: 'Warning',
10
+ error: 'Error',
11
+ };
12
+
13
+ export interface AlertProps {
14
+ type?: AlertType;
15
+ title?: string;
16
+ children: string;
17
+ className?: string;
18
+ }
19
+
20
+ export function Alert({ type = 'info', title, children, className }: AlertProps) {
21
+ return (
22
+ <div className={cn(styles.alert, styles[type], className)} role={type === 'error' ? 'alert' : 'status'}>
23
+ <p className={styles.title}>{title ?? TITLES[type]}</p>
24
+ <p className={styles.message}>{children}</p>
25
+ </div>
26
+ );
27
+ }
@@ -0,0 +1 @@
1
+ export { Alert, type AlertProps, type AlertType } from './Alert';
@@ -0,0 +1,37 @@
1
+ .avatar {
2
+ display: inline-flex;
3
+ align-items: center;
4
+ justify-content: center;
5
+ border: 2px solid #fff;
6
+ border-radius: 50%;
7
+ background: var(--color-primary);
8
+ color: #fff;
9
+ font-weight: 600;
10
+ letter-spacing: 0.5px;
11
+ }
12
+
13
+ .sm {
14
+ width: 32px;
15
+ height: 32px;
16
+ border-width: 1.5px;
17
+ font-size: 12px;
18
+ }
19
+
20
+ .md {
21
+ width: 40px;
22
+ height: 40px;
23
+ font-size: 14px;
24
+ }
25
+
26
+ .lg {
27
+ width: 48px;
28
+ height: 48px;
29
+ font-size: 18px;
30
+ }
31
+
32
+ .xl {
33
+ width: 64px;
34
+ height: 64px;
35
+ border-width: 2.5px;
36
+ font-size: 24px;
37
+ }
@@ -0,0 +1,9 @@
1
+ import { render, screen } from '@testing-library/react';
2
+ import { Avatar } from './Avatar';
3
+
4
+ describe('<Avatar>', () => {
5
+ it('should render the initials', () => {
6
+ render(<Avatar initials="JD" />);
7
+ expect(screen.getByText('JD')).toBeInTheDocument();
8
+ });
9
+ });
@@ -0,0 +1,18 @@
1
+ import { cn } from '@/lib/cn';
2
+ import styles from './Avatar.module.css';
3
+
4
+ export type AvatarSize = 'sm' | 'md' | 'lg' | 'xl';
5
+
6
+ export interface AvatarProps {
7
+ initials: string;
8
+ size?: AvatarSize;
9
+ className?: string;
10
+ }
11
+
12
+ export function Avatar({ initials, size = 'md', className }: AvatarProps) {
13
+ return (
14
+ <span className={cn(styles.avatar, styles[size], className)} aria-hidden="true">
15
+ {initials}
16
+ </span>
17
+ );
18
+ }
@@ -0,0 +1 @@
1
+ export { Avatar, type AvatarProps, type AvatarSize } from './Avatar';
@@ -0,0 +1,37 @@
1
+ .badge {
2
+ display: inline-flex;
3
+ align-items: center;
4
+ justify-content: center;
5
+ min-width: 112px;
6
+ height: 30px;
7
+ padding: 0 12px;
8
+ border-radius: var(--radius-pill);
9
+ font-size: 11px;
10
+ font-weight: 600;
11
+ line-height: 1.3;
12
+ }
13
+
14
+ .pending {
15
+ background: var(--color-warning-bg);
16
+ color: var(--color-warning);
17
+ }
18
+
19
+ .transit {
20
+ background: var(--color-info-bg);
21
+ color: var(--color-info);
22
+ }
23
+
24
+ .available {
25
+ background: var(--color-primary-soft);
26
+ color: var(--color-primary);
27
+ }
28
+
29
+ .delivered {
30
+ background: var(--color-success-bg);
31
+ color: var(--color-success);
32
+ }
33
+
34
+ .error {
35
+ background: var(--color-error-bg);
36
+ color: var(--color-error);
37
+ }
@@ -0,0 +1,14 @@
1
+ import { render, screen } from '@testing-library/react';
2
+ import { Badge } from './Badge';
3
+
4
+ describe('<Badge>', () => {
5
+ it('should render the pending label', () => {
6
+ render(<Badge />);
7
+ expect(screen.getByText('En attente')).toBeInTheDocument();
8
+ });
9
+
10
+ it('should render the delivered label', () => {
11
+ render(<Badge status="delivered" />);
12
+ expect(screen.getByText('Livré')).toBeInTheDocument();
13
+ });
14
+ });
@@ -0,0 +1,21 @@
1
+ import { cn } from '@/lib/cn';
2
+ import styles from './Badge.module.css';
3
+
4
+ export type ParcelStatus = 'pending' | 'transit' | 'available' | 'delivered' | 'error';
5
+
6
+ const LABELS: Record<ParcelStatus, string> = {
7
+ pending: 'En attente',
8
+ transit: 'En transit',
9
+ available: 'Disponible',
10
+ delivered: 'Livré',
11
+ error: 'Erreur',
12
+ };
13
+
14
+ export interface BadgeProps {
15
+ status?: ParcelStatus;
16
+ className?: string;
17
+ }
18
+
19
+ export function Badge({ status = 'pending', className }: BadgeProps) {
20
+ return <span className={cn(styles.badge, styles[status], className)}>{LABELS[status]}</span>;
21
+ }
@@ -0,0 +1 @@
1
+ export { Badge, type BadgeProps, type ParcelStatus } from './Badge';
@@ -0,0 +1,57 @@
1
+ .chart {
2
+ display: flex;
3
+ flex-direction: column;
4
+ gap: 12px;
5
+ width: 320px;
6
+ height: 200px;
7
+ padding: 16px;
8
+ border-radius: var(--radius-control);
9
+ background: var(--color-surface-muted);
10
+ }
11
+
12
+ .title {
13
+ font-size: 14px;
14
+ font-weight: 600;
15
+ }
16
+
17
+ .body {
18
+ display: flex;
19
+ flex: 1;
20
+ gap: 8px;
21
+ min-height: 0;
22
+ }
23
+
24
+ .axis {
25
+ display: flex;
26
+ flex-direction: column;
27
+ justify-content: space-between;
28
+ color: var(--color-text-muted);
29
+ font-size: 9px;
30
+ }
31
+
32
+ .bars {
33
+ display: flex;
34
+ flex: 1;
35
+ align-items: flex-end;
36
+ justify-content: space-between;
37
+ gap: 8px;
38
+ }
39
+
40
+ .column {
41
+ display: flex;
42
+ flex-direction: column;
43
+ align-items: center;
44
+ justify-content: flex-end;
45
+ gap: 6px;
46
+ height: 100%;
47
+ }
48
+
49
+ .bar {
50
+ width: 28px;
51
+ border-radius: 4px 4px 0 0;
52
+ }
53
+
54
+ .label {
55
+ color: var(--color-text-muted);
56
+ font-size: 10px;
57
+ }