@metadiv-studio/dialog
v0.5.1
Published
A lightweight, accessible React dialog/modal component built with TypeScript and Tailwind CSS. Perfect for creating beautiful, responsive modals with minimal setup.
Readme
@metadiv-studio/dialog
A lightweight, accessible React dialog/modal component built with TypeScript and Tailwind CSS. Perfect for creating beautiful, responsive modals with minimal setup.
📦 Installation
npm i @metadiv-studio/dialog🎯 Description
The @metadiv-studio/dialog package provides a modern, accessible dialog component that:
- Accessible by default - Built with proper ARIA attributes and keyboard navigation
- Responsive design - Automatically adapts to different screen sizes
- Dark mode support - Includes built-in dark/light theme support
- Keyboard shortcuts - ESC key to close, backdrop click to dismiss
- Body scroll lock - Prevents background scrolling when dialog is open
- Customizable styling - Easy to customize with Tailwind CSS classes
- TypeScript support - Full type safety with comprehensive interfaces
🚀 Usage
Basic Dialog
import Dialog from '@metadiv-studio/dialog';
import { useState } from 'react';
function App() {
const [isOpen, setIsOpen] = useState(false);
return (
<div>
<button onClick={() => setIsOpen(true)}>
Open Dialog
</button>
<Dialog
open={isOpen}
onClose={() => setIsOpen(false)}
title="Welcome!"
>
<p>This is a simple dialog with some content.</p>
<button onClick={() => setIsOpen(false)}>
Close
</button>
</Dialog>
</div>
);
}Dialog with Custom Content
import Dialog from '@metadiv-studio/dialog';
import { useState } from 'react';
function UserProfileDialog() {
const [isOpen, setIsOpen] = useState(false);
return (
<div>
<button onClick={() => setIsOpen(true)}>
View Profile
</button>
<Dialog
open={isOpen}
onClose={() => setIsOpen(false)}
title="User Profile"
className="max-w-lg"
>
<div className="space-y-4">
<div className="flex items-center space-x-3">
<img
src="/avatar.jpg"
alt="User avatar"
className="w-16 h-16 rounded-full"
/>
<div>
<h3 className="text-lg font-semibold">John Doe</h3>
<p className="text-gray-600 dark:text-gray-400">Software Developer</p>
</div>
</div>
<div className="border-t pt-4">
<h4 className="font-medium mb-2">Contact Information</h4>
<p>Email: [email protected]</p>
<p>Phone: +1 (555) 123-4567</p>
</div>
<div className="flex space-x-2 pt-4">
<button
onClick={() => setIsOpen(false)}
className="px-4 py-2 bg-gray-200 dark:bg-gray-700 rounded-md hover:bg-gray-300 dark:hover:bg-gray-600"
>
Close
</button>
<button className="px-4 py-2 bg-blue-500 text-white rounded-md hover:bg-blue-600">
Edit Profile
</button>
</div>
</div>
</Dialog>
</div>
);
}Form Dialog
import Dialog from '@metadiv-studio/dialog';
import { useState } from 'react';
function ContactFormDialog() {
const [isOpen, setIsOpen] = useState(false);
const [formData, setFormData] = useState({ name: '', email: '', message: '' });
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
// Handle form submission
console.log('Form submitted:', formData);
setIsOpen(false);
};
return (
<div>
<button onClick={() => setIsOpen(true)}>
Contact Us
</button>
<Dialog
open={isOpen}
onClose={() => setIsOpen(false)}
title="Send us a message"
className="max-w-md"
>
<form onSubmit={handleSubmit} className="space-y-4">
<div>
<label htmlFor="name" className="block text-sm font-medium mb-1">
Name
</label>
<input
type="text"
id="name"
value={formData.name}
onChange={(e) => setFormData({ ...formData, name: e.target.value })}
className="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 dark:bg-gray-800"
required
/>
</div>
<div>
<label htmlFor="email" className="block text-sm font-medium mb-1">
Email
</label>
<input
type="email"
id="email"
value={formData.email}
onChange={(e) => setFormData({ ...formData, email: e.target.value })}
className="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 dark:bg-gray-800"
required
/>
</div>
<div>
<label htmlFor="message" className="block text-sm font-medium mb-1">
Message
</label>
<textarea
id="message"
rows={4}
value={formData.message}
onChange={(e) => setFormData({ ...formData, message: e.target.value })}
className="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 dark:bg-gray-800"
required
/>
</div>
<div className="flex space-x-2 pt-2">
<button
type="button"
onClick={() => setIsOpen(false)}
className="px-4 py-2 bg-gray-200 dark:bg-gray-700 rounded-md hover:bg-gray-300 dark:hover:bg-gray-600"
>
Cancel
</button>
<button
type="submit"
className="px-4 py-2 bg-blue-500 text-white rounded-md hover:bg-blue-600"
>
Send Message
</button>
</div>
</form>
</Dialog>
</div>
);
}🔧 Props
| Prop | Type | Required | Default | Description |
|------|------|----------|---------|-------------|
| open | boolean | ✅ | - | Controls whether the dialog is visible |
| onClose | () => void | ✅ | - | Callback function called when dialog should close |
| title | string | ✅ | - | The title displayed in the dialog header |
| children | React.ReactNode | ✅ | - | The content to display in the dialog body |
| className | string | ❌ | '' | Additional CSS classes for custom styling |
🎨 Customization
Styling with Tailwind CSS
The dialog component is built with Tailwind CSS and can be easily customized:
<Dialog
open={isOpen}
onClose={() => setIsOpen(false)}
title="Custom Styled Dialog"
className="max-w-2xl bg-gradient-to-r from-blue-50 to-indigo-50 dark:from-gray-800 dark:to-gray-900"
>
{/* Your content */}
</Dialog>Responsive Design
The dialog automatically handles responsive behavior:
- Mobile: Full width with margins (
mx-4) - Desktop: Maximum width with centered positioning
- Height: Automatically adjusts to content with
max-h-[90vh]
♿ Accessibility Features
- Keyboard navigation: ESC key closes the dialog
- Focus management: Focus is trapped within the dialog when open
- Screen reader support: Proper ARIA attributes and semantic HTML
- Backdrop click: Clicking outside the dialog closes it
- Body scroll lock: Prevents background scrolling when dialog is open
🌙 Dark Mode Support
The dialog automatically supports both light and dark themes using Tailwind CSS classes:
- Light theme: White background with gray borders
- Dark theme: Dark gray background with subtle white borders
- Automatic: Follows your app's dark mode configuration
📱 Browser Support
- Modern browsers (Chrome, Firefox, Safari, Edge)
- React 18+
- TypeScript 5+
🔗 Dependencies
- React: ^18 (peer dependency)
- React DOM: ^18 (peer dependency)
- Tailwind CSS: For styling (must be configured in your project)
📋 Tailwind CSS Configuration
To use the dialog component, ensure your tailwind.config.js includes the package path:
// tailwind.config.js
module.exports = {
content: [
// ... other content paths
"./node_modules/@metadiv-studio/**/*.{js,ts,jsx,tsx}",
],
// ... rest of config
}🤝 Contributing
This package is part of the @metadiv-studio component library. For issues, feature requests, or contributions, please refer to the main repository.
📄 License
UNLICENSED - See package.json for details.
