@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.
- package/package.json +17 -9
- package/src/button/index.ts +1 -0
- package/src/social-login-button/index.ts +1 -0
- package/src/{social-login-button.tsx → social-login-button/social-login-button.tsx} +5 -5
- package/src/user-avatar/index.ts +1 -0
- package/src/{user-avatar.tsx → user-avatar/user-avatar.tsx} +4 -4
- package/eslint.config.js +0 -89
- package/src/__tests__/data-grid.test.tsx +0 -125
- package/src/__tests__/package-wiring.test.ts +0 -41
- package/src/__tests__/setup.ts +0 -1
- package/src/__tests__/social-login-button.test.tsx +0 -186
- package/src/__tests__/user-avatar.test.tsx +0 -195
- package/src/__tests__/viewport.test.ts +0 -50
- package/src/components/command/__tests__/command.test.tsx +0 -112
- package/src/components/data-display/Alert/Alert.stories.tsx +0 -559
- package/src/components/data-display/Alert/Alert.test.stories.tsx +0 -707
- package/src/components/data-display/AlertDialog/AlertDialog.stories.tsx +0 -362
- package/src/components/data-display/AlertDialog/AlertDialog.test.stories.tsx +0 -763
- package/src/components/data-display/AsyncStateContainer/AsyncStateContainer.stories.tsx +0 -230
- package/src/components/data-display/AsyncStateContainer/AsyncStateContainer.test.stories.tsx +0 -270
- package/src/components/data-display/Avatar/Avatar.stories.tsx +0 -721
- package/src/components/data-display/Avatar/Avatar.test.stories.tsx +0 -822
- package/src/components/data-display/Badge/Badge.stories.tsx +0 -1134
- package/src/components/data-display/Badge/Badge.test.stories.tsx +0 -1194
- package/src/components/data-display/Banner/Banner.stories.tsx +0 -528
- package/src/components/data-display/Banner/Banner.test.stories.tsx +0 -511
- package/src/components/data-display/Carousel/Carousel.stories.tsx +0 -607
- package/src/components/data-display/Carousel/Carousel.test.stories.tsx +0 -701
- package/src/components/data-display/Chart/Chart.stories.tsx +0 -568
- package/src/components/data-display/Chart/Chart.test.stories.tsx +0 -174
- package/src/components/data-display/Chart/SpecChart.stories.tsx +0 -150
- package/src/components/data-display/Chart/SpecChart.test.stories.tsx +0 -56
- package/src/components/data-display/Chart/__tests__/SpecChart.test.tsx +0 -60
- package/src/components/data-display/Chart/__tests__/chart-format.test.ts +0 -43
- package/src/components/data-display/Chart/__tests__/chart-spec.test.ts +0 -119
- package/src/components/data-display/Chip/Chip.stories.tsx +0 -252
- package/src/components/data-display/Chip/Chip.test.stories.tsx +0 -266
- package/src/components/data-display/DataGrid/DataGrid.stories.tsx +0 -515
- package/src/components/data-display/DataGrid/DataGrid.test.stories.tsx +0 -653
- package/src/components/data-display/DataViews/__tests__/DataViewsGrid.test.tsx +0 -271
- package/src/components/data-display/DataViews/__tests__/DataViewsTableBase.test.tsx +0 -134
- package/src/components/data-display/DataViews/__tests__/SaveViewModal.test.tsx +0 -83
- package/src/components/data-display/DataViews/__tests__/data-views-filter.test.ts +0 -115
- package/src/components/data-display/DataViews/__tests__/data-views-preview.test.ts +0 -53
- package/src/components/data-display/DataViews/__tests__/range-pill.test.tsx +0 -114
- package/src/components/data-display/DataViews/base-card.stories.tsx +0 -136
- package/src/components/data-display/DescriptionItem/DescriptionItem.stories.tsx +0 -254
- package/src/components/data-display/EmptyState/EmptyState.stories.tsx +0 -282
- package/src/components/data-display/EmptyState/EmptyState.test.stories.tsx +0 -441
- package/src/components/data-display/ErrorState/ErrorState.stories.tsx +0 -110
- package/src/components/data-display/ErrorState/ErrorState.test.stories.tsx +0 -133
- package/src/components/data-display/HoverCard/HoverCard.stories.tsx +0 -650
- package/src/components/data-display/HoverCard/HoverCard.test.stories.tsx +0 -929
- package/src/components/data-display/InteractiveTooltip/InteractiveTooltip.stories.tsx +0 -411
- package/src/components/data-display/LazyImage/LazyImage.stories.tsx +0 -387
- package/src/components/data-display/Lightbox/Lightbox.stories.tsx +0 -315
- package/src/components/data-display/Lightbox/Lightbox.test.stories.tsx +0 -598
- package/src/components/data-display/LoadingState/LoadingState.stories.tsx +0 -124
- package/src/components/data-display/LoadingState/LoadingState.test.stories.tsx +0 -99
- package/src/components/data-display/MapPreview/MapPreview.stories.tsx +0 -458
- package/src/components/data-display/MapPreview/MapPreview.test.stories.tsx +0 -394
- package/src/components/data-display/Popover/Popover.stories.tsx +0 -295
- package/src/components/data-display/Popover/Popover.test.stories.tsx +0 -1162
- package/src/components/data-display/Progress/Progress.stories.tsx +0 -481
- package/src/components/data-display/Progress/Progress.test.stories.tsx +0 -2070
- package/src/components/data-display/SectionOnboarding/SectionOnboarding.stories.tsx +0 -160
- package/src/components/data-display/SectionOnboarding/SectionOnboarding.test.stories.tsx +0 -190
- package/src/components/data-display/Sheet/Sheet.stories.tsx +0 -883
- package/src/components/data-display/Sheet/Sheet.test.stories.tsx +0 -1105
- package/src/components/data-display/StatCard/StatCard.stories.tsx +0 -167
- package/src/components/data-display/StatCard/StatCard.test.stories.tsx +0 -240
- package/src/components/data-display/Stepper/Stepper.stories.tsx +0 -540
- package/src/components/data-display/Stepper/Stepper.test.stories.tsx +0 -600
- package/src/components/data-display/Table/Table.stories.tsx +0 -803
- package/src/components/data-display/Table/Table.test.stories.tsx +0 -369
- package/src/components/data-display/Timeline/Timeline.stories.tsx +0 -442
- package/src/components/data-display/Timeline/Timeline.test.stories.tsx +0 -930
- package/src/components/data-display/TimingDiagram/TimingDiagram.stories.tsx +0 -475
- package/src/components/data-display/TimingDiagram/TimingDiagram.test.stories.tsx +0 -734
- package/src/components/data-display/Tooltip/Tooltip.stories.tsx +0 -468
- package/src/components/data-display/Tooltip/Tooltip.test.stories.tsx +0 -1154
- package/src/components/feedback/ConfirmAction/ConfirmAction.stories.tsx +0 -146
- package/src/components/feedback/ConfirmAction/ConfirmAction.test.stories.tsx +0 -114
- package/src/components/feedback/ConfirmAction/__tests__/confirm-action.test.tsx +0 -288
- package/src/components/feedback/Dialog/Dialog.stories.tsx +0 -833
- package/src/components/feedback/Dialog/Dialog.test.stories.tsx +0 -964
- package/src/components/feedback/Dialog/__tests__/dialog-content-spacing.test.tsx +0 -66
- package/src/components/feedback/Modal/Modal.stories.tsx +0 -765
- package/src/components/feedback/Modal/Modal.test.stories.tsx +0 -251
- package/src/components/feedback/Sonner/Sonner.stories.tsx +0 -698
- package/src/components/feedback/Sonner/Sonner.test.stories.tsx +0 -896
- package/src/components/feedback/StackedModal/StackedModal.stories.tsx +0 -1783
- package/src/components/feedback/StackedModal/StackedModal.test.stories.tsx +0 -973
- package/src/components/feedback/StackedModal/__tests__/stacked-modal-viewport.test.tsx +0 -104
- package/src/components/feedback/Toast/Toast.stories.tsx +0 -548
- package/src/components/feedback/Toast/Toast.test.stories.tsx +0 -834
- package/src/components/feedback/TutorialOverlay/TutorialOverlay.stories.tsx +0 -691
- package/src/components/feedback/TutorialOverlay/TutorialOverlay.test.stories.tsx +0 -634
- package/src/components/form/AddressAutocomplete/AddressAutocomplete.stories.tsx +0 -665
- package/src/components/form/AddressAutocomplete/AddressAutocomplete.test.stories.tsx +0 -727
- package/src/components/form/Autocomplete/Autocomplete.stories.tsx +0 -715
- package/src/components/form/Autocomplete/Autocomplete.test.stories.tsx +0 -825
- package/src/components/form/Button/Button.stories.tsx +0 -365
- package/src/components/form/Button/Button.test.stories.tsx +0 -607
- package/src/components/form/Calendar/Calendar.stories.tsx +0 -349
- package/src/components/form/Calendar/Calendar.test.stories.tsx +0 -464
- package/src/components/form/CepField/CepField.stories.tsx +0 -138
- package/src/components/form/CepField/CepField.test.stories.tsx +0 -281
- package/src/components/form/Checkbox/Checkbox.stories.tsx +0 -265
- package/src/components/form/Checkbox/Checkbox.test.stories.tsx +0 -181
- package/src/components/form/CodeEditor/CodeEditor.stories.tsx +0 -871
- package/src/components/form/CodeEditor/CodeEditor.test.stories.tsx +0 -574
- package/src/components/form/Command/Command.stories.tsx +0 -580
- package/src/components/form/Command/Command.test.stories.tsx +0 -215
- package/src/components/form/CreatableSelect/CreatableSelect.stories.tsx +0 -112
- package/src/components/form/CreatableSelect/CreatableSelect.test.stories.tsx +0 -134
- package/src/components/form/Form/Form.stories.tsx +0 -687
- package/src/components/form/Form/Form.test.stories.tsx +0 -601
- package/src/components/form/Input/Input.stories.tsx +0 -260
- package/src/components/form/Input/Input.test.stories.tsx +0 -1191
- package/src/components/form/InputOTP/InputOTP.stories.tsx +0 -774
- package/src/components/form/InputOTP/InputOTP.test.stories.tsx +0 -588
- package/src/components/form/Label/Label.stories.tsx +0 -473
- package/src/components/form/Label/Label.test.stories.tsx +0 -915
- package/src/components/form/Menubar/Menubar.stories.tsx +0 -472
- package/src/components/form/Menubar/Menubar.test.stories.tsx +0 -584
- package/src/components/form/PasswordStrength/PasswordStrength.stories.tsx +0 -562
- package/src/components/form/PasswordStrength/PasswordStrength.test.stories.tsx +0 -327
- package/src/components/form/PhoneInput/PhoneInput.stories.tsx +0 -495
- package/src/components/form/PhoneInput/PhoneInput.test.stories.tsx +0 -666
- package/src/components/form/RadioGroup/RadioGroup.stories.tsx +0 -518
- package/src/components/form/RadioGroup/RadioGroup.test.stories.tsx +0 -685
- package/src/components/form/RichTextEditor/RichTextEditor.stories.tsx +0 -261
- package/src/components/form/RichTextEditor/RichTextEditor.test.stories.tsx +0 -491
- package/src/components/form/SearchPalette/SearchPalette.stories.tsx +0 -135
- package/src/components/form/Select/Select.stories.tsx +0 -364
- package/src/components/form/Select/Select.test.stories.tsx +0 -985
- package/src/components/form/Slider/Slider.stories.tsx +0 -418
- package/src/components/form/Slider/Slider.test.stories.tsx +0 -1042
- package/src/components/form/Switch/Switch.stories.tsx +0 -697
- package/src/components/form/Switch/Switch.test.stories.tsx +0 -597
- package/src/components/form/Textarea/Textarea.stories.tsx +0 -473
- package/src/components/form/Textarea/Textarea.test.stories.tsx +0 -702
- package/src/components/form/Toggle/Toggle.stories.tsx +0 -638
- package/src/components/form/Toggle/Toggle.test.stories.tsx +0 -1159
- package/src/components/form/ToggleGroup/ToggleGroup.stories.tsx +0 -617
- package/src/components/form/ToggleGroup/ToggleGroup.test.stories.tsx +0 -915
- package/src/components/form/UploadButton/UploadButton.stories.tsx +0 -367
- package/src/components/form/UploadButton/UploadButton.test.stories.tsx +0 -573
- package/src/components/form/total-form/total-form.test.tsx +0 -214
- package/src/components/layout/Accordion/Accordion.stories.tsx +0 -694
- package/src/components/layout/Accordion/Accordion.test.stories.tsx +0 -1344
- package/src/components/layout/Card/Card.stories.tsx +0 -591
- package/src/components/layout/Card/Card.test.stories.tsx +0 -1134
- package/src/components/layout/CardGrid/__tests__/CardGrid.test.tsx +0 -92
- package/src/components/layout/Collapsible/Collapsible.stories.tsx +0 -180
- package/src/components/layout/Collapsible/Collapsible.test.stories.tsx +0 -308
- package/src/components/layout/Container/Container.stories.tsx +0 -557
- package/src/components/layout/Container/Container.test.stories.tsx +0 -745
- package/src/components/layout/ContentToolbar/ContentToolbar.stories.tsx +0 -129
- package/src/components/layout/ContentToolbar/ContentToolbar.test.stories.tsx +0 -251
- package/src/components/layout/ContentToolbar/__tests__/ColumnsMenu.test.tsx +0 -39
- package/src/components/layout/ContentToolbar/__tests__/MultiSelectDropdown.test.tsx +0 -131
- package/src/components/layout/ContentToolbar/__tests__/SavedViewsMenu.test.tsx +0 -99
- package/src/components/layout/Dashboard/Dashboard.stories.tsx +0 -104
- package/src/components/layout/Dashboard/Dashboard.test.stories.tsx +0 -190
- package/src/components/layout/Drawer/Drawer.stories.tsx +0 -658
- package/src/components/layout/Drawer/Drawer.test.stories.tsx +0 -1343
- package/src/components/layout/Resizable/Resizable.stories.tsx +0 -1039
- package/src/components/layout/Resizable/Resizable.test.stories.tsx +0 -754
- package/src/components/layout/ScrollArea/ScrollArea.stories.tsx +0 -651
- package/src/components/layout/ScrollArea/ScrollArea.test.stories.tsx +0 -619
- package/src/components/layout/Separator/Separator.stories.tsx +0 -563
- package/src/components/layout/Separator/Separator.test.stories.tsx +0 -518
- package/src/components/layout/SettingsLayout/SettingsLayout.stories.tsx +0 -192
- package/src/components/layout/SettingsLayout/SettingsLayout.test.stories.tsx +0 -175
- package/src/components/layout/Sidebar/Sidebar.stories.tsx +0 -609
- package/src/components/layout/Sidebar/Sidebar.test.stories.tsx +0 -1324
- package/src/components/layout/Skeleton/Skeleton.stories.tsx +0 -689
- package/src/components/layout/Skeleton/Skeleton.test.stories.tsx +0 -521
- package/src/components/layout/Spacer/Spacer.stories.tsx +0 -502
- package/src/components/layout/Spacer/Spacer.test.stories.tsx +0 -474
- package/src/components/layout/TableFilter/TableFilter.stories.tsx +0 -82
- package/src/components/layout/TableFilter/TableFilter.test.stories.tsx +0 -87
- package/src/components/navigation/Breadcrumbs/Breadcrumbs.stories.tsx +0 -638
- package/src/components/navigation/Breadcrumbs/Breadcrumbs.test.stories.tsx +0 -1008
- package/src/components/navigation/CommandPalette/CommandPalette.stories.tsx +0 -386
- package/src/components/navigation/CommandPalette/CommandPalette.test.stories.tsx +0 -435
- package/src/components/navigation/ContextMenu/ContextMenu.stories.tsx +0 -614
- package/src/components/navigation/ContextMenu/ContextMenu.test.stories.tsx +0 -845
- package/src/components/navigation/DropdownMenu/DropdownMenu.stories.tsx +0 -578
- package/src/components/navigation/DropdownMenu/DropdownMenu.test.stories.tsx +0 -660
- package/src/components/navigation/NavigationMenu/stories/NavigationMenu.stories.tsx +0 -516
- package/src/components/navigation/NavigationMenu/stories/NavigationMenu.test.stories.tsx +0 -935
- package/src/components/navigation/NavigationMenu/stories/NavigationMenuHorizontal.stories.tsx +0 -501
- package/src/components/navigation/NavigationMenu/stories/NavigationMenuVertical.stories.tsx +0 -453
- package/src/components/navigation/Pagination/Pagination.stories.tsx +0 -602
- package/src/components/navigation/Pagination/Pagination.test.stories.tsx +0 -520
- package/src/components/navigation/Tabs/Tabs.stories.tsx +0 -1004
- package/src/components/navigation/Tabs/Tabs.test.stories.tsx +0 -1225
- package/src/components/typography/Blockquote/Blockquote.stories.tsx +0 -359
- package/src/components/typography/Blockquote/Blockquote.test.stories.tsx +0 -432
- package/src/components/typography/Code/Code.stories.tsx +0 -686
- package/src/components/typography/Code/Code.test.stories.tsx +0 -703
- package/src/components/typography/Heading/Heading.stories.tsx +0 -451
- package/src/components/typography/Heading/Heading.test.stories.tsx +0 -830
- package/src/components/typography/Paragraph/Paragraph.stories.tsx +0 -280
- package/src/components/typography/Paragraph/Paragraph.test.stories.tsx +0 -231
- package/src/components/typography/Text/Text.stories.tsx +0 -359
- package/src/components/typography/Text/Text.test.stories.tsx +0 -759
- package/src/components/utility/AnimatedIcon/AnimatedIcon.stories.tsx +0 -945
- package/src/components/utility/AnimatedIcon/AnimatedIcon.test.stories.tsx +0 -603
- package/src/components/utility/AspectRatio/AspectRatio.stories.tsx +0 -414
- package/src/components/utility/AspectRatio/AspectRatio.test.stories.tsx +0 -859
- package/src/components/utility/InfiniteScroll/InfiniteScroll.stories.tsx +0 -620
- package/src/components/utility/InfiniteScroll/InfiniteScroll.test.stories.tsx +0 -361
- package/src/components/utility/InstallPrompt/InstallPrompt.stories.tsx +0 -118
- package/src/components/utility/InstallPrompt/InstallPrompt.test.stories.tsx +0 -83
- package/src/components/utility/InstallPrompt/__tests__/InstallPrompt.ios.test.tsx +0 -65
- package/src/components/utility/InstallPrompt/__tests__/usePwaInstall.test.tsx +0 -271
- package/src/components/utility/Portal/Portal.stories.tsx +0 -340
- package/src/components/utility/Portal/Portal.test.stories.tsx +0 -2086
- package/src/components/utility/Transition/Transition.stories.tsx +0 -493
- package/src/components/utility/Transition/Transition.test.stories.tsx +0 -854
- package/src/components/utility/VirtualList/VirtualList.stories.tsx +0 -1073
- package/src/components/utility/VirtualList/VirtualList.test.stories.tsx +0 -1085
- package/src/components/utility/WorkflowStep/WorkflowStep.stories.tsx +0 -431
- package/src/components/utility/WorkflowStep/WorkflowStep.test.stories.tsx +0 -364
- /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
|
-
};
|