diff --git a/apps/site/src/demos/ModalV2Demo.tsx b/apps/site/src/demos/ModalV2Demo.tsx new file mode 100644 index 000000000..984234b5d --- /dev/null +++ b/apps/site/src/demos/ModalV2Demo.tsx @@ -0,0 +1,1058 @@ +import { ModalV2 } from '../../../../packages/blend/lib/components/ModalV2' +import { ButtonV2 } from '../../../../packages/blend/lib/components/ButtonV2' +import { + ButtonV2Type, + ButtonV2Size, +} from '../../../../packages/blend/lib/components/ButtonV2' +import { useState } from 'react' +import { + Menu, + MultiSelect, + Popover, + SingleSelect, +} from '../../../../packages/blend/lib/main' +import { LogOut, Settings, User } from 'lucide-react' +import Text from '../../../../packages/blend/lib/components/Text/Text' +import TagV2 from '../../../../packages/blend/lib/components/TagV2/TagV2' +import { TagV2Color } from '../../../../packages/blend/lib/components/TagV2/TagV2.types' + +const ModalV2Demo = () => { + const [isModalOpen, setIsModalOpen] = useState(false) + const [showSkeleton, setShowSkeleton] = useState(false) + // Configuration state + const [config, setConfig] = useState({ + title: 'Modal Heading', + subtitle: 'One line description of the modal', + primaryButtonText: 'Confirm', + secondaryButtonText: 'Cancel', + primaryButtonType: ButtonV2Type.PRIMARY, + secondaryButtonType: ButtonV2Type.SECONDARY, + showCloseButton: true, + showDivider: true, + closeOnBackdropClick: true, + primaryButtonDisabled: false, + secondaryButtonDisabled: false, + showPrimaryButton: true, + showSecondaryButton: true, + contentType: 'basic', + }) + + const handleCheckboxChange = + (field: string) => (e: React.ChangeEvent) => { + setConfig({ + ...config, + [field]: e.target.checked, + }) + } + + const handleInputChange = + (field: string) => (e: React.ChangeEvent) => { + setConfig({ + ...config, + [field]: e.target.value, + }) + } + + const handleSelectChange = + (field: string) => (e: React.ChangeEvent) => { + setConfig({ + ...config, + [field]: e.target.value, + }) + } + + const renderModalContent = () => { + switch (config.contentType) { + case 'basic': + return ( +
+

+ This is a configurable modal for demonstration + purposes. You can adjust various settings using the + controls. +

+
+ ) + case 'form': + return ( +
+
+ + +
+ +
+ + +
+ +
+ + +
+
+ ) + case 'long': + return ( +
+ {Array.from({ length: 10 }).map((_, index) => ( +
+

+ Section {index + 1}: Lorem ipsum dolor sit + amet, consectetur adipiscing elit. Nullam + auctor, nisl eget ultricies tincidunt, nisl + nisl aliquam nisl, eget ultricies nisl nisl + eget nisl. Nullam auctor, nisl eget + ultricies tincidunt, nisl nisl aliquam nisl, + eget ultricies nisl nisl eget nisl. +

+
+ ))} +
+ ) + default: + return

Simple modal content

+ } + } + + return ( +
+
+

+ Modal Configuration Playground +

+

+ Customize the modal to see different configurations in + action +

+
+ +
+
+ {/* Left Column */} +
+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+
+ + {/* Right Column */} +
+
+ + +
+ +
+ + +
+ +
+
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+
+
+
+ +
+ setIsModalOpen(true)} + size={ButtonV2Size.MEDIUM} + /> +
+
+ + {/* Example Modals Section */} +
+
+

+ Modal Examples +

+

+ Pre-configured modal examples for common use cases +

+
+ +
+ {/* Confirmation Modal */} +
+

+ Confirmation Modal +

+

+ Standard confirmation dialog with primary and + secondary actions +

+ +
+ + {/* Form Modal */} +
+

+ Form Modal +

+

+ Modal containing form elements for data input +

+ +
+ + {/* Info Modal */} +
+

+ Info Modal +

+

+ Simple informational modal with single action +

+ +
+ + {/* Warning Modal */} +
+

+ Warning Modal +

+

+ Warning modal with danger action styling +

+ +
+ + {/* Long Content Modal */} +
+

+ Scrollable Content +

+

+ Modal with long content that requires scrolling +

+ +
+ + {/* No Actions Modal */} +
+

+ No Actions Modal +

+

+ Modal without action buttons, close button only +

+ +
+ + {/* Nested Modal */} +
+

+ Nested Modal +

+

+ Modal that opens another modal from primary button +

+ +
+
+
+ + {/* Modal with current configuration */} + } + skeleton={{ + show: showSkeleton, + bodySkeletonProps: { + show: true, + width: '900px', + // height: '100%', + }, + variant: 'pulse', + }} + data-component="popUpConfirm Some PopUp6" + isOpen={isModalOpen} + onClose={() => setIsModalOpen(false)} + title={config.title} + subtitle={config.subtitle} + primaryAction={ + config.showPrimaryButton + ? { + text: config.primaryButtonText, + onClick: () => alert('Primary action clicked!'), + disabled: config.primaryButtonDisabled, + buttonType: config.primaryButtonType, + } + : undefined + } + secondaryAction={ + config.showSecondaryButton + ? { + text: config.secondaryButtonText, + onClick: () => alert('Secondary action clicked!'), + disabled: config.secondaryButtonDisabled, + buttonType: config.secondaryButtonType, + } + : undefined + } + showCloseButton={config.showCloseButton} + closeOnBackdropClick={config.closeOnBackdropClick} + showDivider={config.showDivider} + > + {renderModalContent()} + +
+ ) +} + +// Example Modal Components +const ConfirmationModalExample = () => { + const [isOpen, setIsOpen] = useState(false) + + return ( + <> + setIsOpen(true)} + /> + setIsOpen(false)} + title="Delete Item" + subtitle="Are you sure you want to delete this item? This action cannot be undone." + primaryAction={{ + text: 'Delete', + onClick: () => { + alert('Item deleted!') + setIsOpen(false) + }, + buttonType: ButtonV2Type.DANGER, + }} + secondaryAction={{ + text: 'Cancel', + onClick: () => setIsOpen(false), + buttonType: ButtonV2Type.SECONDARY, + }} + > +

+ This will permanently remove the item from your account. All + associated data will be lost. +

+
+ + ) +} + +const FormModalExample = () => { + const [isOpen, setIsOpen] = useState(false) + + return ( + <> + setIsOpen(true)} + /> + setIsOpen(false)} + title="Create New Project" + subtitle="Fill in the details to create a new project" + primaryAction={{ + text: 'Create Project', + onClick: () => { + alert('Project created!') + setIsOpen(false) + }, + buttonType: ButtonV2Type.PRIMARY, + }} + secondaryAction={{ + text: 'Cancel', + onClick: () => setIsOpen(false), + buttonType: ButtonV2Type.SECONDARY, + }} + > +
{ + e.stopPropagation() + console.log('submitted') + }} + className="space-y-4 h-30 overflow-y-auto position-relative z-0 w-[500px]" + > + + } + > +
+ console.log(value)} + placeholder="Select category" + maxMenuHeight={100} + /> + console.log(value)} + placeholder="Select category" + maxMenuHeight={100} + /> + + } + items={[ + { + items: [ + { + label: 'Profile', + slot1: , + onClick: () => + console.log( + 'Profile clicked' + ), + }, + { + label: 'Settings', + slot1: , + slot2: ( + + ⌘, + + ), + onClick: () => + console.log( + 'Settings clicked' + ), + }, + { + label: 'Sign Out', + slot1: , + onClick: () => + console.log( + 'Sign out clicked' + ), + }, + ], + }, + ]} + /> +
+
+ +
+ +