The Drawer component provides a slide-out panel interface for displaying content, navigation, and interactive elements. It's commonly used for sidebars, navigation menus, and any content that needs to be displayed in a slide-out panel.
import { Drawer } from '@dashflowx/core'export default function DrawerExample() {return (<Drawerheader={<div>Drawer Header</div>}contentElement={<div>Drawer content goes here.</div>}footer={<div>Drawer Footer</div>}anchorOrigin={{ horizontal: 'right', vertical: 'top' }}key="drawer-1"className="w-80"/>)}
Preview:
| Prop | Type | Default | Description |
|---|---|---|---|
header | JSX.Element | - | The header content of the drawer |
contentElement | JSX.Element | - | The main content of the drawer |
footer | JSX.Element | - | The footer content of the drawer |
anchorOrigin | Object | { horizontal: 'right', vertical: 'top' } | The position of the drawer |
key | string | - | Unique key for the drawer |
className | string | - | Additional CSS classes for the drawer |
containerClassName | string | - | Additional CSS classes for the container |
headerClassName | string | - | Additional CSS classes for the header |
footerClassName | string | - | Additional CSS classes for the footer |
interface AnchorOrigin {horizontal: 'left' | 'right';vertical: 'top' | 'bottom';}
<Drawerheader={<div className="text-lg font-semibold">Settings</div>}contentElement={<div className="space-y-4"><p>Drawer content goes here.</p></div>}footer={<div className="text-sm text-gray-500">Footer content</div>}anchorOrigin={{ horizontal: 'right', vertical: 'top' }}key="settings-drawer"className="w-80"/>
Preview:
<Drawerheader={<div className="text-lg font-semibold">Navigation</div>}contentElement={<div className="space-y-2"><div className="p-2 hover:bg-gray-100 rounded">Home</div><div className="p-2 hover:bg-gray-100 rounded">About</div><div className="p-2 hover:bg-gray-100 rounded">Contact</div></div>}footer={<div className="text-sm text-gray-500">Navigation Footer</div>}anchorOrigin={{ horizontal: 'left', vertical: 'top' }}key="nav-drawer"className="w-64"/>
Preview:
<Drawerheader={<div className="text-lg font-semibold">Cart</div>}contentElement={<div className="space-y-4"><div className="border-b pb-4"><h3 className="font-medium">Cart Items</h3><p className="text-sm text-gray-500">3 items in cart</p></div><div className="space-y-2"><div className="flex justify-between"><span>Item 1</span><span>$10.00</span></div><div className="flex justify-between"><span>Item 2</span><span>$15.00</span></div></div></div>}footer={<div className="space-y-2"><div className="flex justify-between font-semibold"><span>Total</span><span>$25.00</span></div><button className="w-full bg-blue-600 text-white py-2 rounded">Checkout</button></div>}anchorOrigin={{ horizontal: 'right', vertical: 'top' }}key="cart-drawer"className="w-96"/>
Preview:
<Drawerheader={<div className="text-lg font-semibold text-blue-600">Custom Styled</div>}contentElement={<div className="space-y-4"><p>This drawer has custom styling.</p></div>}footer={<div className="text-sm text-blue-500">Custom Footer</div>}anchorOrigin={{ horizontal: 'right', vertical: 'top' }}key="custom-drawer"className="w-80 border-2 border-blue-500 rounded-l-xl"/>
Preview:
<Drawerheader={<div className="text-xl font-bold">Large Drawer</div>}contentElement={<div className="space-y-6"><div><h3 className="text-lg font-semibold mb-2">Section 1</h3><p>This is a larger drawer with more content space.</p></div><div><h3 className="text-lg font-semibold mb-2">Section 2</h3><p>It can contain multiple sections and form elements.</p></div><div><h3 className="text-lg font-semibold mb-2">Section 3</h3><p>Perfect for complex forms and detailed content.</p></div></div>}footer={<div className="flex space-x-2"><button className="flex-1 bg-gray-200 text-gray-800 py-2 rounded">Cancel</button><button className="flex-1 bg-blue-600 text-white py-2 rounded">Save</button></div>}anchorOrigin={{ horizontal: 'right', vertical: 'top' }}key="large-drawer"className="w-96"/>
Preview:
<Drawerheader={<div className="flex items-center space-x-2"><span className="text-lg font-semibold">Menu</span></div>}contentElement={<div className="space-y-1"><div className="p-3 hover:bg-gray-100 rounded cursor-pointer"><div className="flex items-center space-x-3"><span>🏠</span><span>Dashboard</span></div></div><div className="p-3 hover:bg-gray-100 rounded cursor-pointer"><div className="flex items-center space-x-3"><span>📊</span><span>Analytics</span></div></div><div className="p-3 hover:bg-gray-100 rounded cursor-pointer"><div className="flex items-center space-x-3"><span>👥</span><span>Users</span></div></div><div className="p-3 hover:bg-gray-100 rounded cursor-pointer"><div className="flex items-center space-x-3"><span>⚙️</span><span>Settings</span></div></div></div>}footer={<div className="text-sm text-gray-500">Version 1.0.0</div>}anchorOrigin={{ horizontal: 'left', vertical: 'top' }}key="nav-sidebar"className="w-64"/>
<Drawerheader={<div className="flex items-center justify-between"><span className="text-lg font-semibold">Shopping Cart</span><span className="text-sm text-gray-500">3 items</span></div>}contentElement={<div className="space-y-4"><div className="border-b pb-4"><div className="flex items-center space-x-3"><div className="w-16 h-16 bg-gray-200 rounded"></div><div className="flex-1"><h3 className="font-medium">Product Name</h3><p className="text-sm text-gray-500">Size: M, Color: Blue</p><p className="text-sm font-semibold">$29.99</p></div><div className="flex items-center space-x-2"><button className="w-6 h-6 bg-gray-200 rounded">-</button><span>1</span><button className="w-6 h-6 bg-gray-200 rounded">+</button></div></div></div><div className="border-b pb-4"><div className="flex items-center space-x-3"><div className="w-16 h-16 bg-gray-200 rounded"></div><div className="flex-1"><h3 className="font-medium">Another Product</h3><p className="text-sm text-gray-500">Size: L, Color: Red</p><p className="text-sm font-semibold">$39.99</p></div><div className="flex items-center space-x-2"><button className="w-6 h-6 bg-gray-200 rounded">-</button><span>2</span><button className="w-6 h-6 bg-gray-200 rounded">+</button></div></div></div></div>}footer={<div className="space-y-3"><div className="flex justify-between text-lg font-semibold"><span>Total</span><span>$109.97</span></div><button className="w-full bg-blue-600 text-white py-3 rounded font-medium">Proceed to Checkout</button></div>}anchorOrigin={{ horizontal: 'right', vertical: 'top' }}key="shopping-cart"className="w-96"/>
<Drawerheader={<div className="flex items-center space-x-2"><span className="text-lg font-semibold">Settings</span></div>}contentElement={<div className="space-y-6"><div><h3 className="text-sm font-semibold text-gray-500 uppercase tracking-wide mb-3">Account</h3><div className="space-y-3"><div className="flex items-center justify-between"><span className="text-sm">Email Notifications</span><input type="checkbox" className="rounded" defaultChecked /></div><div className="flex items-center justify-between"><span className="text-sm">SMS Notifications</span><input type="checkbox" className="rounded" /></div></div></div><div><h3 className="text-sm font-semibold text-gray-500 uppercase tracking-wide mb-3">Privacy</h3><div className="space-y-3"><div className="flex items-center justify-between"><span className="text-sm">Profile Visibility</span><select className="text-sm border rounded px-2 py-1"><option>Public</option><option>Private</option></select></div><div className="flex items-center justify-between"><span className="text-sm">Data Sharing</span><input type="checkbox" className="rounded" /></div></div></div></div>}footer={<div className="flex space-x-2"><button className="flex-1 bg-gray-200 text-gray-800 py-2 rounded text-sm">Reset</button><button className="flex-1 bg-blue-600 text-white py-2 rounded text-sm">Save Changes</button></div>}anchorOrigin={{ horizontal: 'right', vertical: 'top' }}key="settings-panel"className="w-80"/>
<Drawerheader={<div className="flex items-center justify-between"><span className="text-lg font-semibold">Filters</span><button className="text-sm text-blue-600">Clear All</button></div>}contentElement={<div className="space-y-6"><div><h3 className="text-sm font-semibold mb-3">Price Range</h3><div className="space-y-2"><inputtype="range"min="0"max="1000"className="w-full"/><div className="flex justify-between text-sm text-gray-500"><span>$0</span><span>$1000</span></div></div></div><div><h3 className="text-sm font-semibold mb-3">Category</h3><div className="space-y-2"><label className="flex items-center"><input type="checkbox" className="rounded mr-2" /><span className="text-sm">Electronics</span></label><label className="flex items-center"><input type="checkbox" className="rounded mr-2" /><span className="text-sm">Clothing</span></label><label className="flex items-center"><input type="checkbox" className="rounded mr-2" /><span className="text-sm">Books</span></label></div></div><div><h3 className="text-sm font-semibold mb-3">Brand</h3><div className="space-y-2"><label className="flex items-center"><input type="checkbox" className="rounded mr-2" /><span className="text-sm">Brand A</span></label><label className="flex items-center"><input type="checkbox" className="rounded mr-2" /><span className="text-sm">Brand B</span></label></div></div></div>}footer={<div className="flex space-x-2"><button className="flex-1 bg-gray-200 text-gray-800 py-2 rounded text-sm">Reset</button><button className="flex-1 bg-blue-600 text-white py-2 rounded text-sm">Apply Filters</button></div>}anchorOrigin={{ horizontal: 'left', vertical: 'top' }}key="filter-panel"className="w-80"/>
Use clear and descriptive header content.
// ✅ Good - Clear header<Drawerheader={<div className="text-lg font-semibold">User Settings</div>}contentElement={<div>Settings content</div>}footer={<div>Footer</div>}anchorOrigin={{ horizontal: 'right', vertical: 'top' }}key="settings"className="w-80"/>// ❌ Avoid - Unclear header<Drawerheader={<div>Settings</div>}contentElement={<div>Content</div>}footer={<div>Footer</div>}anchorOrigin={{ horizontal: 'right', vertical: 'top' }}key="settings"className="w-80"/>
Use appropriate drawer sizes for different content types.
// ✅ Good - Appropriate sizing<Drawerheader={<div>Navigation</div>}contentElement={<div>Navigation content</div>}footer={<div>Footer</div>}anchorOrigin={{ horizontal: 'left', vertical: 'top' }}key="nav"className="w-64" // Narrow for navigation/><Drawerheader={<div>Settings</div>}contentElement={<div>Settings content</div>}footer={<div>Footer</div>}anchorOrigin={{ horizontal: 'right', vertical: 'top' }}key="settings"className="w-96" // Wider for forms/>
Use consistent positioning for similar drawer types.
// ✅ Good - Consistent positioningconst navigationDrawer = (<DraweranchorOrigin={{ horizontal: 'left', vertical: 'top' }}// ... other props/>);const settingsDrawer = (<DraweranchorOrigin={{ horizontal: 'right', vertical: 'top' }}// ... other props/>);
Ensure drawers are accessible to all users.
// ✅ Good - Accessible<Drawerheader={<div role="heading" aria-level="2">Settings</div>}contentElement={<div role="main">Settings content</div>}footer={<div role="contentinfo">Footer</div>}anchorOrigin={{ horizontal: 'right', vertical: 'top' }}key="settings"className="w-80"/>
Structure drawer content logically.
// ✅ Good - Proper structure<Drawerheader={<div>User Profile</div>}contentElement={<div className="space-y-4"><div><label className="block text-sm font-medium mb-2">Name</label><input type="text" className="w-full border rounded px-3 py-2" /></div><div><label className="block text-sm font-medium mb-2">Email</label><input type="email" className="w-full border rounded px-3 py-2" /></div></div>}footer={<div className="flex space-x-2"><button>Cancel</button><button>Save</button></div>}anchorOrigin={{ horizontal: 'right', vertical: 'top' }}key="profile"className="w-80"/>
You can customize the drawer appearance using CSS classes:
<Drawerheader={<div>Custom Styled</div>}contentElement={<div>Custom content</div>}footer={<div>Custom footer</div>}anchorOrigin={{ horizontal: 'right', vertical: 'top' }}key="custom"className="w-80 border-2 border-purple-500 rounded-l-xl"/>
Use different themes for different contexts:
// Light theme<Drawerheader={<div>Light Theme</div>}contentElement={<div>Content</div>}footer={<div>Footer</div>}anchorOrigin={{ horizontal: 'right', vertical: 'top' }}key="light"className="w-80 bg-white border-gray-200"/>// Dark theme<Drawerheader={<div>Dark Theme</div>}contentElement={<div>Content</div>}footer={<div>Footer</div>}anchorOrigin={{ horizontal: 'right', vertical: 'top' }}key="dark"className="w-80 bg-gray-900 border-gray-700 text-white"/>
Use different sizes for different content types:
// Small drawer<Drawerheader={<div>Small</div>}contentElement={<div>Simple content</div>}footer={<div>Footer</div>}anchorOrigin={{ horizontal: 'right', vertical: 'top' }}key="small"className="w-64"/>// Large drawer<Drawerheader={<div>Large</div>}contentElement={<div>Complex content</div>}footer={<div>Footer</div>}anchorOrigin={{ horizontal: 'right', vertical: 'top' }}key="large"className="w-96"/>
Load drawer content dynamically:
const [drawerContent, setDrawerContent] = useState(null);const openDrawer = (type: string) => {switch (type) {case 'settings':setDrawerContent(settingsContent);break;case 'profile':setDrawerContent(profileContent);break;default:setDrawerContent(defaultContent);}};
Manage drawer state effectively:
const [isOpen, setIsOpen] = useState(false);const [drawerType, setDrawerType] = useState('');const openDrawer = (type: string) => {setDrawerType(type);setIsOpen(true);};const closeDrawer = () => {setIsOpen(false);setDrawerType('');};
Handle multiple drawers in the same application:
const [activeDrawer, setActiveDrawer] = useState(null);const openDrawer = (drawerId: string) => {setActiveDrawer(drawerId);};const closeDrawer = () => {setActiveDrawer(null);};
- Modal: For modal overlays
- Popover: For popup content
- Sheet: For slide-out content
- Sidebar: For navigation sidebars
- Panel: For content panels
For the complete API reference and advanced usage patterns, see the Drawer API documentation.
