@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
@@ -0,0 +1,80 @@
1
+ 'use client';
2
+
3
+ import { Box, Button } from '@mui/material';
4
+ import type { ButtonProps } from '@mui/material';
5
+ import type { ReactNode } from 'react';
6
+
7
+ type Breakpoint = 'sm' | 'md' | 'lg';
8
+
9
+ export interface HeaderButtonProps {
10
+ /** The label — shown next to the icon on wide screens, hidden (icon-only) below `collapseBelow`. */
11
+ text: ReactNode;
12
+ /** Leading icon/image — always visible. */
13
+ icon: ReactNode;
14
+ /** Optional trailing icon (e.g. a dropdown chevron) — always visible. */
15
+ endIcon?: ReactNode;
16
+ onClick?: ButtonProps['onClick'];
17
+ /** MUI variant. @default 'contained' */
18
+ variant?: ButtonProps['variant'];
19
+ /** MUI color. @default 'primary' */
20
+ color?: ButtonProps['color'];
21
+ disabled?: boolean;
22
+ /** Width below which the button collapses to icon-only. @default 'md' */
23
+ collapseBelow?: Breakpoint;
24
+ fullWidth?: boolean;
25
+ 'aria-haspopup'?: ButtonProps['aria-haspopup'];
26
+ 'aria-expanded'?: boolean;
27
+ dataTestId?: string;
28
+ }
29
+
30
+ /**
31
+ * A page-header action that adapts to width: below `collapseBelow` it renders
32
+ * ONLY its icon (compact, so several fit one line on phones); at/above it renders
33
+ * the icon + text label. The accessible name is always `text`, so the icon-only
34
+ * state stays labeled for screen readers.
35
+ */
36
+ export function HeaderButton({
37
+ text,
38
+ icon,
39
+ endIcon,
40
+ onClick,
41
+ variant = 'contained',
42
+ color = 'primary',
43
+ disabled,
44
+ collapseBelow = 'md',
45
+ fullWidth,
46
+ dataTestId,
47
+ ...aria
48
+ }: HeaderButtonProps): React.JSX.Element {
49
+ // Hide the label below the breakpoint; keep the icon(s). `gap` collapses around
50
+ // the display:none label, so on mobile it reads as a compact icon button.
51
+ const labelDisplay = { xs: 'none', [collapseBelow]: 'inline' };
52
+ const horizontalPad = { xs: 1, [collapseBelow]: 2 };
53
+ return (
54
+ <Button
55
+ variant={variant}
56
+ color={color}
57
+ size="medium"
58
+ onClick={onClick}
59
+ disabled={disabled}
60
+ fullWidth={fullWidth}
61
+ aria-label={typeof text === 'string' ? text : undefined}
62
+ aria-haspopup={aria['aria-haspopup']}
63
+ aria-expanded={aria['aria-expanded']}
64
+ data-testid={dataTestId}
65
+ sx={{ minWidth: 0, gap: 0.75, px: horizontalPad, py: 1, fontSize: '1rem', textTransform: 'none' }}
66
+ >
67
+ <Box component="span" sx={{ display: 'inline-flex', alignItems: 'center' }}>
68
+ {icon}
69
+ </Box>
70
+ <Box component="span" sx={{ display: labelDisplay }}>
71
+ {text}
72
+ </Box>
73
+ {endIcon != null && (
74
+ <Box component="span" sx={{ display: 'inline-flex', alignItems: 'center' }}>
75
+ {endIcon}
76
+ </Box>
77
+ )}
78
+ </Button>
79
+ );
80
+ }
@@ -0,0 +1,2 @@
1
+ export { HeaderButton } from './HeaderButton';
2
+ export type { HeaderButtonProps } from './HeaderButton';
@@ -1,4 +1,8 @@
1
- import { Email, Lock, Search, Visibility, VisibilityOff } from '@mui/icons-material';
1
+ import Email from '@mui/icons-material/Email';
2
+ import Lock from '@mui/icons-material/Lock';
3
+ import Search from '@mui/icons-material/Search';
4
+ import Visibility from '@mui/icons-material/Visibility';
5
+ import VisibilityOff from '@mui/icons-material/VisibilityOff';
2
6
  import { IconButton } from '@mui/material';
3
7
  import type { Meta, StoryObj } from '@storybook/react-vite';
4
8
  import { useState } from 'react';
@@ -0,0 +1,176 @@
1
+ import { alpha, keyframes } from '@mui/material';
2
+ import type { CSSObject, Theme } from '@mui/material';
3
+
4
+ import type { InputProps } from './Input.types';
5
+
6
+ type InputVariant = NonNullable<InputProps['variant']>;
7
+
8
+ // Define pulse animation
9
+ const pulseAnimation = keyframes`
10
+ 0% {
11
+ box-shadow: 0 0 0 0 currentColor;
12
+ opacity: 1;
13
+ }
14
+ 70% {
15
+ box-shadow: 0 0 0 10px currentColor;
16
+ opacity: 0;
17
+ }
18
+ 100% {
19
+ box-shadow: 0 0 0 0 currentColor;
20
+ opacity: 0;
21
+ }
22
+ `;
23
+
24
+ /** Our four variants map onto MUI's three; `glass` and `gradient` restyle an outline. */
25
+ export const muiVariantFor = (variant: InputVariant): 'outlined' | 'filled' | 'standard' => {
26
+ switch (variant) {
27
+ case 'underline':
28
+ return 'standard';
29
+ case 'glass':
30
+ case 'gradient':
31
+ return 'outlined';
32
+ default:
33
+ return variant as 'outlined' | 'filled' | 'standard';
34
+ }
35
+ };
36
+
37
+ export const SIZE_MAP = {
38
+ sm: { size: 'small' as const },
39
+ md: { size: 'medium' as const },
40
+ lg: { size: 'medium' as const, sx: { '& .MuiInputBase-input': { padding: '16px 14px' } } },
41
+ };
42
+
43
+ export const glowStyles = (theme: Theme): CSSObject => ({
44
+ '& .MuiInputBase-root': {
45
+ boxShadow: `0 0 15px ${alpha(theme.palette.primary.main, 0.3)}`,
46
+ '&.Mui-focused': {
47
+ boxShadow: `0 0 20px ${alpha(theme.palette.primary.main, 0.5)}`,
48
+ },
49
+ },
50
+ });
51
+
52
+ // A bar behind the field rather than a border on it, so it can pulse outward
53
+ // without the input resizing.
54
+ export const pulseStyles = (theme: Theme): CSSObject => ({
55
+ '&::after': {
56
+ content: '""',
57
+ position: 'absolute',
58
+ top: '50%',
59
+ left: '0',
60
+ right: '0',
61
+ height: '56px',
62
+ transform: 'translateY(-50%)',
63
+ borderRadius: theme.spacing(0.5),
64
+ backgroundColor: theme.palette.primary.main,
65
+ opacity: 0.3,
66
+ animation: `${pulseAnimation} 2s infinite`,
67
+ pointerEvents: 'none',
68
+ zIndex: -1,
69
+ },
70
+ });
71
+
72
+ export const floatingLabelStyles = (theme: Theme): CSSObject => ({
73
+ '& .MuiInputLabel-root': {
74
+ transform: 'translate(14px, 16px) scale(1)',
75
+ '&.MuiInputLabel-shrink': {
76
+ transform: 'translate(14px, -9px) scale(0.75)',
77
+ backgroundColor: theme.palette.background.paper,
78
+ padding: '0 4px',
79
+ },
80
+ },
81
+ });
82
+
83
+ export const inputBaseStyles = (theme: Theme, variant?: InputVariant): CSSObject => {
84
+ switch (variant) {
85
+ case 'glass':
86
+ return {
87
+ backgroundColor: alpha(theme.palette.background.paper, 0.1),
88
+ backdropFilter: 'blur(20px)',
89
+ border: `1px solid ${alpha(theme.palette.divider, 0.2)}`,
90
+ '&:hover': {
91
+ backgroundColor: alpha(theme.palette.background.paper, 0.15),
92
+ borderColor: alpha(theme.palette.primary.main, 0.3),
93
+ },
94
+ '&.Mui-focused': {
95
+ backgroundColor: alpha(theme.palette.background.paper, 0.2),
96
+ borderColor: theme.palette.primary.main,
97
+ boxShadow: `0 0 0 2px ${alpha(theme.palette.primary.main, 0.1)}`,
98
+ },
99
+ };
100
+ case 'underline':
101
+ return {
102
+ '&:before': {
103
+ borderBottomColor: alpha(theme.palette.divider, 0.42),
104
+ },
105
+ '&:hover:not(.Mui-disabled):before': {
106
+ borderBottomColor: theme.palette.primary.main,
107
+ },
108
+ '&:after': {
109
+ borderBottomColor: theme.palette.primary.main,
110
+ },
111
+ };
112
+ case 'gradient':
113
+ return gradientStyles(theme);
114
+ default:
115
+ return {};
116
+ }
117
+ };
118
+
119
+ // The border is a gradient painted behind the field and masked to a 2px ring,
120
+ // since CSS cannot put a gradient on `border-color` directly.
121
+ const gradientStyles = (theme: Theme): CSSObject => ({
122
+ background: `linear-gradient(135deg, ${alpha(theme.palette.primary.main, 0.1)}, ${alpha(theme.palette.secondary.main, 0.1)})`,
123
+ border: `2px solid transparent`,
124
+ backgroundOrigin: 'border-box',
125
+ backgroundClip: 'padding-box, border-box',
126
+ position: 'relative',
127
+ '&::before': {
128
+ content: '""',
129
+ position: 'absolute',
130
+ top: 0,
131
+ left: 0,
132
+ right: 0,
133
+ bottom: 0,
134
+ borderRadius: 'inherit',
135
+ background: `linear-gradient(135deg, ${theme.palette.primary.main}, ${theme.palette.secondary.main})`,
136
+ mask: 'linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0)',
137
+ maskComposite: 'exclude',
138
+ padding: '2px',
139
+ zIndex: -1,
140
+ },
141
+ '&:hover': {
142
+ background: `linear-gradient(135deg, ${alpha(theme.palette.primary.main, 0.15)}, ${alpha(theme.palette.secondary.main, 0.15)})`,
143
+ },
144
+ '&.Mui-focused': {
145
+ background: `linear-gradient(135deg, ${alpha(theme.palette.primary.main, 0.2)}, ${alpha(theme.palette.secondary.main, 0.2)})`,
146
+ '&::before': {
147
+ background: `linear-gradient(135deg, ${theme.palette.primary.dark}, ${theme.palette.secondary.dark})`,
148
+ },
149
+ },
150
+ });
151
+
152
+ export const outlinedStyles = (theme: Theme): CSSObject => ({
153
+ '& fieldset': {
154
+ borderColor: alpha(theme.palette.divider, 0.23),
155
+ },
156
+ '&:hover fieldset': {
157
+ borderColor: theme.palette.primary.main,
158
+ },
159
+ '&.Mui-focused fieldset': {
160
+ borderColor: theme.palette.primary.main,
161
+ borderWidth: 2,
162
+ },
163
+ '&.Mui-error fieldset': {
164
+ borderColor: theme.palette.error.main,
165
+ },
166
+ });
167
+
168
+ export const filledStyles = (theme: Theme): CSSObject => ({
169
+ backgroundColor: alpha(theme.palette.action.hover, 0.04),
170
+ '&:hover': {
171
+ backgroundColor: alpha(theme.palette.action.hover, 0.08),
172
+ },
173
+ '&.Mui-focused': {
174
+ backgroundColor: alpha(theme.palette.action.hover, 0.12),
175
+ },
176
+ });
@@ -1,4 +1,8 @@
1
- import { Email, Lock, Person,Visibility, VisibilityOff } from '@mui/icons-material';
1
+ import Email from '@mui/icons-material/Email';
2
+ import Lock from '@mui/icons-material/Lock';
3
+ import Person from '@mui/icons-material/Person';
4
+ import Visibility from '@mui/icons-material/Visibility';
5
+ import VisibilityOff from '@mui/icons-material/VisibilityOff';
2
6
  import { IconButton } from '@mui/material';
3
7
  import type { Meta, StoryObj } from '@storybook/react-vite';
4
8
  import { useState } from 'react';
@@ -160,9 +164,11 @@ export const StateChangeTest: Story = {
160
164
  setError(inputValue.length < 3);
161
165
  };
162
166
 
167
+ // Toggle only. The old version also queued a 2s timer to clear the flag,
168
+ // which made the rendered state depend on wall-clock time — a play
169
+ // function that ran slowly would see `loading` flip under it.
163
170
  const handleLoadingToggle = () => {
164
- setLoading(!loading);
165
- window.setTimeout(() => setLoading(false), 2000);
171
+ setLoading((previous) => !previous);
166
172
  };
167
173
 
168
174
  return (
@@ -277,13 +283,13 @@ export const KeyboardNavigation: Story = {
277
283
  const firstInput = canvas.getByTestId('first-input');
278
284
  const secondInput = canvas.getByTestId('second-input');
279
285
 
280
- // Focus first element
281
- firstInput.focus();
282
- await expect(firstInput).toHaveFocus();
286
+ // Tab in from the body rather than calling .focus().
287
+ await userEvent.tab();
288
+ await waitFor(() => expect(firstInput).toHaveFocus());
283
289
 
284
290
  // Tab to next element
285
291
  await userEvent.tab();
286
- await expect(secondInput).toHaveFocus();
292
+ await waitFor(() => expect(secondInput).toHaveFocus());
287
293
  });
288
294
 
289
295
  await step('Tab navigation continues', async () => {
@@ -291,28 +297,28 @@ export const KeyboardNavigation: Story = {
291
297
  const button = canvas.getByTestId('after-inputs');
292
298
 
293
299
  await userEvent.tab();
294
- await expect(thirdInput).toHaveFocus();
300
+ await waitFor(() => expect(thirdInput).toHaveFocus());
295
301
 
296
302
  await userEvent.tab();
297
- await expect(button).toHaveFocus();
303
+ await waitFor(() => expect(button).toHaveFocus());
298
304
  });
299
305
 
300
306
  await step('Tab navigation backward', async () => {
301
307
  const thirdInput = canvas.getByTestId('third-input');
302
308
 
303
309
  await userEvent.tab({ shift: true });
304
- await expect(thirdInput).toHaveFocus();
310
+ await waitFor(() => expect(thirdInput).toHaveFocus());
305
311
  });
306
312
 
307
313
  await step('Enter key in input (should not submit)', async () => {
308
314
  const firstInput = canvas.getByTestId('first-input');
309
- firstInput.focus();
310
315
 
316
+ // Typing into an input focuses it, so the extra .focus() was redundant.
311
317
  await userEvent.type(firstInput, 'test');
312
318
  await userEvent.keyboard('{Enter}');
313
319
 
314
320
  // Input should still have focus and content
315
- await expect(firstInput).toHaveFocus();
321
+ await waitFor(() => expect(firstInput).toHaveFocus());
316
322
  await expect(firstInput).toHaveValue('test');
317
323
  });
318
324
  },
@@ -471,8 +477,9 @@ export const FocusManagement: Story = {
471
477
  const closeButton = within(modal).getByTestId('close-modal');
472
478
  const openButton = canvas.getByTestId('open-modal');
473
479
 
474
- // Set focus to open button before closing
475
- openButton.focus();
480
+ // No pre-focus: the assertion below is about the modal being removed, and
481
+ // .focus() on the open button neither affected that nor was ever checked.
482
+ await expect(openButton).toBeInTheDocument();
476
483
  await userEvent.click(closeButton);
477
484
 
478
485
  // Modal should be gone
@@ -567,13 +574,13 @@ export const ResponsiveDesign: Story = {
567
574
 
568
575
  // Test interaction on each input
569
576
  await userEvent.click(input1);
570
- await expect(input1).toHaveFocus();
577
+ await waitFor(() => expect(input1).toHaveFocus());
571
578
 
572
579
  await userEvent.click(input2);
573
- await expect(input2).toHaveFocus();
580
+ await waitFor(() => expect(input2).toHaveFocus());
574
581
 
575
582
  await userEvent.click(input3);
576
- await expect(input3).toHaveFocus();
583
+ await waitFor(() => expect(input3).toHaveFocus());
577
584
  });
578
585
  },
579
586
  };
@@ -630,10 +637,10 @@ export const ThemeVariations: Story = {
630
637
 
631
638
  // Focus each input to test theme-aware focus styles
632
639
  await userEvent.click(outlinedInput);
633
- await expect(outlinedInput).toHaveFocus();
640
+ await waitFor(() => expect(outlinedInput).toHaveFocus());
634
641
 
635
642
  await userEvent.click(glassInput);
636
- await expect(glassInput).toHaveFocus();
643
+ await waitFor(() => expect(glassInput).toHaveFocus());
637
644
  });
638
645
  },
639
646
  };
@@ -692,7 +699,7 @@ export const VisualStates: Story = {
692
699
  await step('Focus state interaction', async () => {
693
700
  const focusInput = canvas.getByTestId('focus-state');
694
701
  await userEvent.click(focusInput);
695
- await expect(focusInput).toHaveFocus();
702
+ await waitFor(() => expect(focusInput).toHaveFocus());
696
703
  });
697
704
 
698
705
  await step('Disabled state verification', async () => {
@@ -700,7 +707,7 @@ export const VisualStates: Story = {
700
707
  await expect(disabledInput).toBeDisabled();
701
708
  // Try to click (should not gain focus)
702
709
  await userEvent.click(disabledInput);
703
- await expect(disabledInput).not.toHaveFocus();
710
+ await waitFor(() => expect(disabledInput).not.toHaveFocus());
704
711
  });
705
712
 
706
713
  await step('Error state verification', async () => {
@@ -720,7 +727,7 @@ export const VisualStates: Story = {
720
727
  await step('Glow state interaction', async () => {
721
728
  const glowInput = canvas.getByTestId('glow-state');
722
729
  await userEvent.click(glowInput);
723
- await expect(glowInput).toHaveFocus();
730
+ await waitFor(() => expect(glowInput).toHaveFocus());
724
731
  // Glow effect should be visible via CSS
725
732
  });
726
733
  },
@@ -811,7 +818,7 @@ export const EdgeCases: Story = {
811
818
 
812
819
  // Should be visible and interactive despite all effects
813
820
  await userEvent.click(allEffectsInput);
814
- await expect(allEffectsInput).toHaveFocus();
821
+ await waitFor(() => expect(allEffectsInput).toHaveFocus());
815
822
 
816
823
  await userEvent.type(allEffectsInput, 'works with all effects');
817
824
  await expect(allEffectsInput).toHaveValue('works with all effects');