引き出しコンポーネント
ネイティブ チェックボックス トグルを使用した CSS のみの Tailwind CSS ドロワー。 JavaScript を使用しないナビゲーションまたはフィルター用のスライドイン サイド パネル。 WCAG AA にアクセス可能で、Django、HTMX、Laravel、React、およびあらゆるスタックで動作します。
Drawer components slide in from the sides of the viewport to reveal hidden navigation, filters, or additional content. Built on the native HTML dialog element with CSS animations, drawers provide a responsive way to manage layouts on mobile and desktop devices. The Frutjam drawer system supports customizable widths, smooth animations, and overlay backgrounds for professional sidebar navigation.
CSS-only, no JavaScript required. WCAG AA accessible and framework-agnostic — works with Django, HTMX, Laravel, React, and any stack.
| Class | Type | Description |
|---|---|---|
| drawer | Base | Slide-in panel built on the native dialog element |
| drawer-content | Modifier | Inner content area of the drawer |
| drawer-backdrop | Modifier | Overlay behind the drawer |
| drawer-start | Modifier | Slides in from the left |
| drawer-end | Modifier | Slides in from the right |
| drawer-top | Modifier | Slides in from the top |
| drawer-bottom | Modifier | Slides in from the bottom |
Basic Usage
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | <button type="button" class="btn btn-sm" onclick="defaultDrawer.show()">Open drawer</button> <dialog class="drawer" id="defaultDrawer"> <div class="drawer-content w-full lg:w-56 p-4"> <ul class="menu"> <li class="menu-title"><span>Dashboard</span></li> <li><a class="menu-item">Overview</a></li> <li><a class="menu-item">Analytics</a></li> <li class="menu-title mt-4"><span>Management</span></li> <li><a class="menu-item">Users</a></li> <li><a class="menu-item">Inventory</a></li> <li><a class="menu-item">Settings</a></li> </ul> </div> <button type="button" class="drawer-backdrop" onclick="defaultDrawer.close()">Close Drawer via Backdrop</button> </dialog> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | import { useDrawer } from 'frutjam/react' export default function DrawerDemo() { const drawer = useDrawer() return ( <> <button type="button" className="btn btn-sm" onClick={drawer.open}>Open drawer</button> <dialog ref={drawer.ref} className="drawer"> <div className="drawer-content w-full lg:w-56 p-4"> <ul className="menu"> <li className="menu-title"><span>Dashboard</span></li> <li><a className="menu-item">Overview</a></li> <li><a className="menu-item">Analytics</a></li> <li className="menu-title mt-4"><span>Management</span></li> <li><a className="menu-item">Users</a></li> <li><a className="menu-item">Inventory</a></li> <li><a className="menu-item">Settings</a></li> </ul> </div> <button type="button" className="drawer-backdrop" onClick={drawer.close}>Close Drawer via Backdrop</button> </dialog> </> ) } |
JS & React Helper
Use createDrawer from frutjam/js or useDrawer from frutjam/react when the trigger lives outside the drawer or you need programmatic control from anywhere in your code.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <button class="btn btn-sm" id="helper-open-btn">Open drawer</button> <dialog class="drawer" id="helper-drawer"> <div class="drawer-content w-full lg:w-56 p-4"> <p class="mb-4 text-sm opacity-70">Controlled via <code>createDrawer</code>.</p> <button class="btn btn-sm" id="helper-close-btn">Close</button> </div> <button type="button" class="drawer-backdrop" id="helper-backdrop">Close</button> </dialog> <script type="module"> import { createDrawer } from 'frutjam/js' const drawer = createDrawer(document.getElementById('helper-drawer')) document.getElementById('helper-open-btn').onclick = () => drawer.open() document.getElementById('helper-close-btn').onclick = () => drawer.close() document.getElementById('helper-backdrop').onclick = () => drawer.close() </script> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | import { useDrawer } from 'frutjam/react' export default function DrawerDemo() { const drawer = useDrawer() return ( <> <button className="btn btn-sm" onClick={drawer.open}>Open drawer</button> <dialog ref={drawer.ref} className="drawer"> <div className="drawer-content w-full lg:w-56 p-4"> <p className="mb-4 text-sm opacity-70">Controlled via useDrawer.</p> <button className="btn btn-sm" onClick={drawer.close}>Close</button> </div> <button type="button" className="drawer-backdrop" onClick={drawer.close}>Close</button> </dialog> </> ) } |
Drawer Customization
The .drawer-backdrop provides a clickable background that closes the drawer when clicked outside the drawer, by removing this element by default prevent drawer not close when click outside.
Close on Backdrop Click
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | <button type="button" class="btn btn-sm" onclick="closeDrawerOnBackdropClick.show()">Open drawer</button> <dialog class="drawer" id="closeDrawerOnBackdropClick"> <div class="drawer-content w-full lg:w-56 p-4"> <div class="flex justify-between mb-3"> <strong>Drawer</strong> <button type="button" class="btn btn-xs btn-square btn-rounded btn-ghost" onclick="closeDrawerOnBackdropClick.close()"> <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M18 6l-12 12" /><path d="M6 6l12 12" /></svg> </button> </div> <ul class="menu"> <li class="menu-title"><span>Dashboard</span></li> <li><a class="menu-item">Overview</a></li> <li><a class="menu-item">Analytics</a></li> <li class="menu-title mt-4"><span>Management</span></li> <li><a class="menu-item">Users</a></li> <li><a class="menu-item">Inventory</a></li> <li><a class="menu-item">Settings</a></li> </ul> </div> <button type="button" class="drawer-backdrop" onclick="closeDrawerOnBackdropClick.close()">Close Drawer via Backdrop</button> </dialog> |
Prevent Close on Click Outside
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | <button type="button" class="btn btn-sm" onclick="preventCloseClickOutsideDrawer.show()">Open drawer</button> <dialog class="drawer" id="preventCloseClickOutsideDrawer"> <div class="drawer-content w-full lg:w-56 p-4"> <div class="flex justify-between mb-3"> <strong>Drawer</strong> <button type="button" class="btn btn-xs btn-square btn-rounded btn-ghost" onclick="preventCloseClickOutsideDrawer.close()"> <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M18 6l-12 12" /><path d="M6 6l12 12" /></svg> </button> </div> <ul class="menu"> <li class="menu-title"><span>Dashboard</span></li> <li><a class="menu-item">Overview</a></li> <li><a class="menu-item">Analytics</a></li> <li class="menu-title mt-4"><span>Management</span></li> <li><a class="menu-item">Users</a></li> <li><a class="menu-item">Inventory</a></li> <li><a class="menu-item">Settings</a></li> </ul> </div> </dialog> |
Drawer Placements
Left Drawer (Start)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | <button type="button" class="btn btn-sm" onclick="leftDrawer.show()">Open drawer</button> <dialog class="drawer drawer-start" id="leftDrawer"> <div class="drawer-content w-full lg:w-56 p-4"> <ul class="menu"> <li> <div class="menu-title">Dashboard</div> <ul> <li><a class="menu-item">Overview</a></li> <li><a class="menu-item">Analytics</a></li> </ul> </li> <li> <div class="menu-title">Management</div> <ul> <li><a class="menu-item">Users</a></li> <li><a class="menu-item">Inventory</a></li> <li><a class="menu-item">Settings</a></li> </ul> </li> </ul> </div> <button type="button" class="drawer-backdrop" onclick="leftDrawer.close()">Close Drawer via Backdrop</button> </dialog> |
Right Drawer (End)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | <button type="button" class="btn btn-sm" onclick="rightDrawer.show()">Open drawer</button> <dialog class="drawer drawer-end" id="rightDrawer"> <div class="drawer-content w-full lg:w-56 p-4"> <ul class="menu w-full"> <li> <div class="menu-title">Dashboard</div> <ul> <li><a class="menu-item">Overview</a></li> <li><a class="menu-item">Analytics</a></li> </ul> </li> <li> <div class="menu-title">Management</div> <ul> <li><a class="menu-item">Users</a></li> <li><a class="menu-item">Inventory</a></li> <li><a class="menu-item">Settings</a></li> </ul> </li> </ul> </div> <button type="button" class="drawer-backdrop" onclick="rightDrawer.close()">Close Drawer via Backdrop</button> </dialog> |
Top Drawer
1 2 3 4 5 6 7 8 9 10 11 12 | <button type="button" class="btn btn-sm" onclick="topDrawer.show()">Open drawer</button> <dialog class="drawer drawer-top" id="topDrawer"> <div class="drawer-content p-4"> <div class="heading-3xl mb-3">Contact us</div> <form class="grid grid-cols-12 gap-3"> <input type="text" placeholder="Enter your text here" class="input col-span-5"> <input type="text" placeholder="Enter your text here" class="input col-span-5"> <button class="btn col-span-2">Submit</button> </form> </div> <button type="button" class="drawer-backdrop" onclick="topDrawer.close()">Close Drawer via Backdrop</button> </dialog> |
Bottom Drawer
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | <button type="button" class="btn btn-sm" onclick="bottomDrawer.show()">Open drawer</button> <dialog class="drawer drawer-bottom" id="bottomDrawer"> <div class="drawer-content p-4"> <ul class="menu menu-md w-full"> <li> <div class="accordion accordion-flush"> <details name="nav" open> <summary><span class="heading-md">Dashboard</span></summary> <div class="accordion-content"> <ul> <li class="menu-item"><span>Overview</span></li> <li class="menu-item"> <span>Analytics</span> <div class="badge badge-xs badge-accent ml-1 uppercase">Live</div> </li> </ul> </div> </details> <details name="nav"> <summary><span class="heading-md">Settings</span></summary> <div class="accordion-content"> <ul> <li class="menu-item"><span>Profile</span></li> <li class="menu-item"><span>Security</span></li> </ul> </div> </details> </div> </li> </ul> </div> <button type="button" class="drawer-backdrop" onclick="bottomDrawer.close()">Close Drawer viaBackdrop</button> </dialog> |