Skip to main content

Overview

The Modal component displays content in a layer above the main application, blocking interaction with the underlying page until dismissed.

Basic Usage

import { Modal, Button } from '@yourproject/components';
import { useState } from 'react';

function Example() {
  const [isOpen, setIsOpen] = useState(false);
  
  return (
    <>
      <Button onClick={() => setIsOpen(true)}>
        Open Modal
      </Button>
      
      <Modal 
        isOpen={isOpen} 
        onClose={() => setIsOpen(false)}
      >
        <h2>Modal Title</h2>
        <p>Modal content goes here.</p>
      </Modal>
    </>
  );
}

Sizes

Modals come in multiple sizes to accommodate different content needs:
<Modal size="sm" isOpen={isOpen} onClose={onClose}>
  Small modal for brief messages or simple forms.
</Modal>
import { Modal, ModalHeader, ModalBody, ModalFooter, Button } from '@yourproject/components';

function Example() {
  const [isOpen, setIsOpen] = useState(false);
  
  return (
    <Modal isOpen={isOpen} onClose={() => setIsOpen(false)}>
      <ModalHeader>
        Confirm Action
      </ModalHeader>
      
      <ModalBody>
        Are you sure you want to proceed? This action cannot be undone.
      </ModalBody>
      
      <ModalFooter>
        <Button variant="secondary" onClick={() => setIsOpen(false)}>
          Cancel
        </Button>
        <Button variant="primary" onClick={handleConfirm}>
          Confirm
        </Button>
      </ModalFooter>
    </Modal>
  );
}

Close Behavior

Disable Outside Click

<Modal 
  isOpen={isOpen} 
  onClose={onClose}
  closeOnOutsideClick={false}
>
  This modal won't close when clicking the backdrop.
</Modal>

Disable Escape Key

<Modal 
  isOpen={isOpen} 
  onClose={onClose}
  closeOnEscape={false}
>
  This modal won't close with the Escape key.
</Modal>

Hide Close Button

<Modal 
  isOpen={isOpen} 
  onClose={onClose}
  showCloseButton={false}
>
  This modal has no close button (must be closed programmatically).
</Modal>

Props

isOpen
boolean
required
Controls whether the modal is visible
onClose
function
required
Callback function when modal should close: () => void
size
string
default:"md"
Modal size: sm, md, lg, or full
closeOnOutsideClick
boolean
default:"true"
Whether clicking the backdrop closes the modal
closeOnEscape
boolean
default:"true"
Whether pressing Escape closes the modal
showCloseButton
boolean
default:"true"
Whether to show the X close button in the header
children
ReactNode
required
The content to display in the modal
className
string
Additional CSS class names to apply
overlayClassName
string
CSS class names for the backdrop overlay

ModalHeader Props

children
ReactNode
required
Header content (typically a title)

ModalBody Props

children
ReactNode
required
Main modal content

ModalFooter Props

children
ReactNode
required
Footer content (typically action buttons)
align
string
default:"right"
Alignment of footer content: left, center, or right

TypeScript Interfaces

interface ModalProps {
  isOpen: boolean;
  onClose: () => void;
  size?: 'sm' | 'md' | 'lg' | 'full';
  closeOnOutsideClick?: boolean;
  closeOnEscape?: boolean;
  showCloseButton?: boolean;
  children: React.ReactNode;
  className?: string;
  overlayClassName?: string;
}

interface ModalHeaderProps {
  children: React.ReactNode;
  className?: string;
}

interface ModalBodyProps {
  children: React.ReactNode;
  className?: string;
}

interface ModalFooterProps {
  children: React.ReactNode;
  align?: 'left' | 'center' | 'right';
  className?: string;
}

Advanced Examples

Confirmation Modal

import { Modal, ModalHeader, ModalBody, ModalFooter, Button } from '@yourproject/components';
import { useState } from 'react';

function DeleteConfirmation() {
  const [isOpen, setIsOpen] = useState(false);
  
  const handleDelete = async () => {
    await deleteItem();
    setIsOpen(false);
  };
  
  return (
    <>
      <Button variant="danger" onClick={() => setIsOpen(true)}>
        Delete Item
      </Button>
      
      <Modal 
        isOpen={isOpen} 
        onClose={() => setIsOpen(false)}
        size="sm"
      >
        <ModalHeader>
          Confirm Deletion
        </ModalHeader>
        
        <ModalBody>
          Are you sure you want to delete this item? This action cannot be undone.
        </ModalBody>
        
        <ModalFooter>
          <Button variant="secondary" onClick={() => setIsOpen(false)}>
            Cancel
          </Button>
          <Button variant="danger" onClick={handleDelete}>
            Delete
          </Button>
        </ModalFooter>
      </Modal>
    </>
  );
}

Form Modal

import { Modal, ModalHeader, ModalBody, ModalFooter, Input, Button } from '@yourproject/components';
import { useState } from 'react';

function CreateUserModal() {
  const [isOpen, setIsOpen] = useState(false);
  const [formData, setFormData] = useState({ name: '', email: '' });
  
  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    await createUser(formData);
    setIsOpen(false);
  };
  
  return (
    <>
      <Button onClick={() => setIsOpen(true)}>
        Create User
      </Button>
      
      <Modal isOpen={isOpen} onClose={() => setIsOpen(false)}>
        <form onSubmit={handleSubmit}>
          <ModalHeader>
            Create New User
          </ModalHeader>
          
          <ModalBody>
            <Input 
              label="Name"
              value={formData.name}
              onChange={(e) => setFormData({ ...formData, name: e.target.value })}
              required
            />
            <Input 
              label="Email"
              type="email"
              value={formData.email}
              onChange={(e) => setFormData({ ...formData, email: e.target.value })}
              required
            />
          </ModalBody>
          
          <ModalFooter>
            <Button variant="secondary" onClick={() => setIsOpen(false)}>
              Cancel
            </Button>
            <Button variant="primary" type="submit">
              Create
            </Button>
          </ModalFooter>
        </form>
      </Modal>
    </>
  );
}
Use the closeOnOutsideClick={false} prop for forms to prevent accidental data loss.
Modals automatically trap focus within them and restore focus when closed for better accessibility.

Accessibility

  • Implements proper ARIA attributes (role="dialog", aria-modal)
  • Traps focus within the modal while open
  • Restores focus to trigger element on close
  • Supports Escape key to close (configurable)
  • Prevents body scroll when modal is open
  • Screen reader compatible with proper announcements

Build docs developers (and LLMs) love