@12-apps/ui 1.0.0 → 1.3.1

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 (448) hide show
  1. package/components-catalog.md +14 -0
  2. package/package.json +42 -27
  3. package/src/__tests__/data-grid.test.tsx +125 -0
  4. package/src/__tests__/package-wiring.test.ts +12 -8
  5. package/src/__tests__/social-login-button.test.tsx +5 -5
  6. package/src/__tests__/viewport.test.ts +50 -0
  7. package/src/charts/index.ts +8 -0
  8. package/src/components/data-display/Alert/Alert.md +1 -1
  9. package/src/components/data-display/Alert/Alert.stories.tsx +5 -7
  10. package/src/components/data-display/Alert/Alert.styles.tsx +255 -0
  11. package/src/components/data-display/Alert/Alert.test.stories.tsx +11 -13
  12. package/src/components/data-display/Alert/Alert.tsx +135 -328
  13. package/src/components/data-display/AlertDialog/AlertDialog.stories.tsx +3 -1
  14. package/src/components/data-display/AlertDialog/AlertDialog.tsx +191 -78
  15. package/src/components/data-display/AlertDialog/AlertDialog.types.ts +8 -1
  16. package/src/components/data-display/AsyncStateContainer/AsyncStateContainer.test.stories.tsx +5 -5
  17. package/src/components/data-display/AsyncStateContainer/AsyncStateContainer.tsx +44 -35
  18. package/src/components/data-display/Avatar/Avatar.stories.tsx +4 -1
  19. package/src/components/data-display/Avatar/Avatar.test.stories.tsx +5 -3
  20. package/src/components/data-display/Avatar/Avatar.tsx +154 -450
  21. package/src/components/data-display/Avatar/Avatar.view.tsx +396 -0
  22. package/src/components/data-display/Badge/Badge.animations.ts +67 -0
  23. package/src/components/data-display/Badge/Badge.helpers.ts +74 -0
  24. package/src/components/data-display/Badge/Badge.stories.tsx +14 -16
  25. package/src/components/data-display/Badge/Badge.styles.ts +261 -0
  26. package/src/components/data-display/Badge/Badge.test.stories.tsx +32 -31
  27. package/src/components/data-display/Badge/Badge.tsx +151 -557
  28. package/src/components/data-display/Badge/Badge.variants.ts +106 -0
  29. package/src/components/data-display/Badge/BadgeContent.tsx +107 -0
  30. package/src/components/data-display/Banner/Banner.stories.tsx +5 -1
  31. package/src/components/data-display/Banner/Banner.styles.ts +120 -0
  32. package/src/components/data-display/Banner/Banner.tsx +179 -224
  33. package/src/components/data-display/Chart/Chart.md +48 -1
  34. package/src/components/data-display/Chart/Chart.tsx +82 -500
  35. package/src/components/data-display/Chart/Chart.types.ts +2 -0
  36. package/src/components/data-display/Chart/ChartComposables.tsx +121 -0
  37. package/src/components/data-display/Chart/ChartSpec.types.ts +70 -0
  38. package/src/components/data-display/Chart/SpecChart.stories.tsx +150 -0
  39. package/src/components/data-display/Chart/SpecChart.test.stories.tsx +56 -0
  40. package/src/components/data-display/Chart/SpecChart.tsx +53 -0
  41. package/src/components/data-display/Chart/__tests__/SpecChart.test.tsx +60 -0
  42. package/src/components/data-display/Chart/__tests__/chart-format.test.ts +43 -0
  43. package/src/components/data-display/Chart/__tests__/chart-spec.test.ts +119 -0
  44. package/src/components/data-display/Chart/chart-format.ts +26 -0
  45. package/src/components/data-display/Chart/chart-internals.ts +148 -0
  46. package/src/components/data-display/Chart/chart-renderers.tsx +338 -0
  47. package/src/components/data-display/Chart/chart-spec-registry.ts +74 -0
  48. package/src/components/data-display/Chart/chart-spec.ts +171 -0
  49. package/src/components/data-display/Chart/index.ts +30 -0
  50. package/src/components/data-display/Chip/Chip.helpers.tsx +131 -0
  51. package/src/components/data-display/Chip/Chip.stories.tsx +2 -1
  52. package/src/components/data-display/Chip/Chip.test.stories.tsx +11 -8
  53. package/src/components/data-display/Chip/Chip.tsx +31 -94
  54. package/src/components/data-display/DataGrid/DataGrid.body.tsx +141 -0
  55. package/src/components/data-display/DataGrid/DataGrid.cells.tsx +238 -0
  56. package/src/components/data-display/DataGrid/DataGrid.model.ts +315 -0
  57. package/src/components/data-display/DataGrid/DataGrid.rows.ts +112 -0
  58. package/src/components/data-display/DataGrid/DataGrid.states.tsx +102 -0
  59. package/src/components/data-display/DataGrid/DataGrid.test.stories.tsx +6 -12
  60. package/src/components/data-display/DataGrid/DataGrid.tsx +129 -725
  61. package/src/components/data-display/DataViews/DataViewsGrid.tsx +187 -0
  62. package/src/components/data-display/DataViews/DataViewsTableBase.tsx +400 -0
  63. package/src/components/data-display/DataViews/ManageViewsDialog.tsx +140 -0
  64. package/src/components/data-display/DataViews/SaveViewModal.tsx +289 -0
  65. package/src/components/data-display/DataViews/__tests__/DataViewsGrid.test.tsx +271 -0
  66. package/src/components/data-display/DataViews/__tests__/DataViewsTableBase.test.tsx +134 -0
  67. package/src/components/data-display/DataViews/__tests__/SaveViewModal.test.tsx +83 -0
  68. package/src/components/data-display/DataViews/__tests__/data-views-filter.test.ts +115 -0
  69. package/src/components/data-display/DataViews/__tests__/data-views-preview.test.ts +53 -0
  70. package/src/components/data-display/DataViews/__tests__/range-pill.test.tsx +114 -0
  71. package/src/components/data-display/DataViews/base-card.stories.tsx +136 -0
  72. package/src/components/data-display/DataViews/base-card.tsx +278 -0
  73. package/src/components/data-display/DataViews/data-views-filter-panel.tsx +184 -0
  74. package/src/components/data-display/DataViews/data-views-filter.ts +138 -0
  75. package/src/components/data-display/DataViews/data-views-grid-helpers.tsx +248 -0
  76. package/src/components/data-display/DataViews/data-views-grid-parts.tsx +400 -0
  77. package/src/components/data-display/DataViews/data-views-inline-bar.tsx +257 -0
  78. package/src/components/data-display/DataViews/data-views-layout-context.tsx +176 -0
  79. package/src/components/data-display/DataViews/data-views-pagination.tsx +31 -0
  80. package/src/components/data-display/DataViews/data-views-preview.ts +53 -0
  81. package/src/components/data-display/DataViews/data-views-range-pill.tsx +277 -0
  82. package/src/components/data-display/DataViews/data-views-table-parts.tsx +150 -0
  83. package/src/components/data-display/DataViews/data-views-toolbar.tsx +149 -0
  84. package/src/components/data-display/DataViews/data-views-types.ts +312 -0
  85. package/src/components/data-display/DataViews/data-views-view-mutations.ts +68 -0
  86. package/src/components/data-display/DataViews/index.ts +33 -0
  87. package/src/components/data-display/DataViews/use-data-views-state.ts +349 -0
  88. package/src/components/data-display/DateTimeDisplay/DateTimeDisplay.hooks.ts +104 -0
  89. package/src/components/data-display/DateTimeDisplay/DateTimeDisplay.tsx +68 -118
  90. package/src/components/data-display/DescriptionItem/DescriptionItem.stories.tsx +1 -1
  91. package/src/components/data-display/DescriptionItem/DescriptionItem.tsx +52 -34
  92. package/src/components/data-display/EmptyState/EmptyState.test.stories.tsx +6 -6
  93. package/src/components/data-display/EmptyState/EmptyState.tsx +218 -135
  94. package/src/components/data-display/ErrorState/ErrorState.test.stories.tsx +2 -2
  95. package/src/components/data-display/ErrorState/ErrorState.tsx +83 -55
  96. package/src/components/data-display/HoverCard/HoverCard.stories.tsx +3 -1
  97. package/src/components/data-display/HoverCard/HoverCard.test.stories.tsx +5 -5
  98. package/src/components/data-display/InteractiveTooltip/InteractiveTooltip.hooks.ts +99 -0
  99. package/src/components/data-display/InteractiveTooltip/InteractiveTooltip.styles.ts +87 -0
  100. package/src/components/data-display/InteractiveTooltip/InteractiveTooltip.tsx +28 -155
  101. package/src/components/data-display/LazyImage/LazyImage.hooks.ts +203 -0
  102. package/src/components/data-display/LazyImage/LazyImage.md +1 -1
  103. package/src/components/data-display/LazyImage/LazyImage.stories.tsx +3 -3
  104. package/src/components/data-display/LazyImage/LazyImage.tsx +144 -243
  105. package/src/components/data-display/Lightbox/Lightbox.constants.ts +53 -0
  106. package/src/components/data-display/Lightbox/Lightbox.helpers.ts +39 -0
  107. package/src/components/data-display/Lightbox/Lightbox.hooks.ts +259 -0
  108. package/src/components/data-display/Lightbox/Lightbox.test.stories.tsx +28 -35
  109. package/src/components/data-display/Lightbox/Lightbox.tsx +98 -658
  110. package/src/components/data-display/Lightbox/LightboxControls.tsx +152 -0
  111. package/src/components/data-display/Lightbox/LightboxCurrentMedia.tsx +50 -0
  112. package/src/components/data-display/Lightbox/LightboxMedia.tsx +76 -0
  113. package/src/components/data-display/Lightbox/LightboxOverlay.tsx +83 -0
  114. package/src/components/data-display/Lightbox/LightboxStage.tsx +97 -0
  115. package/src/components/data-display/Lightbox/LightboxThumbnails.tsx +83 -0
  116. package/src/components/data-display/Lightbox/useLightbox.ts +80 -0
  117. package/src/components/data-display/LoadingState/LoadingState.helpers.ts +52 -0
  118. package/src/components/data-display/LoadingState/LoadingState.tsx +117 -87
  119. package/src/components/data-display/MapPreview/MapControlBar.tsx +116 -0
  120. package/src/components/data-display/MapPreview/MapDecorations.tsx +155 -0
  121. package/src/components/data-display/MapPreview/MapLayers.tsx +70 -0
  122. package/src/components/data-display/MapPreview/MapMarkers.tsx +84 -0
  123. package/src/components/data-display/MapPreview/MapOverlays.tsx +68 -0
  124. package/src/components/data-display/MapPreview/MapPreview.constants.ts +19 -0
  125. package/src/components/data-display/MapPreview/MapPreview.helpers.ts +63 -0
  126. package/src/components/data-display/MapPreview/MapPreview.hooks.ts +265 -0
  127. package/src/components/data-display/MapPreview/MapPreview.test.stories.tsx +14 -10
  128. package/src/components/data-display/MapPreview/MapPreview.tsx +52 -882
  129. package/src/components/data-display/MapPreview/MapPreview.types.ts +8 -1
  130. package/src/components/data-display/MapPreview/MapSearchBar.tsx +64 -0
  131. package/src/components/data-display/MapPreview/MapTiles.tsx +70 -0
  132. package/src/components/data-display/MapPreview/StaticMapView.tsx +63 -0
  133. package/src/components/data-display/MapPreview/mapProjection.ts +52 -0
  134. package/src/components/data-display/MapPreview/mapSurface.ts +37 -0
  135. package/src/components/data-display/MapPreview/useMapPreview.ts +62 -0
  136. package/src/components/data-display/Popover/Popover.test.stories.tsx +13 -19
  137. package/src/components/data-display/Progress/Progress.helpers.ts +37 -0
  138. package/src/components/data-display/Progress/Progress.styles.ts +101 -0
  139. package/src/components/data-display/Progress/Progress.tsx +185 -213
  140. package/src/components/data-display/SectionOnboarding/SectionOnboarding.stories.tsx +1 -1
  141. package/src/components/data-display/SectionOnboarding/SectionOnboarding.tsx +1 -1
  142. package/src/components/data-display/StatCard/StatCard.md +117 -0
  143. package/src/components/data-display/StatCard/StatCard.stories.tsx +167 -0
  144. package/src/components/data-display/StatCard/StatCard.test.stories.tsx +240 -0
  145. package/src/components/data-display/StatCard/StatCard.tsx +236 -0
  146. package/src/components/data-display/StatCard/StatCard.types.ts +62 -0
  147. package/src/components/data-display/StatCard/index.ts +7 -0
  148. package/src/components/data-display/Stepper/Stepper.test.stories.tsx +12 -19
  149. package/src/components/data-display/Stepper/Stepper.tsx +1 -1
  150. package/src/components/data-display/Table/Table.helpers.ts +31 -0
  151. package/src/components/data-display/Table/Table.hooks.ts +161 -0
  152. package/src/components/data-display/Table/Table.stories.tsx +3 -1
  153. package/src/components/data-display/Table/Table.styles.ts +223 -0
  154. package/src/components/data-display/Table/Table.test.stories.tsx +4 -4
  155. package/src/components/data-display/Table/Table.tsx +291 -748
  156. package/src/components/data-display/Table/TableParts.hooks.tsx +112 -0
  157. package/src/components/data-display/Table/TableParts.tsx +298 -0
  158. package/src/components/data-display/Table/TableStates.tsx +21 -0
  159. package/src/components/data-display/Timeline/Timeline.stories.tsx +10 -12
  160. package/src/components/data-display/Timeline/Timeline.test.stories.tsx +30 -44
  161. package/src/components/data-display/Timeline/Timeline.tsx +23 -284
  162. package/src/components/data-display/Timeline/TimelineRow.tsx +346 -0
  163. package/src/components/data-display/TimingDiagram/TimingDiagram.tsx +38 -311
  164. package/src/components/data-display/TimingDiagram/TimingDiagram.views.tsx +346 -0
  165. package/src/components/data-display/Tooltip/Tooltip.stories.tsx +4 -1
  166. package/src/components/data-display/Tooltip/Tooltip.test.stories.tsx +44 -58
  167. package/src/components/data-display/Tooltip/Tooltip.tsx +67 -62
  168. package/src/components/data-display/index.ts +1 -0
  169. package/src/components/feedback/ConfirmAction/ConfirmAction.hooks.ts +96 -0
  170. package/src/components/feedback/ConfirmAction/ConfirmAction.md +140 -0
  171. package/src/components/feedback/ConfirmAction/ConfirmAction.parts.tsx +154 -0
  172. package/src/components/feedback/ConfirmAction/ConfirmAction.stories.tsx +146 -0
  173. package/src/components/feedback/ConfirmAction/ConfirmAction.test.stories.tsx +114 -0
  174. package/src/components/feedback/ConfirmAction/ConfirmAction.tsx +46 -0
  175. package/src/components/feedback/ConfirmAction/ConfirmAction.types.ts +111 -0
  176. package/src/components/feedback/ConfirmAction/ConfirmButton.tsx +18 -0
  177. package/src/components/feedback/ConfirmAction/__tests__/confirm-action.test.tsx +288 -0
  178. package/src/components/feedback/ConfirmAction/index.ts +16 -0
  179. package/src/components/feedback/ConfirmAction/with-confirmation.tsx +112 -0
  180. package/src/components/feedback/Dialog/Dialog.styles.ts +4 -2
  181. package/src/components/feedback/Dialog/Dialog.tsx +26 -1
  182. package/src/components/feedback/Dialog/__tests__/dialog-content-spacing.test.tsx +66 -0
  183. package/src/components/feedback/Modal/Modal.md +1 -1
  184. package/src/components/feedback/Modal/Modal.stories.tsx +2 -2
  185. package/src/components/feedback/Sonner/Sonner.tsx +104 -288
  186. package/src/components/feedback/Sonner/Sonner.types.ts +7 -0
  187. package/src/components/feedback/Sonner/SonnerToast.tsx +216 -0
  188. package/src/components/feedback/StackedModal/StackedModal.hooks.ts +226 -0
  189. package/src/components/feedback/StackedModal/StackedModal.parts.tsx +311 -0
  190. package/src/components/feedback/StackedModal/StackedModal.stories.tsx +13 -15
  191. package/src/components/feedback/StackedModal/StackedModal.styles.ts +193 -0
  192. package/src/components/feedback/StackedModal/StackedModal.tsx +100 -619
  193. package/src/components/feedback/StackedModal/StackedModal.types.ts +17 -3
  194. package/src/components/feedback/StackedModal/__tests__/stacked-modal-viewport.test.tsx +104 -0
  195. package/src/components/feedback/StackedModal/modal-stack.tsx +119 -0
  196. package/src/components/feedback/Toast/Toast.tsx +92 -81
  197. package/src/components/feedback/TutorialOverlay/TutorialOverlay.geometry.ts +65 -0
  198. package/src/components/feedback/TutorialOverlay/TutorialOverlay.hooks.ts +185 -0
  199. package/src/components/feedback/TutorialOverlay/TutorialOverlay.test.stories.tsx +2 -2
  200. package/src/components/feedback/TutorialOverlay/TutorialOverlay.tsx +156 -414
  201. package/src/components/feedback/TutorialOverlay/TutorialStepBody.tsx +255 -0
  202. package/src/components/feedback/index.ts +1 -0
  203. package/src/components/form/AddressAutocomplete/AddressAutocomplete.helpers.ts +58 -0
  204. package/src/components/form/AddressAutocomplete/AddressAutocomplete.hooks.ts +93 -0
  205. package/src/components/form/AddressAutocomplete/AddressAutocomplete.mapper.ts +57 -0
  206. package/src/components/form/AddressAutocomplete/AddressAutocomplete.stories.tsx +4 -2
  207. package/src/components/form/AddressAutocomplete/AddressAutocomplete.test.stories.tsx +20 -16
  208. package/src/components/form/AddressAutocomplete/AddressAutocomplete.tsx +26 -829
  209. package/src/components/form/AddressAutocomplete/AddressAutocomplete.types.ts +11 -0
  210. package/src/components/form/AddressAutocomplete/AddressAutocompleteField.tsx +86 -0
  211. package/src/components/form/AddressAutocomplete/AddressFallbackField.tsx +64 -0
  212. package/src/components/form/AddressAutocomplete/AddressInputField.tsx +80 -0
  213. package/src/components/form/AddressAutocomplete/AddressOption.tsx +83 -0
  214. package/src/components/form/AddressAutocomplete/AddressSuggestionsPaper.tsx +24 -0
  215. package/src/components/form/AddressAutocomplete/AddressTextField.tsx +43 -0
  216. package/src/components/form/AddressAutocomplete/mockPlaces.ts +208 -0
  217. package/src/components/form/AddressAutocomplete/useAddressPredictions.ts +136 -0
  218. package/src/components/form/AddressAutocomplete/useAddressSelection.ts +113 -0
  219. package/src/components/form/AddressAutocomplete/useCurrentLocation.ts +116 -0
  220. package/src/components/form/AddressAutocomplete/useGoogleMapsAPI.ts +75 -0
  221. package/src/components/form/Button/Button.helpers.ts +36 -0
  222. package/src/components/form/Button/Button.stories.tsx +4 -1
  223. package/src/components/form/Button/Button.styles.ts +225 -0
  224. package/src/components/form/Button/Button.test.stories.tsx +25 -21
  225. package/src/components/form/Button/Button.tsx +45 -252
  226. package/src/components/form/Calendar/Calendar.dates.ts +100 -0
  227. package/src/components/form/Calendar/Calendar.helpers.ts +32 -0
  228. package/src/components/form/Calendar/Calendar.hooks.ts +278 -0
  229. package/src/components/form/Calendar/Calendar.keyboard.ts +32 -0
  230. package/src/components/form/Calendar/Calendar.selection.ts +156 -0
  231. package/src/components/form/Calendar/Calendar.test.stories.tsx +33 -34
  232. package/src/components/form/Calendar/Calendar.tsx +63 -551
  233. package/src/components/form/Calendar/Calendar.types.ts +16 -0
  234. package/src/components/form/Calendar/CalendarDay.tsx +127 -0
  235. package/src/components/form/Calendar/CalendarDayCell.tsx +52 -0
  236. package/src/components/form/Calendar/CalendarMonth.tsx +128 -0
  237. package/src/components/form/CepField/CepField.md +138 -0
  238. package/src/components/form/CepField/CepField.stories.tsx +138 -0
  239. package/src/components/form/CepField/CepField.test.stories.tsx +281 -0
  240. package/src/components/form/CepField/CepField.tsx +211 -0
  241. package/src/components/form/CepField/CepField.types.ts +73 -0
  242. package/src/components/form/CepField/index.ts +2 -0
  243. package/src/components/form/Checkbox/Checkbox.helpers.ts +28 -0
  244. package/src/components/form/Checkbox/Checkbox.tsx +19 -16
  245. package/src/components/form/CodeEditor/CodeEditor.helpers.ts +45 -0
  246. package/src/components/form/CodeEditor/CodeEditor.hooks.ts +104 -0
  247. package/src/components/form/CodeEditor/CodeEditor.monaco.ts +109 -0
  248. package/src/components/form/CodeEditor/CodeEditor.test.stories.tsx +17 -18
  249. package/src/components/form/CodeEditor/CodeEditor.tsx +81 -330
  250. package/src/components/form/CodeEditor/CodeEditorToolbar.tsx +168 -0
  251. package/src/components/form/Command/Command.hooks.ts +207 -0
  252. package/src/components/form/Command/Command.parts.tsx +58 -0
  253. package/src/components/form/Command/Command.styles.ts +83 -0
  254. package/src/components/form/Command/Command.tsx +61 -270
  255. package/src/components/form/CreatableSelect/CreatableSelect.md +1 -1
  256. package/src/components/form/CreatableSelect/CreatableSelect.test.stories.tsx +1 -1
  257. package/src/components/form/CreatableSelect/CreatableSelect.tsx +152 -71
  258. package/src/components/form/CreatableSelect/CreatableSelect.types.ts +13 -0
  259. package/src/components/form/HeaderButton/HeaderButton.tsx +80 -0
  260. package/src/components/form/HeaderButton/index.ts +2 -0
  261. package/src/components/form/Input/Input.stories.tsx +5 -1
  262. package/src/components/form/Input/Input.styles.ts +176 -0
  263. package/src/components/form/Input/Input.test.stories.tsx +30 -23
  264. package/src/components/form/Input/Input.tsx +71 -211
  265. package/src/components/form/Input/Input.types.ts +11 -0
  266. package/src/components/form/InputOTP/InputOTP.test.stories.tsx +9 -17
  267. package/src/components/form/Menubar/Menubar.test.stories.tsx +4 -8
  268. package/src/components/form/PasswordStrength/PasswordStrength.helpers.tsx +117 -0
  269. package/src/components/form/PasswordStrength/PasswordStrength.test.stories.tsx +3 -3
  270. package/src/components/form/PasswordStrength/PasswordStrength.tsx +202 -255
  271. package/src/components/form/PhoneInput/PhoneInput.hooks.ts +134 -0
  272. package/src/components/form/PhoneInput/PhoneInput.test.stories.tsx +4 -4
  273. package/src/components/form/PhoneInput/PhoneInput.tsx +279 -292
  274. package/src/components/form/PhoneInput/countries.ts +54 -0
  275. package/src/components/form/PhoneInput/phone.ts +47 -0
  276. package/src/components/form/RadioGroup/RadioGroup.test.stories.tsx +9 -9
  277. package/src/components/form/RichTextEditor/RichTextEditor.dom.ts +124 -0
  278. package/src/components/form/RichTextEditor/RichTextEditor.format.ts +61 -0
  279. package/src/components/form/RichTextEditor/RichTextEditor.hooks.ts +142 -0
  280. package/src/components/form/RichTextEditor/RichTextEditor.test.stories.tsx +5 -12
  281. package/src/components/form/RichTextEditor/RichTextEditor.tsx +98 -410
  282. package/src/components/form/RichTextEditor/RichTextEditorToolbar.tsx +187 -0
  283. package/src/components/form/SearchPalette/SearchPalette.parts.tsx +22 -0
  284. package/src/components/form/SearchPalette/SearchPalette.tsx +13 -9
  285. package/src/components/form/Select/Select.test.stories.tsx +35 -27
  286. package/src/components/form/Slider/Slider.test.stories.tsx +9 -11
  287. package/src/components/form/Switch/Switch.md +2 -1
  288. package/src/components/form/Switch/Switch.test.stories.tsx +6 -6
  289. package/src/components/form/Textarea/Textarea.styles.ts +143 -0
  290. package/src/components/form/Textarea/Textarea.test.stories.tsx +20 -26
  291. package/src/components/form/Textarea/Textarea.tsx +114 -535
  292. package/src/components/form/Textarea/TextareaRichEditor.tsx +377 -0
  293. package/src/components/form/Toggle/Toggle.styles.ts +211 -0
  294. package/src/components/form/Toggle/Toggle.test.stories.tsx +19 -27
  295. package/src/components/form/Toggle/Toggle.tsx +10 -185
  296. package/src/components/form/UploadButton/UploadButton.hooks.ts +323 -0
  297. package/src/components/form/UploadButton/UploadButton.parts.tsx +210 -0
  298. package/src/components/form/UploadButton/UploadButton.stories.tsx +2 -1
  299. package/src/components/form/UploadButton/UploadButton.test.stories.tsx +123 -4
  300. package/src/components/form/UploadButton/UploadButton.tsx +76 -305
  301. package/src/components/form/UploadButton/UploadButton.types.ts +16 -0
  302. package/src/components/form/index.ts +1 -0
  303. package/src/components/form/total-form/Fields/CepField.tsx +143 -0
  304. package/src/components/form/total-form/Fields/ToggleField.tsx +61 -0
  305. package/src/components/form/total-form/Fields/index.ts +4 -0
  306. package/src/components/form/total-form/FormContainer.tsx +3 -3
  307. package/src/components/form/total-form/SubmitButton.tsx +25 -2
  308. package/src/components/form/total-form/total-form.test.tsx +118 -1
  309. package/src/components/layout/Accordion/Accordion.md +1 -1
  310. package/src/components/layout/Accordion/Accordion.stories.tsx +5 -1
  311. package/src/components/layout/Accordion/Accordion.styles.ts +80 -0
  312. package/src/components/layout/Accordion/Accordion.test.stories.tsx +32 -50
  313. package/src/components/layout/Accordion/Accordion.tsx +2 -75
  314. package/src/components/layout/Card/Card.helpers.ts +30 -0
  315. package/src/components/layout/Card/Card.stories.tsx +9 -11
  316. package/src/components/layout/Card/Card.styles.ts +182 -0
  317. package/src/components/layout/Card/Card.test.stories.tsx +46 -46
  318. package/src/components/layout/Card/Card.tsx +24 -241
  319. package/src/components/layout/CardGrid/CardGrid.md +96 -0
  320. package/src/components/layout/CardGrid/CardGrid.tsx +140 -0
  321. package/src/components/layout/CardGrid/__tests__/CardGrid.test.tsx +92 -0
  322. package/src/components/layout/CardGrid/index.ts +2 -0
  323. package/src/components/layout/Collapsible/Collapsible.helpers.ts +83 -0
  324. package/src/components/layout/Collapsible/Collapsible.test.stories.tsx +7 -3
  325. package/src/components/layout/Collapsible/Collapsible.tsx +111 -107
  326. package/src/components/layout/Container/Container.test.stories.tsx +11 -16
  327. package/src/components/layout/ContentToolbar/ColumnsMenu.tsx +1 -1
  328. package/src/components/layout/ContentToolbar/ContentToolbar.tsx +120 -44
  329. package/src/components/layout/ContentToolbar/ContentToolbar.types.ts +9 -0
  330. package/src/components/layout/ContentToolbar/FilterTrigger.tsx +1 -1
  331. package/src/components/layout/ContentToolbar/MultiSelectDropdown.tsx +58 -43
  332. package/src/components/layout/ContentToolbar/MultiSelectTriggers.tsx +139 -0
  333. package/src/components/layout/ContentToolbar/SavedViewsMenu.tsx +10 -3
  334. package/src/components/layout/ContentToolbar/SortByDropdown.tsx +35 -11
  335. package/src/components/layout/ContentToolbar/ViewSelector.tsx +5 -6
  336. package/src/components/layout/ContentToolbar/__tests__/MultiSelectDropdown.test.tsx +21 -0
  337. package/src/components/layout/Dashboard/Dashboard.test.stories.tsx +27 -1
  338. package/src/components/layout/Dashboard/Dashboard.tsx +27 -8
  339. package/src/components/layout/Dashboard/DashboardParts.tsx +12 -19
  340. package/src/components/layout/Dashboard/index.ts +2 -1
  341. package/src/components/layout/Drawer/Drawer.stories.tsx +8 -10
  342. package/src/components/layout/Drawer/Drawer.test.stories.tsx +18 -14
  343. package/src/components/layout/Drawer/Drawer.tsx +67 -53
  344. package/src/components/layout/Resizable/Resizable.helpers.ts +133 -0
  345. package/src/components/layout/Resizable/Resizable.hooks.ts +68 -0
  346. package/src/components/layout/Resizable/Resizable.tsx +38 -153
  347. package/src/components/layout/ScrollArea/ScrollArea.helpers.ts +51 -0
  348. package/src/components/layout/ScrollArea/ScrollArea.styles.ts +248 -0
  349. package/src/components/layout/ScrollArea/ScrollArea.tsx +183 -374
  350. package/src/components/layout/ScrollArea/ScrollAreaContent.tsx +70 -0
  351. package/src/components/layout/ScrollArea/ScrollViewport.tsx +90 -0
  352. package/src/components/layout/Separator/Separator.styles.ts +128 -0
  353. package/src/components/layout/Separator/Separator.test.stories.tsx +3 -12
  354. package/src/components/layout/Separator/Separator.tsx +6 -132
  355. package/src/components/layout/SettingsLayout/SettingsLayout.parts.tsx +2 -1
  356. package/src/components/layout/SettingsLayout/SettingsLayout.stories.tsx +6 -8
  357. package/src/components/layout/Sidebar/Sidebar.stories.tsx +10 -12
  358. package/src/components/layout/Sidebar/Sidebar.test.stories.tsx +35 -37
  359. package/src/components/layout/Skeleton/Skeleton.helpers.ts +33 -0
  360. package/src/components/layout/Skeleton/Skeleton.styles.ts +114 -0
  361. package/src/components/layout/Skeleton/Skeleton.test.stories.tsx +3 -3
  362. package/src/components/layout/Skeleton/Skeleton.tsx +67 -155
  363. package/src/components/layout/TableFilter/TableFilter.tsx +2 -1
  364. package/src/components/navigation/Breadcrumbs/BreadcrumbEntry.tsx +305 -0
  365. package/src/components/navigation/Breadcrumbs/Breadcrumbs.md +2 -1
  366. package/src/components/navigation/Breadcrumbs/Breadcrumbs.stories.tsx +12 -14
  367. package/src/components/navigation/Breadcrumbs/Breadcrumbs.styles.tsx +212 -0
  368. package/src/components/navigation/Breadcrumbs/Breadcrumbs.test.stories.tsx +62 -61
  369. package/src/components/navigation/Breadcrumbs/Breadcrumbs.tsx +116 -429
  370. package/src/components/navigation/CommandPalette/CommandPalette.helpers.ts +82 -0
  371. package/src/components/navigation/CommandPalette/CommandPalette.hooks.ts +202 -0
  372. package/src/components/navigation/CommandPalette/CommandPalette.stories.tsx +3 -1
  373. package/src/components/navigation/CommandPalette/CommandPalette.test.stories.tsx +3 -5
  374. package/src/components/navigation/CommandPalette/CommandPalette.tsx +108 -341
  375. package/src/components/navigation/CommandPalette/CommandPaletteResults.tsx +182 -0
  376. package/src/components/navigation/CommandPalette/ShortcutChip.tsx +18 -0
  377. package/src/components/navigation/ContextMenu/ContextMenu.md +3 -1
  378. package/src/components/navigation/ContextMenu/ContextMenu.stories.tsx +4 -1
  379. package/src/components/navigation/ContextMenu/ContextMenu.test.stories.tsx +19 -24
  380. package/src/components/navigation/ContextMenu/ContextMenu.tsx +70 -54
  381. package/src/components/navigation/DropdownMenu/DropdownMenu.md +3 -1
  382. package/src/components/navigation/DropdownMenu/DropdownMenu.stories.tsx +17 -19
  383. package/src/components/navigation/DropdownMenu/DropdownMenu.test.stories.tsx +26 -26
  384. package/src/components/navigation/DropdownMenu/DropdownMenu.tsx +189 -111
  385. package/src/components/navigation/NavigationMenu/NavigationMegaSection.tsx +66 -0
  386. package/src/components/navigation/NavigationMenu/NavigationMenu.md +7 -2
  387. package/src/components/navigation/NavigationMenu/NavigationMenu.shell.tsx +218 -0
  388. package/src/components/navigation/NavigationMenu/NavigationMenu.styles.ts +223 -0
  389. package/src/components/navigation/NavigationMenu/NavigationMenu.tsx +119 -808
  390. package/src/components/navigation/NavigationMenu/NavigationMenuItem.hooks.ts +126 -0
  391. package/src/components/navigation/NavigationMenu/NavigationMenuItem.tsx +352 -0
  392. package/src/components/navigation/NavigationMenu/NavigationStandardBody.tsx +148 -0
  393. package/src/components/navigation/NavigationMenu/stories/NavigationMenu.stories.tsx +15 -17
  394. package/src/components/navigation/NavigationMenu/stories/NavigationMenu.test.stories.tsx +27 -23
  395. package/src/components/navigation/NavigationMenu/stories/NavigationMenuHorizontal.stories.tsx +11 -13
  396. package/src/components/navigation/NavigationMenu/stories/NavigationMenuVertical.stories.tsx +9 -11
  397. package/src/components/navigation/Pagination/Pagination.helpers.tsx +85 -0
  398. package/src/components/navigation/Pagination/Pagination.md +2 -1
  399. package/src/components/navigation/Pagination/Pagination.stories.tsx +4 -6
  400. package/src/components/navigation/Pagination/Pagination.styles.ts +135 -0
  401. package/src/components/navigation/Pagination/Pagination.tsx +178 -313
  402. package/src/components/navigation/Pagination/PaginationParts.tsx +81 -0
  403. package/src/components/navigation/Tabs/Tabs.md +3 -1
  404. package/src/components/navigation/Tabs/Tabs.stories.tsx +21 -23
  405. package/src/components/navigation/Tabs/Tabs.styles.ts +163 -0
  406. package/src/components/navigation/Tabs/Tabs.test.stories.tsx +37 -37
  407. package/src/components/navigation/Tabs/Tabs.tsx +192 -361
  408. package/src/components/navigation/Tabs/TabsPanel.tsx +100 -0
  409. package/src/components/typography/Blockquote/Blockquote.tsx +1 -1
  410. package/src/components/typography/Code/Code.test.stories.tsx +5 -5
  411. package/src/components/typography/Code/Code.tsx +74 -49
  412. package/src/components/typography/Heading/Heading.test.stories.tsx +8 -8
  413. package/src/components/typography/Paragraph/Paragraph.test.stories.tsx +5 -12
  414. package/src/components/typography/Text/Text.tsx +84 -77
  415. package/src/components/utility/AnimatedIcon/AnimatedIcon.md +4 -4
  416. package/src/components/utility/AnimatedIcon/AnimatedIcon.stories.tsx +19 -21
  417. package/src/components/utility/AnimatedIcon/AnimatedIcon.test.stories.tsx +19 -12
  418. package/src/components/utility/AspectRatio/AspectRatio.test.stories.tsx +9 -9
  419. package/src/components/utility/InfiniteScroll/InfiniteScroll.hooks.ts +118 -0
  420. package/src/components/utility/InfiniteScroll/InfiniteScroll.parts.tsx +54 -0
  421. package/src/components/utility/InfiniteScroll/InfiniteScroll.test.stories.tsx +12 -9
  422. package/src/components/utility/InfiniteScroll/InfiniteScroll.tsx +29 -148
  423. package/src/components/utility/InstallPrompt/InstallPrompt.helpers.ts +124 -0
  424. package/src/components/utility/InstallPrompt/InstallPrompt.md +113 -0
  425. package/src/components/utility/InstallPrompt/InstallPrompt.stories.tsx +118 -0
  426. package/src/components/utility/InstallPrompt/InstallPrompt.styles.ts +50 -0
  427. package/src/components/utility/InstallPrompt/InstallPrompt.test.stories.tsx +83 -0
  428. package/src/components/utility/InstallPrompt/InstallPrompt.tsx +192 -0
  429. package/src/components/utility/InstallPrompt/InstallPrompt.types.ts +78 -0
  430. package/src/components/utility/InstallPrompt/__tests__/InstallPrompt.ios.test.tsx +65 -0
  431. package/src/components/utility/InstallPrompt/__tests__/usePwaInstall.test.tsx +271 -0
  432. package/src/components/utility/InstallPrompt/index.ts +10 -0
  433. package/src/components/utility/InstallPrompt/usePwaInstall.ts +171 -0
  434. package/src/components/utility/Transition/Transition.helpers.ts +40 -0
  435. package/src/components/utility/Transition/Transition.tsx +17 -68
  436. package/src/components/utility/VirtualList/VirtualList.hooks.ts +319 -0
  437. package/src/components/utility/VirtualList/VirtualList.test.stories.tsx +49 -38
  438. package/src/components/utility/VirtualList/VirtualList.tsx +110 -315
  439. package/src/components/utility/WorkflowStep/WorkflowStep.helpers.ts +151 -0
  440. package/src/components/utility/WorkflowStep/WorkflowStep.parts.tsx +371 -0
  441. package/src/components/utility/WorkflowStep/WorkflowStep.stories.tsx +9 -11
  442. package/src/components/utility/WorkflowStep/WorkflowStep.test.stories.tsx +7 -7
  443. package/src/components/utility/WorkflowStep/WorkflowStep.tsx +51 -449
  444. package/src/components/utility/WorkflowStep/WorkflowStepRow.tsx +96 -0
  445. package/src/components/utility/index.ts +1 -0
  446. package/src/mui/Link.ts +2 -0
  447. package/src/utils/index.ts +2 -1
  448. package/src/utils/viewport.ts +65 -0
@@ -1,17 +1,15 @@
1
- import {
2
- AccountTree,
3
- Analytics,
4
- Article,
5
- Category,
6
- CloudUpload,
7
- Code,
8
- Dashboard,
9
- Folder,
10
- Home,
11
- Security,
12
- Settings,
13
- Storage,
14
- } from '@mui/icons-material';
1
+ import AccountTree from '@mui/icons-material/AccountTree';
2
+ import Analytics from '@mui/icons-material/Analytics';
3
+ import Article from '@mui/icons-material/Article';
4
+ import Category from '@mui/icons-material/Category';
5
+ import CloudUpload from '@mui/icons-material/CloudUpload';
6
+ import Code from '@mui/icons-material/Code';
7
+ import Dashboard from '@mui/icons-material/Dashboard';
8
+ import Folder from '@mui/icons-material/Folder';
9
+ import Home from '@mui/icons-material/Home';
10
+ import Security from '@mui/icons-material/Security';
11
+ import Settings from '@mui/icons-material/Settings';
12
+ import Storage from '@mui/icons-material/Storage';
15
13
  import { Box, createTheme, CssBaseline, Paper, Stack,ThemeProvider } from '@mui/material';
16
14
  import { Button, Typography } from '@mui/material';
17
15
  import type { Meta, StoryObj } from '@storybook/react-vite';
@@ -0,0 +1,212 @@
1
+ import { alpha, keyframes } from '@mui/material';
2
+ import type { CSSObject, Theme } from '@mui/material/styles';
3
+
4
+ export const slideIn = keyframes`
5
+ from {
6
+ opacity: 0;
7
+ transform: translateX(-10px);
8
+ }
9
+ to {
10
+ opacity: 1;
11
+ transform: translateX(0);
12
+ }
13
+ `;
14
+
15
+ export const pulse = keyframes`
16
+ 0% {
17
+ box-shadow: 0 0 0 0 rgba(99, 102, 241, 0.4);
18
+ }
19
+ 70% {
20
+ box-shadow: 0 0 0 10px rgba(99, 102, 241, 0);
21
+ }
22
+ 100% {
23
+ box-shadow: 0 0 0 0 rgba(99, 102, 241, 0);
24
+ }
25
+ `;
26
+
27
+ const BAR_VARIANTS: Record<string, (theme: Theme, elevation: number) => CSSObject> = {
28
+ glass: (theme, elevation) => ({
29
+ background:
30
+ theme.palette.mode === 'dark' ? 'rgba(17, 24, 39, 0.7)' : 'rgba(255, 255, 255, 0.7)',
31
+ backdropFilter: 'blur(10px)',
32
+ WebkitBackdropFilter: 'blur(10px)',
33
+ border: `1px solid ${
34
+ theme.palette.mode === 'dark' ? 'rgba(255, 255, 255, 0.1)' : 'rgba(0, 0, 0, 0.1)'
35
+ }`,
36
+ boxShadow:
37
+ theme.palette.mode === 'dark'
38
+ ? `0 ${elevation * 4}px ${elevation * 8}px rgba(0, 0, 0, 0.3), inset 0 1px 0 rgba(255, 255, 255, 0.1)`
39
+ : `0 ${elevation * 4}px ${elevation * 8}px rgba(0, 0, 0, 0.08), inset 0 1px 0 rgba(255, 255, 255, 0.8)` }),
40
+ elevated: (theme, elevation) => ({
41
+ background: theme.palette.background.paper,
42
+ boxShadow: theme.shadows[elevation] || theme.shadows[1],
43
+ borderRadius: theme.spacing(1.5) }),
44
+ outlined: (theme, _elevation) => ({
45
+ border: `1px solid ${theme.palette.divider}`,
46
+ borderRadius: theme.spacing(1) }) };
47
+
48
+ // Spacing and colour for the separator glyphs between crumbs.
49
+ const separatorStyles = (
50
+ theme: Theme,
51
+ size: string | undefined,
52
+ color: string | undefined,
53
+ _visualStyle: string | undefined,
54
+ ): CSSObject => ({
55
+ '& .MuiBreadcrumbs-separator': {
56
+ marginLeft: theme.spacing(size === 'sm' ? 0.5 : size === 'lg' ? 1.5 : 1),
57
+ marginRight: theme.spacing(size === 'sm' ? 0.5 : size === 'lg' ? 1.5 : 1),
58
+ opacity: 0.6,
59
+ transition: 'all 0.2s ease',
60
+ ...(color === 'primary' && {
61
+ color: theme.palette.primary.main }),
62
+ ...(color === 'secondary' && {
63
+ color: theme.palette.secondary.main }) } });
64
+
65
+ // Only one visual style applies at a time, so a lookup replaces three mutually
66
+ // exclusive spreads.
67
+ const barVariantStyles = (theme: Theme, visualStyle: string | undefined, elevation: number): CSSObject =>
68
+ visualStyle ? (BAR_VARIANTS[visualStyle]?.(theme, elevation) ?? {}) : {};
69
+
70
+ // The bar's own styling, lifted out so the styled() callback is a single spread
71
+ // rather than seventy lines of conditionals.
72
+ export const breadcrumbsBarStyles = ({
73
+ theme,
74
+ size,
75
+ color,
76
+ visualStyle,
77
+ elevation = 0 }: {
78
+ theme: Theme;
79
+ size?: string;
80
+ color?: string;
81
+ visualStyle?: string;
82
+ elevation?: number;
83
+ }): CSSObject => ({
84
+ padding: theme.spacing(size === 'sm' ? 0.75 : size === 'lg' ? 1.5 : 1, 2),
85
+ borderRadius: theme.spacing(visualStyle === 'glass' ? 2 : 1),
86
+ ...barVariantStyles(theme, visualStyle, elevation),
87
+ animation: `${slideIn} 0.3s ease-out`,
88
+ transition: 'all 0.3s cubic-bezier(0.4, 0, 0.2, 1)',
89
+ position: 'relative',
90
+
91
+ // Glass morphism effect
92
+
93
+
94
+ // Elevated variant
95
+
96
+
97
+ // Outlined variant
98
+
99
+
100
+ '& .MuiBreadcrumbs-ol': {
101
+ alignItems: 'center',
102
+ flexWrap: 'nowrap',
103
+ [theme.breakpoints.down('sm')]: {
104
+ flexWrap: 'wrap',
105
+ gap: theme.spacing(0.5) } },
106
+
107
+ ...separatorStyles(theme, size, color, visualStyle),
108
+
109
+
110
+ '&:hover': {
111
+ ...(visualStyle === 'glass' && {
112
+ background:
113
+ theme.palette.mode === 'dark' ? 'rgba(17, 24, 39, 0.85)' : 'rgba(255, 255, 255, 0.85)',
114
+ boxShadow:
115
+ theme.palette.mode === 'dark'
116
+ ? `0 ${elevation * 6}px ${elevation * 12}px rgba(0, 0, 0, 0.4)`
117
+ : `0 ${elevation * 6}px ${elevation * 12}px rgba(0, 0, 0, 0.12)` }) } });
118
+
119
+ // The idle glass treatment and the active-crumb treatment are mutually
120
+ // exclusive; keeping them as named pieces takes both branches out of the main
121
+ // style function.
122
+ const linkGlassIdleStyles = (theme: Theme): CSSObject => ({
123
+ '&::before': {
124
+ content: '""',
125
+ position: 'absolute',
126
+ top: 0,
127
+ left: 0,
128
+ right: 0,
129
+ bottom: 0,
130
+ background: `linear-gradient(135deg, ${alpha(theme.palette.primary.main, 0)} 0%, ${alpha(theme.palette.primary.main, 0.05)} 100%)`,
131
+ opacity: 0,
132
+ transition: 'opacity 0.3s ease',
133
+ borderRadius: 'inherit' } });
134
+
135
+ const linkActiveStyles = (theme: Theme, visualStyle?: string): CSSObject => ({
136
+ pointerEvents: 'none',
137
+ cursor: 'default',
138
+ color: theme.palette.primary.main,
139
+ fontWeight: 600,
140
+
141
+ ...(visualStyle === 'glass' && {
142
+ background: `linear-gradient(135deg, ${alpha(theme.palette.primary.main, 0.1)} 0%, ${alpha(theme.palette.primary.main, 0.05)} 100%)`,
143
+ animation: `${pulse} 2s infinite` }) });
144
+
145
+ // Hover treatment. The tint is a touch stronger on the glass variant so it still
146
+ // reads against the translucent bar.
147
+ const linkHoverStyles = (theme: Theme, visualStyle?: string): CSSObject => ({
148
+ '&:hover, &[data-hover="true"]': {
149
+ color: theme.palette.primary.main,
150
+ backgroundColor: alpha(theme.palette.primary.main, visualStyle === 'glass' ? 0.1 : 0.08),
151
+ transform: 'translateY(-1px)',
152
+
153
+ '&::before': {
154
+ opacity: 1 },
155
+
156
+ '& .breadcrumb-icon': {
157
+ transform: 'scale(1.1)' } } });
158
+
159
+ export const breadcrumbLinkStyles = ({
160
+ theme,
161
+ size,
162
+ active,
163
+ visualStyle }: {
164
+ theme: Theme;
165
+ size?: string;
166
+ active?: boolean;
167
+ visualStyle?: string;
168
+ }): CSSObject => ({
169
+ ...(visualStyle === 'glass' && !active ? linkGlassIdleStyles(theme) : {}),
170
+ ...(active ? linkActiveStyles(theme, visualStyle) : {}),
171
+ display: 'flex',
172
+ alignItems: 'center',
173
+ gap: theme.spacing(0.5),
174
+ textDecoration: 'none',
175
+ fontSize: size === 'sm' ? '0.875rem' : size === 'lg' ? '1.125rem' : '1rem',
176
+ fontWeight: active ? 600 : 400,
177
+ color: active ? theme.palette.text.primary : theme.palette.text.secondary,
178
+ padding: theme.spacing(0.5, 0.75),
179
+ borderRadius: theme.spacing(0.75),
180
+ position: 'relative',
181
+ overflow: 'hidden',
182
+ transition: 'all 0.3s cubic-bezier(0.4, 0, 0.2, 1)',
183
+
184
+ // Add subtle background for glass variant
185
+
186
+
187
+ ...linkHoverStyles(theme, visualStyle),
188
+
189
+
190
+ '&:active': {
191
+ transform: 'translateY(0)',
192
+ backgroundColor: alpha(theme.palette.primary.main, 0.12) },
193
+
194
+ '&:focus-visible': {
195
+ outline: `2px solid ${theme.palette.primary.main}`,
196
+ outlineOffset: 2,
197
+ backgroundColor: alpha(theme.palette.primary.main, 0.04) },
198
+
199
+
200
+
201
+ '& .breadcrumb-icon': {
202
+ transition: 'transform 0.2s ease' },
203
+
204
+ // Mobile responsiveness
205
+ [theme.breakpoints.down('sm')]: {
206
+ fontSize: size === 'lg' ? '1rem' : size === 'sm' ? '0.75rem' : '0.875rem',
207
+ padding: theme.spacing(0.375, 0.5) } });
208
+
209
+ export const sizeIconMap = {
210
+ sm: 'small' as const,
211
+ md: 'small' as const,
212
+ lg: 'medium' as const };
@@ -1,4 +1,10 @@
1
- import { AccountTree, Article, Code,Dashboard, Folder, Home, Settings } from '@mui/icons-material';
1
+ import AccountTree from '@mui/icons-material/AccountTree';
2
+ import Article from '@mui/icons-material/Article';
3
+ import Code from '@mui/icons-material/Code';
4
+ import Dashboard from '@mui/icons-material/Dashboard';
5
+ import Folder from '@mui/icons-material/Folder';
6
+ import Home from '@mui/icons-material/Home';
7
+ import Settings from '@mui/icons-material/Settings';
2
8
  import type { Meta, StoryObj } from '@storybook/react-vite';
3
9
  import { expect, fn,userEvent, waitFor, within } from 'storybook/test';
4
10
 
@@ -228,43 +234,38 @@ export const KeyboardNavigation: Story = {
228
234
  await step('Tab navigation forward', async () => {
229
235
  const links = canvas.getAllByRole('link');
230
236
 
231
- // Ensure we have links to test
232
- await expect(links.length).toBeGreaterThan(0);
237
+ // This story renders a fixed trail, so assert the shape up front and then
238
+ // walk it unconditionally. The old version guarded every assertion behind
239
+ // a length check, so a breadcrumb that rendered one link would have passed
240
+ // the whole step without testing any navigation.
241
+ await expect(links.length).toBeGreaterThanOrEqual(3);
233
242
 
234
- // Focus first link
235
- if (links[0]) {
236
- links[0].focus();
237
- await expect(links[0]).toHaveFocus();
238
- }
243
+ await userEvent.tab();
244
+ await waitFor(() => expect(links[0]).toHaveFocus());
239
245
 
240
- // Tab to next link if available
241
- if (links.length > 1) {
242
- await userEvent.tab();
243
- await expect(links[1]).toHaveFocus();
244
- }
246
+ await userEvent.tab();
247
+ await waitFor(() => expect(links[1]).toHaveFocus());
245
248
 
246
- // Tab to third link if available
247
- if (links.length > 2) {
248
- await userEvent.tab();
249
- await expect(links[2]).toHaveFocus();
250
- }
249
+ await userEvent.tab();
250
+ await waitFor(() => expect(links[2]).toHaveFocus());
251
251
  });
252
252
 
253
253
  await step('Tab navigation backward', async () => {
254
254
  const links = canvas.getAllByRole('link');
255
255
 
256
- // Only test backward navigation if we have multiple links
257
- if (links.length > 1) {
258
- await userEvent.tab({ shift: true });
259
- // The focused element should move backward
260
- const focusedIndex = links.findIndex((link) => link === document.activeElement);
261
- await expect(focusedIndex).toBeGreaterThanOrEqual(0);
262
- }
256
+ // Focus is on the third link from the previous step; shift-tab steps back
257
+ // to the second one.
258
+ await userEvent.tab({ shift: true });
259
+ await waitFor(() => expect(links[1]).toHaveFocus());
263
260
  });
264
261
 
265
262
  await step('Enter key activation', async () => {
266
263
  const homeLink = canvas.getByRole('link', { name: /home/i });
267
- homeLink.focus();
264
+
265
+ // Shift-tab back to the first link rather than calling .focus() on it.
266
+ await userEvent.tab({ shift: true });
267
+ await waitFor(() => expect(homeLink).toHaveFocus());
268
+
268
269
  await userEvent.keyboard('{Enter}');
269
270
  // Verify navigation was prevented
270
271
  await expect(window.location.pathname).not.toContain('home');
@@ -272,7 +273,8 @@ export const KeyboardNavigation: Story = {
272
273
 
273
274
  await step('Focus visible on keyboard navigation', async () => {
274
275
  const link = canvas.getAllByRole('link')[0];
275
- link.focus();
276
+ // Focus is already on the first link from the previous step.
277
+ await waitFor(() => expect(link).toHaveFocus());
276
278
 
277
279
  const computedStyle = window.getComputedStyle(link);
278
280
  // Check for focus outline
@@ -379,18 +381,18 @@ export const FocusManagement: Story = {
379
381
 
380
382
  await step('Focus trap prevention', async () => {
381
383
  const links = canvas.getAllByRole('link');
382
- if (links.length >= 3) {
383
- const firstLink = links[0];
384
- const lastLink = links[links.length - 1];
385
-
386
- if (lastLink) {
387
- lastLink.focus();
388
- await userEvent.tab();
384
+ await expect(links.length).toBeGreaterThanOrEqual(3);
385
+ const lastLink = links[links.length - 1];
389
386
 
390
- // Focus should move outside the breadcrumb
391
- await expect(document.activeElement).not.toBe(firstLink);
392
- }
387
+ // Tab through every link to reach the last one, then once more: focus must
388
+ // leave the breadcrumb rather than wrap back to the start.
389
+ for (let i = 0; i < links.length; i++) {
390
+ await userEvent.tab();
393
391
  }
392
+ await waitFor(() => expect(lastLink).toHaveFocus());
393
+
394
+ await userEvent.tab();
395
+ await waitFor(() => expect(lastLink).not.toHaveFocus());
394
396
  });
395
397
 
396
398
  await step('Focus restoration after interaction', async () => {
@@ -398,15 +400,12 @@ export const FocusManagement: Story = {
398
400
  // Find a link with "products" or use the first available link
399
401
  const link = links.find((l) => l.textContent?.toLowerCase().includes('products')) || links[0];
400
402
 
401
- if (link) {
402
- link.focus();
403
- const initialFocused = document.activeElement;
404
-
405
- await userEvent.click(link);
403
+ await expect(link).toBeInTheDocument();
406
404
 
407
- // Focus should remain on the clicked element
408
- await expect(document.activeElement).toBe(initialFocused);
409
- }
405
+ // Clicking a link focuses it, so the pre-focus this step used to do only
406
+ // asserted that focus() works. Click, then check focus landed and stayed.
407
+ await userEvent.click(link);
408
+ await waitFor(() => expect(link).toHaveFocus());
410
409
  });
411
410
  },
412
411
  };
@@ -476,28 +475,30 @@ export const ResponsiveDesign: Story = {
476
475
  const nav = canvas.getByRole('navigation');
477
476
  const items = within(nav).getAllByRole('listitem');
478
477
 
479
- // Check if items are properly sized for mobile
480
- if (window.innerWidth <= 768) {
481
- const firstItem = items[0];
482
- const computedStyle = window.getComputedStyle(firstItem);
483
-
484
- // Font size should be appropriate for mobile
485
- const fontSize = parseFloat(computedStyle.fontSize);
486
- await expect(fontSize).toBeGreaterThanOrEqual(14);
487
- }
478
+ // Font size should be legible regardless of the runner's window size. The
479
+ // old `window.innerWidth <= 768` guard meant this assertion simply did not
480
+ // run on a wider viewport, so the story silently tested nothing there.
481
+ const computedStyle = window.getComputedStyle(items[0]);
482
+ const fontSize = parseFloat(computedStyle.fontSize);
483
+ await expect(fontSize).toBeGreaterThanOrEqual(14);
488
484
  });
489
485
 
490
486
  await step('Verify touch target sizes', async () => {
491
487
  const links = canvas.getAllByRole('link');
492
488
 
493
- links.forEach(async (link) => {
489
+ // for...of rather than forEach(async …): the old callbacks returned
490
+ // promises nobody awaited, so a failed assertion surfaced as an unhandled
491
+ // rejection instead of a failing step.
492
+ //
493
+ // The assertion is that each link renders with a real box. The previous
494
+ // 20px touch-target check ran only when the runner's window happened to be
495
+ // ≤768px wide, and its own comment notes MUI's breadcrumb targets can be
496
+ // smaller than that — so making it unconditional would have asserted
497
+ // something the component does not actually promise.
498
+ for (const link of links) {
494
499
  const rect = link.getBoundingClientRect();
495
- // Touch targets should be at least 20px on mobile (adjusted for actual MUI Breadcrumbs rendering)
496
- // MUI Breadcrumbs may have smaller touch targets but are still usable
497
- if (window.innerWidth <= 768) {
498
- await expect(rect.height).toBeGreaterThanOrEqual(20);
499
- }
500
- });
500
+ await expect(rect.height).toBeGreaterThan(0);
501
+ }
501
502
  });
502
503
  },
503
504
  };