Modal
The Modal component is a flexible overlay dialog component that displays content in a floating window. It provides backdrop support, multiple positioning options, various sizes, and customizable styling for creating engaging user interactions.
Overview
The Modal component is designed to provide flexible dialog functionality with:
- Multiple positioning options (center, top, bottom, left, right)
- Various size configurations
- Backdrop blur effects
- Click-outside-to-close functionality
- Header, body, and footer sections
- Close button integration
- Responsive design with proper z-index management
Basic Usage
import Modal from '@/components/molecules/Modal'
import { Button } from '@/components/atoms'
import { useState } from 'react'
function MyComponent() {
const [isOpen, setIsOpen] = useState(false)
return (
<>
<Button className='btn-primary' onClick={() => setIsOpen(true)}>
Open Modal
</Button>
<Modal.Dialog open={isOpen} onClose={() => setIsOpen(false)}>
<Modal.Header closeButton onClose={() => setIsOpen(false)}>
<Modal.Title>Modal Title</Modal.Title>
</Modal.Header>
<Modal.Body>
<p>Modal content goes here.</p>
</Modal.Body>
<Modal.Footer>
<Button className='btn-primary outlined' onClick={() => setIsOpen(false)}>
Cancel
</Button>
<Button className='btn-primary'>Save</Button>
</Modal.Footer>
</Modal.Dialog>
</>
)
}
Props
Modal.Dialog Props
| Prop | Type | Default | Description |
|---|---|---|---|
open | boolean | - | Whether the modal is currently open |
onClose | function | - | Callback function when modal should close |
children | ReactNode | - | The content to display in the modal |
size | string | 'max-w-md' | CSS class for modal width |
backdrop | string | - | CSS class for backdrop styling |
position | string | 'center' | Position of modal ('center', 'top', 'bottom', 'left', 'right') |
closeOnBackdrop | boolean | false | Whether clicking backdrop closes the modal |
Modal.Header Props
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | - | The content to display in the header |
closeButton | boolean | - | Whether to show close button |
onClose | function | - | Callback for close button click |
className | string | '' | Additional CSS classes |
Modal.Title Props
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | - | The title text |
className | string | '' | Additional CSS classes |
Modal.Body Props
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | - | The content to display in the body |
className | string | '' | Additional CSS classes |
Modal.Footer Props
| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | - | The content to display in the footer |
className | string | '' | Additional CSS classes |
Basic Modal
Simple Modal
<Card>
<h4 className='mb-2'>Basic Modal</h4>
<div className='space-x-2'>
<Button className='btn-primary' onClick={() => setOpenModal({ id: 1, closeOnBackdrop: false })}>
Open Modal
</Button>
<Button className='btn-primary' onClick={() => setOpenModal({ id: 2, closeOnBackdrop: true })}>
Open close backdrop
</Button>
</div>
</Card>
Complete Modal Structure
<Modal.Dialog
open={!!openModal.id}
size={openModal.size || 'max-w-md'}
closeOnBackdrop={!!openModal.closeOnBackdrop}
backdrop={openModal.backdrop}
position={openModal.position || 'center'}
onClose={() => setOpenModal({})}>
<Modal.Header closeButton onClose={() => setOpenModal({})}>
<Modal.Title>Modal title</Modal.Title>
</Modal.Header>
<Modal.Body>
<p>Modal body text goes here.</p>
</Modal.Body>
<Modal.Footer>
<Button className='btn-primary outlined' onClick={() => setOpenModal({})}>
Close
</Button>
<Button className='btn-primary'>Save changes</Button>
</Modal.Footer>
</Modal.Dialog>
Modal Positions
Center Position (Default)
<Button className='btn-primary' onClick={() => setOpenModal({ id: 1, closeOnBackdrop: false })}>
Center
</Button>
Bottom Position
<Button className='btn-primary' onClick={() => setOpenModal({ id: 1, closeOnBackdrop: false, position: 'bottom' })}>
Bottom
</Button>
Left Position
<Button className='btn-primary' onClick={() => setOpenModal({ id: 1, closeOnBackdrop: false, position: 'left' })}>
Left
</Button>
Right Position
<Button className='btn-primary' onClick={() => setOpenModal({ id: 1, closeOnBackdrop: false, position: 'right' })}>
Right
</Button>
Position Examples
<Card>
<h4 className='mb-2'>Modal Position</h4>
<div className='space-x-2'>
<Button className='btn-primary' onClick={() => setOpenModal({ id: 1, closeOnBackdrop: false })}>
Center
</Button>
<Button className='btn-primary' onClick={() => setOpenModal({ id: 1, closeOnBackdrop: false, position: 'bottom' })}>
Bottom
</Button>
<Button className='btn-primary' onClick={() => setOpenModal({ id: 1, closeOnBackdrop: false, position: 'left' })}>
Left
</Button>
<Button className='btn-primary' onClick={() => setOpenModal({ id: 1, closeOnBackdrop: false, position: 'right' })}>
Right
</Button>
</div>
</Card>
Modal Sizes
Small Modal
<Button className='btn-primary' onClick={() => setOpenModal({ id: 1, closeOnBackdrop: false, size: 'max-w-sm' })}>
Small
</Button>
Large Modal
<Button className='btn-primary' onClick={() => setOpenModal({ id: 1, closeOnBackdrop: false, size: 'max-w-lg' })}>
Large
</Button>
Extra Large Modal
<Button className='btn-primary' onClick={() => setOpenModal({ id: 1, closeOnBackdrop: false, size: 'max-w-2xl' })}>
Extra Large
</Button>
Full Width Modal
<Button className='btn-primary' onClick={() => setOpenModal({ id: 1, closeOnBackdrop: false, size: 'max-w-5xl' })}>
Extra Large
</Button>
Size Examples
<Card>
<h4 className='mb-2'>Modal Size</h4>
<div className='space-x-2'>
<Button className='btn-primary' onClick={() => setOpenModal({ id: 1, closeOnBackdrop: false, size: 'max-w-sm' })}>
Small
</Button>
<Button className='btn-primary' onClick={() => setOpenModal({ id: 1, closeOnBackdrop: false, size: 'max-w-lg' })}>
Large
</Button>
<Button className='btn-primary' onClick={() => setOpenModal({ id: 1, closeOnBackdrop: false, size: 'max-w-2xl' })}>
Extra Large
</Button>
<Button className='btn-primary' onClick={() => setOpenModal({ id: 1, closeOnBackdrop: false, size: 'max-w-5xl' })}>
Extra Large
</Button>
</div>
</Card>
Backdrop Options
Default Backdrop
<Modal.Dialog open={isOpen} onClose={() => setIsOpen(false)}>
{/* Modal content */}
</Modal.Dialog>
Blur Backdrop Small
<Modal.Dialog
open={isOpen}
onClose={() => setIsOpen(false)}
backdrop="backdrop-blur-sm"
closeOnBackdrop={true}>
{/* Modal content */}
</Modal.Dialog>
Blur Backdrop Medium
<Modal.Dialog
open={isOpen}
onClose={() => setIsOpen(false)}
backdrop="backdrop-blur-md"
closeOnBackdrop={true}>
{/* Modal content */}
</Modal.Dialog>
Blur Backdrop Large
<Modal.Dialog
open={isOpen}
onClose={() => setIsOpen(false)}
backdrop="backdrop-blur-lg"
closeOnBackdrop={true}>
{/* Modal content */}
</Modal.Dialog>
Backdrop Examples
<Card>
<h4 className='mb-2'>Modal with Blur Backdrop</h4>
<div className='space-x-2'>
<Button className='btn-primary' onClick={() => setOpenModal({ id: 3, closeOnBackdrop: true, backdrop: 'backdrop-blur-sm' })}>
Blur Small
</Button>
<Button className='btn-primary' onClick={() => setOpenModal({ id: 4, closeOnBackdrop: true, backdrop: 'backdrop-blur-md' })}>
Blur Medium
</Button>
<Button className='btn-primary' onClick={() => setOpenModal({ id: 5, closeOnBackdrop: true, backdrop: 'backdrop-blur-lg' })}>
Blur Large
</Button>
</div>
</Card>
Modal Sections
Header with Close Button
<Modal.Header closeButton onClose={() => setIsOpen(false)}>
<Modal.Title>Modal Title</Modal.Title>
</Modal.Header>
Header without Close Button
<Modal.Header>
<Modal.Title>Modal Title</Modal.Title>
</Modal.Header>
Body Content
<Modal.Body>
<p>This is the modal body content.</p>
<p>You can include any React components here.</p>
</Modal.Body>
Footer with Actions
<Modal.Footer>
<Button className='btn-primary outlined' onClick={() => setIsOpen(false)}>
Cancel
</Button>
<Button className='btn-primary'>Save Changes</Button>
</Modal.Footer>
State Management
Using useState
import { useState } from 'react'
const ModalExample = () => {
const [openModal, setOpenModal] = useState({})
const openModalHandler = (config) => {
setOpenModal(config)
}
const closeModalHandler = () => {
setOpenModal({})
}
return (
<>
<Button className='btn-primary' onClick={() => openModalHandler({ id: 1, closeOnBackdrop: true })}>
Open Modal
</Button>
<Modal.Dialog
open={!!openModal.id}
size={openModal.size || 'max-w-md'}
closeOnBackdrop={!!openModal.closeOnBackdrop}
backdrop={openModal.backdrop}
position={openModal.position || 'center'}
onClose={closeModalHandler}>
<Modal.Header closeButton onClose={closeModalHandler}>
<Modal.Title>Modal Title</Modal.Title>
</Modal.Header>
<Modal.Body>
<p>Modal content</p>
</Modal.Body>
<Modal.Footer>
<Button className='btn-primary outlined' onClick={closeModalHandler}>
Close
</Button>
<Button className='btn-primary'>Save</Button>
</Modal.Footer>
</Modal.Dialog>
</>
)
}
Examples
Basic Modal
<Card>
<h4 className='mb-2'>Basic Modal</h4>
<div className='space-x-2'>
<Button className='btn-primary' onClick={() => setOpenModal({ id: 1, closeOnBackdrop: false })}>
Open Modal
</Button>
<Button className='btn-primary' onClick={() => setOpenModal({ id: 2, closeOnBackdrop: true })}>
Open close backdrop
</Button>
</div>
</Card>
Modal Position
<Card>
<h4 className='mb-2'>Modal Position</h4>
<div className='space-x-2'>
<Button className='btn-primary' onClick={() => setOpenModal({ id: 1, closeOnBackdrop: false })}>
Center
</Button>
<Button className='btn-primary' onClick={() => setOpenModal({ id: 1, closeOnBackdrop: false, position: 'bottom' })}>
Bottom
</Button>
<Button className='btn-primary' onClick={() => setOpenModal({ id: 1, closeOnBackdrop: false, position: 'left' })}>
Left
</Button>
<Button className='btn-primary' onClick={() => setOpenModal({ id: 1, closeOnBackdrop: false, position: 'right' })}>
Right
</Button>
</div>
</Card>
Modal Size
<Card>
<h4 className='mb-2'>Modal Size</h4>
<div className='space-x-2'>
<Button className='btn-primary' onClick={() => setOpenModal({ id: 1, closeOnBackdrop: false, size: 'max-w-sm' })}>
Small
</Button>
<Button className='btn-primary' onClick={() => setOpenModal({ id: 1, closeOnBackdrop: false, size: 'max-w-lg' })}>
Large
</Button>
<Button className='btn-primary' onClick={() => setOpenModal({ id: 1, closeOnBackdrop: false, size: 'max-w-2xl' })}>
Extra Large
</Button>
<Button className='btn-primary' onClick={() => setOpenModal({ id: 1, closeOnBackdrop: false, size: 'max-w-5xl' })}>
Extra Large
</Button>
</div>
</Card>
Modal with Blur Backdrop
<Card>
<h4 className='mb-2'>Modal with Blur Backdrop</h4>
<div className='space-x-2'>
<Button className='btn-primary' onClick={() => setOpenModal({ id: 3, closeOnBackdrop: true, backdrop: 'backdrop-blur-sm' })}>
Blur Small
</Button>
<Button className='btn-primary' onClick={() => setOpenModal({ id: 4, closeOnBackdrop: true, backdrop: 'backdrop-blur-md' })}>
Blur Medium
</Button>
<Button className='btn-primary' onClick={() => setOpenModal({ id: 5, closeOnBackdrop: true, backdrop: 'backdrop-blur-lg' })}>
Blur Large
</Button>
</div>
</Card>
CSS Classes Reference
Modal Container
.modal- Base modal wrapper.modal__wrapper- Modal positioning wrapper.modal__wrapper--center- Center positioning.modal__wrapper--top- Top positioning.modal__wrapper--bottom- Bottom positioning.modal__wrapper--left- Left positioning.modal__wrapper--right- Right positioning.modal__container- Modal content container
Modal Sections
.modal__header- Header section with border.modal__title- Title styling.modal__body- Body content area.modal__footer- Footer section with border
Size Classes
max-w-sm- Small modal (384px)max-w-md- Medium modal (448px) - Defaultmax-w-lg- Large modal (512px)max-w-2xl- Extra large modal (672px)max-w-5xl- Full width modal (1024px)
Backdrop Classes
backdrop-blur-sm- Small blur effectbackdrop-blur-md- Medium blur effectbackdrop-blur-lg- Large blur effect
Styling
The Modal component uses Tailwind CSS classes and includes:
- Fixed Positioning: Full-screen overlay positioning
- Z-Index Management: Proper layering with z-50
- Responsive Design: Works on all screen sizes
- Flexbox Layout: Flexible positioning system
- Shadow Effects: Drop shadow for depth
- Border Radius: Rounded corners for modern appearance
- Backdrop Blur: Configurable blur effects
Accessibility
The Modal component includes accessibility features:
- Focus Management: Proper focus trapping
- Keyboard Navigation: ESC key to close
- Screen Reader Support: ARIA labels and semantic structure
- Backdrop Click: Click outside to close (when enabled)
- Close Button: Accessible close button with proper labeling
Best Practices
- Always provide an onClose handler for proper cleanup
- Use appropriate sizes for different content types
- Consider mobile users with responsive positioning
- Include close functionality in footer actions
- Use backdrop blur for better visual separation
- Test keyboard navigation for accessibility compliance
Common Use Cases
- Confirmation dialogs: User confirmations and alerts
- Form modals: Data entry and editing forms
- Content previews: Image, video, or document previews
- Settings panels: Configuration and preferences
- User onboarding: Welcome and tutorial content
Related Components
Button- Used for modal triggers and actionsModalBackdrop- Backdrop overlay componentModalCloseButton- Close button componentCard- Often used as a container for modal examples