custom-headless-modal
v1.3.0
Published
Accessible, animated React modal with scoped Tailwind CSS, focus trapping, and portal rendering
Readme
Modal Component
Description
The Modal component is a fully accessible, animated modal with built-in dark mode support, focus trapping, portal rendering, and scoped Tailwind CSS that won't interfere with your app's styles.
Installation
npm install custom-headless-modal@latestFeatures
- ✅ Accessible - Focus trapping, Escape to close, ARIA attributes, screen reader support
- ✅ Animated - Smooth fade + scale enter/exit transitions
- ✅ Portal rendering - Renders to
document.body, avoids stacking context issues - ✅ Scroll lock - Prevents background scrolling while open
- ✅ Scoped Tailwind CSS - Won't override your app's styles
- ✅ Built-in dark mode support with custom theme variables
- ✅ Self-contained styling - No external CSS setup required
- ✅ Flexible customization via props
Usage
import React, { useState } from "react";
import { Modal } from "custom-headless-modal";
const App = () => {
const [isOpen, setIsOpen] = useState(false);
return (
<div>
<button onClick={() => setIsOpen(true)}>Open Modal</button>
<Modal
isOpen={isOpen}
onClose={() => setIsOpen(false)}
title="Example Modal"
size="lg"
footer={
<div>
<button onClick={() => setIsOpen(false)}>Cancel</button>
<button onClick={() => setIsOpen(false)}>Save</button>
</div>
}
>
<p>This is the modal content.</p>
</Modal>
</div>
);
};Props
Modal Props
| Prop | Type | Default | Description |
| --------------------- | ------------------------------------------ | ------------------------------------ | ------------------------------------------------------------------------ |
| isOpen | boolean | - | Controls whether the modal is visible or hidden. |
| onClose | function | - | A callback function invoked when the modal is requested to close. |
| title | string | - | Optional title displayed in the modal header. |
| children | ReactNode | - | The content of the modal body. |
| size | "sm" \| "md" \| "lg" \| "xl" \| "full" | - | Preset modal width. Alternative to widthClass. |
| widthClass | string | "lg:w-1/2" | Tailwind class for controlling modal width. Takes precedence over size.|
| colorClass | string | "dark:bg-background-dark bg-white" | Custom background color classes for the modal. Supports dark mode. |
| footer | ReactNode | - | Optional footer content displayed at the bottom of the modal. |
| closeOnOverlayClick | boolean | true | Whether clicking the backdrop closes the modal. |
Size Presets
| Size | Max Width |
| ------ | --------- |
| sm | 384px |
| md | 448px |
| lg | 512px |
| xl | 576px |
| full | 896px |
Accessibility
The Modal component is fully WCAG 2.1 AA compliant:
- Focus trap - Tab and Shift+Tab cycle through focusable elements inside the modal
- Focus management - Focus moves into the modal on open and returns to the trigger element on close
- Escape key - Pressing Escape closes the modal
- ARIA attributes -
role="dialog",aria-modal="true",aria-labelledbylinked to the title - Screen reader support - Proper semantic structure for assistive technologies
Styles
The Modal component uses scoped Tailwind CSS that won't conflict with your application's styles. All Tailwind utilities are contained within the .modal-scoped wrapper.
Built-in Theme Variables
The component includes custom theme variables for consistent styling:
background-dark- Custom dark background color (#212529)- Full Tailwind v4 utility support within the modal scope
Dark Mode Support
The component automatically adapts to dark mode when the dark class is present on a parent element:
// Enable dark mode for the entire app
<body className="dark">
<App />
</body>
// Or scope it to a specific section
<div className="dark">
<Modal ... />
</div>No Setup Required
The Modal component is completely self-contained:
- ✅ No external CSS imports needed
- ✅ Won't override your app's Tailwind setup
- ✅ Works independently of your project's CSS configuration
Customization
The modal component is highly customizable through props. You can:
- Control the modal width using
sizepresets orwidthClass - Prevent overlay click closing with
closeOnOverlayClick={false} - Add custom headers and footers
- Override the modal background with
colorClass - Use the built-in dark mode support
- Pass any React content as children or footer
