@12-apps/ui 1.5.0 → 1.5.2

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 (229) hide show
  1. package/package.json +17 -9
  2. package/src/button/index.ts +1 -0
  3. package/src/social-login-button/index.ts +1 -0
  4. package/src/{social-login-button.tsx → social-login-button/social-login-button.tsx} +5 -5
  5. package/src/user-avatar/index.ts +1 -0
  6. package/src/{user-avatar.tsx → user-avatar/user-avatar.tsx} +4 -4
  7. package/eslint.config.js +0 -89
  8. package/src/__tests__/data-grid.test.tsx +0 -125
  9. package/src/__tests__/package-wiring.test.ts +0 -41
  10. package/src/__tests__/setup.ts +0 -1
  11. package/src/__tests__/social-login-button.test.tsx +0 -186
  12. package/src/__tests__/user-avatar.test.tsx +0 -195
  13. package/src/__tests__/viewport.test.ts +0 -50
  14. package/src/components/command/__tests__/command.test.tsx +0 -112
  15. package/src/components/data-display/Alert/Alert.stories.tsx +0 -559
  16. package/src/components/data-display/Alert/Alert.test.stories.tsx +0 -707
  17. package/src/components/data-display/AlertDialog/AlertDialog.stories.tsx +0 -362
  18. package/src/components/data-display/AlertDialog/AlertDialog.test.stories.tsx +0 -763
  19. package/src/components/data-display/AsyncStateContainer/AsyncStateContainer.stories.tsx +0 -230
  20. package/src/components/data-display/AsyncStateContainer/AsyncStateContainer.test.stories.tsx +0 -270
  21. package/src/components/data-display/Avatar/Avatar.stories.tsx +0 -721
  22. package/src/components/data-display/Avatar/Avatar.test.stories.tsx +0 -822
  23. package/src/components/data-display/Badge/Badge.stories.tsx +0 -1134
  24. package/src/components/data-display/Badge/Badge.test.stories.tsx +0 -1194
  25. package/src/components/data-display/Banner/Banner.stories.tsx +0 -528
  26. package/src/components/data-display/Banner/Banner.test.stories.tsx +0 -511
  27. package/src/components/data-display/Carousel/Carousel.stories.tsx +0 -607
  28. package/src/components/data-display/Carousel/Carousel.test.stories.tsx +0 -701
  29. package/src/components/data-display/Chart/Chart.stories.tsx +0 -568
  30. package/src/components/data-display/Chart/Chart.test.stories.tsx +0 -174
  31. package/src/components/data-display/Chart/SpecChart.stories.tsx +0 -150
  32. package/src/components/data-display/Chart/SpecChart.test.stories.tsx +0 -56
  33. package/src/components/data-display/Chart/__tests__/SpecChart.test.tsx +0 -60
  34. package/src/components/data-display/Chart/__tests__/chart-format.test.ts +0 -43
  35. package/src/components/data-display/Chart/__tests__/chart-spec.test.ts +0 -119
  36. package/src/components/data-display/Chip/Chip.stories.tsx +0 -252
  37. package/src/components/data-display/Chip/Chip.test.stories.tsx +0 -266
  38. package/src/components/data-display/DataGrid/DataGrid.stories.tsx +0 -515
  39. package/src/components/data-display/DataGrid/DataGrid.test.stories.tsx +0 -653
  40. package/src/components/data-display/DataViews/__tests__/DataViewsGrid.test.tsx +0 -271
  41. package/src/components/data-display/DataViews/__tests__/DataViewsTableBase.test.tsx +0 -134
  42. package/src/components/data-display/DataViews/__tests__/SaveViewModal.test.tsx +0 -83
  43. package/src/components/data-display/DataViews/__tests__/data-views-filter.test.ts +0 -115
  44. package/src/components/data-display/DataViews/__tests__/data-views-preview.test.ts +0 -53
  45. package/src/components/data-display/DataViews/__tests__/range-pill.test.tsx +0 -114
  46. package/src/components/data-display/DataViews/base-card.stories.tsx +0 -136
  47. package/src/components/data-display/DescriptionItem/DescriptionItem.stories.tsx +0 -254
  48. package/src/components/data-display/EmptyState/EmptyState.stories.tsx +0 -282
  49. package/src/components/data-display/EmptyState/EmptyState.test.stories.tsx +0 -441
  50. package/src/components/data-display/ErrorState/ErrorState.stories.tsx +0 -110
  51. package/src/components/data-display/ErrorState/ErrorState.test.stories.tsx +0 -133
  52. package/src/components/data-display/HoverCard/HoverCard.stories.tsx +0 -650
  53. package/src/components/data-display/HoverCard/HoverCard.test.stories.tsx +0 -929
  54. package/src/components/data-display/InteractiveTooltip/InteractiveTooltip.stories.tsx +0 -411
  55. package/src/components/data-display/LazyImage/LazyImage.stories.tsx +0 -387
  56. package/src/components/data-display/Lightbox/Lightbox.stories.tsx +0 -315
  57. package/src/components/data-display/Lightbox/Lightbox.test.stories.tsx +0 -598
  58. package/src/components/data-display/LoadingState/LoadingState.stories.tsx +0 -124
  59. package/src/components/data-display/LoadingState/LoadingState.test.stories.tsx +0 -99
  60. package/src/components/data-display/MapPreview/MapPreview.stories.tsx +0 -458
  61. package/src/components/data-display/MapPreview/MapPreview.test.stories.tsx +0 -394
  62. package/src/components/data-display/Popover/Popover.stories.tsx +0 -295
  63. package/src/components/data-display/Popover/Popover.test.stories.tsx +0 -1162
  64. package/src/components/data-display/Progress/Progress.stories.tsx +0 -481
  65. package/src/components/data-display/Progress/Progress.test.stories.tsx +0 -2070
  66. package/src/components/data-display/SectionOnboarding/SectionOnboarding.stories.tsx +0 -160
  67. package/src/components/data-display/SectionOnboarding/SectionOnboarding.test.stories.tsx +0 -190
  68. package/src/components/data-display/Sheet/Sheet.stories.tsx +0 -883
  69. package/src/components/data-display/Sheet/Sheet.test.stories.tsx +0 -1105
  70. package/src/components/data-display/StatCard/StatCard.stories.tsx +0 -167
  71. package/src/components/data-display/StatCard/StatCard.test.stories.tsx +0 -240
  72. package/src/components/data-display/Stepper/Stepper.stories.tsx +0 -540
  73. package/src/components/data-display/Stepper/Stepper.test.stories.tsx +0 -600
  74. package/src/components/data-display/Table/Table.stories.tsx +0 -803
  75. package/src/components/data-display/Table/Table.test.stories.tsx +0 -369
  76. package/src/components/data-display/Timeline/Timeline.stories.tsx +0 -442
  77. package/src/components/data-display/Timeline/Timeline.test.stories.tsx +0 -930
  78. package/src/components/data-display/TimingDiagram/TimingDiagram.stories.tsx +0 -475
  79. package/src/components/data-display/TimingDiagram/TimingDiagram.test.stories.tsx +0 -734
  80. package/src/components/data-display/Tooltip/Tooltip.stories.tsx +0 -468
  81. package/src/components/data-display/Tooltip/Tooltip.test.stories.tsx +0 -1154
  82. package/src/components/feedback/ConfirmAction/ConfirmAction.stories.tsx +0 -146
  83. package/src/components/feedback/ConfirmAction/ConfirmAction.test.stories.tsx +0 -114
  84. package/src/components/feedback/ConfirmAction/__tests__/confirm-action.test.tsx +0 -288
  85. package/src/components/feedback/Dialog/Dialog.stories.tsx +0 -833
  86. package/src/components/feedback/Dialog/Dialog.test.stories.tsx +0 -964
  87. package/src/components/feedback/Dialog/__tests__/dialog-content-spacing.test.tsx +0 -66
  88. package/src/components/feedback/Modal/Modal.stories.tsx +0 -765
  89. package/src/components/feedback/Modal/Modal.test.stories.tsx +0 -251
  90. package/src/components/feedback/Sonner/Sonner.stories.tsx +0 -698
  91. package/src/components/feedback/Sonner/Sonner.test.stories.tsx +0 -896
  92. package/src/components/feedback/StackedModal/StackedModal.stories.tsx +0 -1783
  93. package/src/components/feedback/StackedModal/StackedModal.test.stories.tsx +0 -973
  94. package/src/components/feedback/StackedModal/__tests__/stacked-modal-viewport.test.tsx +0 -104
  95. package/src/components/feedback/Toast/Toast.stories.tsx +0 -548
  96. package/src/components/feedback/Toast/Toast.test.stories.tsx +0 -834
  97. package/src/components/feedback/TutorialOverlay/TutorialOverlay.stories.tsx +0 -691
  98. package/src/components/feedback/TutorialOverlay/TutorialOverlay.test.stories.tsx +0 -634
  99. package/src/components/form/AddressAutocomplete/AddressAutocomplete.stories.tsx +0 -665
  100. package/src/components/form/AddressAutocomplete/AddressAutocomplete.test.stories.tsx +0 -727
  101. package/src/components/form/Autocomplete/Autocomplete.stories.tsx +0 -715
  102. package/src/components/form/Autocomplete/Autocomplete.test.stories.tsx +0 -825
  103. package/src/components/form/Button/Button.stories.tsx +0 -365
  104. package/src/components/form/Button/Button.test.stories.tsx +0 -607
  105. package/src/components/form/Calendar/Calendar.stories.tsx +0 -349
  106. package/src/components/form/Calendar/Calendar.test.stories.tsx +0 -464
  107. package/src/components/form/CepField/CepField.stories.tsx +0 -138
  108. package/src/components/form/CepField/CepField.test.stories.tsx +0 -281
  109. package/src/components/form/Checkbox/Checkbox.stories.tsx +0 -265
  110. package/src/components/form/Checkbox/Checkbox.test.stories.tsx +0 -181
  111. package/src/components/form/CodeEditor/CodeEditor.stories.tsx +0 -871
  112. package/src/components/form/CodeEditor/CodeEditor.test.stories.tsx +0 -574
  113. package/src/components/form/Command/Command.stories.tsx +0 -580
  114. package/src/components/form/Command/Command.test.stories.tsx +0 -215
  115. package/src/components/form/CreatableSelect/CreatableSelect.stories.tsx +0 -112
  116. package/src/components/form/CreatableSelect/CreatableSelect.test.stories.tsx +0 -134
  117. package/src/components/form/Form/Form.stories.tsx +0 -687
  118. package/src/components/form/Form/Form.test.stories.tsx +0 -601
  119. package/src/components/form/Input/Input.stories.tsx +0 -260
  120. package/src/components/form/Input/Input.test.stories.tsx +0 -1191
  121. package/src/components/form/InputOTP/InputOTP.stories.tsx +0 -774
  122. package/src/components/form/InputOTP/InputOTP.test.stories.tsx +0 -588
  123. package/src/components/form/Label/Label.stories.tsx +0 -473
  124. package/src/components/form/Label/Label.test.stories.tsx +0 -915
  125. package/src/components/form/Menubar/Menubar.stories.tsx +0 -472
  126. package/src/components/form/Menubar/Menubar.test.stories.tsx +0 -584
  127. package/src/components/form/PasswordStrength/PasswordStrength.stories.tsx +0 -562
  128. package/src/components/form/PasswordStrength/PasswordStrength.test.stories.tsx +0 -327
  129. package/src/components/form/PhoneInput/PhoneInput.stories.tsx +0 -495
  130. package/src/components/form/PhoneInput/PhoneInput.test.stories.tsx +0 -666
  131. package/src/components/form/RadioGroup/RadioGroup.stories.tsx +0 -518
  132. package/src/components/form/RadioGroup/RadioGroup.test.stories.tsx +0 -685
  133. package/src/components/form/RichTextEditor/RichTextEditor.stories.tsx +0 -261
  134. package/src/components/form/RichTextEditor/RichTextEditor.test.stories.tsx +0 -491
  135. package/src/components/form/SearchPalette/SearchPalette.stories.tsx +0 -135
  136. package/src/components/form/Select/Select.stories.tsx +0 -364
  137. package/src/components/form/Select/Select.test.stories.tsx +0 -985
  138. package/src/components/form/Slider/Slider.stories.tsx +0 -418
  139. package/src/components/form/Slider/Slider.test.stories.tsx +0 -1042
  140. package/src/components/form/Switch/Switch.stories.tsx +0 -697
  141. package/src/components/form/Switch/Switch.test.stories.tsx +0 -597
  142. package/src/components/form/Textarea/Textarea.stories.tsx +0 -473
  143. package/src/components/form/Textarea/Textarea.test.stories.tsx +0 -702
  144. package/src/components/form/Toggle/Toggle.stories.tsx +0 -638
  145. package/src/components/form/Toggle/Toggle.test.stories.tsx +0 -1159
  146. package/src/components/form/ToggleGroup/ToggleGroup.stories.tsx +0 -617
  147. package/src/components/form/ToggleGroup/ToggleGroup.test.stories.tsx +0 -915
  148. package/src/components/form/UploadButton/UploadButton.stories.tsx +0 -367
  149. package/src/components/form/UploadButton/UploadButton.test.stories.tsx +0 -573
  150. package/src/components/form/total-form/total-form.test.tsx +0 -214
  151. package/src/components/layout/Accordion/Accordion.stories.tsx +0 -694
  152. package/src/components/layout/Accordion/Accordion.test.stories.tsx +0 -1344
  153. package/src/components/layout/Card/Card.stories.tsx +0 -591
  154. package/src/components/layout/Card/Card.test.stories.tsx +0 -1134
  155. package/src/components/layout/CardGrid/__tests__/CardGrid.test.tsx +0 -92
  156. package/src/components/layout/Collapsible/Collapsible.stories.tsx +0 -180
  157. package/src/components/layout/Collapsible/Collapsible.test.stories.tsx +0 -308
  158. package/src/components/layout/Container/Container.stories.tsx +0 -557
  159. package/src/components/layout/Container/Container.test.stories.tsx +0 -745
  160. package/src/components/layout/ContentToolbar/ContentToolbar.stories.tsx +0 -129
  161. package/src/components/layout/ContentToolbar/ContentToolbar.test.stories.tsx +0 -251
  162. package/src/components/layout/ContentToolbar/__tests__/ColumnsMenu.test.tsx +0 -39
  163. package/src/components/layout/ContentToolbar/__tests__/MultiSelectDropdown.test.tsx +0 -131
  164. package/src/components/layout/ContentToolbar/__tests__/SavedViewsMenu.test.tsx +0 -99
  165. package/src/components/layout/Dashboard/Dashboard.stories.tsx +0 -104
  166. package/src/components/layout/Dashboard/Dashboard.test.stories.tsx +0 -190
  167. package/src/components/layout/Drawer/Drawer.stories.tsx +0 -658
  168. package/src/components/layout/Drawer/Drawer.test.stories.tsx +0 -1343
  169. package/src/components/layout/Resizable/Resizable.stories.tsx +0 -1039
  170. package/src/components/layout/Resizable/Resizable.test.stories.tsx +0 -754
  171. package/src/components/layout/ScrollArea/ScrollArea.stories.tsx +0 -651
  172. package/src/components/layout/ScrollArea/ScrollArea.test.stories.tsx +0 -619
  173. package/src/components/layout/Separator/Separator.stories.tsx +0 -563
  174. package/src/components/layout/Separator/Separator.test.stories.tsx +0 -518
  175. package/src/components/layout/SettingsLayout/SettingsLayout.stories.tsx +0 -192
  176. package/src/components/layout/SettingsLayout/SettingsLayout.test.stories.tsx +0 -175
  177. package/src/components/layout/Sidebar/Sidebar.stories.tsx +0 -609
  178. package/src/components/layout/Sidebar/Sidebar.test.stories.tsx +0 -1324
  179. package/src/components/layout/Skeleton/Skeleton.stories.tsx +0 -689
  180. package/src/components/layout/Skeleton/Skeleton.test.stories.tsx +0 -521
  181. package/src/components/layout/Spacer/Spacer.stories.tsx +0 -502
  182. package/src/components/layout/Spacer/Spacer.test.stories.tsx +0 -474
  183. package/src/components/layout/TableFilter/TableFilter.stories.tsx +0 -82
  184. package/src/components/layout/TableFilter/TableFilter.test.stories.tsx +0 -87
  185. package/src/components/navigation/Breadcrumbs/Breadcrumbs.stories.tsx +0 -638
  186. package/src/components/navigation/Breadcrumbs/Breadcrumbs.test.stories.tsx +0 -1008
  187. package/src/components/navigation/CommandPalette/CommandPalette.stories.tsx +0 -386
  188. package/src/components/navigation/CommandPalette/CommandPalette.test.stories.tsx +0 -435
  189. package/src/components/navigation/ContextMenu/ContextMenu.stories.tsx +0 -614
  190. package/src/components/navigation/ContextMenu/ContextMenu.test.stories.tsx +0 -845
  191. package/src/components/navigation/DropdownMenu/DropdownMenu.stories.tsx +0 -578
  192. package/src/components/navigation/DropdownMenu/DropdownMenu.test.stories.tsx +0 -660
  193. package/src/components/navigation/NavigationMenu/stories/NavigationMenu.stories.tsx +0 -516
  194. package/src/components/navigation/NavigationMenu/stories/NavigationMenu.test.stories.tsx +0 -935
  195. package/src/components/navigation/NavigationMenu/stories/NavigationMenuHorizontal.stories.tsx +0 -501
  196. package/src/components/navigation/NavigationMenu/stories/NavigationMenuVertical.stories.tsx +0 -453
  197. package/src/components/navigation/Pagination/Pagination.stories.tsx +0 -602
  198. package/src/components/navigation/Pagination/Pagination.test.stories.tsx +0 -520
  199. package/src/components/navigation/Tabs/Tabs.stories.tsx +0 -1004
  200. package/src/components/navigation/Tabs/Tabs.test.stories.tsx +0 -1225
  201. package/src/components/typography/Blockquote/Blockquote.stories.tsx +0 -359
  202. package/src/components/typography/Blockquote/Blockquote.test.stories.tsx +0 -432
  203. package/src/components/typography/Code/Code.stories.tsx +0 -686
  204. package/src/components/typography/Code/Code.test.stories.tsx +0 -703
  205. package/src/components/typography/Heading/Heading.stories.tsx +0 -451
  206. package/src/components/typography/Heading/Heading.test.stories.tsx +0 -830
  207. package/src/components/typography/Paragraph/Paragraph.stories.tsx +0 -280
  208. package/src/components/typography/Paragraph/Paragraph.test.stories.tsx +0 -231
  209. package/src/components/typography/Text/Text.stories.tsx +0 -359
  210. package/src/components/typography/Text/Text.test.stories.tsx +0 -759
  211. package/src/components/utility/AnimatedIcon/AnimatedIcon.stories.tsx +0 -945
  212. package/src/components/utility/AnimatedIcon/AnimatedIcon.test.stories.tsx +0 -603
  213. package/src/components/utility/AspectRatio/AspectRatio.stories.tsx +0 -414
  214. package/src/components/utility/AspectRatio/AspectRatio.test.stories.tsx +0 -859
  215. package/src/components/utility/InfiniteScroll/InfiniteScroll.stories.tsx +0 -620
  216. package/src/components/utility/InfiniteScroll/InfiniteScroll.test.stories.tsx +0 -361
  217. package/src/components/utility/InstallPrompt/InstallPrompt.stories.tsx +0 -118
  218. package/src/components/utility/InstallPrompt/InstallPrompt.test.stories.tsx +0 -83
  219. package/src/components/utility/InstallPrompt/__tests__/InstallPrompt.ios.test.tsx +0 -65
  220. package/src/components/utility/InstallPrompt/__tests__/usePwaInstall.test.tsx +0 -271
  221. package/src/components/utility/Portal/Portal.stories.tsx +0 -340
  222. package/src/components/utility/Portal/Portal.test.stories.tsx +0 -2086
  223. package/src/components/utility/Transition/Transition.stories.tsx +0 -493
  224. package/src/components/utility/Transition/Transition.test.stories.tsx +0 -854
  225. package/src/components/utility/VirtualList/VirtualList.stories.tsx +0 -1073
  226. package/src/components/utility/VirtualList/VirtualList.test.stories.tsx +0 -1085
  227. package/src/components/utility/WorkflowStep/WorkflowStep.stories.tsx +0 -431
  228. package/src/components/utility/WorkflowStep/WorkflowStep.test.stories.tsx +0 -364
  229. /package/src/{button.tsx → button/button.tsx} +0 -0
@@ -1,1783 +0,0 @@
1
- import AddIcon from '@mui/icons-material/Add';
2
- import CheckCircleIcon from '@mui/icons-material/CheckCircle';
3
- import CloudUploadIcon from '@mui/icons-material/CloudUpload';
4
- import DeleteIcon from '@mui/icons-material/Delete';
5
- import DownloadIcon from '@mui/icons-material/Download';
6
- import EditIcon from '@mui/icons-material/Edit';
7
- import FilterListIcon from '@mui/icons-material/FilterList';
8
- import InfoIcon from '@mui/icons-material/Info';
9
- import MoreVertIcon from '@mui/icons-material/MoreVert';
10
- import SaveIcon from '@mui/icons-material/Save';
11
- import SearchIcon from '@mui/icons-material/Search';
12
- import SettingsIcon from '@mui/icons-material/Settings';
13
- import ShareIcon from '@mui/icons-material/Share';
14
- import {
15
- Alert,
16
- Avatar,
17
- Box,
18
- Button,
19
- Card,
20
- CardActions,
21
- CardContent,
22
- Chip,
23
- Divider,
24
- FormControl,
25
- FormControlLabel,
26
- Grid,
27
- IconButton,
28
- InputLabel,
29
- LinearProgress,
30
- List,
31
- ListItem,
32
- ListItemText,
33
- MenuItem,
34
- Paper,
35
- Select,
36
- Stack,
37
- Step,
38
- StepLabel,
39
- Stepper,
40
- Switch,
41
- Tab,
42
- Table,
43
- TableBody,
44
- TableCell,
45
- TableContainer,
46
- TableHead,
47
- TableRow,
48
- Tabs,
49
- TextField,
50
- Typography,
51
- useMediaQuery,
52
- useTheme,
53
- } from '@mui/material';
54
- import type { Meta, StoryObj } from '@storybook/react-vite';
55
- import React, { useEffect,useState } from 'react';
56
-
57
- import {
58
- StackedModalActions,
59
- StackedModalContent,
60
- ModalStackProvider,
61
- StackedModal,
62
- useModalStack,
63
- } from './StackedModal';
64
-
65
- const meta: Meta<typeof StackedModal> = {
66
- title: 'Enhanced/StackedModal',
67
- component: StackedModal,
68
- parameters: {
69
- layout: 'fullscreen',
70
- docs: {
71
- description: {
72
- component:
73
- "A sophisticated nested modal system inspired by Google Tag Manager's UI with glass morphism, smart transitions, and responsive design.",
74
- },
75
- },
76
- },
77
- decorators: [
78
- (Story) => (
79
- <ModalStackProvider>
80
- <Box sx={{ p: 3, minHeight: '100vh', bgcolor: 'grey.50' }}>
81
- <Story />
82
- </Box>
83
- </ModalStackProvider>
84
- ),
85
- ],
86
- tags: ['autodocs', 'component:StackedModal'],
87
- };
88
-
89
- export default meta;
90
- type Story = StoryObj<typeof StackedModal>;
91
-
92
- // Basic usage story
93
- const DefaultComponent = () => {
94
- const BasicModal = () => {
95
- const [open, setOpen] = useState(false);
96
-
97
- return (
98
- <>
99
- <Button variant="contained" onClick={() => setOpen(true)}>
100
- Open Basic Modal
101
- </Button>
102
- <StackedModal
103
- open={open}
104
- onClose={() => setOpen(false)}
105
- navigationTitle="Basic Modal"
106
- actions={
107
- <Button variant="contained" size="small">
108
- Save Changes
109
- </Button>
110
- }
111
- >
112
- <StackedModalContent>
113
- <Typography variant="h5" gutterBottom>
114
- Welcome to StackedModal
115
- </Typography>
116
- <Typography paragraph>
117
- This is a basic implementation of the StackedModal component. It provides a clean and
118
- modern interface for displaying content.
119
- </Typography>
120
- <TextField fullWidth label="Enter your name" variant="outlined" margin="normal" />
121
- </StackedModalContent>
122
- </StackedModal>
123
- </>
124
- );
125
- };
126
-
127
- return <BasicModal />;
128
- };
129
-
130
- export const Default: Story = {
131
- render: () => <DefaultComponent />,
132
- };
133
-
134
- // Glass morphism effect
135
- const GlassMorphismComponent = () => {
136
- const GlassModal = () => {
137
- const [open, setOpen] = useState(false);
138
-
139
- return (
140
- <>
141
- <Box
142
- sx={{
143
- p: 4,
144
- background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
145
- borderRadius: 2,
146
- }}
147
- >
148
- <Typography variant="h4" color="white" gutterBottom>
149
- Beautiful Background
150
- </Typography>
151
- <Typography color="white" paragraph>
152
- This colorful background will be visible through the glass effect
153
- </Typography>
154
- <Button
155
- variant="contained"
156
- onClick={() => setOpen(true)}
157
- sx={{ bgcolor: 'white', color: 'primary.main' }}
158
- >
159
- Open Glass Modal
160
- </Button>
161
- </Box>
162
-
163
- <StackedModal
164
- open={open}
165
- onClose={() => setOpen(false)}
166
- glass={true}
167
- navigationTitle="Glass Morphism Modal"
168
- >
169
- <StackedModalContent>
170
- <Typography variant="h5" gutterBottom>
171
- Glass Effect Active
172
- </Typography>
173
- <Typography paragraph>
174
- Notice the beautiful blur effect that reveals the content behind the modal. This
175
- creates a modern, sophisticated UI that maintains context while focusing attention.
176
- </Typography>
177
- <Alert severity="info">
178
- The glass effect automatically adjusts based on the theme and provides excellent
179
- readability while maintaining visual appeal.
180
- </Alert>
181
- </StackedModalContent>
182
- <StackedModalActions>
183
- <Button variant="outlined" size="small" onClick={() => setOpen(false)}>
184
- Cancel
185
- </Button>
186
- <Button variant="contained" size="small">
187
- Confirm
188
- </Button>
189
- </StackedModalActions>
190
- </StackedModal>
191
- </>
192
- );
193
- };
194
-
195
- return <GlassModal />;
196
- };
197
-
198
- export const GlassMorphism: Story = {
199
- render: () => <GlassMorphismComponent />,
200
- };
201
-
202
- // Multi-level stacking demonstration
203
- const MultiLevelStackingComponent = () => {
204
- const StackingDemo = () => {
205
- const [firstOpen, setFirstOpen] = useState(false);
206
- const [secondOpen, setSecondOpen] = useState(false);
207
- const [thirdOpen, setThirdOpen] = useState(false);
208
- const [fourthOpen, setFourthOpen] = useState(false);
209
-
210
- return (
211
- <>
212
- <Card>
213
- <CardContent>
214
- <Typography variant="h5" gutterBottom>
215
- Multi-Level Modal Stacking
216
- </Typography>
217
- <Typography paragraph color="text.secondary">
218
- This demonstrates how modals stack and transition smoothly between states. Each modal
219
- becomes secondary when a new one opens.
220
- </Typography>
221
- </CardContent>
222
- <CardActions>
223
- <Button variant="contained" onClick={() => setFirstOpen(true)} startIcon={<AddIcon />}>
224
- Start Workflow
225
- </Button>
226
- </CardActions>
227
- </Card>
228
-
229
- {/* Level 1 Modal */}
230
- <StackedModal
231
- open={firstOpen}
232
- onClose={() => setFirstOpen(false)}
233
- glass={true}
234
- navigationTitle="Step 1: Choose Project"
235
- modalId="modal-level-1"
236
- >
237
- <StackedModalContent>
238
- <Typography variant="h5" gutterBottom>
239
- Select Project Type
240
- </Typography>
241
- <Grid container spacing={2} sx={{ mt: 2 }}>
242
- <Grid item xs={12} md={6}>
243
- <Card
244
- sx={{ cursor: 'pointer', '&:hover': { boxShadow: 4 } }}
245
- onClick={() => setSecondOpen(true)}
246
- >
247
- <CardContent>
248
- <Typography variant="h6">Web Application</Typography>
249
- <Typography color="text.secondary">
250
- Create a responsive web application
251
- </Typography>
252
- </CardContent>
253
- </Card>
254
- </Grid>
255
- <Grid item xs={12} md={6}>
256
- <Card
257
- sx={{ cursor: 'pointer', '&:hover': { boxShadow: 4 } }}
258
- onClick={() => setSecondOpen(true)}
259
- >
260
- <CardContent>
261
- <Typography variant="h6">Mobile App</Typography>
262
- <Typography color="text.secondary">
263
- Build a native mobile application
264
- </Typography>
265
- </CardContent>
266
- </Card>
267
- </Grid>
268
- </Grid>
269
- </StackedModalContent>
270
- </StackedModal>
271
-
272
- {/* Level 2 Modal */}
273
- <StackedModal
274
- open={secondOpen}
275
- onClose={() => setSecondOpen(false)}
276
- navigationTitle="Step 2: Configuration"
277
- modalId="modal-level-2"
278
- actions={
279
- <Button variant="contained" size="small" onClick={() => setThirdOpen(true)}>
280
- Next Step
281
- </Button>
282
- }
283
- >
284
- <StackedModalContent>
285
- <Typography variant="h5" gutterBottom>
286
- Configure Your Project
287
- </Typography>
288
- <Stack spacing={3} sx={{ mt: 3 }}>
289
- <TextField fullWidth label="Project Name" defaultValue="My Awesome Project" />
290
- <FormControl fullWidth>
291
- <InputLabel>Framework</InputLabel>
292
- <Select label="Framework" defaultValue="react">
293
- <MenuItem value="react">React</MenuItem>
294
- <MenuItem value="vue">Vue.js</MenuItem>
295
- <MenuItem value="angular">Angular</MenuItem>
296
- </Select>
297
- </FormControl>
298
- <FormControlLabel control={<Switch defaultChecked />} label="Enable TypeScript" />
299
- <FormControlLabel
300
- control={<Switch defaultChecked />}
301
- label="Include Testing Framework"
302
- />
303
- </Stack>
304
- </StackedModalContent>
305
- </StackedModal>
306
-
307
- {/* Level 3 Modal */}
308
- <StackedModal
309
- open={thirdOpen}
310
- onClose={() => setThirdOpen(false)}
311
- navigationTitle="Step 3: Features"
312
- modalId="modal-level-3"
313
- actions={
314
- <Button variant="contained" size="small" onClick={() => setFourthOpen(true)}>
315
- Add Dependencies
316
- </Button>
317
- }
318
- >
319
- <StackedModalContent>
320
- <Typography variant="h5" gutterBottom>
321
- Select Features
322
- </Typography>
323
- <List>
324
- <ListItem>
325
- <ListItemText primary="Authentication" secondary="User login and registration" />
326
- <Switch defaultChecked />
327
- </ListItem>
328
- <ListItem>
329
- <ListItemText primary="Database" secondary="PostgreSQL integration" />
330
- <Switch defaultChecked />
331
- </ListItem>
332
- <ListItem>
333
- <ListItemText primary="API" secondary="RESTful API endpoints" />
334
- <Switch />
335
- </ListItem>
336
- <ListItem>
337
- <ListItemText primary="Real-time" secondary="WebSocket support" />
338
- <Switch />
339
- </ListItem>
340
- </List>
341
- </StackedModalContent>
342
- </StackedModal>
343
-
344
- {/* Level 4 Modal */}
345
- <StackedModal
346
- open={fourthOpen}
347
- onClose={() => setFourthOpen(false)}
348
- navigationTitle="Step 4: Review"
349
- modalId="modal-level-4"
350
- actions={
351
- <Stack direction="row" spacing={1}>
352
- <Button
353
- variant="outlined"
354
- size="small"
355
- onClick={() => {
356
- setFourthOpen(false);
357
- setThirdOpen(false);
358
- setSecondOpen(false);
359
- setFirstOpen(false);
360
- }}
361
- >
362
- Cancel All
363
- </Button>
364
- <Button
365
- variant="contained"
366
- color="success"
367
- size="small"
368
- startIcon={<CheckCircleIcon />}
369
- onClick={() => {
370
- window.alert('Project created successfully!');
371
- setFourthOpen(false);
372
- setThirdOpen(false);
373
- setSecondOpen(false);
374
- setFirstOpen(false);
375
- }}
376
- >
377
- Create Project
378
- </Button>
379
- </Stack>
380
- }
381
- >
382
- <StackedModalContent>
383
- <Alert severity="success" sx={{ mb: 3 }}>
384
- Your project is ready to be created!
385
- </Alert>
386
- <Typography variant="h5" gutterBottom>
387
- Project Summary
388
- </Typography>
389
- <Paper sx={{ p: 2, bgcolor: 'grey.50' }}>
390
- <Stack spacing={2}>
391
- <Box>
392
- <Typography variant="caption" color="text.secondary">
393
- Project Type
394
- </Typography>
395
- <Typography>Web Application</Typography>
396
- </Box>
397
- <Divider />
398
- <Box>
399
- <Typography variant="caption" color="text.secondary">
400
- Framework
401
- </Typography>
402
- <Typography>React with TypeScript</Typography>
403
- </Box>
404
- <Divider />
405
- <Box>
406
- <Typography variant="caption" color="text.secondary">
407
- Features
408
- </Typography>
409
- <Stack direction="row" spacing={1} sx={{ mt: 1 }}>
410
- <Chip label="Authentication" size="small" />
411
- <Chip label="Database" size="small" />
412
- <Chip label="Testing" size="small" />
413
- </Stack>
414
- </Box>
415
- </Stack>
416
- </Paper>
417
- <Typography variant="caption" color="text.secondary" sx={{ mt: 2, display: 'block' }}>
418
- Note: Only the current and previous modals are rendered for optimal performance.
419
- </Typography>
420
- </StackedModalContent>
421
- </StackedModal>
422
- </>
423
- );
424
- };
425
-
426
- return <StackingDemo />;
427
- };
428
-
429
- export const MultiLevelStacking: Story = {
430
- render: () => <MultiLevelStackingComponent />,
431
- };
432
-
433
- // Mobile responsive bottom sheet
434
- export const MobileResponsive: Story = {
435
- parameters: {
436
- viewport: {
437
- defaultViewport: 'mobile1',
438
- },
439
- },
440
- render: () => {
441
- const MobileDemo = () => {
442
- const [open, setOpen] = useState(false);
443
- const theme = useTheme();
444
- const isMobile = useMediaQuery(theme.breakpoints.down('sm'));
445
-
446
- return (
447
- <>
448
- <Alert severity="info" sx={{ mb: 2 }}>
449
- {isMobile
450
- ? 'Mobile view active - Modal will slide from bottom'
451
- : 'Desktop view - Switch to mobile viewport to see bottom sheet behavior'}
452
- </Alert>
453
- <Button
454
- variant="contained"
455
- fullWidth={isMobile}
456
- onClick={() => setOpen(true)}
457
- startIcon={<AddIcon />}
458
- >
459
- Open Mobile Modal
460
- </Button>
461
-
462
- <StackedModal
463
- open={open}
464
- onClose={() => setOpen(false)}
465
- navigationTitle="Mobile Optimized"
466
- actions={
467
- <Button variant="contained" size="small" onClick={() => setOpen(false)}>
468
- Close
469
- </Button>
470
- }
471
- >
472
- <StackedModalContent>
473
- <Typography variant="h5" gutterBottom>
474
- Mobile-First Design
475
- </Typography>
476
- <Typography paragraph>
477
- On mobile devices, the modal slides up from the bottom like a native mobile sheet.
478
- On desktop, it fades in with responsive sizing.
479
- </Typography>
480
- <Stack spacing={2}>
481
- <Button variant="outlined" fullWidth startIcon={<CloudUploadIcon />}>
482
- Upload File
483
- </Button>
484
- <Button variant="outlined" fullWidth startIcon={<DownloadIcon />}>
485
- Download Report
486
- </Button>
487
- <Button variant="outlined" fullWidth startIcon={<ShareIcon />}>
488
- Share Document
489
- </Button>
490
- </Stack>
491
- </StackedModalContent>
492
- </StackedModal>
493
- </>
494
- );
495
- };
496
-
497
- return <MobileDemo />;
498
- },
499
- };
500
-
501
- // Async content with loading states
502
- const AsyncContentLoadingComponent = () => {
503
- const AsyncModal = () => {
504
- const [open, setOpen] = useState(false);
505
- const [addUserOpen, setAddUserOpen] = useState(false);
506
- const [loading, setLoading] = useState(false);
507
- const [data, setData] = useState<{
508
- users: Array<{ id: number; name: string; role: string; status: string }>;
509
- } | null>(null);
510
-
511
- const loadData = () => {
512
- setOpen(true);
513
- setLoading(true);
514
- setData(null);
515
-
516
- // Simulate API call
517
- window.window.setTimeout(() => {
518
- setData({
519
- users: [
520
- { id: 1, name: 'John Doe', role: 'Admin', status: 'Active' },
521
- { id: 2, name: 'Jane Smith', role: 'User', status: 'Active' },
522
- { id: 3, name: 'Bob Johnson', role: 'User', status: 'Inactive' },
523
- { id: 4, name: 'Alice Brown', role: 'Moderator', status: 'Active' },
524
- ],
525
- });
526
- setLoading(false);
527
- }, 2000);
528
- };
529
-
530
- return (
531
- <>
532
- <Card>
533
- <CardContent>
534
- <Typography variant="h6" gutterBottom>
535
- Async Data Loading
536
- </Typography>
537
- <Typography color="text.secondary">
538
- Modal with skeleton loading state while fetching data
539
- </Typography>
540
- </CardContent>
541
- <CardActions>
542
- <Button variant="contained" onClick={loadData}>
543
- Load User Data
544
- </Button>
545
- </CardActions>
546
- </Card>
547
-
548
- <StackedModal
549
- open={open}
550
- onClose={() => setOpen(false)}
551
- navigationTitle="User Management"
552
- loading={loading}
553
- loadingText="Fetching user data..."
554
- actions={
555
- !loading && (
556
- <Button
557
- variant="contained"
558
- size="small"
559
- startIcon={<AddIcon />}
560
- onClick={() => setAddUserOpen(true)}
561
- >
562
- Add User
563
- </Button>
564
- )
565
- }
566
- >
567
- {!loading && data && (
568
- <Box>
569
- <TableContainer>
570
- <Table>
571
- <TableHead>
572
- <TableRow>
573
- <TableCell>Name</TableCell>
574
- <TableCell>Role</TableCell>
575
- <TableCell>Status</TableCell>
576
- <TableCell>Actions</TableCell>
577
- </TableRow>
578
- </TableHead>
579
- <TableBody>
580
- {data.users.map((user) => (
581
- <TableRow key={user.id}>
582
- <TableCell>
583
- <Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>
584
- <Avatar sx={{ width: 32, height: 32 }}>{user.name.charAt(0)}</Avatar>
585
- {user.name}
586
- </Box>
587
- </TableCell>
588
- <TableCell>
589
- <Chip
590
- label={user.role}
591
- size="small"
592
- color={user.role === 'Admin' ? 'primary' : 'default'}
593
- />
594
- </TableCell>
595
- <TableCell>
596
- <Chip
597
- label={user.status}
598
- size="small"
599
- color={user.status === 'Active' ? 'success' : 'default'}
600
- />
601
- </TableCell>
602
- <TableCell>
603
- <IconButton size="small">
604
- <EditIcon fontSize="small" />
605
- </IconButton>
606
- <IconButton size="small">
607
- <DeleteIcon fontSize="small" />
608
- </IconButton>
609
- </TableCell>
610
- </TableRow>
611
- ))}
612
- </TableBody>
613
- </Table>
614
- </TableContainer>
615
- </Box>
616
- )}
617
- </StackedModal>
618
-
619
- {/* Add User Modal */}
620
- <StackedModal
621
- open={addUserOpen}
622
- onClose={() => setAddUserOpen(false)}
623
- navigationTitle="Add New User"
624
- modalId="add-user-modal"
625
- >
626
- <StackedModalContent>
627
- <Typography variant="h5" gutterBottom>
628
- Create New User
629
- </Typography>
630
- <Stack spacing={3} sx={{ mt: 3 }}>
631
- <TextField
632
- fullWidth
633
- label="Full Name"
634
- required
635
- helperText="Enter the user's full name"
636
- />
637
- <TextField
638
- fullWidth
639
- label="Email Address"
640
- type="email"
641
- required
642
- helperText="This will be used for login"
643
- />
644
- <FormControl fullWidth>
645
- <InputLabel>Role</InputLabel>
646
- <Select label="Role" defaultValue="">
647
- <MenuItem value="admin">Admin</MenuItem>
648
- <MenuItem value="user">User</MenuItem>
649
- <MenuItem value="moderator">Moderator</MenuItem>
650
- </Select>
651
- </FormControl>
652
- <FormControlLabel control={<Switch defaultChecked />} label="Send invitation email" />
653
- <Alert severity="info">
654
- The user will receive an email invitation to set their password and complete
655
- registration.
656
- </Alert>
657
- </Stack>
658
- </StackedModalContent>
659
- <StackedModalActions>
660
- <Button variant="outlined" onClick={() => setAddUserOpen(false)}>
661
- Cancel
662
- </Button>
663
- <Button
664
- variant="contained"
665
- startIcon={<AddIcon />}
666
- onClick={() => {
667
- window.alert('User added successfully!');
668
- setAddUserOpen(false);
669
- }}
670
- >
671
- Create User
672
- </Button>
673
- </StackedModalActions>
674
- </StackedModal>
675
- </>
676
- );
677
- };
678
-
679
- return <AsyncModal />;
680
- };
681
-
682
- export const AsyncContentLoading: Story = {
683
- render: () => <AsyncContentLoadingComponent />,
684
- };
685
-
686
- // Custom actions and buttons
687
- const CustomActionsComponent = () => {
688
- const CustomActionsModal = () => {
689
- const [open, setOpen] = useState(false);
690
- const [progress, setProgress] = useState(0);
691
-
692
- useEffect(() => {
693
- if (open && progress < 100) {
694
- const timer = window.window.setTimeout(() => {
695
- setProgress((prev) => Math.min(prev + 10, 100));
696
- }, 500);
697
- return () => window.window.clearTimeout(timer);
698
- }
699
- }, [open, progress]);
700
-
701
- return (
702
- <>
703
- <Button
704
- variant="contained"
705
- onClick={() => {
706
- setOpen(true);
707
- setProgress(0);
708
- }}
709
- startIcon={<SettingsIcon />}
710
- >
711
- Open Settings Modal
712
- </Button>
713
-
714
- <StackedModal
715
- open={open}
716
- onClose={() => setOpen(false)}
717
- navigationTitle="Advanced Settings"
718
- actions={
719
- <Stack direction="row" spacing={1}>
720
- <IconButton size="small">
721
- <SearchIcon />
722
- </IconButton>
723
- <IconButton size="small">
724
- <FilterListIcon />
725
- </IconButton>
726
- <IconButton size="small">
727
- <MoreVertIcon />
728
- </IconButton>
729
- <Divider orientation="vertical" flexItem />
730
- <Button variant="outlined" size="small" startIcon={<InfoIcon />}>
731
- Help
732
- </Button>
733
- <Button
734
- variant="contained"
735
- size="small"
736
- color="success"
737
- startIcon={<SaveIcon />}
738
- disabled={progress < 100}
739
- >
740
- Save
741
- </Button>
742
- </Stack>
743
- }
744
- >
745
- <StackedModalContent>
746
- <Tabs value={0}>
747
- <Tab label="General" />
748
- <Tab label="Privacy" />
749
- <Tab label="Notifications" />
750
- <Tab label="Advanced" />
751
- </Tabs>
752
-
753
- <Box sx={{ mt: 3 }}>
754
- <Typography variant="h6" gutterBottom>
755
- General Settings
756
- </Typography>
757
-
758
- <Stack spacing={3}>
759
- <TextField fullWidth label="Display Name" defaultValue="John Doe" />
760
- <TextField
761
- fullWidth
762
- label="Email"
763
- type="email"
764
- defaultValue="john.doe@example.com"
765
- />
766
- <FormControlLabel control={<Switch defaultChecked />} label="Enable dark mode" />
767
- <FormControlLabel control={<Switch defaultChecked />} label="Show notifications" />
768
-
769
- <Box>
770
- <Typography variant="body2" color="text.secondary" gutterBottom>
771
- Profile completion: {progress}%
772
- </Typography>
773
- <LinearProgress variant="determinate" value={progress} />
774
- </Box>
775
- </Stack>
776
- </Box>
777
- </StackedModalContent>
778
- </StackedModal>
779
- </>
780
- );
781
- };
782
-
783
- return <CustomActionsModal />;
784
- };
785
-
786
- export const CustomActions: Story = {
787
- render: () => <CustomActionsComponent />,
788
- };
789
-
790
- // Complex workflow example (multi-step form)
791
- const ComplexWorkflowComponent = () => {
792
- const WorkflowModal = () => {
793
- const [open, setOpen] = useState(false);
794
- const [activeStep, setActiveStep] = useState(0);
795
- const [nestedOpen, setNestedOpen] = useState(false);
796
-
797
- const steps = ['Basic Info', 'Address', 'Payment', 'Review'];
798
-
799
- const handleNext = () => {
800
- setActiveStep((prev) => prev + 1);
801
- };
802
-
803
- const handleBack = () => {
804
- setActiveStep((prev) => prev - 1);
805
- };
806
-
807
- const handleReset = () => {
808
- setActiveStep(0);
809
- };
810
-
811
- return (
812
- <>
813
- <Card>
814
- <CardContent>
815
- <Typography variant="h5" gutterBottom>
816
- Multi-Step Registration
817
- </Typography>
818
- <Typography color="text.secondary" paragraph>
819
- Complex workflow with nested modals and step-by-step process
820
- </Typography>
821
- </CardContent>
822
- <CardActions>
823
- <Button
824
- variant="contained"
825
- size="large"
826
- onClick={() => setOpen(true)}
827
- startIcon={<AddIcon />}
828
- >
829
- Start Registration
830
- </Button>
831
- </CardActions>
832
- </Card>
833
-
834
- <StackedModal
835
- open={open}
836
- onClose={() => {
837
- setOpen(false);
838
- handleReset();
839
- }}
840
- navigationTitle="User Registration"
841
- modalId="workflow-main"
842
- actions={
843
- activeStep === steps.length ? (
844
- <Button
845
- variant="contained"
846
- color="success"
847
- onClick={() => {
848
- setOpen(false);
849
- handleReset();
850
- }}
851
- >
852
- Complete
853
- </Button>
854
- ) : (
855
- <Typography variant="body2" color="text.secondary">
856
- Step {activeStep + 1} of {steps.length}
857
- </Typography>
858
- )
859
- }
860
- >
861
- <StackedModalContent>
862
- <Stepper activeStep={activeStep} sx={{ mb: 4 }}>
863
- {steps.map((label) => (
864
- <Step key={label}>
865
- <StepLabel>{label}</StepLabel>
866
- </Step>
867
- ))}
868
- </Stepper>
869
-
870
- {activeStep === steps.length ? (
871
- <Box sx={{ textAlign: 'center', py: 4 }}>
872
- <CheckCircleIcon sx={{ fontSize: 64, color: 'success.main', mb: 2 }} />
873
- <Typography variant="h5" gutterBottom>
874
- Registration Complete!
875
- </Typography>
876
- <Typography color="text.secondary">
877
- Your account has been successfully created.
878
- </Typography>
879
- </Box>
880
- ) : (
881
- <>
882
- <Box sx={{ mb: 4 }}>
883
- {activeStep === 0 && (
884
- <Stack spacing={2}>
885
- <Typography variant="h6">Basic Information</Typography>
886
- <TextField fullWidth label="First Name" />
887
- <TextField fullWidth label="Last Name" />
888
- <TextField fullWidth label="Email" type="email" />
889
- <TextField fullWidth label="Phone" />
890
- <Button variant="outlined" onClick={() => setNestedOpen(true)}>
891
- Add Additional Contact
892
- </Button>
893
- </Stack>
894
- )}
895
-
896
- {activeStep === 1 && (
897
- <Stack spacing={2}>
898
- <Typography variant="h6">Address Information</Typography>
899
- <TextField fullWidth label="Street Address" />
900
- <TextField fullWidth label="City" />
901
- <Grid container spacing={2}>
902
- <Grid item xs={6}>
903
- <TextField fullWidth label="State" />
904
- </Grid>
905
- <Grid item xs={6}>
906
- <TextField fullWidth label="ZIP Code" />
907
- </Grid>
908
- </Grid>
909
- <TextField fullWidth label="Country" />
910
- </Stack>
911
- )}
912
-
913
- {activeStep === 2 && (
914
- <Stack spacing={2}>
915
- <Typography variant="h6">Payment Information</Typography>
916
- <TextField fullWidth label="Card Number" />
917
- <TextField fullWidth label="Cardholder Name" />
918
- <Grid container spacing={2}>
919
- <Grid item xs={6}>
920
- <TextField fullWidth label="Expiry Date" placeholder="MM/YY" />
921
- </Grid>
922
- <Grid item xs={6}>
923
- <TextField fullWidth label="CVV" />
924
- </Grid>
925
- </Grid>
926
- <FormControlLabel
927
- control={<Switch />}
928
- label="Save payment method for future use"
929
- />
930
- </Stack>
931
- )}
932
-
933
- {activeStep === 3 && (
934
- <Stack spacing={2}>
935
- <Typography variant="h6">Review Your Information</Typography>
936
- <Paper sx={{ p: 2, bgcolor: 'grey.50' }}>
937
- <Typography variant="subtitle2" gutterBottom>
938
- Personal Details
939
- </Typography>
940
- <Typography variant="body2" color="text.secondary">
941
- John Doe - john.doe@example.com
942
- </Typography>
943
- </Paper>
944
- <Paper sx={{ p: 2, bgcolor: 'grey.50' }}>
945
- <Typography variant="subtitle2" gutterBottom>
946
- Address
947
- </Typography>
948
- <Typography variant="body2" color="text.secondary">
949
- 123 Main St, New York, NY 10001
950
- </Typography>
951
- </Paper>
952
- <Paper sx={{ p: 2, bgcolor: 'grey.50' }}>
953
- <Typography variant="subtitle2" gutterBottom>
954
- Payment Method
955
- </Typography>
956
- <Typography variant="body2" color="text.secondary">
957
- Card ending in 1234
958
- </Typography>
959
- </Paper>
960
- <FormControlLabel
961
- control={<Switch defaultChecked />}
962
- label="I agree to the terms and conditions"
963
- />
964
- </Stack>
965
- )}
966
- </Box>
967
-
968
- <Box sx={{ display: 'flex', justifyContent: 'space-between' }}>
969
- <Button disabled={activeStep === 0} onClick={handleBack}>
970
- Back
971
- </Button>
972
- <Button variant="contained" onClick={handleNext}>
973
- {activeStep === steps.length - 1 ? 'Finish' : 'Continue'}
974
- </Button>
975
- </Box>
976
- </>
977
- )}
978
-
979
- {/* Nested Modal for Additional Contact */}
980
- <StackedModal
981
- open={nestedOpen}
982
- onClose={() => setNestedOpen(false)}
983
- navigationTitle="Additional Contact"
984
- modalId="workflow-nested"
985
- actions={
986
- <Button variant="contained" size="small" onClick={() => setNestedOpen(false)}>
987
- Add Contact
988
- </Button>
989
- }
990
- >
991
- <StackedModalContent>
992
- <Typography variant="h6" gutterBottom>
993
- Emergency Contact Information
994
- </Typography>
995
- <Stack spacing={2}>
996
- <TextField fullWidth label="Contact Name" />
997
- <TextField fullWidth label="Relationship" />
998
- <TextField fullWidth label="Phone Number" />
999
- <TextField fullWidth label="Email" type="email" />
1000
- </Stack>
1001
- </StackedModalContent>
1002
- </StackedModal>
1003
- </StackedModalContent>
1004
- </StackedModal>
1005
- </>
1006
- );
1007
- };
1008
-
1009
- return <WorkflowModal />;
1010
- };
1011
-
1012
- export const ComplexWorkflow: Story = {
1013
- render: () => <ComplexWorkflowComponent />,
1014
- };
1015
-
1016
- // Performance demo with many modals
1017
- const PerformanceDemoComponent = () => {
1018
- const PerformanceTest = () => {
1019
- const [modals, setModals] = useState<boolean[]>(Array(10).fill(false));
1020
- const { stack } = useModalStack();
1021
-
1022
- const openModal = (index: number) => {
1023
- setModals((prev) => {
1024
- const newModals = [...prev];
1025
- newModals[index] = true;
1026
- return newModals;
1027
- });
1028
- };
1029
-
1030
- const closeModal = (index: number) => {
1031
- setModals((prev) => {
1032
- const newModals = [...prev];
1033
- newModals[index] = false;
1034
- return newModals;
1035
- });
1036
- };
1037
-
1038
- return (
1039
- <>
1040
- <Card>
1041
- <CardContent>
1042
- <Typography variant="h5" gutterBottom>
1043
- Performance Test
1044
- </Typography>
1045
- <Typography color="text.secondary" paragraph>
1046
- Test the modal system with multiple nested modals. Only 2 modals are rendered at once
1047
- for optimal performance.
1048
- </Typography>
1049
- <Alert severity="info" sx={{ mt: 2 }}>
1050
- Current stack depth: {stack.length} modal(s)
1051
- </Alert>
1052
- </CardContent>
1053
- <CardActions>
1054
- <Button variant="contained" onClick={() => openModal(0)} startIcon={<AddIcon />}>
1055
- Open First Modal
1056
- </Button>
1057
- </CardActions>
1058
- </Card>
1059
-
1060
- {modals.map((isOpen, index) => (
1061
- <StackedModal
1062
- key={index}
1063
- open={isOpen}
1064
- onClose={() => closeModal(index)}
1065
- navigationTitle={`Modal Level ${index + 1}`}
1066
- modalId={`perf-modal-${index}`}
1067
- glass={index === 0}
1068
- actions={
1069
- index === modals.length - 1 ? (
1070
- <Button
1071
- variant="contained"
1072
- color="error"
1073
- size="small"
1074
- onClick={() => {
1075
- setModals(Array(10).fill(false));
1076
- }}
1077
- >
1078
- Close All
1079
- </Button>
1080
- ) : (
1081
- <Button
1082
- variant="contained"
1083
- size="small"
1084
- onClick={() => openModal(index + 1)}
1085
- disabled={index >= 9}
1086
- >
1087
- Open Next
1088
- </Button>
1089
- )
1090
- }
1091
- >
1092
- <StackedModalContent>
1093
- <Typography variant="h5" gutterBottom>
1094
- Level {index + 1} Content
1095
- </Typography>
1096
- <Typography paragraph>
1097
- This is modal number {index + 1} in the stack.
1098
- {index > 1 && ' Only this modal and its parent are rendered.'}
1099
- </Typography>
1100
-
1101
- <Grid container spacing={2}>
1102
- {Array.from({ length: 6 }).map((_, i) => (
1103
- <Grid item xs={12} md={6} key={i}>
1104
- <Card>
1105
- <CardContent>
1106
- <Typography variant="h6">Card {i + 1}</Typography>
1107
- <Typography color="text.secondary">
1108
- Sample content to test rendering performance
1109
- </Typography>
1110
- </CardContent>
1111
- </Card>
1112
- </Grid>
1113
- ))}
1114
- </Grid>
1115
-
1116
- {index < 9 && (
1117
- <Box sx={{ mt: 3 }}>
1118
- <Button variant="outlined" fullWidth onClick={() => openModal(index + 1)}>
1119
- Open Modal {index + 2}
1120
- </Button>
1121
- </Box>
1122
- )}
1123
- </StackedModalContent>
1124
- </StackedModal>
1125
- ))}
1126
- </>
1127
- );
1128
- };
1129
-
1130
- return <PerformanceTest />;
1131
- };
1132
-
1133
- export const PerformanceDemo: Story = {
1134
- render: () => <PerformanceDemoComponent />,
1135
- };
1136
-
1137
- // RTL Support
1138
- const RTLSupportComponent = () => {
1139
- const RTLModal = () => {
1140
- const [open, setOpen] = useState(false);
1141
- const [rtl, setRtl] = useState(false);
1142
-
1143
- return (
1144
- <>
1145
- <Card>
1146
- <CardContent>
1147
- <Typography variant="h5" gutterBottom>
1148
- RTL Language Support
1149
- </Typography>
1150
- <Typography color="text.secondary" paragraph>
1151
- Toggle RTL mode to see how the modal adapts to right-to-left languages
1152
- </Typography>
1153
- <FormControlLabel
1154
- control={<Switch checked={rtl} onChange={(e) => setRtl(e.target.checked)} />}
1155
- label="Enable RTL Mode"
1156
- />
1157
- </CardContent>
1158
- <CardActions>
1159
- <Button variant="contained" onClick={() => setOpen(true)}>
1160
- {rtl ? 'فتح مشروط' : 'Open Modal'}
1161
- </Button>
1162
- </CardActions>
1163
- </Card>
1164
-
1165
- <StackedModal
1166
- open={open}
1167
- onClose={() => setOpen(false)}
1168
- navigationTitle={rtl ? 'نموذج مع دعم RTL' : 'Modal with RTL Support'}
1169
- rtl={rtl}
1170
- glass={true}
1171
- actions={
1172
- <Stack direction="row" spacing={1}>
1173
- <Button variant="outlined" size="small" onClick={() => setOpen(false)}>
1174
- {rtl ? 'إلغاء' : 'Cancel'}
1175
- </Button>
1176
- <Button variant="contained" size="small">
1177
- {rtl ? 'حفظ' : 'Save'}
1178
- </Button>
1179
- </Stack>
1180
- }
1181
- >
1182
- <StackedModalContent>
1183
- <Typography variant="h5" gutterBottom>
1184
- {rtl ? 'مرحبا بالعالم' : 'Hello World'}
1185
- </Typography>
1186
- <Typography paragraph>
1187
- {rtl
1188
- ? 'هذا مثال على النص العربي في واجهة المستخدم. يتكيف التخطيط تلقائيًا مع اتجاه RTL.'
1189
- : 'This is an example of English text in the UI. The layout automatically adapts to LTR direction.'}
1190
- </Typography>
1191
- <Stack spacing={2}>
1192
- <TextField fullWidth label={rtl ? 'الاسم' : 'Name'} dir={rtl ? 'rtl' : 'ltr'} />
1193
- <TextField
1194
- fullWidth
1195
- label={rtl ? 'البريد الإلكتروني' : 'Email'}
1196
- dir={rtl ? 'rtl' : 'ltr'}
1197
- />
1198
- </Stack>
1199
- </StackedModalContent>
1200
- </StackedModal>
1201
- </>
1202
- );
1203
- };
1204
-
1205
- return <RTLModal />;
1206
- };
1207
-
1208
- export const RTLSupport: Story = {
1209
- render: () => <RTLSupportComponent />,
1210
- };
1211
-
1212
- // Accessibility Features
1213
- const AccessibilityShowcaseComponent = () => {
1214
- const AccessibleModal = () => {
1215
- const [open, setOpen] = useState(false);
1216
- const [announcement, setAnnouncement] = useState('');
1217
-
1218
- return (
1219
- <>
1220
- <Card>
1221
- <CardContent>
1222
- <Typography variant="h5" gutterBottom>
1223
- Accessibility Features
1224
- </Typography>
1225
- <Typography color="text.secondary" paragraph>
1226
- Full ARIA support, keyboard navigation, and focus management
1227
- </Typography>
1228
- <Alert severity="success" sx={{ mt: 2 }}>
1229
- <Typography variant="body2">
1230
- • Press ESC to close modal
1231
- <br />
1232
- • Use Tab/Shift+Tab to navigate
1233
- <br />
1234
- • Focus is trapped within modal
1235
- <br />• Screen reader announcements
1236
- </Typography>
1237
- </Alert>
1238
- </CardContent>
1239
- <CardActions>
1240
- <Button
1241
- variant="contained"
1242
- onClick={() => {
1243
- setOpen(true);
1244
- setAnnouncement('Modal opened. Use Tab to navigate.');
1245
- }}
1246
- >
1247
- Open Accessible Modal
1248
- </Button>
1249
- </CardActions>
1250
- </Card>
1251
-
1252
- {announcement && (
1253
- <Alert severity="info" onClose={() => setAnnouncement('')} sx={{ mt: 2 }}>
1254
- {announcement}
1255
- </Alert>
1256
- )}
1257
-
1258
- <StackedModal
1259
- open={open}
1260
- onClose={() => {
1261
- setOpen(false);
1262
- setAnnouncement('Modal closed.');
1263
- }}
1264
- navigationTitle="Accessible Form"
1265
- closeOnEsc={true}
1266
- closeOnClickOutside={true}
1267
- aria-labelledby="accessible-modal-title"
1268
- aria-describedby="accessible-modal-description"
1269
- actions={
1270
- <Stack direction="row" spacing={1}>
1271
- <Button
1272
- variant="outlined"
1273
- size="small"
1274
- onClick={() => {
1275
- setOpen(false);
1276
- setAnnouncement('Modal closed without saving.');
1277
- }}
1278
- >
1279
- Cancel
1280
- </Button>
1281
- <Button
1282
- variant="contained"
1283
- size="small"
1284
- onClick={() => {
1285
- setOpen(false);
1286
- setAnnouncement('Form submitted successfully.');
1287
- }}
1288
- >
1289
- Submit
1290
- </Button>
1291
- </Stack>
1292
- }
1293
- >
1294
- <StackedModalContent>
1295
- <Typography id="accessible-modal-title" variant="h5" gutterBottom>
1296
- Fully Accessible Modal
1297
- </Typography>
1298
- <Typography id="accessible-modal-description" paragraph>
1299
- This modal demonstrates all accessibility features including proper ARIA labels,
1300
- keyboard navigation, and focus management.
1301
- </Typography>
1302
-
1303
- <Stack spacing={3}>
1304
- <TextField
1305
- fullWidth
1306
- label="First Name"
1307
- helperText="Press Tab to move to next field"
1308
- inputProps={{
1309
- 'aria-label': 'First name input field',
1310
- 'aria-required': 'true',
1311
- }}
1312
- />
1313
- <TextField
1314
- fullWidth
1315
- label="Last Name"
1316
- helperText="Press Shift+Tab to move to previous field"
1317
- inputProps={{
1318
- 'aria-label': 'Last name input field',
1319
- 'aria-required': 'true',
1320
- }}
1321
- />
1322
- <FormControlLabel
1323
- control={
1324
- <Switch
1325
- inputProps={{
1326
- 'aria-label': 'Subscribe to newsletter',
1327
- }}
1328
- />
1329
- }
1330
- label="Subscribe to newsletter"
1331
- />
1332
- </Stack>
1333
- </StackedModalContent>
1334
- </StackedModal>
1335
- </>
1336
- );
1337
- };
1338
-
1339
- return <AccessibleModal />;
1340
- };
1341
-
1342
- export const AccessibilityShowcase: Story = {
1343
- render: () => <AccessibilityShowcaseComponent />,
1344
- };
1345
-
1346
- // Required story exports for validation
1347
- const AllVariantsComponent = () => {
1348
- const [basicOpen, setBasicOpen] = useState(false);
1349
- const [glassOpen, setGlassOpen] = useState(false);
1350
- const [loadingOpen, setLoadingOpen] = useState(false);
1351
-
1352
- return (
1353
- <>
1354
- <Stack spacing={2}>
1355
- <Button variant="contained" onClick={() => setBasicOpen(true)}>
1356
- Basic Modal
1357
- </Button>
1358
- <Button variant="contained" onClick={() => setGlassOpen(true)}>
1359
- Glass Modal
1360
- </Button>
1361
- <Button variant="contained" onClick={() => setLoadingOpen(true)}>
1362
- Loading Modal
1363
- </Button>
1364
- </Stack>
1365
-
1366
- <StackedModal
1367
- open={basicOpen}
1368
- onClose={() => setBasicOpen(false)}
1369
- navigationTitle="Basic Variant"
1370
- >
1371
- <StackedModalContent>
1372
- <Typography>Basic modal variant without special effects</Typography>
1373
- </StackedModalContent>
1374
- </StackedModal>
1375
-
1376
- <StackedModal
1377
- open={glassOpen}
1378
- onClose={() => setGlassOpen(false)}
1379
- glass
1380
- navigationTitle="Glass Variant"
1381
- >
1382
- <StackedModalContent>
1383
- <Typography>Glass morphism modal variant</Typography>
1384
- </StackedModalContent>
1385
- </StackedModal>
1386
-
1387
- <StackedModal
1388
- open={loadingOpen}
1389
- onClose={() => setLoadingOpen(false)}
1390
- loading
1391
- loadingText="Loading data..."
1392
- navigationTitle="Loading Variant"
1393
- >
1394
- <StackedModalContent>
1395
- <Typography>This content won't show during loading</Typography>
1396
- </StackedModalContent>
1397
- </StackedModal>
1398
- </>
1399
- );
1400
- };
1401
-
1402
- export const AllVariants: Story = {
1403
- render: () => <AllVariantsComponent />,
1404
- };
1405
-
1406
- const AllSizesComponent = () => {
1407
- const [smallOpen, setSmallOpen] = useState(false);
1408
- const [mediumOpen, setMediumOpen] = useState(false);
1409
- const [largeOpen, setLargeOpen] = useState(false);
1410
- const [fullscreenOpen, setFullscreenOpen] = useState(false);
1411
-
1412
- return (
1413
- <>
1414
- <Stack spacing={2}>
1415
- <Button variant="contained" onClick={() => setSmallOpen(true)}>
1416
- Small Modal
1417
- </Button>
1418
- <Button variant="contained" onClick={() => setMediumOpen(true)}>
1419
- Medium Modal
1420
- </Button>
1421
- <Button variant="contained" onClick={() => setLargeOpen(true)}>
1422
- Large Modal
1423
- </Button>
1424
- <Button variant="contained" onClick={() => setFullscreenOpen(true)}>
1425
- Fullscreen Modal
1426
- </Button>
1427
- </Stack>
1428
-
1429
- <StackedModal
1430
- open={smallOpen}
1431
- onClose={() => setSmallOpen(false)}
1432
- navigationTitle="Small Size"
1433
- maxWidth="sm"
1434
- >
1435
- <StackedModalContent>
1436
- <Typography>Small modal content (max-width: sm)</Typography>
1437
- </StackedModalContent>
1438
- </StackedModal>
1439
-
1440
- <StackedModal
1441
- open={mediumOpen}
1442
- onClose={() => setMediumOpen(false)}
1443
- navigationTitle="Medium Size"
1444
- maxWidth="md"
1445
- >
1446
- <StackedModalContent>
1447
- <Typography>Medium modal content (max-width: md)</Typography>
1448
- </StackedModalContent>
1449
- </StackedModal>
1450
-
1451
- <StackedModal
1452
- open={largeOpen}
1453
- onClose={() => setLargeOpen(false)}
1454
- navigationTitle="Large Size"
1455
- maxWidth="lg"
1456
- >
1457
- <StackedModalContent>
1458
- <Typography>Large modal content (max-width: lg)</Typography>
1459
- </StackedModalContent>
1460
- </StackedModal>
1461
-
1462
- <StackedModal
1463
- open={fullscreenOpen}
1464
- onClose={() => setFullscreenOpen(false)}
1465
- navigationTitle="Fullscreen"
1466
- fullScreen
1467
- >
1468
- <StackedModalContent>
1469
- <Typography>Fullscreen modal content</Typography>
1470
- </StackedModalContent>
1471
- </StackedModal>
1472
- </>
1473
- );
1474
- };
1475
-
1476
- export const AllSizes: Story = {
1477
- render: () => <AllSizesComponent />,
1478
- };
1479
-
1480
- const AllStatesComponent = () => {
1481
- const [normalOpen, setNormalOpen] = useState(false);
1482
- const [loadingOpen, setLoadingOpen] = useState(false);
1483
- const [errorOpen, setErrorOpen] = useState(false);
1484
- const [disabledActionsOpen, setDisabledActionsOpen] = useState(false);
1485
-
1486
- return (
1487
- <>
1488
- <Stack spacing={2}>
1489
- <Button variant="contained" onClick={() => setNormalOpen(true)}>
1490
- Normal State
1491
- </Button>
1492
- <Button variant="contained" onClick={() => setLoadingOpen(true)}>
1493
- Loading State
1494
- </Button>
1495
- <Button variant="contained" onClick={() => setErrorOpen(true)}>
1496
- Error State
1497
- </Button>
1498
- <Button variant="contained" onClick={() => setDisabledActionsOpen(true)}>
1499
- Disabled Actions
1500
- </Button>
1501
- </Stack>
1502
-
1503
- <StackedModal
1504
- open={normalOpen}
1505
- onClose={() => setNormalOpen(false)}
1506
- navigationTitle="Normal State"
1507
- >
1508
- <StackedModalContent>
1509
- <Typography>Normal modal state with default styling</Typography>
1510
- </StackedModalContent>
1511
- </StackedModal>
1512
-
1513
- <StackedModal
1514
- open={loadingOpen}
1515
- onClose={() => setLoadingOpen(false)}
1516
- loading
1517
- loadingText="Processing..."
1518
- navigationTitle="Loading State"
1519
- >
1520
- <StackedModalContent>
1521
- <Typography>Content hidden during loading</Typography>
1522
- </StackedModalContent>
1523
- </StackedModal>
1524
-
1525
- <StackedModal
1526
- open={errorOpen}
1527
- onClose={() => setErrorOpen(false)}
1528
- navigationTitle="Error State"
1529
- >
1530
- <StackedModalContent>
1531
- <Alert severity="error" sx={{ mb: 2 }}>
1532
- An error occurred while processing your request
1533
- </Alert>
1534
- <Typography>Modal with error state displayed</Typography>
1535
- </StackedModalContent>
1536
- </StackedModal>
1537
-
1538
- <StackedModal
1539
- open={disabledActionsOpen}
1540
- onClose={() => setDisabledActionsOpen(false)}
1541
- navigationTitle="Disabled Actions"
1542
- actions={
1543
- <Button variant="contained" size="small" disabled>
1544
- Disabled Action
1545
- </Button>
1546
- }
1547
- >
1548
- <StackedModalContent>
1549
- <Typography>Modal with disabled action buttons</Typography>
1550
- </StackedModalContent>
1551
- </StackedModal>
1552
- </>
1553
- );
1554
- };
1555
-
1556
- export const AllStates: Story = {
1557
- render: () => <AllStatesComponent />,
1558
- };
1559
-
1560
- const InteractiveStatesComponent = () => {
1561
- const [formOpen, setFormOpen] = useState(false);
1562
- const [confirmOpen, setConfirmOpen] = useState(false);
1563
- const [formData, setFormData] = useState({ name: '', email: '' });
1564
- const [submitting, setSubmitting] = useState(false);
1565
-
1566
- const handleSubmit = () => {
1567
- setSubmitting(true);
1568
- window.setTimeout(() => {
1569
- setSubmitting(false);
1570
- setFormOpen(false);
1571
- setConfirmOpen(true);
1572
- }, 2000);
1573
- };
1574
-
1575
- return (
1576
- <>
1577
- <Button variant="contained" onClick={() => setFormOpen(true)}>
1578
- Interactive Form Modal
1579
- </Button>
1580
-
1581
- <StackedModal
1582
- open={formOpen}
1583
- onClose={() => setFormOpen(false)}
1584
- navigationTitle="Interactive Form"
1585
- loading={submitting}
1586
- loadingText="Submitting form..."
1587
- actions={
1588
- !submitting && (
1589
- <Stack direction="row" spacing={1}>
1590
- <Button variant="outlined" size="small" onClick={() => setFormOpen(false)}>
1591
- Cancel
1592
- </Button>
1593
- <Button
1594
- variant="contained"
1595
- size="small"
1596
- onClick={handleSubmit}
1597
- disabled={!formData.name || !formData.email}
1598
- >
1599
- Submit
1600
- </Button>
1601
- </Stack>
1602
- )
1603
- }
1604
- >
1605
- <StackedModalContent>
1606
- <Typography variant="h6" gutterBottom>
1607
- Interactive Form
1608
- </Typography>
1609
- <Stack spacing={2}>
1610
- <TextField
1611
- fullWidth
1612
- label="Name"
1613
- value={formData.name}
1614
- onChange={(e) => setFormData({ ...formData, name: e.target.value })}
1615
- helperText={!formData.name ? 'Name is required' : ''}
1616
- error={!formData.name}
1617
- />
1618
- <TextField
1619
- fullWidth
1620
- label="Email"
1621
- type="email"
1622
- value={formData.email}
1623
- onChange={(e) => setFormData({ ...formData, email: e.target.value })}
1624
- helperText={!formData.email ? 'Email is required' : ''}
1625
- error={!formData.email}
1626
- />
1627
- </Stack>
1628
- </StackedModalContent>
1629
- </StackedModal>
1630
-
1631
- <StackedModal
1632
- open={confirmOpen}
1633
- onClose={() => setConfirmOpen(false)}
1634
- navigationTitle="Success"
1635
- actions={
1636
- <Button variant="contained" size="small" onClick={() => setConfirmOpen(false)}>
1637
- Close
1638
- </Button>
1639
- }
1640
- >
1641
- <StackedModalContent>
1642
- <Alert severity="success">Form submitted successfully!</Alert>
1643
- <Typography sx={{ mt: 2 }}>Thank you for your submission, {formData.name}.</Typography>
1644
- </StackedModalContent>
1645
- </StackedModal>
1646
- </>
1647
- );
1648
- };
1649
-
1650
- export const InteractiveStates: Story = {
1651
- render: () => <InteractiveStatesComponent />,
1652
- };
1653
-
1654
- const ResponsiveComponent = () => {
1655
- const [mobileOpen, setMobileOpen] = useState(false);
1656
- const [tabletOpen, setTabletOpen] = useState(false);
1657
- const [desktopOpen, setDesktopOpen] = useState(false);
1658
- const theme = useTheme();
1659
- const isMobile = useMediaQuery(theme.breakpoints.down('sm'));
1660
- const isTablet = useMediaQuery(theme.breakpoints.down('md'));
1661
-
1662
- const getDeviceInfo = () => {
1663
- if (isMobile) return 'Mobile (< 600px)';
1664
- if (isTablet) return 'Tablet (600px - 960px)';
1665
- return 'Desktop (> 960px)';
1666
- };
1667
-
1668
- return (
1669
- <>
1670
- <Alert severity="info" sx={{ mb: 2 }}>
1671
- Current viewport: {getDeviceInfo()}
1672
- </Alert>
1673
-
1674
- <Stack spacing={2}>
1675
- <Button variant="contained" onClick={() => setMobileOpen(true)}>
1676
- Mobile Optimized Modal
1677
- </Button>
1678
- <Button variant="contained" onClick={() => setTabletOpen(true)}>
1679
- Tablet Optimized Modal
1680
- </Button>
1681
- <Button variant="contained" onClick={() => setDesktopOpen(true)}>
1682
- Desktop Modal
1683
- </Button>
1684
- </Stack>
1685
-
1686
- <StackedModal
1687
- open={mobileOpen}
1688
- onClose={() => setMobileOpen(false)}
1689
- navigationTitle="Mobile Modal"
1690
- maxWidth={isMobile ? false : 'sm'}
1691
- >
1692
- <StackedModalContent>
1693
- <Typography variant="h6" gutterBottom>
1694
- Mobile-Optimized Content
1695
- </Typography>
1696
- <Typography paragraph>
1697
- This modal adapts to mobile screens with bottom sheet behavior and touch-friendly
1698
- interactions.
1699
- </Typography>
1700
- <Stack spacing={2}>
1701
- <Button variant="outlined" fullWidth>
1702
- Mobile Action 1
1703
- </Button>
1704
- <Button variant="outlined" fullWidth>
1705
- Mobile Action 2
1706
- </Button>
1707
- </Stack>
1708
- </StackedModalContent>
1709
- </StackedModal>
1710
-
1711
- <StackedModal
1712
- open={tabletOpen}
1713
- onClose={() => setTabletOpen(false)}
1714
- navigationTitle="Tablet Modal"
1715
- maxWidth="md"
1716
- >
1717
- <StackedModalContent>
1718
- <Typography variant="h5" gutterBottom>
1719
- Tablet-Optimized Layout
1720
- </Typography>
1721
- <Grid container spacing={2}>
1722
- <Grid item xs={12} sm={6}>
1723
- <Paper sx={{ p: 2 }}>
1724
- <Typography variant="h6">Left Panel</Typography>
1725
- <Typography>Content optimized for tablet screens</Typography>
1726
- </Paper>
1727
- </Grid>
1728
- <Grid item xs={12} sm={6}>
1729
- <Paper sx={{ p: 2 }}>
1730
- <Typography variant="h6">Right Panel</Typography>
1731
- <Typography>Multi-column layout on tablets</Typography>
1732
- </Paper>
1733
- </Grid>
1734
- </Grid>
1735
- </StackedModalContent>
1736
- </StackedModal>
1737
-
1738
- <StackedModal
1739
- open={desktopOpen}
1740
- onClose={() => setDesktopOpen(false)}
1741
- navigationTitle="Desktop Modal"
1742
- maxWidth="lg"
1743
- >
1744
- <StackedModalContent>
1745
- <Typography variant="h4" gutterBottom>
1746
- Desktop-Optimized Experience
1747
- </Typography>
1748
- <Typography paragraph>
1749
- Large modal with extensive content suitable for desktop viewing.
1750
- </Typography>
1751
- <Grid container spacing={3}>
1752
- {Array.from({ length: 6 }).map((_, i) => (
1753
- <Grid item xs={12} md={4} key={i}>
1754
- <Card>
1755
- <CardContent>
1756
- <Typography variant="h6">Feature {i + 1}</Typography>
1757
- <Typography color="text.secondary">
1758
- Desktop users can see more content at once
1759
- </Typography>
1760
- </CardContent>
1761
- </Card>
1762
- </Grid>
1763
- ))}
1764
- </Grid>
1765
- </StackedModalContent>
1766
- </StackedModal>
1767
- </>
1768
- );
1769
- };
1770
-
1771
- export const Responsive: Story = {
1772
- parameters: {
1773
- viewport: {
1774
- viewports: {
1775
- mobile: { name: 'Mobile', styles: { width: '375px', height: '667px' } },
1776
- tablet: { name: 'Tablet', styles: { width: '768px', height: '1024px' } },
1777
- desktop: { name: 'Desktop', styles: { width: '1440px', height: '900px' } },
1778
- },
1779
- defaultViewport: 'mobile',
1780
- },
1781
- },
1782
- render: () => <ResponsiveComponent />,
1783
- };