@12-apps/ui 1.0.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 (633) hide show
  1. package/components-catalog.md +806 -0
  2. package/components-guidelines.md +347 -0
  3. package/dist/index.cjs +2 -0
  4. package/dist/index.cjs.map +1 -0
  5. package/dist/index.d.cts +2 -0
  6. package/dist/index.d.ts +2 -0
  7. package/dist/index.js +1 -0
  8. package/dist/index.js.map +1 -0
  9. package/eslint.config.js +77 -0
  10. package/package.json +247 -0
  11. package/src/__tests__/package-wiring.test.ts +37 -0
  12. package/src/__tests__/setup.ts +1 -0
  13. package/src/__tests__/social-login-button.test.tsx +186 -0
  14. package/src/__tests__/user-avatar.test.tsx +195 -0
  15. package/src/button.tsx +22 -0
  16. package/src/components/command/__tests__/command.test.tsx +112 -0
  17. package/src/components/data-display/Alert/Alert.md +209 -0
  18. package/src/components/data-display/Alert/Alert.stories.tsx +561 -0
  19. package/src/components/data-display/Alert/Alert.test.stories.tsx +709 -0
  20. package/src/components/data-display/Alert/Alert.tsx +449 -0
  21. package/src/components/data-display/Alert/Alert.types.ts +79 -0
  22. package/src/components/data-display/Alert/index.ts +2 -0
  23. package/src/components/data-display/AlertDialog/AlertDialog.md +408 -0
  24. package/src/components/data-display/AlertDialog/AlertDialog.stories.tsx +360 -0
  25. package/src/components/data-display/AlertDialog/AlertDialog.test.stories.tsx +753 -0
  26. package/src/components/data-display/AlertDialog/AlertDialog.tsx +273 -0
  27. package/src/components/data-display/AlertDialog/AlertDialog.types.ts +74 -0
  28. package/src/components/data-display/AlertDialog/index.ts +2 -0
  29. package/src/components/data-display/AsyncStateContainer/AsyncStateContainer.stories.tsx +230 -0
  30. package/src/components/data-display/AsyncStateContainer/AsyncStateContainer.test.stories.tsx +270 -0
  31. package/src/components/data-display/AsyncStateContainer/AsyncStateContainer.tsx +116 -0
  32. package/src/components/data-display/AsyncStateContainer/AsyncStateContainer.types.ts +70 -0
  33. package/src/components/data-display/AsyncStateContainer/index.ts +2 -0
  34. package/src/components/data-display/Avatar/Avatar.md +568 -0
  35. package/src/components/data-display/Avatar/Avatar.stories.tsx +718 -0
  36. package/src/components/data-display/Avatar/Avatar.test.stories.tsx +820 -0
  37. package/src/components/data-display/Avatar/Avatar.tsx +507 -0
  38. package/src/components/data-display/Avatar/Avatar.types.ts +88 -0
  39. package/src/components/data-display/Avatar/index.ts +2 -0
  40. package/src/components/data-display/Badge/Badge.md +469 -0
  41. package/src/components/data-display/Badge/Badge.stories.tsx +1136 -0
  42. package/src/components/data-display/Badge/Badge.test.stories.tsx +1193 -0
  43. package/src/components/data-display/Badge/Badge.tsx +606 -0
  44. package/src/components/data-display/Badge/Badge.types.ts +118 -0
  45. package/src/components/data-display/Badge/index.ts +2 -0
  46. package/src/components/data-display/Banner/Banner.stories.tsx +524 -0
  47. package/src/components/data-display/Banner/Banner.test.stories.tsx +503 -0
  48. package/src/components/data-display/Banner/Banner.tsx +350 -0
  49. package/src/components/data-display/Banner/Banner.types.ts +41 -0
  50. package/src/components/data-display/Banner/banner.md +141 -0
  51. package/src/components/data-display/Banner/index.ts +2 -0
  52. package/src/components/data-display/Carousel/Carousel.md +815 -0
  53. package/src/components/data-display/Carousel/Carousel.stories.tsx +607 -0
  54. package/src/components/data-display/Carousel/Carousel.test.stories.tsx +691 -0
  55. package/src/components/data-display/Carousel/Carousel.tsx +765 -0
  56. package/src/components/data-display/Carousel/Carousel.types.ts +79 -0
  57. package/src/components/data-display/Carousel/index.ts +8 -0
  58. package/src/components/data-display/Chart/Chart.md +352 -0
  59. package/src/components/data-display/Chart/Chart.stories.tsx +568 -0
  60. package/src/components/data-display/Chart/Chart.test.stories.tsx +174 -0
  61. package/src/components/data-display/Chart/Chart.tsx +520 -0
  62. package/src/components/data-display/Chart/Chart.types.ts +65 -0
  63. package/src/components/data-display/Chart/index.ts +2 -0
  64. package/src/components/data-display/Chip/Chip.stories.tsx +251 -0
  65. package/src/components/data-display/Chip/Chip.test.stories.tsx +263 -0
  66. package/src/components/data-display/Chip/Chip.tsx +134 -0
  67. package/src/components/data-display/Chip/Chip.types.ts +51 -0
  68. package/src/components/data-display/Chip/chip.md +395 -0
  69. package/src/components/data-display/Chip/index.ts +2 -0
  70. package/src/components/data-display/DataGrid/DataGrid.md +602 -0
  71. package/src/components/data-display/DataGrid/DataGrid.stories.tsx +515 -0
  72. package/src/components/data-display/DataGrid/DataGrid.test.stories.tsx +659 -0
  73. package/src/components/data-display/DataGrid/DataGrid.tsx +743 -0
  74. package/src/components/data-display/DataGrid/DataGrid.types.ts +171 -0
  75. package/src/components/data-display/DataGrid/index.ts +21 -0
  76. package/src/components/data-display/DateTimeDisplay/DateTimeDisplay.tsx +197 -0
  77. package/src/components/data-display/DateTimeDisplay/DateTimeDisplay.types.ts +46 -0
  78. package/src/components/data-display/DateTimeDisplay/index.ts +2 -0
  79. package/src/components/data-display/DescriptionItem/DescriptionItem.md +226 -0
  80. package/src/components/data-display/DescriptionItem/DescriptionItem.stories.tsx +254 -0
  81. package/src/components/data-display/DescriptionItem/DescriptionItem.tsx +100 -0
  82. package/src/components/data-display/DescriptionItem/DescriptionItem.types.ts +1 -0
  83. package/src/components/data-display/DescriptionItem/index.ts +2 -0
  84. package/src/components/data-display/EmptyState/EmptyState.md +265 -0
  85. package/src/components/data-display/EmptyState/EmptyState.stories.tsx +282 -0
  86. package/src/components/data-display/EmptyState/EmptyState.test.stories.tsx +441 -0
  87. package/src/components/data-display/EmptyState/EmptyState.tsx +180 -0
  88. package/src/components/data-display/EmptyState/EmptyState.types.ts +31 -0
  89. package/src/components/data-display/EmptyState/index.ts +2 -0
  90. package/src/components/data-display/ErrorState/ErrorState.stories.tsx +110 -0
  91. package/src/components/data-display/ErrorState/ErrorState.test.stories.tsx +133 -0
  92. package/src/components/data-display/ErrorState/ErrorState.tsx +118 -0
  93. package/src/components/data-display/ErrorState/ErrorState.types.ts +45 -0
  94. package/src/components/data-display/ErrorState/index.ts +2 -0
  95. package/src/components/data-display/HoverCard/HoverCard.md +389 -0
  96. package/src/components/data-display/HoverCard/HoverCard.stories.tsx +648 -0
  97. package/src/components/data-display/HoverCard/HoverCard.test.stories.tsx +929 -0
  98. package/src/components/data-display/HoverCard/HoverCard.tsx +657 -0
  99. package/src/components/data-display/HoverCard/HoverCard.types.ts +116 -0
  100. package/src/components/data-display/HoverCard/index.ts +2 -0
  101. package/src/components/data-display/InteractiveTooltip/InteractiveTooltip.md +532 -0
  102. package/src/components/data-display/InteractiveTooltip/InteractiveTooltip.stories.tsx +411 -0
  103. package/src/components/data-display/InteractiveTooltip/InteractiveTooltip.tsx +245 -0
  104. package/src/components/data-display/InteractiveTooltip/InteractiveTooltip.types.ts +64 -0
  105. package/src/components/data-display/InteractiveTooltip/index.ts +2 -0
  106. package/src/components/data-display/LazyImage/LazyImage.md +356 -0
  107. package/src/components/data-display/LazyImage/LazyImage.stories.tsx +387 -0
  108. package/src/components/data-display/LazyImage/LazyImage.tsx +323 -0
  109. package/src/components/data-display/LazyImage/LazyImage.types.ts +205 -0
  110. package/src/components/data-display/LazyImage/index.ts +2 -0
  111. package/src/components/data-display/Lightbox/Lightbox.stories.tsx +315 -0
  112. package/src/components/data-display/Lightbox/Lightbox.test.stories.tsx +605 -0
  113. package/src/components/data-display/Lightbox/Lightbox.tsx +666 -0
  114. package/src/components/data-display/Lightbox/Lightbox.types.ts +49 -0
  115. package/src/components/data-display/Lightbox/index.ts +2 -0
  116. package/src/components/data-display/Lightbox/lightbox.md +298 -0
  117. package/src/components/data-display/LoadingState/LoadingState.stories.tsx +124 -0
  118. package/src/components/data-display/LoadingState/LoadingState.test.stories.tsx +99 -0
  119. package/src/components/data-display/LoadingState/LoadingState.tsx +103 -0
  120. package/src/components/data-display/LoadingState/LoadingState.types.ts +37 -0
  121. package/src/components/data-display/LoadingState/index.ts +2 -0
  122. package/src/components/data-display/MapPreview/MapPreview.md +154 -0
  123. package/src/components/data-display/MapPreview/MapPreview.stories.tsx +458 -0
  124. package/src/components/data-display/MapPreview/MapPreview.test.stories.tsx +390 -0
  125. package/src/components/data-display/MapPreview/MapPreview.tsx +922 -0
  126. package/src/components/data-display/MapPreview/MapPreview.types.ts +56 -0
  127. package/src/components/data-display/MapPreview/index.ts +2 -0
  128. package/src/components/data-display/Popover/Popover.md +245 -0
  129. package/src/components/data-display/Popover/Popover.stories.tsx +295 -0
  130. package/src/components/data-display/Popover/Popover.test.stories.tsx +1168 -0
  131. package/src/components/data-display/Popover/Popover.tsx +132 -0
  132. package/src/components/data-display/Popover/Popover.types.ts +33 -0
  133. package/src/components/data-display/Popover/index.ts +2 -0
  134. package/src/components/data-display/Progress/Progress.md +450 -0
  135. package/src/components/data-display/Progress/Progress.stories.tsx +481 -0
  136. package/src/components/data-display/Progress/Progress.test.stories.tsx +2070 -0
  137. package/src/components/data-display/Progress/Progress.tsx +332 -0
  138. package/src/components/data-display/Progress/Progress.types.ts +61 -0
  139. package/src/components/data-display/Progress/index.ts +2 -0
  140. package/src/components/data-display/SectionOnboarding/SectionOnboarding.md +108 -0
  141. package/src/components/data-display/SectionOnboarding/SectionOnboarding.stories.tsx +160 -0
  142. package/src/components/data-display/SectionOnboarding/SectionOnboarding.test.stories.tsx +190 -0
  143. package/src/components/data-display/SectionOnboarding/SectionOnboarding.tsx +224 -0
  144. package/src/components/data-display/SectionOnboarding/SectionOnboarding.types.ts +101 -0
  145. package/src/components/data-display/SectionOnboarding/index.ts +7 -0
  146. package/src/components/data-display/Sheet/Sheet.md +475 -0
  147. package/src/components/data-display/Sheet/Sheet.stories.tsx +883 -0
  148. package/src/components/data-display/Sheet/Sheet.test.stories.tsx +1101 -0
  149. package/src/components/data-display/Sheet/Sheet.tsx +978 -0
  150. package/src/components/data-display/Sheet/Sheet.types.ts +93 -0
  151. package/src/components/data-display/Sheet/index.ts +8 -0
  152. package/src/components/data-display/Stepper/Stepper.md +542 -0
  153. package/src/components/data-display/Stepper/Stepper.stories.tsx +540 -0
  154. package/src/components/data-display/Stepper/Stepper.test.stories.tsx +607 -0
  155. package/src/components/data-display/Stepper/Stepper.tsx +328 -0
  156. package/src/components/data-display/Stepper/Stepper.types.ts +97 -0
  157. package/src/components/data-display/Stepper/index.ts +2 -0
  158. package/src/components/data-display/Table/Table.md +243 -0
  159. package/src/components/data-display/Table/Table.stories.tsx +801 -0
  160. package/src/components/data-display/Table/Table.test.stories.tsx +369 -0
  161. package/src/components/data-display/Table/Table.tsx +831 -0
  162. package/src/components/data-display/Table/Table.types.ts +335 -0
  163. package/src/components/data-display/Table/index.ts +2 -0
  164. package/src/components/data-display/Timeline/Timeline.md +201 -0
  165. package/src/components/data-display/Timeline/Timeline.stories.tsx +444 -0
  166. package/src/components/data-display/Timeline/Timeline.test.stories.tsx +944 -0
  167. package/src/components/data-display/Timeline/Timeline.tsx +348 -0
  168. package/src/components/data-display/Timeline/Timeline.types.ts +26 -0
  169. package/src/components/data-display/Timeline/index.ts +2 -0
  170. package/src/components/data-display/TimingDiagram/TimingDiagram.md +162 -0
  171. package/src/components/data-display/TimingDiagram/TimingDiagram.stories.tsx +475 -0
  172. package/src/components/data-display/TimingDiagram/TimingDiagram.test.stories.tsx +734 -0
  173. package/src/components/data-display/TimingDiagram/TimingDiagram.tsx +399 -0
  174. package/src/components/data-display/TimingDiagram/TimingDiagram.types.ts +19 -0
  175. package/src/components/data-display/TimingDiagram/index.ts +2 -0
  176. package/src/components/data-display/Tooltip/Tooltip.md +397 -0
  177. package/src/components/data-display/Tooltip/Tooltip.stories.tsx +465 -0
  178. package/src/components/data-display/Tooltip/Tooltip.test.stories.tsx +1168 -0
  179. package/src/components/data-display/Tooltip/Tooltip.tsx +161 -0
  180. package/src/components/data-display/Tooltip/Tooltip.types.ts +33 -0
  181. package/src/components/data-display/Tooltip/index.ts +2 -0
  182. package/src/components/data-display/index.ts +29 -0
  183. package/src/components/feedback/Dialog/Dialog.md +527 -0
  184. package/src/components/feedback/Dialog/Dialog.stories.tsx +833 -0
  185. package/src/components/feedback/Dialog/Dialog.styles.ts +171 -0
  186. package/src/components/feedback/Dialog/Dialog.test.stories.tsx +955 -0
  187. package/src/components/feedback/Dialog/Dialog.tsx +256 -0
  188. package/src/components/feedback/Dialog/Dialog.types.ts +46 -0
  189. package/src/components/feedback/Dialog/index.ts +9 -0
  190. package/src/components/feedback/Modal/Modal.md +629 -0
  191. package/src/components/feedback/Modal/Modal.stories.tsx +765 -0
  192. package/src/components/feedback/Modal/Modal.test.stories.tsx +251 -0
  193. package/src/components/feedback/Modal/Modal.tsx +279 -0
  194. package/src/components/feedback/Modal/Modal.types.ts +26 -0
  195. package/src/components/feedback/Modal/index.ts +7 -0
  196. package/src/components/feedback/Sonner/Sonner.stories.tsx +698 -0
  197. package/src/components/feedback/Sonner/Sonner.test.stories.tsx +896 -0
  198. package/src/components/feedback/Sonner/Sonner.tsx +493 -0
  199. package/src/components/feedback/Sonner/Sonner.types.ts +65 -0
  200. package/src/components/feedback/Sonner/index.ts +8 -0
  201. package/src/components/feedback/StackedModal/StackedModal.md +273 -0
  202. package/src/components/feedback/StackedModal/StackedModal.stories.tsx +1785 -0
  203. package/src/components/feedback/StackedModal/StackedModal.test.stories.tsx +975 -0
  204. package/src/components/feedback/StackedModal/StackedModal.tsx +664 -0
  205. package/src/components/feedback/StackedModal/StackedModal.types.ts +70 -0
  206. package/src/components/feedback/StackedModal/index.ts +11 -0
  207. package/src/components/feedback/Toast/Toast.md +547 -0
  208. package/src/components/feedback/Toast/Toast.stories.tsx +548 -0
  209. package/src/components/feedback/Toast/Toast.test.stories.tsx +834 -0
  210. package/src/components/feedback/Toast/Toast.tsx +279 -0
  211. package/src/components/feedback/Toast/Toast.types.ts +59 -0
  212. package/src/components/feedback/Toast/index.ts +8 -0
  213. package/src/components/feedback/TutorialOverlay/TutorialOverlay.md +610 -0
  214. package/src/components/feedback/TutorialOverlay/TutorialOverlay.stories.tsx +691 -0
  215. package/src/components/feedback/TutorialOverlay/TutorialOverlay.test.stories.tsx +634 -0
  216. package/src/components/feedback/TutorialOverlay/TutorialOverlay.tsx +554 -0
  217. package/src/components/feedback/TutorialOverlay/TutorialOverlay.types.ts +30 -0
  218. package/src/components/feedback/TutorialOverlay/index.ts +2 -0
  219. package/src/components/feedback/index.ts +6 -0
  220. package/src/components/form/AddressAutocomplete/AddressAutocomplete.md +633 -0
  221. package/src/components/form/AddressAutocomplete/AddressAutocomplete.stories.tsx +663 -0
  222. package/src/components/form/AddressAutocomplete/AddressAutocomplete.test.stories.tsx +723 -0
  223. package/src/components/form/AddressAutocomplete/AddressAutocomplete.tsx +836 -0
  224. package/src/components/form/AddressAutocomplete/AddressAutocomplete.types.ts +37 -0
  225. package/src/components/form/AddressAutocomplete/index.ts +2 -0
  226. package/src/components/form/Autocomplete/Autocomplete.helpers.ts +115 -0
  227. package/src/components/form/Autocomplete/Autocomplete.keys.ts +134 -0
  228. package/src/components/form/Autocomplete/Autocomplete.parts.tsx +337 -0
  229. package/src/components/form/Autocomplete/Autocomplete.stories.tsx +715 -0
  230. package/src/components/form/Autocomplete/Autocomplete.test.stories.tsx +825 -0
  231. package/src/components/form/Autocomplete/Autocomplete.tsx +166 -0
  232. package/src/components/form/Autocomplete/Autocomplete.types.ts +116 -0
  233. package/src/components/form/Autocomplete/autocomplete.md +789 -0
  234. package/src/components/form/Autocomplete/index.ts +8 -0
  235. package/src/components/form/Autocomplete/useAutocomplete.ts +311 -0
  236. package/src/components/form/Button/Button.md +411 -0
  237. package/src/components/form/Button/Button.stories.tsx +362 -0
  238. package/src/components/form/Button/Button.test.stories.tsx +603 -0
  239. package/src/components/form/Button/Button.tsx +326 -0
  240. package/src/components/form/Button/Button.types.ts +74 -0
  241. package/src/components/form/Button/index.ts +2 -0
  242. package/src/components/form/Calendar/Calendar.md +807 -0
  243. package/src/components/form/Calendar/Calendar.stories.tsx +349 -0
  244. package/src/components/form/Calendar/Calendar.test.stories.tsx +465 -0
  245. package/src/components/form/Calendar/Calendar.tsx +571 -0
  246. package/src/components/form/Calendar/Calendar.types.ts +81 -0
  247. package/src/components/form/Calendar/index.ts +11 -0
  248. package/src/components/form/Checkbox/Checkbox.md +200 -0
  249. package/src/components/form/Checkbox/Checkbox.stories.tsx +265 -0
  250. package/src/components/form/Checkbox/Checkbox.test.stories.tsx +181 -0
  251. package/src/components/form/Checkbox/Checkbox.tsx +170 -0
  252. package/src/components/form/Checkbox/Checkbox.types.ts +20 -0
  253. package/src/components/form/Checkbox/index.ts +2 -0
  254. package/src/components/form/CodeEditor/CodeEditor.md +350 -0
  255. package/src/components/form/CodeEditor/CodeEditor.stories.tsx +871 -0
  256. package/src/components/form/CodeEditor/CodeEditor.test.stories.tsx +575 -0
  257. package/src/components/form/CodeEditor/CodeEditor.tsx +415 -0
  258. package/src/components/form/CodeEditor/CodeEditor.types.ts +38 -0
  259. package/src/components/form/CodeEditor/index.ts +2 -0
  260. package/src/components/form/Command/Command.md +468 -0
  261. package/src/components/form/Command/Command.stories.tsx +580 -0
  262. package/src/components/form/Command/Command.test.stories.tsx +215 -0
  263. package/src/components/form/Command/Command.tsx +545 -0
  264. package/src/components/form/Command/Command.types.ts +116 -0
  265. package/src/components/form/Command/index.ts +12 -0
  266. package/src/components/form/CreatableSelect/CreatableSelect.md +114 -0
  267. package/src/components/form/CreatableSelect/CreatableSelect.stories.tsx +112 -0
  268. package/src/components/form/CreatableSelect/CreatableSelect.test.stories.tsx +134 -0
  269. package/src/components/form/CreatableSelect/CreatableSelect.tsx +149 -0
  270. package/src/components/form/CreatableSelect/CreatableSelect.types.ts +37 -0
  271. package/src/components/form/CreatableSelect/index.ts +2 -0
  272. package/src/components/form/Form/Form.md +325 -0
  273. package/src/components/form/Form/Form.stories.tsx +687 -0
  274. package/src/components/form/Form/Form.test.stories.tsx +601 -0
  275. package/src/components/form/Form/Form.tsx +136 -0
  276. package/src/components/form/Form/Form.types.ts +42 -0
  277. package/src/components/form/Form/index.ts +8 -0
  278. package/src/components/form/Input/Input.md +252 -0
  279. package/src/components/form/Input/Input.stories.tsx +256 -0
  280. package/src/components/form/Input/Input.test.stories.tsx +1184 -0
  281. package/src/components/form/Input/Input.tsx +263 -0
  282. package/src/components/form/Input/Input.types.ts +24 -0
  283. package/src/components/form/Input/index.ts +2 -0
  284. package/src/components/form/InputOTP/InputOTP.md +419 -0
  285. package/src/components/form/InputOTP/InputOTP.stories.tsx +774 -0
  286. package/src/components/form/InputOTP/InputOTP.test.stories.tsx +596 -0
  287. package/src/components/form/InputOTP/InputOTP.tsx +231 -0
  288. package/src/components/form/InputOTP/InputOTP.types.ts +68 -0
  289. package/src/components/form/InputOTP/index.ts +2 -0
  290. package/src/components/form/Label/Label.md +426 -0
  291. package/src/components/form/Label/Label.stories.tsx +473 -0
  292. package/src/components/form/Label/Label.test.stories.tsx +909 -0
  293. package/src/components/form/Label/Label.tsx +367 -0
  294. package/src/components/form/Label/Label.types.ts +35 -0
  295. package/src/components/form/Label/index.ts +2 -0
  296. package/src/components/form/Menubar/Menubar.md +275 -0
  297. package/src/components/form/Menubar/Menubar.stories.tsx +472 -0
  298. package/src/components/form/Menubar/Menubar.test.stories.tsx +588 -0
  299. package/src/components/form/Menubar/Menubar.tsx +467 -0
  300. package/src/components/form/Menubar/Menubar.types.ts +71 -0
  301. package/src/components/form/Menubar/index.ts +8 -0
  302. package/src/components/form/PasswordStrength/PasswordStrength.md +139 -0
  303. package/src/components/form/PasswordStrength/PasswordStrength.stories.tsx +562 -0
  304. package/src/components/form/PasswordStrength/PasswordStrength.test.stories.tsx +327 -0
  305. package/src/components/form/PasswordStrength/PasswordStrength.tsx +419 -0
  306. package/src/components/form/PasswordStrength/PasswordStrength.types.ts +18 -0
  307. package/src/components/form/PasswordStrength/index.ts +2 -0
  308. package/src/components/form/PhoneInput/PhoneInput.md +578 -0
  309. package/src/components/form/PhoneInput/PhoneInput.stories.tsx +495 -0
  310. package/src/components/form/PhoneInput/PhoneInput.test.stories.tsx +666 -0
  311. package/src/components/form/PhoneInput/PhoneInput.tsx +376 -0
  312. package/src/components/form/PhoneInput/PhoneInput.types.ts +25 -0
  313. package/src/components/form/PhoneInput/index.ts +2 -0
  314. package/src/components/form/RadioGroup/RadioGroup.md +477 -0
  315. package/src/components/form/RadioGroup/RadioGroup.stories.tsx +518 -0
  316. package/src/components/form/RadioGroup/RadioGroup.test.stories.tsx +685 -0
  317. package/src/components/form/RadioGroup/RadioGroup.tsx +664 -0
  318. package/src/components/form/RadioGroup/RadioGroup.types.ts +82 -0
  319. package/src/components/form/RadioGroup/index.ts +2 -0
  320. package/src/components/form/RichTextEditor/RichTextEditor.md +710 -0
  321. package/src/components/form/RichTextEditor/RichTextEditor.stories.tsx +261 -0
  322. package/src/components/form/RichTextEditor/RichTextEditor.test.stories.tsx +498 -0
  323. package/src/components/form/RichTextEditor/RichTextEditor.tsx +468 -0
  324. package/src/components/form/RichTextEditor/RichTextEditor.types.ts +72 -0
  325. package/src/components/form/RichTextEditor/index.ts +2 -0
  326. package/src/components/form/SearchPalette/SearchPalette.md +69 -0
  327. package/src/components/form/SearchPalette/SearchPalette.parts.tsx +358 -0
  328. package/src/components/form/SearchPalette/SearchPalette.stories.tsx +135 -0
  329. package/src/components/form/SearchPalette/SearchPalette.tsx +141 -0
  330. package/src/components/form/SearchPalette/SearchPalette.types.ts +82 -0
  331. package/src/components/form/SearchPalette/index.ts +7 -0
  332. package/src/components/form/Select/Select.md +254 -0
  333. package/src/components/form/Select/Select.stories.tsx +364 -0
  334. package/src/components/form/Select/Select.test.stories.tsx +977 -0
  335. package/src/components/form/Select/Select.tsx +239 -0
  336. package/src/components/form/Select/Select.types.ts +57 -0
  337. package/src/components/form/Select/index.ts +2 -0
  338. package/src/components/form/Slider/Slider.md +326 -0
  339. package/src/components/form/Slider/Slider.stories.tsx +418 -0
  340. package/src/components/form/Slider/Slider.test.stories.tsx +1044 -0
  341. package/src/components/form/Slider/Slider.tsx +374 -0
  342. package/src/components/form/Slider/Slider.types.ts +113 -0
  343. package/src/components/form/Slider/index.ts +2 -0
  344. package/src/components/form/Switch/Switch.md +565 -0
  345. package/src/components/form/Switch/Switch.stories.tsx +697 -0
  346. package/src/components/form/Switch/Switch.test.stories.tsx +597 -0
  347. package/src/components/form/Switch/Switch.tsx +578 -0
  348. package/src/components/form/Switch/Switch.types.ts +130 -0
  349. package/src/components/form/Switch/index.ts +2 -0
  350. package/src/components/form/Textarea/Textarea.stories.tsx +473 -0
  351. package/src/components/form/Textarea/Textarea.test.stories.tsx +708 -0
  352. package/src/components/form/Textarea/Textarea.tsx +678 -0
  353. package/src/components/form/Textarea/Textarea.types.ts +84 -0
  354. package/src/components/form/Textarea/index.ts +2 -0
  355. package/src/components/form/Toggle/Toggle.md +234 -0
  356. package/src/components/form/Toggle/Toggle.stories.tsx +638 -0
  357. package/src/components/form/Toggle/Toggle.test.stories.tsx +1167 -0
  358. package/src/components/form/Toggle/Toggle.tsx +265 -0
  359. package/src/components/form/Toggle/Toggle.types.ts +79 -0
  360. package/src/components/form/Toggle/index.ts +2 -0
  361. package/src/components/form/ToggleGroup/ToggleGroup.md +329 -0
  362. package/src/components/form/ToggleGroup/ToggleGroup.stories.tsx +617 -0
  363. package/src/components/form/ToggleGroup/ToggleGroup.test.stories.tsx +918 -0
  364. package/src/components/form/ToggleGroup/ToggleGroup.tsx +129 -0
  365. package/src/components/form/ToggleGroup/ToggleGroup.types.ts +53 -0
  366. package/src/components/form/ToggleGroup/index.ts +2 -0
  367. package/src/components/form/UploadButton/UploadButton.md +44 -0
  368. package/src/components/form/UploadButton/UploadButton.stories.tsx +366 -0
  369. package/src/components/form/UploadButton/UploadButton.test.stories.tsx +454 -0
  370. package/src/components/form/UploadButton/UploadButton.tsx +312 -0
  371. package/src/components/form/UploadButton/UploadButton.types.ts +58 -0
  372. package/src/components/form/UploadButton/index.ts +2 -0
  373. package/src/components/form/index.ts +25 -0
  374. package/src/components/form/total-form/Fields/SelectField.tsx +57 -0
  375. package/src/components/form/total-form/Fields/TextField.tsx +58 -0
  376. package/src/components/form/total-form/Fields/index.ts +4 -0
  377. package/src/components/form/total-form/FormContainer.tsx +104 -0
  378. package/src/components/form/total-form/FormContext.tsx +38 -0
  379. package/src/components/form/total-form/FormErrorSnackbar.tsx +35 -0
  380. package/src/components/form/total-form/SubmitButton.tsx +27 -0
  381. package/src/components/form/total-form/index.ts +12 -0
  382. package/src/components/form/total-form/total-form.test.tsx +97 -0
  383. package/src/components/index.ts +7 -0
  384. package/src/components/layout/Accordion/Accordion.md +725 -0
  385. package/src/components/layout/Accordion/Accordion.stories.tsx +690 -0
  386. package/src/components/layout/Accordion/Accordion.test.stories.tsx +1362 -0
  387. package/src/components/layout/Accordion/Accordion.tsx +242 -0
  388. package/src/components/layout/Accordion/Accordion.types.ts +32 -0
  389. package/src/components/layout/Accordion/index.ts +8 -0
  390. package/src/components/layout/Card/Card.md +533 -0
  391. package/src/components/layout/Card/Card.stories.tsx +593 -0
  392. package/src/components/layout/Card/Card.test.stories.tsx +1134 -0
  393. package/src/components/layout/Card/Card.tsx +404 -0
  394. package/src/components/layout/Card/Card.types.ts +57 -0
  395. package/src/components/layout/Card/index.ts +8 -0
  396. package/src/components/layout/Collapsible/Collapsible.md +135 -0
  397. package/src/components/layout/Collapsible/Collapsible.stories.tsx +180 -0
  398. package/src/components/layout/Collapsible/Collapsible.test.stories.tsx +304 -0
  399. package/src/components/layout/Collapsible/Collapsible.tsx +198 -0
  400. package/src/components/layout/Collapsible/Collapsible.types.ts +35 -0
  401. package/src/components/layout/Collapsible/index.ts +6 -0
  402. package/src/components/layout/Container/Container.md +420 -0
  403. package/src/components/layout/Container/Container.stories.tsx +557 -0
  404. package/src/components/layout/Container/Container.test.stories.tsx +750 -0
  405. package/src/components/layout/Container/Container.tsx +72 -0
  406. package/src/components/layout/Container/Container.types.ts +11 -0
  407. package/src/components/layout/Container/index.ts +2 -0
  408. package/src/components/layout/ContentToolbar/ColumnsMenu.tsx +99 -0
  409. package/src/components/layout/ContentToolbar/ContentToolbar.md +75 -0
  410. package/src/components/layout/ContentToolbar/ContentToolbar.stories.tsx +129 -0
  411. package/src/components/layout/ContentToolbar/ContentToolbar.test.stories.tsx +251 -0
  412. package/src/components/layout/ContentToolbar/ContentToolbar.tsx +108 -0
  413. package/src/components/layout/ContentToolbar/ContentToolbar.types.ts +229 -0
  414. package/src/components/layout/ContentToolbar/FilterTrigger.tsx +71 -0
  415. package/src/components/layout/ContentToolbar/MultiSelectDropdown.tsx +297 -0
  416. package/src/components/layout/ContentToolbar/SavedViewsMenu.tsx +334 -0
  417. package/src/components/layout/ContentToolbar/SortByDropdown.tsx +213 -0
  418. package/src/components/layout/ContentToolbar/ViewSelector.tsx +98 -0
  419. package/src/components/layout/ContentToolbar/__tests__/ColumnsMenu.test.tsx +39 -0
  420. package/src/components/layout/ContentToolbar/__tests__/MultiSelectDropdown.test.tsx +110 -0
  421. package/src/components/layout/ContentToolbar/__tests__/SavedViewsMenu.test.tsx +99 -0
  422. package/src/components/layout/ContentToolbar/index.ts +24 -0
  423. package/src/components/layout/ContentToolbar/tests.md +42 -0
  424. package/src/components/layout/ContentToolbar/track.md +41 -0
  425. package/src/components/layout/Dashboard/Dashboard.md +71 -0
  426. package/src/components/layout/Dashboard/Dashboard.stories.tsx +104 -0
  427. package/src/components/layout/Dashboard/Dashboard.test.stories.tsx +164 -0
  428. package/src/components/layout/Dashboard/Dashboard.tsx +297 -0
  429. package/src/components/layout/Dashboard/Dashboard.types.ts +157 -0
  430. package/src/components/layout/Dashboard/DashboardContext.tsx +47 -0
  431. package/src/components/layout/Dashboard/DashboardParts.tsx +216 -0
  432. package/src/components/layout/Dashboard/index.ts +18 -0
  433. package/src/components/layout/Dashboard/tests.md +46 -0
  434. package/src/components/layout/Dashboard/track.md +50 -0
  435. package/src/components/layout/Drawer/Drawer.md +479 -0
  436. package/src/components/layout/Drawer/Drawer.stories.tsx +660 -0
  437. package/src/components/layout/Drawer/Drawer.test.stories.tsx +1339 -0
  438. package/src/components/layout/Drawer/Drawer.tsx +150 -0
  439. package/src/components/layout/Drawer/Drawer.types.ts +34 -0
  440. package/src/components/layout/Drawer/index.ts +2 -0
  441. package/src/components/layout/Resizable/Resizable.md +308 -0
  442. package/src/components/layout/Resizable/Resizable.stories.tsx +1039 -0
  443. package/src/components/layout/Resizable/Resizable.test.stories.tsx +750 -0
  444. package/src/components/layout/Resizable/Resizable.tsx +190 -0
  445. package/src/components/layout/Resizable/Resizable.types.ts +34 -0
  446. package/src/components/layout/Resizable/index.ts +2 -0
  447. package/src/components/layout/ScrollArea/ScrollArea.md +122 -0
  448. package/src/components/layout/ScrollArea/ScrollArea.stories.tsx +651 -0
  449. package/src/components/layout/ScrollArea/ScrollArea.test.stories.tsx +619 -0
  450. package/src/components/layout/ScrollArea/ScrollArea.tsx +449 -0
  451. package/src/components/layout/ScrollArea/ScrollArea.types.ts +80 -0
  452. package/src/components/layout/ScrollArea/index.ts +7 -0
  453. package/src/components/layout/Separator/Separator.stories.tsx +563 -0
  454. package/src/components/layout/Separator/Separator.test.stories.tsx +527 -0
  455. package/src/components/layout/Separator/Separator.tsx +187 -0
  456. package/src/components/layout/Separator/Separator.types.ts +17 -0
  457. package/src/components/layout/Separator/index.ts +2 -0
  458. package/src/components/layout/SettingsLayout/SettingsLayout.md +139 -0
  459. package/src/components/layout/SettingsLayout/SettingsLayout.parts.tsx +357 -0
  460. package/src/components/layout/SettingsLayout/SettingsLayout.stories.tsx +194 -0
  461. package/src/components/layout/SettingsLayout/SettingsLayout.test.stories.tsx +175 -0
  462. package/src/components/layout/SettingsLayout/SettingsLayout.tsx +69 -0
  463. package/src/components/layout/SettingsLayout/SettingsLayout.types.ts +61 -0
  464. package/src/components/layout/SettingsLayout/index.ts +6 -0
  465. package/src/components/layout/Sidebar/Sidebar.md +367 -0
  466. package/src/components/layout/Sidebar/Sidebar.stories.tsx +611 -0
  467. package/src/components/layout/Sidebar/Sidebar.test.stories.tsx +1326 -0
  468. package/src/components/layout/Sidebar/Sidebar.tsx +131 -0
  469. package/src/components/layout/Sidebar/Sidebar.types.ts +30 -0
  470. package/src/components/layout/Sidebar/index.ts +7 -0
  471. package/src/components/layout/Skeleton/Skeleton.md +240 -0
  472. package/src/components/layout/Skeleton/Skeleton.stories.tsx +689 -0
  473. package/src/components/layout/Skeleton/Skeleton.test.stories.tsx +521 -0
  474. package/src/components/layout/Skeleton/Skeleton.tsx +166 -0
  475. package/src/components/layout/Skeleton/Skeleton.types.ts +19 -0
  476. package/src/components/layout/Skeleton/index.ts +2 -0
  477. package/src/components/layout/Spacer/Spacer.md +84 -0
  478. package/src/components/layout/Spacer/Spacer.stories.tsx +502 -0
  479. package/src/components/layout/Spacer/Spacer.test.stories.tsx +472 -0
  480. package/src/components/layout/Spacer/Spacer.tsx +68 -0
  481. package/src/components/layout/Spacer/Spacer.types.ts +12 -0
  482. package/src/components/layout/Spacer/index.ts +2 -0
  483. package/src/components/layout/TableFilter/TableFilter.md +55 -0
  484. package/src/components/layout/TableFilter/TableFilter.stories.tsx +82 -0
  485. package/src/components/layout/TableFilter/TableFilter.test.stories.tsx +87 -0
  486. package/src/components/layout/TableFilter/TableFilter.tsx +383 -0
  487. package/src/components/layout/TableFilter/TableFilter.types.ts +87 -0
  488. package/src/components/layout/TableFilter/TableFilterContext.tsx +29 -0
  489. package/src/components/layout/TableFilter/index.ts +15 -0
  490. package/src/components/layout/TableFilter/tests.md +37 -0
  491. package/src/components/layout/TableFilter/track.md +36 -0
  492. package/src/components/layout/index.ts +14 -0
  493. package/src/components/navigation/Breadcrumbs/Breadcrumbs.md +558 -0
  494. package/src/components/navigation/Breadcrumbs/Breadcrumbs.stories.tsx +640 -0
  495. package/src/components/navigation/Breadcrumbs/Breadcrumbs.test.stories.tsx +1007 -0
  496. package/src/components/navigation/Breadcrumbs/Breadcrumbs.tsx +516 -0
  497. package/src/components/navigation/Breadcrumbs/Breadcrumbs.types.ts +132 -0
  498. package/src/components/navigation/Breadcrumbs/index.ts +2 -0
  499. package/src/components/navigation/CommandPalette/CommandPalette.md +201 -0
  500. package/src/components/navigation/CommandPalette/CommandPalette.stories.tsx +384 -0
  501. package/src/components/navigation/CommandPalette/CommandPalette.test.stories.tsx +437 -0
  502. package/src/components/navigation/CommandPalette/CommandPalette.tsx +434 -0
  503. package/src/components/navigation/CommandPalette/CommandPalette.types.ts +25 -0
  504. package/src/components/navigation/CommandPalette/index.ts +2 -0
  505. package/src/components/navigation/ContextMenu/ContextMenu.md +535 -0
  506. package/src/components/navigation/ContextMenu/ContextMenu.stories.tsx +611 -0
  507. package/src/components/navigation/ContextMenu/ContextMenu.test.stories.tsx +850 -0
  508. package/src/components/navigation/ContextMenu/ContextMenu.tsx +254 -0
  509. package/src/components/navigation/ContextMenu/ContextMenu.types.ts +96 -0
  510. package/src/components/navigation/ContextMenu/index.ts +2 -0
  511. package/src/components/navigation/DropdownMenu/DropdownMenu.md +514 -0
  512. package/src/components/navigation/DropdownMenu/DropdownMenu.stories.tsx +580 -0
  513. package/src/components/navigation/DropdownMenu/DropdownMenu.test.stories.tsx +660 -0
  514. package/src/components/navigation/DropdownMenu/DropdownMenu.tsx +305 -0
  515. package/src/components/navigation/DropdownMenu/DropdownMenu.types.ts +116 -0
  516. package/src/components/navigation/DropdownMenu/index.ts +2 -0
  517. package/src/components/navigation/NavigationMenu/NavigationMenu.md +580 -0
  518. package/src/components/navigation/NavigationMenu/NavigationMenu.tsx +874 -0
  519. package/src/components/navigation/NavigationMenu/NavigationMenu.types.ts +135 -0
  520. package/src/components/navigation/NavigationMenu/index.ts +2 -0
  521. package/src/components/navigation/NavigationMenu/stories/NavigationMenu.stories.tsx +518 -0
  522. package/src/components/navigation/NavigationMenu/stories/NavigationMenu.test.stories.tsx +931 -0
  523. package/src/components/navigation/NavigationMenu/stories/NavigationMenuHorizontal.stories.tsx +503 -0
  524. package/src/components/navigation/NavigationMenu/stories/NavigationMenuVertical.stories.tsx +455 -0
  525. package/src/components/navigation/Pagination/Pagination.md +699 -0
  526. package/src/components/navigation/Pagination/Pagination.stories.tsx +604 -0
  527. package/src/components/navigation/Pagination/Pagination.test.stories.tsx +520 -0
  528. package/src/components/navigation/Pagination/Pagination.tsx +356 -0
  529. package/src/components/navigation/Pagination/Pagination.types.ts +129 -0
  530. package/src/components/navigation/Pagination/index.ts +2 -0
  531. package/src/components/navigation/Tabs/Tabs.md +774 -0
  532. package/src/components/navigation/Tabs/Tabs.stories.tsx +1006 -0
  533. package/src/components/navigation/Tabs/Tabs.test.stories.tsx +1225 -0
  534. package/src/components/navigation/Tabs/Tabs.tsx +433 -0
  535. package/src/components/navigation/Tabs/Tabs.types.ts +239 -0
  536. package/src/components/navigation/Tabs/index.ts +2 -0
  537. package/src/components/navigation/index.ts +7 -0
  538. package/src/components/typography/Blockquote/Blockquote.md +130 -0
  539. package/src/components/typography/Blockquote/Blockquote.stories.tsx +359 -0
  540. package/src/components/typography/Blockquote/Blockquote.test.stories.tsx +432 -0
  541. package/src/components/typography/Blockquote/Blockquote.tsx +166 -0
  542. package/src/components/typography/Blockquote/Blockquote.types.ts +11 -0
  543. package/src/components/typography/Blockquote/index.ts +2 -0
  544. package/src/components/typography/Code/Code.md +182 -0
  545. package/src/components/typography/Code/Code.stories.tsx +686 -0
  546. package/src/components/typography/Code/Code.test.stories.tsx +703 -0
  547. package/src/components/typography/Code/Code.tsx +228 -0
  548. package/src/components/typography/Code/Code.types.ts +12 -0
  549. package/src/components/typography/Code/index.ts +2 -0
  550. package/src/components/typography/Heading/Heading.md +143 -0
  551. package/src/components/typography/Heading/Heading.stories.tsx +451 -0
  552. package/src/components/typography/Heading/Heading.test.stories.tsx +830 -0
  553. package/src/components/typography/Heading/Heading.tsx +178 -0
  554. package/src/components/typography/Heading/Heading.types.ts +11 -0
  555. package/src/components/typography/Heading/index.ts +2 -0
  556. package/src/components/typography/Paragraph/Paragraph.md +80 -0
  557. package/src/components/typography/Paragraph/Paragraph.stories.tsx +280 -0
  558. package/src/components/typography/Paragraph/Paragraph.test.stories.tsx +238 -0
  559. package/src/components/typography/Paragraph/Paragraph.tsx +99 -0
  560. package/src/components/typography/Paragraph/Paragraph.types.ts +10 -0
  561. package/src/components/typography/Paragraph/index.ts +2 -0
  562. package/src/components/typography/Text/Text.md +129 -0
  563. package/src/components/typography/Text/Text.stories.tsx +359 -0
  564. package/src/components/typography/Text/Text.test.stories.tsx +762 -0
  565. package/src/components/typography/Text/Text.tsx +159 -0
  566. package/src/components/typography/Text/Text.types.ts +15 -0
  567. package/src/components/typography/Text/index.ts +2 -0
  568. package/src/components/typography/index.ts +5 -0
  569. package/src/components/utility/AnimatedIcon/AnimatedIcon.md +359 -0
  570. package/src/components/utility/AnimatedIcon/AnimatedIcon.stories.tsx +947 -0
  571. package/src/components/utility/AnimatedIcon/AnimatedIcon.test.stories.tsx +596 -0
  572. package/src/components/utility/AnimatedIcon/AnimatedIcon.tsx +595 -0
  573. package/src/components/utility/AnimatedIcon/AnimatedIcon.types.ts +98 -0
  574. package/src/components/utility/AnimatedIcon/index.ts +2 -0
  575. package/src/components/utility/AspectRatio/AspectRatio.md +200 -0
  576. package/src/components/utility/AspectRatio/AspectRatio.stories.tsx +414 -0
  577. package/src/components/utility/AspectRatio/AspectRatio.test.stories.tsx +859 -0
  578. package/src/components/utility/AspectRatio/AspectRatio.tsx +76 -0
  579. package/src/components/utility/AspectRatio/AspectRatio.types.ts +13 -0
  580. package/src/components/utility/AspectRatio/index.ts +2 -0
  581. package/src/components/utility/InfiniteScroll/InfiniteScroll.md +531 -0
  582. package/src/components/utility/InfiniteScroll/InfiniteScroll.stories.tsx +620 -0
  583. package/src/components/utility/InfiniteScroll/InfiniteScroll.test.stories.tsx +358 -0
  584. package/src/components/utility/InfiniteScroll/InfiniteScroll.tsx +204 -0
  585. package/src/components/utility/InfiniteScroll/InfiniteScroll.types.ts +39 -0
  586. package/src/components/utility/InfiniteScroll/index.ts +6 -0
  587. package/src/components/utility/Portal/Portal.button-container.example.tsx +99 -0
  588. package/src/components/utility/Portal/Portal.md +593 -0
  589. package/src/components/utility/Portal/Portal.stories.tsx +340 -0
  590. package/src/components/utility/Portal/Portal.test.stories.tsx +2086 -0
  591. package/src/components/utility/Portal/Portal.tsx +39 -0
  592. package/src/components/utility/Portal/Portal.types.ts +7 -0
  593. package/src/components/utility/Portal/index.ts +2 -0
  594. package/src/components/utility/Transition/Transition.md +684 -0
  595. package/src/components/utility/Transition/Transition.stories.tsx +493 -0
  596. package/src/components/utility/Transition/Transition.test.stories.tsx +854 -0
  597. package/src/components/utility/Transition/Transition.tsx +140 -0
  598. package/src/components/utility/Transition/Transition.types.ts +14 -0
  599. package/src/components/utility/Transition/index.ts +6 -0
  600. package/src/components/utility/VirtualList/VirtualList.md +520 -0
  601. package/src/components/utility/VirtualList/VirtualList.stories.tsx +1073 -0
  602. package/src/components/utility/VirtualList/VirtualList.test.stories.tsx +1074 -0
  603. package/src/components/utility/VirtualList/VirtualList.tsx +369 -0
  604. package/src/components/utility/VirtualList/VirtualList.types.ts +56 -0
  605. package/src/components/utility/VirtualList/index.ts +7 -0
  606. package/src/components/utility/WorkflowStep/WorkflowStep.md +187 -0
  607. package/src/components/utility/WorkflowStep/WorkflowStep.stories.tsx +433 -0
  608. package/src/components/utility/WorkflowStep/WorkflowStep.test.stories.tsx +364 -0
  609. package/src/components/utility/WorkflowStep/WorkflowStep.tsx +506 -0
  610. package/src/components/utility/WorkflowStep/WorkflowStep.types.ts +133 -0
  611. package/src/components/utility/WorkflowStep/index.ts +13 -0
  612. package/src/components/utility/index.ts +7 -0
  613. package/src/index.ts +17 -0
  614. package/src/mui/AppBar.ts +2 -0
  615. package/src/mui/Box.ts +2 -0
  616. package/src/mui/CssBaseline.ts +2 -0
  617. package/src/mui/FormControl.ts +2 -0
  618. package/src/mui/FormControlLabel.ts +2 -0
  619. package/src/mui/Grid2.ts +2 -0
  620. package/src/mui/InputLabel.ts +2 -0
  621. package/src/mui/List.ts +2 -0
  622. package/src/mui/ListItem.ts +2 -0
  623. package/src/mui/ListItemButton.ts +2 -0
  624. package/src/mui/ListItemText.ts +2 -0
  625. package/src/mui/Stack.ts +2 -0
  626. package/src/mui/SvgIcon.ts +2 -0
  627. package/src/mui/Toolbar.ts +2 -0
  628. package/src/mui/styles.ts +2 -0
  629. package/src/mui/useMediaQuery.ts +1 -0
  630. package/src/social-login-button.tsx +199 -0
  631. package/src/user-avatar.tsx +102 -0
  632. package/src/utils/cn.ts +9 -0
  633. package/src/utils/index.ts +1 -0
@@ -0,0 +1,1326 @@
1
+ import {
2
+ ChevronLeft as ChevronLeftIcon,
3
+ ChevronRight as ChevronRightIcon,
4
+ Dashboard as DashboardIcon,
5
+ Home as HomeIcon,
6
+ Inbox as InboxIcon,
7
+ Menu as MenuIcon,
8
+ Person as PersonIcon,
9
+ Send as SendIcon,
10
+ Settings as SettingsIcon,
11
+ Star as StarIcon,
12
+ } from '@mui/icons-material';
13
+ import {
14
+ Avatar,
15
+ Box,
16
+ Button,
17
+ IconButton,
18
+ List,
19
+ ListItemButton,
20
+ ListItemIcon,
21
+ ListItemText,
22
+ Typography,
23
+ } from '@mui/material';
24
+ import type { Meta, StoryObj } from '@storybook/react-vite';
25
+ import React, { useState } from 'react';
26
+ import { expect, fn,userEvent, waitFor, within } from 'storybook/test';
27
+
28
+ import { Sidebar, SidebarContent, SidebarFooter,SidebarHeader } from './Sidebar';
29
+
30
+ const meta: Meta<typeof Sidebar> = {
31
+ title: 'Layout/Sidebar/Tests',
32
+ component: Sidebar,
33
+ parameters: {
34
+ layout: 'fullscreen',
35
+ chromatic: { disableSnapshot: false },
36
+ docs: {
37
+ description: {
38
+ component:
39
+ 'Comprehensive test suite for the Sidebar component covering interaction, accessibility, visual states, and performance.',
40
+ },
41
+ },
42
+ },
43
+ tags: ['autodocs', 'test', 'component:Sidebar'],
44
+ argTypes: {
45
+ variant: {
46
+ control: { type: 'select' },
47
+ options: ['fixed', 'collapsible', 'floating', 'glass'],
48
+ },
49
+ open: {
50
+ control: { type: 'boolean' },
51
+ },
52
+ width: {
53
+ control: { type: 'number' },
54
+ },
55
+ collapsedWidth: {
56
+ control: { type: 'number' },
57
+ },
58
+ position: {
59
+ control: { type: 'select' },
60
+ options: ['left', 'right'],
61
+ },
62
+ },
63
+ };
64
+ export default meta;
65
+ export type Story = StoryObj<typeof meta>;
66
+
67
+ const navigationItems = [
68
+ { icon: <HomeIcon />, label: 'Home', 'data-testid': 'nav-home' },
69
+ { icon: <DashboardIcon />, label: 'Dashboard', 'data-testid': 'nav-dashboard' },
70
+ { icon: <InboxIcon />, label: 'Inbox', 'data-testid': 'nav-inbox' },
71
+ { icon: <StarIcon />, label: 'Favorites', 'data-testid': 'nav-favorites' },
72
+ { icon: <SendIcon />, label: 'Sent', 'data-testid': 'nav-sent' },
73
+ ];
74
+
75
+ // Basic Interaction Tests
76
+ const BasicInteractionComponent = () => {
77
+ const [open, setOpen] = useState(true);
78
+ const mockOnToggle = fn();
79
+
80
+ return (
81
+ <Box sx={{ display: 'flex', height: '500px', bgcolor: 'grey.50', position: 'relative' }}>
82
+ <Sidebar variant="fixed" open={open} onToggle={mockOnToggle} data-testid="sidebar">
83
+ <SidebarHeader data-testid="sidebar-header">
84
+ <Typography variant="h6">Test Sidebar</Typography>
85
+ </SidebarHeader>
86
+
87
+ <SidebarContent data-testid="sidebar-content">
88
+ <List>
89
+ {navigationItems.map((item, index) => (
90
+ <ListItemButton key={index} data-testid={item['data-testid']}>
91
+ <ListItemIcon>{item.icon}</ListItemIcon>
92
+ <ListItemText primary={item.label} />
93
+ </ListItemButton>
94
+ ))}
95
+ </List>
96
+ </SidebarContent>
97
+
98
+ <SidebarFooter data-testid="sidebar-footer">
99
+ <Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>
100
+ <Avatar sx={{ width: 32, height: 32 }} data-testid="user-avatar">
101
+ U
102
+ </Avatar>
103
+ <Typography variant="body2">Test User</Typography>
104
+ </Box>
105
+ </SidebarFooter>
106
+ </Sidebar>
107
+
108
+ <Box sx={{ flex: 1, p: 3 }}>
109
+ <Typography variant="h5" data-testid="main-content">
110
+ Main Content
111
+ </Typography>
112
+ <Button onClick={() => setOpen(!open)} data-testid="toggle-button">
113
+ Toggle Sidebar
114
+ </Button>
115
+ </Box>
116
+ </Box>
117
+ );
118
+ };
119
+
120
+ export const BasicInteraction: Story = {
121
+ render: () => <BasicInteractionComponent />,
122
+ play: async ({ canvasElement }) => {
123
+ const canvas = within(canvasElement);
124
+
125
+ // Test basic rendering
126
+ await expect(canvas.getByTestId('sidebar')).toBeInTheDocument();
127
+ await expect(canvas.getByTestId('sidebar-header')).toBeInTheDocument();
128
+ await expect(canvas.getByTestId('sidebar-content')).toBeInTheDocument();
129
+ await expect(canvas.getByTestId('sidebar-footer')).toBeInTheDocument();
130
+ await expect(canvas.getByTestId('main-content')).toBeInTheDocument();
131
+
132
+ // Test navigation items are rendered
133
+ await expect(canvas.getByTestId('nav-home')).toBeInTheDocument();
134
+ await expect(canvas.getByTestId('nav-dashboard')).toBeInTheDocument();
135
+ await expect(canvas.getByTestId('nav-inbox')).toBeInTheDocument();
136
+ await expect(canvas.getByTestId('nav-favorites')).toBeInTheDocument();
137
+ await expect(canvas.getByTestId('nav-sent')).toBeInTheDocument();
138
+
139
+ // Test user avatar is rendered
140
+ await expect(canvas.getByTestId('user-avatar')).toBeInTheDocument();
141
+
142
+ // Test sidebar has expected width
143
+ const sidebar = canvas.getByTestId('sidebar');
144
+ const sidebarStyles = window.getComputedStyle(sidebar);
145
+ await expect(sidebarStyles.width).toBe('280px');
146
+ },
147
+ };
148
+
149
+ // Form Interaction Test
150
+ const FormInteractionComponent = () => {
151
+ const [selectedItem, setSelectedItem] = useState('');
152
+
153
+ return (
154
+ <Box sx={{ display: 'flex', height: '500px', bgcolor: 'grey.50', position: 'relative' }}>
155
+ <Sidebar variant="fixed" data-testid="form-sidebar">
156
+ <SidebarHeader>
157
+ <Typography variant="h6">Form Sidebar</Typography>
158
+ </SidebarHeader>
159
+
160
+ <SidebarContent>
161
+ <Box sx={{ p: 2 }}>
162
+ <Typography variant="body1" gutterBottom>
163
+ Selected: {selectedItem}
164
+ </Typography>
165
+ <List>
166
+ {navigationItems.map((item, index) => (
167
+ <ListItemButton
168
+ key={index}
169
+ data-testid={`form-${item['data-testid']}`}
170
+ onClick={() => setSelectedItem(item.label)}
171
+ selected={selectedItem === item.label}
172
+ >
173
+ <ListItemIcon>{item.icon}</ListItemIcon>
174
+ <ListItemText primary={item.label} />
175
+ </ListItemButton>
176
+ ))}
177
+ </List>
178
+ </Box>
179
+ </SidebarContent>
180
+ </Sidebar>
181
+
182
+ <Box sx={{ flex: 1, p: 3 }}>
183
+ <Typography variant="h5">Form Content</Typography>
184
+ <Typography data-testid="selected-display">
185
+ Current selection: {selectedItem || 'None'}
186
+ </Typography>
187
+ </Box>
188
+ </Box>
189
+ );
190
+ };
191
+
192
+ export const FormInteraction: Story = {
193
+ render: () => <FormInteractionComponent />,
194
+ play: async ({ canvasElement }) => {
195
+ const canvas = within(canvasElement);
196
+
197
+ // Initially no item selected
198
+ await expect(canvas.getByTestId('selected-display')).toHaveTextContent(
199
+ 'Current selection: None',
200
+ );
201
+
202
+ // Click on Home item
203
+ await userEvent.click(canvas.getByTestId('form-nav-home'));
204
+ await waitFor(() => {
205
+ expect(canvas.getByTestId('selected-display')).toHaveTextContent('Current selection: Home');
206
+ });
207
+
208
+ // Click on Dashboard item
209
+ await userEvent.click(canvas.getByTestId('form-nav-dashboard'));
210
+ await waitFor(() => {
211
+ expect(canvas.getByTestId('selected-display')).toHaveTextContent(
212
+ 'Current selection: Dashboard',
213
+ );
214
+ });
215
+
216
+ // Click on Inbox item
217
+ await userEvent.click(canvas.getByTestId('form-nav-inbox'));
218
+ await waitFor(() => {
219
+ expect(canvas.getByTestId('selected-display')).toHaveTextContent('Current selection: Inbox');
220
+ });
221
+ },
222
+ };
223
+
224
+ // Keyboard Navigation Test
225
+ export const KeyboardNavigation: Story = {
226
+ render: () => (
227
+ <Box sx={{ display: 'flex', height: '500px', bgcolor: 'grey.50', position: 'relative' }}>
228
+ <Sidebar variant="fixed" data-testid="keyboard-sidebar">
229
+ <SidebarHeader>
230
+ <Typography variant="h6">Keyboard Navigation</Typography>
231
+ </SidebarHeader>
232
+
233
+ <SidebarContent>
234
+ <List>
235
+ {navigationItems.map((item, index) => (
236
+ <ListItemButton
237
+ key={index}
238
+ data-testid={`keyboard-${item['data-testid']}`}
239
+ tabIndex={0}
240
+ role="button"
241
+ aria-label={`Navigate to ${item.label}`}
242
+ >
243
+ <ListItemIcon>{item.icon}</ListItemIcon>
244
+ <ListItemText primary={item.label} />
245
+ </ListItemButton>
246
+ ))}
247
+ </List>
248
+ </SidebarContent>
249
+
250
+ <SidebarFooter>
251
+ <Button data-testid="footer-button" tabIndex={0}>
252
+ Settings
253
+ </Button>
254
+ </SidebarFooter>
255
+ </Sidebar>
256
+
257
+ <Box sx={{ flex: 1, p: 3 }}>
258
+ <Typography variant="h5">Main Content</Typography>
259
+ <Button data-testid="main-button" tabIndex={0}>
260
+ Main Action
261
+ </Button>
262
+ </Box>
263
+ </Box>
264
+ ),
265
+ play: async ({ canvasElement }) => {
266
+ const canvas = within(canvasElement);
267
+
268
+ // Test Tab navigation through sidebar items
269
+ const firstNavItem = canvas.getByTestId('keyboard-nav-home');
270
+ firstNavItem.focus();
271
+ await expect(firstNavItem).toHaveFocus();
272
+
273
+ // Tab to next item
274
+ await userEvent.tab();
275
+ await expect(canvas.getByTestId('keyboard-nav-dashboard')).toHaveFocus();
276
+
277
+ // Tab to next item
278
+ await userEvent.tab();
279
+ await expect(canvas.getByTestId('keyboard-nav-inbox')).toHaveFocus();
280
+
281
+ // Tab to footer button
282
+ await userEvent.tab();
283
+ await userEvent.tab();
284
+ await userEvent.tab();
285
+ await expect(canvas.getByTestId('footer-button')).toHaveFocus();
286
+
287
+ // Tab to main content
288
+ await userEvent.tab();
289
+ await expect(canvas.getByTestId('main-button')).toHaveFocus();
290
+
291
+ // Test Enter key activation
292
+ const homeItem = canvas.getByTestId('keyboard-nav-home');
293
+ homeItem.focus();
294
+ await userEvent.keyboard('{Enter}');
295
+ // Verify item is still accessible after Enter
296
+ await expect(homeItem).toBeInTheDocument();
297
+ },
298
+ };
299
+
300
+ // Screen Reader Accessibility Test
301
+ export const ScreenReader: Story = {
302
+ render: () => (
303
+ <Box sx={{ display: 'flex', height: '500px', bgcolor: 'grey.50', position: 'relative' }}>
304
+ <Sidebar
305
+ variant="fixed"
306
+ data-testid="screen-reader-sidebar"
307
+ role="navigation"
308
+ aria-label="Main navigation sidebar"
309
+ >
310
+ <SidebarHeader>
311
+ <Typography variant="h6" role="banner">
312
+ Screen Reader Test
313
+ </Typography>
314
+ </SidebarHeader>
315
+
316
+ <SidebarContent>
317
+ <nav role="navigation" aria-label="Primary navigation">
318
+ <List role="menu">
319
+ {navigationItems.map((item, index) => (
320
+ <ListItemButton
321
+ key={index}
322
+ data-testid={`sr-${item['data-testid']}`}
323
+ role="menuitem"
324
+ aria-label={`Navigate to ${item.label} section`}
325
+ tabIndex={0}
326
+ >
327
+ <ListItemIcon aria-hidden="true">{item.icon}</ListItemIcon>
328
+ <ListItemText primary={item.label} />
329
+ </ListItemButton>
330
+ ))}
331
+ </List>
332
+ </nav>
333
+ </SidebarContent>
334
+
335
+ <SidebarFooter>
336
+ <Box
337
+ role="contentinfo"
338
+ aria-label="User information"
339
+ sx={{ display: 'flex', alignItems: 'center', gap: 1 }}
340
+ >
341
+ <Avatar sx={{ width: 32, height: 32 }} aria-label="User avatar" data-testid="sr-avatar">
342
+ U
343
+ </Avatar>
344
+ <Box>
345
+ <Typography variant="body2">Screen Reader User</Typography>
346
+ <Typography variant="caption" color="text.secondary">
347
+ sr-user@example.com
348
+ </Typography>
349
+ </Box>
350
+ </Box>
351
+ </SidebarFooter>
352
+ </Sidebar>
353
+
354
+ <main role="main" aria-label="Main content area" style={{ flex: 1, padding: '24px' }}>
355
+ <Typography variant="h5">Main Content Area</Typography>
356
+ <Typography variant="body1">This area contains the main application content.</Typography>
357
+ </main>
358
+ </Box>
359
+ ),
360
+ play: async ({ canvasElement }) => {
361
+ const canvas = within(canvasElement);
362
+
363
+ // Test ARIA attributes
364
+ const sidebar = canvas.getByTestId('screen-reader-sidebar');
365
+ await expect(sidebar).toHaveAttribute('role', 'navigation');
366
+ await expect(sidebar).toHaveAttribute('aria-label', 'Main navigation sidebar');
367
+
368
+ // Test navigation structure
369
+ const navigation = canvas.getByRole('navigation', { name: 'Primary navigation' });
370
+ await expect(navigation).toBeInTheDocument();
371
+
372
+ const menu = canvas.getByRole('menu');
373
+ await expect(menu).toBeInTheDocument();
374
+
375
+ // Test menu items have proper ARIA labels
376
+ const homeMenuItem = canvas.getByTestId('sr-nav-home');
377
+ await expect(homeMenuItem).toHaveAttribute('role', 'menuitem');
378
+ await expect(homeMenuItem).toHaveAttribute('aria-label', 'Navigate to Home section');
379
+
380
+ const dashboardMenuItem = canvas.getByTestId('sr-nav-dashboard');
381
+ await expect(dashboardMenuItem).toHaveAttribute('aria-label', 'Navigate to Dashboard section');
382
+
383
+ // Test avatar accessibility
384
+ const avatar = canvas.getByTestId('sr-avatar');
385
+ await expect(avatar).toHaveAttribute('aria-label', 'User avatar');
386
+
387
+ // Test main content area
388
+ const main = canvas.getByRole('main');
389
+ await expect(main).toHaveAttribute('aria-label', 'Main content area');
390
+
391
+ // Test contentinfo role
392
+ const userInfo = canvas.getByRole('contentinfo');
393
+ await expect(userInfo).toHaveAttribute('aria-label', 'User information');
394
+ },
395
+ };
396
+
397
+ // Focus Management Test
398
+ const FocusManagementComponent = () => {
399
+ const [sidebarVisible, setSidebarVisible] = useState(true);
400
+
401
+ return (
402
+ <Box sx={{ display: 'flex', height: '500px', bgcolor: 'grey.50', position: 'relative' }}>
403
+ {sidebarVisible && (
404
+ <Sidebar variant="fixed" data-testid="focus-sidebar">
405
+ <SidebarHeader>
406
+ <Typography variant="h6">Focus Management</Typography>
407
+ <Button
408
+ data-testid="hide-sidebar-button"
409
+ onClick={() => setSidebarVisible(false)}
410
+ size="small"
411
+ >
412
+ Hide Sidebar
413
+ </Button>
414
+ </SidebarHeader>
415
+
416
+ <SidebarContent>
417
+ <List>
418
+ {navigationItems.slice(0, 3).map((item, index) => (
419
+ <ListItemButton
420
+ key={index}
421
+ data-testid={`focus-${item['data-testid']}`}
422
+ tabIndex={0}
423
+ >
424
+ <ListItemIcon>{item.icon}</ListItemIcon>
425
+ <ListItemText primary={item.label} />
426
+ </ListItemButton>
427
+ ))}
428
+ </List>
429
+ </SidebarContent>
430
+
431
+ <SidebarFooter>
432
+ <Button data-testid="sidebar-action" tabIndex={0}>
433
+ Sidebar Action
434
+ </Button>
435
+ </SidebarFooter>
436
+ </Sidebar>
437
+ )}
438
+
439
+ <Box sx={{ flex: 1, p: 3 }}>
440
+ <Typography variant="h5">Focus Management Test</Typography>
441
+ <Button
442
+ data-testid="show-sidebar-button"
443
+ onClick={() => setSidebarVisible(true)}
444
+ style={{ display: sidebarVisible ? 'none' : 'block' }}
445
+ >
446
+ Show Sidebar
447
+ </Button>
448
+ <Button data-testid="main-focus-button" tabIndex={0}>
449
+ Main Button
450
+ </Button>
451
+ </Box>
452
+ </Box>
453
+ );
454
+ };
455
+
456
+ export const FocusManagement: Story = {
457
+ render: () => <FocusManagementComponent />,
458
+ play: async ({ canvasElement }) => {
459
+ const canvas = within(canvasElement);
460
+
461
+ // Test initial focus on first sidebar item
462
+ const firstItem = canvas.getByTestId('focus-nav-home');
463
+ firstItem.focus();
464
+ await expect(firstItem).toHaveFocus();
465
+
466
+ // Test focus moves through sidebar elements
467
+ await userEvent.tab();
468
+ await expect(canvas.getByTestId('focus-nav-dashboard')).toHaveFocus();
469
+
470
+ await userEvent.tab();
471
+ await expect(canvas.getByTestId('focus-nav-inbox')).toHaveFocus();
472
+
473
+ await userEvent.tab();
474
+ await expect(canvas.getByTestId('sidebar-action')).toHaveFocus();
475
+
476
+ // Test focus moves to main content
477
+ await userEvent.tab();
478
+ await expect(canvas.getByTestId('main-focus-button')).toHaveFocus();
479
+
480
+ // Test hiding sidebar
481
+ const hideButton = canvas.getByTestId('hide-sidebar-button');
482
+ await userEvent.click(hideButton);
483
+
484
+ // Verify sidebar is hidden
485
+ await waitFor(() => {
486
+ expect(canvas.queryByTestId('focus-sidebar')).not.toBeInTheDocument();
487
+ });
488
+
489
+ // Test showing sidebar again
490
+ const showButton = canvas.getByTestId('show-sidebar-button');
491
+ await userEvent.click(showButton);
492
+
493
+ // Verify sidebar is visible again
494
+ await waitFor(() => {
495
+ expect(canvas.getByTestId('focus-sidebar')).toBeInTheDocument();
496
+ });
497
+ },
498
+ };
499
+
500
+ // Responsive Design Test
501
+ export const ResponsiveDesign: Story = {
502
+ parameters: {
503
+ viewport: {
504
+ viewports: {
505
+ mobile: { name: 'Mobile', styles: { width: '375px', height: '667px' } },
506
+ tablet: { name: 'Tablet', styles: { width: '768px', height: '1024px' } },
507
+ desktop: { name: 'Desktop', styles: { width: '1200px', height: '800px' } },
508
+ },
509
+ },
510
+ },
511
+ render: () => (
512
+ <Box sx={{ display: 'flex', height: '100vh', bgcolor: 'grey.50' }}>
513
+ <Sidebar variant="fixed" width={280} data-testid="responsive-sidebar">
514
+ <SidebarHeader>
515
+ <Typography variant="h6" noWrap>
516
+ Responsive Sidebar
517
+ </Typography>
518
+ </SidebarHeader>
519
+
520
+ <SidebarContent>
521
+ <List>
522
+ {navigationItems.map((item, index) => (
523
+ <ListItemButton key={index} data-testid={`resp-${item['data-testid']}`}>
524
+ <ListItemIcon>{item.icon}</ListItemIcon>
525
+ <ListItemText primary={item.label} primaryTypographyProps={{ noWrap: true }} />
526
+ </ListItemButton>
527
+ ))}
528
+ </List>
529
+ </SidebarContent>
530
+
531
+ <SidebarFooter>
532
+ <Typography variant="caption" noWrap data-testid="responsive-footer">
533
+ Responsive Footer
534
+ </Typography>
535
+ </SidebarFooter>
536
+ </Sidebar>
537
+
538
+ <Box
539
+ sx={{
540
+ flex: 1,
541
+ p: { xs: 1, sm: 2, md: 3 },
542
+ overflow: 'auto',
543
+ }}
544
+ >
545
+ <Typography variant="h5" gutterBottom>
546
+ Responsive Content
547
+ </Typography>
548
+ <Typography variant="body1" data-testid="responsive-content">
549
+ This content adapts to different screen sizes. The sidebar maintains its functionality
550
+ across all viewport sizes.
551
+ </Typography>
552
+ </Box>
553
+ </Box>
554
+ ),
555
+ play: async ({ canvasElement }) => {
556
+ const canvas = within(canvasElement);
557
+
558
+ // Test sidebar is present
559
+ const sidebar = canvas.getByTestId('responsive-sidebar');
560
+ await expect(sidebar).toBeInTheDocument();
561
+
562
+ // Test sidebar maintains structure
563
+ await expect(canvas.getByTestId('resp-nav-home')).toBeInTheDocument();
564
+ await expect(canvas.getByTestId('resp-nav-dashboard')).toBeInTheDocument();
565
+ await expect(canvas.getByTestId('responsive-footer')).toBeInTheDocument();
566
+ await expect(canvas.getByTestId('responsive-content')).toBeInTheDocument();
567
+
568
+ // Test sidebar width
569
+ const sidebarStyles = window.getComputedStyle(sidebar);
570
+ await expect(sidebarStyles.width).toBe('280px');
571
+
572
+ // Test overflow handling
573
+ await expect(sidebarStyles.overflow).toBe('hidden');
574
+ // Test that height is set (could be 100vh or computed pixels)
575
+ await expect(parseInt(sidebarStyles.height) > 0).toBe(true);
576
+ },
577
+ };
578
+
579
+ // Theme Variations Test
580
+ const ThemeVariationsComponent = () => {
581
+ const [variant, setVariant] = useState<'fixed' | 'glass' | 'floating'>('fixed');
582
+
583
+ const backgroundStyles =
584
+ variant === 'glass'
585
+ ? { background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)' }
586
+ : { bgcolor: 'grey.100' };
587
+
588
+ return (
589
+ <Box sx={{ ...backgroundStyles, height: '500px', position: 'relative' }}>
590
+ <Box sx={{ display: 'flex', height: '100%' }}>
591
+ <Sidebar variant={variant} data-testid="theme-sidebar">
592
+ <SidebarHeader>
593
+ <Typography variant="h6" sx={{ color: variant === 'glass' ? 'white' : 'inherit' }}>
594
+ {variant.charAt(0).toUpperCase() + variant.slice(1)} Theme
595
+ </Typography>
596
+ </SidebarHeader>
597
+
598
+ <SidebarContent>
599
+ <List>
600
+ {navigationItems.slice(0, 3).map((item, index) => (
601
+ <ListItemButton
602
+ key={index}
603
+ data-testid={`theme-${item['data-testid']}`}
604
+ sx={{ color: variant === 'glass' ? 'white' : 'inherit' }}
605
+ >
606
+ <ListItemIcon sx={{ color: variant === 'glass' ? 'white' : 'inherit' }}>
607
+ {item.icon}
608
+ </ListItemIcon>
609
+ <ListItemText primary={item.label} />
610
+ </ListItemButton>
611
+ ))}
612
+ </List>
613
+ </SidebarContent>
614
+
615
+ <SidebarFooter>
616
+ <Box sx={{ display: 'flex', gap: 1, flexWrap: 'wrap' }}>
617
+ {(['fixed', 'glass', 'floating'] as const).map((themeVariant) => (
618
+ <Button
619
+ key={themeVariant}
620
+ size="small"
621
+ variant={variant === themeVariant ? 'contained' : 'outlined'}
622
+ onClick={() => setVariant(themeVariant)}
623
+ data-testid={`theme-${themeVariant}-button`}
624
+ sx={{
625
+ color: variant === 'glass' ? 'white' : 'inherit',
626
+ borderColor: variant === 'glass' ? 'white' : 'inherit',
627
+ }}
628
+ >
629
+ {themeVariant}
630
+ </Button>
631
+ ))}
632
+ </Box>
633
+ </SidebarFooter>
634
+ </Sidebar>
635
+
636
+ <Box sx={{ flex: 1, p: 3, color: variant === 'glass' ? 'white' : 'inherit' }}>
637
+ <Typography variant="h5" gutterBottom data-testid="theme-title">
638
+ {variant.charAt(0).toUpperCase() + variant.slice(1)} Variant
639
+ </Typography>
640
+ <Typography variant="body1" data-testid="theme-description">
641
+ Current theme variant: {variant}
642
+ </Typography>
643
+ </Box>
644
+ </Box>
645
+ </Box>
646
+ );
647
+ };
648
+
649
+ export const ThemeVariations: Story = {
650
+ render: () => <ThemeVariationsComponent />,
651
+ play: async ({ canvasElement }) => {
652
+ const canvas = within(canvasElement);
653
+
654
+ // Test initial fixed theme
655
+ await expect(canvas.getByTestId('theme-title')).toHaveTextContent('Fixed Variant');
656
+ await expect(canvas.getByTestId('theme-description')).toHaveTextContent(
657
+ 'Current theme variant: fixed',
658
+ );
659
+
660
+ // Test switching to glass theme
661
+ await userEvent.click(canvas.getByTestId('theme-glass-button'));
662
+ await waitFor(() => {
663
+ expect(canvas.getByTestId('theme-title')).toHaveTextContent('Glass Variant');
664
+ expect(canvas.getByTestId('theme-description')).toHaveTextContent(
665
+ 'Current theme variant: glass',
666
+ );
667
+ });
668
+
669
+ // Test switching to floating theme
670
+ await userEvent.click(canvas.getByTestId('theme-floating-button'));
671
+ await waitFor(() => {
672
+ expect(canvas.getByTestId('theme-title')).toHaveTextContent('Floating Variant');
673
+ expect(canvas.getByTestId('theme-description')).toHaveTextContent(
674
+ 'Current theme variant: floating',
675
+ );
676
+ });
677
+
678
+ // Test switching back to fixed theme
679
+ await userEvent.click(canvas.getByTestId('theme-fixed-button'));
680
+ await waitFor(() => {
681
+ expect(canvas.getByTestId('theme-title')).toHaveTextContent('Fixed Variant');
682
+ expect(canvas.getByTestId('theme-description')).toHaveTextContent(
683
+ 'Current theme variant: fixed',
684
+ );
685
+ });
686
+
687
+ // Verify sidebar maintains structure across theme changes
688
+ await expect(canvas.getByTestId('theme-sidebar')).toBeInTheDocument();
689
+ await expect(canvas.getByTestId('theme-nav-home')).toBeInTheDocument();
690
+ await expect(canvas.getByTestId('theme-nav-dashboard')).toBeInTheDocument();
691
+ await expect(canvas.getByTestId('theme-nav-inbox')).toBeInTheDocument();
692
+ },
693
+ };
694
+
695
+ // Visual States Test
696
+ const VisualStatesComponent = () => {
697
+ const [collapsed, setCollapsed] = useState(false);
698
+
699
+ return (
700
+ <Box sx={{ display: 'flex', height: '500px', bgcolor: 'grey.50', position: 'relative' }}>
701
+ <Sidebar
702
+ variant="collapsible"
703
+ open={!collapsed}
704
+ width={280}
705
+ collapsedWidth={64}
706
+ data-testid="visual-states-sidebar"
707
+ >
708
+ <SidebarHeader>
709
+ <Box sx={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
710
+ <Typography variant="h6" sx={{ display: collapsed ? 'none' : 'block' }}>
711
+ Visual States
712
+ </Typography>
713
+ <IconButton
714
+ onClick={() => setCollapsed(!collapsed)}
715
+ data-testid="collapse-toggle"
716
+ size="small"
717
+ >
718
+ {collapsed ? <ChevronRightIcon /> : <ChevronLeftIcon />}
719
+ </IconButton>
720
+ </Box>
721
+ </SidebarHeader>
722
+
723
+ <SidebarContent>
724
+ <List>
725
+ {navigationItems.map((item, index) => (
726
+ <ListItemButton
727
+ key={index}
728
+ data-testid={`visual-${item['data-testid']}`}
729
+ sx={{
730
+ '&:hover': {
731
+ backgroundColor: 'action.hover',
732
+ },
733
+ '&:focus': {
734
+ backgroundColor: 'action.selected',
735
+ },
736
+ }}
737
+ >
738
+ <ListItemIcon
739
+ sx={{
740
+ minWidth: collapsed ? 40 : 56,
741
+ justifyContent: 'center',
742
+ }}
743
+ >
744
+ {item.icon}
745
+ </ListItemIcon>
746
+ {!collapsed && <ListItemText primary={item.label} />}
747
+ </ListItemButton>
748
+ ))}
749
+ </List>
750
+ </SidebarContent>
751
+
752
+ <SidebarFooter>
753
+ {!collapsed ? (
754
+ <Typography variant="caption" data-testid="expanded-footer">
755
+ Expanded Footer
756
+ </Typography>
757
+ ) : (
758
+ <Box sx={{ display: 'flex', justifyContent: 'center' }}>
759
+ <Avatar sx={{ width: 24, height: 24 }} data-testid="collapsed-avatar">
760
+ U
761
+ </Avatar>
762
+ </Box>
763
+ )}
764
+ </SidebarFooter>
765
+ </Sidebar>
766
+
767
+ <Box sx={{ flex: 1, p: 3 }}>
768
+ <Typography variant="h5" gutterBottom>
769
+ Visual States Test
770
+ </Typography>
771
+ <Typography variant="body1" data-testid="collapse-status">
772
+ Sidebar is {collapsed ? 'collapsed' : 'expanded'}
773
+ </Typography>
774
+ <Typography variant="body2" color="text.secondary">
775
+ Toggle the sidebar to see different visual states and transitions.
776
+ </Typography>
777
+ </Box>
778
+ </Box>
779
+ );
780
+ };
781
+
782
+ export const VisualStates: Story = {
783
+ render: () => <VisualStatesComponent />,
784
+ play: async ({ canvasElement }) => {
785
+ const canvas = within(canvasElement);
786
+
787
+ // Test initial expanded state
788
+ const sidebar = canvas.getByTestId('visual-states-sidebar');
789
+ await expect(sidebar).toBeInTheDocument();
790
+ await expect(canvas.getByTestId('collapse-status')).toHaveTextContent('Sidebar is expanded');
791
+ await expect(canvas.getByTestId('expanded-footer')).toBeInTheDocument();
792
+
793
+ // Test sidebar width when expanded
794
+ let sidebarStyles = window.getComputedStyle(sidebar);
795
+ await expect(sidebarStyles.width).toBe('280px');
796
+
797
+ // Test collapsing
798
+ const collapseToggle = canvas.getByTestId('collapse-toggle');
799
+ await userEvent.click(collapseToggle);
800
+
801
+ await waitFor(() => {
802
+ expect(canvas.getByTestId('collapse-status')).toHaveTextContent('Sidebar is collapsed');
803
+ });
804
+
805
+ // Test sidebar width when collapsed
806
+ await waitFor(() => {
807
+ sidebarStyles = window.getComputedStyle(sidebar);
808
+ expect(sidebarStyles.width).toBe('64px');
809
+ });
810
+
811
+ // Test collapsed avatar is visible
812
+ await expect(canvas.getByTestId('collapsed-avatar')).toBeInTheDocument();
813
+
814
+ // Test expanding again
815
+ await userEvent.click(collapseToggle);
816
+
817
+ await waitFor(() => {
818
+ expect(canvas.getByTestId('collapse-status')).toHaveTextContent('Sidebar is expanded');
819
+ });
820
+
821
+ // Test navigation items are still clickable and accessible
822
+ await expect(canvas.getByTestId('visual-nav-home')).toBeInTheDocument();
823
+ await expect(canvas.getByTestId('visual-nav-dashboard')).toBeInTheDocument();
824
+
825
+ // Test that navigation items remain interactive during visual state transitions
826
+ const homeItem = canvas.getByTestId('visual-nav-home');
827
+
828
+ // Verify item is clickable
829
+ await userEvent.click(homeItem);
830
+
831
+ // Verify item is still present and enabled after click
832
+ await expect(homeItem).toBeInTheDocument();
833
+ await expect(homeItem).toBeEnabled();
834
+ },
835
+ };
836
+
837
+ // Performance Test
838
+ const PerformanceComponent = () => {
839
+ const [itemCount, setItemCount] = useState(50);
840
+ const [renderTime, setRenderTime] = useState<number>(0);
841
+
842
+ const generateItems = (count: number) => Array.from({ length: count }, (_, index) => ({
843
+ icon: <HomeIcon />,
844
+ label: `Item ${index + 1}`,
845
+ 'data-testid': `perf-item-${index}`,
846
+ }));
847
+
848
+ const handleRender = () => {
849
+ const start = window.performance.now();
850
+ // Force re-render
851
+ setItemCount((prev) => prev + 0);
852
+ const end = window.performance.now();
853
+ setRenderTime(end - start);
854
+ };
855
+
856
+ const items = generateItems(itemCount);
857
+
858
+ return (
859
+ <Box sx={{ display: 'flex', height: '500px', bgcolor: 'grey.50' }}>
860
+ <Sidebar variant="fixed" data-testid="performance-sidebar">
861
+ <SidebarHeader>
862
+ <Typography variant="h6">Performance Test</Typography>
863
+ <Typography variant="caption" data-testid="render-time">
864
+ Render time: {renderTime.toFixed(2)}ms
865
+ </Typography>
866
+ </SidebarHeader>
867
+
868
+ <SidebarContent>
869
+ <List data-testid="performance-list">
870
+ {items.map((item, index) => (
871
+ <ListItemButton key={index} data-testid={item['data-testid']}>
872
+ <ListItemIcon>{item.icon}</ListItemIcon>
873
+ <ListItemText primary={item.label} />
874
+ </ListItemButton>
875
+ ))}
876
+ </List>
877
+ </SidebarContent>
878
+
879
+ <SidebarFooter>
880
+ <Box sx={{ display: 'flex', gap: 1, flexWrap: 'wrap' }}>
881
+ <Button size="small" onClick={() => setItemCount(25)} data-testid="perf-25-items">
882
+ 25 Items
883
+ </Button>
884
+ <Button size="small" onClick={() => setItemCount(50)} data-testid="perf-50-items">
885
+ 50 Items
886
+ </Button>
887
+ <Button size="small" onClick={() => setItemCount(100)} data-testid="perf-100-items">
888
+ 100 Items
889
+ </Button>
890
+ <Button size="small" onClick={handleRender} data-testid="measure-render">
891
+ Measure
892
+ </Button>
893
+ </Box>
894
+ </SidebarFooter>
895
+ </Sidebar>
896
+
897
+ <Box sx={{ flex: 1, p: 3 }}>
898
+ <Typography variant="h5" gutterBottom>
899
+ Performance Metrics
900
+ </Typography>
901
+ <Typography variant="body1" data-testid="item-count">
902
+ Current items: {itemCount}
903
+ </Typography>
904
+ <Typography variant="body2" color="text.secondary">
905
+ Test sidebar performance with different numbers of items.
906
+ </Typography>
907
+ </Box>
908
+ </Box>
909
+ );
910
+ };
911
+
912
+ export const Performance: Story = {
913
+ render: () => <PerformanceComponent />,
914
+ play: async ({ canvasElement }) => {
915
+ const canvas = within(canvasElement);
916
+
917
+ // Test initial state
918
+ await expect(canvas.getByTestId('performance-sidebar')).toBeInTheDocument();
919
+ await expect(canvas.getByTestId('item-count')).toHaveTextContent('Current items: 50');
920
+
921
+ // Test items are rendered
922
+ await expect(canvas.getByTestId('perf-item-0')).toBeInTheDocument();
923
+ await expect(canvas.getByTestId('perf-item-49')).toBeInTheDocument();
924
+
925
+ // Test performance with different item counts
926
+ await userEvent.click(canvas.getByTestId('perf-25-items'));
927
+ await waitFor(() => {
928
+ expect(canvas.getByTestId('item-count')).toHaveTextContent('Current items: 25');
929
+ });
930
+ await expect(canvas.getByTestId('perf-item-0')).toBeInTheDocument();
931
+ await expect(canvas.getByTestId('perf-item-24')).toBeInTheDocument();
932
+
933
+ await userEvent.click(canvas.getByTestId('perf-100-items'));
934
+ await waitFor(() => {
935
+ expect(canvas.getByTestId('item-count')).toHaveTextContent('Current items: 100');
936
+ });
937
+ await expect(canvas.getByTestId('perf-item-0')).toBeInTheDocument();
938
+ await expect(canvas.getByTestId('perf-item-99')).toBeInTheDocument();
939
+
940
+ // Test render time measurement
941
+ await userEvent.click(canvas.getByTestId('measure-render'));
942
+ const renderTimeElement = canvas.getByTestId('render-time');
943
+ await expect(renderTimeElement).toBeInTheDocument();
944
+
945
+ // Verify list maintains scroll functionality
946
+ const performanceList = canvas.getByTestId('performance-list');
947
+ await expect(performanceList).toBeInTheDocument();
948
+ },
949
+ };
950
+
951
+ // Edge Cases Test
952
+ const EdgeCasesComponent = () => {
953
+ const [contentType, setContentType] = useState<'normal' | 'empty' | 'overflow' | 'special-chars'>(
954
+ 'normal',
955
+ );
956
+
957
+ const getContent = () => {
958
+ switch (contentType) {
959
+ case 'empty':
960
+ return [];
961
+ case 'overflow':
962
+ return Array.from({ length: 100 }, (_, i) => ({
963
+ icon: <HomeIcon />,
964
+ label: `Very long navigation item name that might overflow the container ${i + 1}`,
965
+ 'data-testid': `overflow-item-${i}`,
966
+ }));
967
+ case 'special-chars':
968
+ return [
969
+ { icon: <HomeIcon />, label: '🏠 Home with Emoji', 'data-testid': 'emoji-item' },
970
+ {
971
+ icon: <DashboardIcon />,
972
+ label: 'Spëçíàl Çhäracters',
973
+ 'data-testid': 'special-chars-item',
974
+ },
975
+ { icon: <SettingsIcon />, label: '中文字符', 'data-testid': 'chinese-item' },
976
+ { icon: <PersonIcon />, label: 'العربية', 'data-testid': 'arabic-item' },
977
+ { icon: <InboxIcon />, label: 'Русский', 'data-testid': 'russian-item' },
978
+ ];
979
+ default:
980
+ return navigationItems;
981
+ }
982
+ };
983
+
984
+ const content = getContent();
985
+
986
+ return (
987
+ <Box sx={{ display: 'flex', height: '500px', bgcolor: 'grey.50' }}>
988
+ <Sidebar variant="fixed" data-testid="edge-cases-sidebar">
989
+ <SidebarHeader>
990
+ <Typography variant="h6" noWrap>
991
+ Edge Cases Test
992
+ </Typography>
993
+ <Box sx={{ display: 'flex', gap: 0.5, flexWrap: 'wrap', mt: 1 }}>
994
+ {(['normal', 'empty', 'overflow', 'special-chars'] as const).map((type) => (
995
+ <Button
996
+ key={type}
997
+ size="small"
998
+ variant={contentType === type ? 'contained' : 'outlined'}
999
+ onClick={() => setContentType(type)}
1000
+ data-testid={`edge-${type}-button`}
1001
+ sx={{ fontSize: '0.7rem', minWidth: 'auto' }}
1002
+ >
1003
+ {type}
1004
+ </Button>
1005
+ ))}
1006
+ </Box>
1007
+ </SidebarHeader>
1008
+
1009
+ <SidebarContent data-testid="edge-cases-content">
1010
+ {content.length === 0 ? (
1011
+ <Box sx={{ p: 2, textAlign: 'center' }}>
1012
+ <Typography variant="body2" color="text.secondary" data-testid="empty-state">
1013
+ No navigation items available
1014
+ </Typography>
1015
+ </Box>
1016
+ ) : (
1017
+ <List>
1018
+ {content.map((item, index) => (
1019
+ <ListItemButton key={index} data-testid={item['data-testid']}>
1020
+ <ListItemIcon>{item.icon}</ListItemIcon>
1021
+ <ListItemText
1022
+ primary={item.label}
1023
+ primaryTypographyProps={{
1024
+ noWrap: contentType === 'overflow',
1025
+ title: item.label,
1026
+ }}
1027
+ />
1028
+ </ListItemButton>
1029
+ ))}
1030
+ </List>
1031
+ )}
1032
+ </SidebarContent>
1033
+
1034
+ <SidebarFooter>
1035
+ <Typography variant="caption" data-testid="content-type-display">
1036
+ Current: {contentType} ({content.length} items)
1037
+ </Typography>
1038
+ </SidebarFooter>
1039
+ </Sidebar>
1040
+
1041
+ <Box sx={{ flex: 1, p: 3 }}>
1042
+ <Typography variant="h5" gutterBottom>
1043
+ Edge Cases
1044
+ </Typography>
1045
+ <Typography variant="body1" data-testid="edge-description">
1046
+ Testing sidebar with {contentType} content
1047
+ </Typography>
1048
+ </Box>
1049
+ </Box>
1050
+ );
1051
+ };
1052
+
1053
+ export const EdgeCases: Story = {
1054
+ render: () => <EdgeCasesComponent />,
1055
+ play: async ({ canvasElement }) => {
1056
+ const canvas = within(canvasElement);
1057
+
1058
+ // Test normal state
1059
+ await expect(canvas.getByTestId('edge-cases-sidebar')).toBeInTheDocument();
1060
+ await expect(canvas.getByTestId('content-type-display')).toHaveTextContent(
1061
+ 'Current: normal (5 items)',
1062
+ );
1063
+ await expect(canvas.getByTestId('edge-description')).toHaveTextContent(
1064
+ 'Testing sidebar with normal content',
1065
+ );
1066
+
1067
+ // Test empty state
1068
+ await userEvent.click(canvas.getByTestId('edge-empty-button'));
1069
+ await waitFor(() => {
1070
+ expect(canvas.getByTestId('content-type-display')).toHaveTextContent(
1071
+ 'Current: empty (0 items)',
1072
+ );
1073
+ expect(canvas.getByTestId('empty-state')).toHaveTextContent('No navigation items available');
1074
+ });
1075
+
1076
+ // Test overflow state
1077
+ await userEvent.click(canvas.getByTestId('edge-overflow-button'));
1078
+ await waitFor(() => {
1079
+ expect(canvas.getByTestId('content-type-display')).toHaveTextContent(
1080
+ 'Current: overflow (100 items)',
1081
+ );
1082
+ });
1083
+ await expect(canvas.getByTestId('overflow-item-0')).toBeInTheDocument();
1084
+ await expect(canvas.getByTestId('overflow-item-99')).toBeInTheDocument();
1085
+
1086
+ // Test special characters
1087
+ await userEvent.click(canvas.getByTestId('edge-special-chars-button'));
1088
+ await waitFor(() => {
1089
+ expect(canvas.getByTestId('content-type-display')).toHaveTextContent(
1090
+ 'Current: special-chars (5 items)',
1091
+ );
1092
+ });
1093
+ await expect(canvas.getByTestId('emoji-item')).toHaveTextContent('🏠 Home with Emoji');
1094
+ await expect(canvas.getByTestId('special-chars-item')).toHaveTextContent('Spëçíàl Çhäracters');
1095
+ await expect(canvas.getByTestId('chinese-item')).toHaveTextContent('中文字符');
1096
+ await expect(canvas.getByTestId('arabic-item')).toHaveTextContent('العربية');
1097
+ await expect(canvas.getByTestId('russian-item')).toHaveTextContent('Русский');
1098
+
1099
+ // Test back to normal
1100
+ await userEvent.click(canvas.getByTestId('edge-normal-button'));
1101
+ await waitFor(() => {
1102
+ expect(canvas.getByTestId('content-type-display')).toHaveTextContent(
1103
+ 'Current: normal (5 items)',
1104
+ );
1105
+ });
1106
+ },
1107
+ };
1108
+
1109
+ // Integration Test
1110
+ const IntegrationComponent = () => {
1111
+ const [activeSection, setActiveSection] = useState('home');
1112
+ const [sidebarOpen, setSidebarOpen] = useState(true);
1113
+ const [notifications, setNotifications] = useState(3);
1114
+
1115
+ const integrationItems = [
1116
+ {
1117
+ id: 'home',
1118
+ icon: <HomeIcon />,
1119
+ label: 'Home',
1120
+ 'data-testid': 'integration-home',
1121
+ badge: null,
1122
+ },
1123
+ {
1124
+ id: 'dashboard',
1125
+ icon: <DashboardIcon />,
1126
+ label: 'Dashboard',
1127
+ 'data-testid': 'integration-dashboard',
1128
+ badge: null,
1129
+ },
1130
+ {
1131
+ id: 'inbox',
1132
+ icon: <InboxIcon />,
1133
+ label: 'Messages',
1134
+ 'data-testid': 'integration-inbox',
1135
+ badge: notifications > 0 ? notifications : null,
1136
+ },
1137
+ {
1138
+ id: 'settings',
1139
+ icon: <SettingsIcon />,
1140
+ label: 'Settings',
1141
+ 'data-testid': 'integration-settings',
1142
+ badge: null,
1143
+ },
1144
+ ];
1145
+
1146
+ return (
1147
+ <Box sx={{ display: 'flex', height: '500px', bgcolor: 'grey.50' }}>
1148
+ <Sidebar
1149
+ variant="collapsible"
1150
+ open={sidebarOpen}
1151
+ width={280}
1152
+ collapsedWidth={64}
1153
+ data-testid="integration-sidebar"
1154
+ >
1155
+ <SidebarHeader>
1156
+ <Box sx={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
1157
+ <Typography variant="h6" sx={{ display: sidebarOpen ? 'block' : 'none' }}>
1158
+ Integration Test
1159
+ </Typography>
1160
+ <IconButton
1161
+ onClick={() => setSidebarOpen(!sidebarOpen)}
1162
+ data-testid="integration-toggle"
1163
+ size="small"
1164
+ >
1165
+ {sidebarOpen ? <ChevronLeftIcon /> : <MenuIcon />}
1166
+ </IconButton>
1167
+ </Box>
1168
+ </SidebarHeader>
1169
+
1170
+ <SidebarContent>
1171
+ <List>
1172
+ {integrationItems.map((item) => (
1173
+ <ListItemButton
1174
+ key={item.id}
1175
+ data-testid={item['data-testid']}
1176
+ selected={activeSection === item.id}
1177
+ onClick={() => setActiveSection(item.id)}
1178
+ >
1179
+ <ListItemIcon
1180
+ sx={{
1181
+ minWidth: sidebarOpen ? 56 : 40,
1182
+ justifyContent: 'center',
1183
+ }}
1184
+ >
1185
+ <Box sx={{ position: 'relative' }}>
1186
+ {item.icon}
1187
+ {item.badge && (
1188
+ <Box
1189
+ sx={{
1190
+ position: 'absolute',
1191
+ top: -8,
1192
+ right: -8,
1193
+ backgroundColor: 'error.main',
1194
+ color: 'white',
1195
+ borderRadius: '50%',
1196
+ width: 16,
1197
+ height: 16,
1198
+ display: 'flex',
1199
+ alignItems: 'center',
1200
+ justifyContent: 'center',
1201
+ fontSize: '0.7rem',
1202
+ }}
1203
+ data-testid={`badge-${item.id}`}
1204
+ >
1205
+ {item.badge}
1206
+ </Box>
1207
+ )}
1208
+ </Box>
1209
+ </ListItemIcon>
1210
+ {sidebarOpen && <ListItemText primary={item.label} />}
1211
+ </ListItemButton>
1212
+ ))}
1213
+ </List>
1214
+ </SidebarContent>
1215
+
1216
+ <SidebarFooter>
1217
+ <Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>
1218
+ <Avatar sx={{ width: 32, height: 32 }}>I</Avatar>
1219
+ {sidebarOpen && (
1220
+ <Box>
1221
+ <Typography variant="body2">Integration User</Typography>
1222
+ <Button
1223
+ size="small"
1224
+ onClick={() => setNotifications(0)}
1225
+ data-testid="clear-notifications"
1226
+ disabled={notifications === 0}
1227
+ >
1228
+ Clear ({notifications})
1229
+ </Button>
1230
+ </Box>
1231
+ )}
1232
+ </Box>
1233
+ </SidebarFooter>
1234
+ </Sidebar>
1235
+
1236
+ <Box sx={{ flex: 1, p: 3 }}>
1237
+ <Typography variant="h5" gutterBottom data-testid="integration-title">
1238
+ {integrationItems.find((item) => item.id === activeSection)?.label} Section
1239
+ </Typography>
1240
+ <Typography variant="body1" data-testid="integration-content">
1241
+ Active section: {activeSection}
1242
+ </Typography>
1243
+ <Typography variant="body2" color="text.secondary">
1244
+ Sidebar is {sidebarOpen ? 'expanded' : 'collapsed'}
1245
+ </Typography>
1246
+ <Button
1247
+ variant="outlined"
1248
+ onClick={() => setNotifications((prev) => prev + 1)}
1249
+ data-testid="add-notification"
1250
+ sx={{ mt: 2 }}
1251
+ >
1252
+ Add Notification
1253
+ </Button>
1254
+ </Box>
1255
+ </Box>
1256
+ );
1257
+ };
1258
+
1259
+ export const Integration: Story = {
1260
+ render: () => <IntegrationComponent />,
1261
+ play: async ({ canvasElement }) => {
1262
+ const canvas = within(canvasElement);
1263
+
1264
+ // Test initial state
1265
+ await expect(canvas.getByTestId('integration-sidebar')).toBeInTheDocument();
1266
+ await expect(canvas.getByTestId('integration-title')).toHaveTextContent('Home Section');
1267
+ await expect(canvas.getByTestId('integration-content')).toHaveTextContent(
1268
+ 'Active section: home',
1269
+ );
1270
+
1271
+ // Test notification badge
1272
+ await expect(canvas.getByTestId('badge-inbox')).toHaveTextContent('3');
1273
+
1274
+ // Test navigation
1275
+ await userEvent.click(canvas.getByTestId('integration-dashboard'));
1276
+ await waitFor(() => {
1277
+ expect(canvas.getByTestId('integration-title')).toHaveTextContent('Dashboard Section');
1278
+ expect(canvas.getByTestId('integration-content')).toHaveTextContent(
1279
+ 'Active section: dashboard',
1280
+ );
1281
+ });
1282
+
1283
+ await userEvent.click(canvas.getByTestId('integration-inbox'));
1284
+ await waitFor(() => {
1285
+ expect(canvas.getByTestId('integration-title')).toHaveTextContent('Messages Section');
1286
+ expect(canvas.getByTestId('integration-content')).toHaveTextContent('Active section: inbox');
1287
+ });
1288
+
1289
+ // Test adding notifications
1290
+ await userEvent.click(canvas.getByTestId('add-notification'));
1291
+ await waitFor(() => {
1292
+ expect(canvas.getByTestId('badge-inbox')).toHaveTextContent('4');
1293
+ });
1294
+
1295
+ // Test clearing notifications
1296
+ await userEvent.click(canvas.getByTestId('clear-notifications'));
1297
+ await waitFor(() => {
1298
+ expect(canvas.queryByTestId('badge-inbox')).not.toBeInTheDocument();
1299
+ });
1300
+
1301
+ // Test sidebar collapse
1302
+ await userEvent.click(canvas.getByTestId('integration-toggle'));
1303
+ await waitFor(() => {
1304
+ const sidebar = canvas.getByTestId('integration-sidebar');
1305
+ const sidebarStyles = window.getComputedStyle(sidebar);
1306
+ expect(sidebarStyles.width).toBe('64px');
1307
+ });
1308
+
1309
+ // Test sidebar expand
1310
+ await userEvent.click(canvas.getByTestId('integration-toggle'));
1311
+ await waitFor(() => {
1312
+ const sidebar = canvas.getByTestId('integration-sidebar');
1313
+ const sidebarStyles = window.getComputedStyle(sidebar);
1314
+ expect(sidebarStyles.width).toBe('280px');
1315
+ });
1316
+
1317
+ // Test settings navigation
1318
+ await userEvent.click(canvas.getByTestId('integration-settings'));
1319
+ await waitFor(() => {
1320
+ expect(canvas.getByTestId('integration-title')).toHaveTextContent('Settings Section');
1321
+ expect(canvas.getByTestId('integration-content')).toHaveTextContent(
1322
+ 'Active section: settings',
1323
+ );
1324
+ });
1325
+ },
1326
+ };