# DaisyUI Drawer Pattern - Standard Implementation

This document describes the standard DaisyUI drawer pattern for implementing responsive sidebars. It covers mobile overlay drawers, desktop persistent sidebars, and their combination.

## Core Concept

DaisyUI's drawer component uses a **checkbox-based toggle mechanism** combined with CSS to create accessible, responsive sidebars without custom JavaScript.

### Key Components

1. **`drawer`** - Container element
2. **`drawer-toggle`** - Hidden checkbox that controls open/close state
3. **`drawer-content`** - Main content area
4. **`drawer-side`** - Sidebar content (menu, navigation)
5. **`drawer-overlay`** - Optional overlay for mobile (closes drawer on click)

## HTML Structure

```html
<div class="drawer">
  <!-- Hidden checkbox controls the drawer state -->
  <input id="my-drawer" type="checkbox" class="drawer-toggle" />
  
  <!-- Main content area -->
  <div class="drawer-content">
    <!-- Page content goes here -->
    <label for="my-drawer" class="btn btn-primary">Open drawer</label>
  </div>
  
  <!-- Sidebar content -->
  <div class="drawer-side">
    <label for="my-drawer" aria-label="close sidebar" class="drawer-overlay"></label>
    <ul class="menu p-4 w-80 min-h-full bg-base-200 text-base-content">
      <!-- Sidebar content goes here -->
      <li><a>Sidebar Item 1</a></li>
      <li><a>Sidebar Item 2</a></li>
    </ul>
  </div>
</div>
```

## How drawer-toggle Works

### Mechanism

The `drawer-toggle` is a **hidden checkbox** that serves as the state controller:

```html
<input id="my-drawer" type="checkbox" class="drawer-toggle" />
```

### Toggle Behavior

1. **Label Connection**: Any `<label for="my-drawer">` element can toggle the drawer
2. **Checkbox State**: 
   - `checked` → drawer is open
   - `unchecked` → drawer is closed
3. **CSS Targeting**: DaisyUI uses CSS sibling selectors to show/hide the drawer based on checkbox state
4. **Accessibility**: Native checkbox provides keyboard accessibility (Space/Enter to toggle)

### Toggle Examples

```html
<!-- Button to open drawer -->
<label for="my-drawer" class="btn btn-primary drawer-button">
  Open Menu
</label>

<!-- Close button inside drawer -->
<label for="my-drawer" class="btn btn-sm btn-circle btn-ghost absolute right-2 top-2">✕</label>

<!-- Overlay to close (click outside) -->
<label for="my-drawer" aria-label="close sidebar" class="drawer-overlay"></label>
```

## Mobile Drawer (Overlay)

### Characteristics

- Drawer slides in from the side (usually left)
- Overlays the main content
- Dark overlay (drawer-overlay) behind drawer
- Clicking overlay closes the drawer
- Typically used on mobile/tablet screens

### Implementation

```html
<div class="drawer">
  <input id="mobile-drawer" type="checkbox" class="drawer-toggle" />
  
  <div class="drawer-content">
    <!-- Toggle button in header -->
    <div class="navbar bg-base-100">
      <div class="flex-none">
        <label for="mobile-drawer" class="btn btn-square btn-ghost">
          <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" class="inline-block w-5 h-5 stroke-current">
            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16"></path>
          </svg>
        </label>
      </div>
      <div class="flex-1">
        <a class="btn btn-ghost text-xl">My App</a>
      </div>
    </div>
    
    <!-- Main content -->
    <div class="p-4">
      <h1>Main Content</h1>
    </div>
  </div>
  
  <div class="drawer-side">
    <!-- Overlay - clicking it closes the drawer -->
    <label for="mobile-drawer" aria-label="close sidebar" class="drawer-overlay"></label>
    
    <!-- Sidebar menu -->
    <ul class="menu p-4 w-80 min-h-full bg-base-200">
      <li><a>Home</a></li>
      <li><a>About</a></li>
      <li><a>Contact</a></li>
    </ul>
  </div>
</div>
```

### Styling Notes

- **Width**: Default `w-80` (320px), adjust with Tailwind width utilities
- **Background**: Use DaisyUI color classes like `bg-base-200`
- **Height**: Always use `min-h-full` to ensure full height
- **Padding**: Add `p-4` or similar for inner spacing

## Desktop Sidebar (Persistent)

### Characteristics

- Always visible (no overlay)
- Does not overlay main content
- Main content adjusts to sidebar width
- No toggle button needed
- Used on desktop screens

### Implementation with drawer-open

```html
<div class="drawer lg:drawer-open">
  <input id="desktop-drawer" type="checkbox" class="drawer-toggle" />
  
  <div class="drawer-content">
    <!-- Main content -->
    <div class="p-4">
      <h1>Main Content</h1>
      <p>The sidebar is always visible on desktop (lg and above)</p>
    </div>
  </div>
  
  <div class="drawer-side">
    <!-- No overlay needed for persistent sidebar -->
    <label for="desktop-drawer" aria-label="close sidebar" class="drawer-overlay"></label>
    
    <!-- Sidebar menu -->
    <ul class="menu p-4 w-80 min-h-full bg-base-200">
      <li><a>Dashboard</a></li>
      <li><a>Settings</a></li>
      <li><a>Profile</a></li>
    </ul>
  </div>
</div>
```

### How drawer-open Works

The `drawer-open` class forces the drawer to be **permanently open**:

```html
<div class="drawer drawer-open">
```

- Drawer is always visible
- Cannot be toggled closed
- `drawer-toggle` checkbox is ignored
- `drawer-overlay` is not shown
- Main content automatically shifts to accommodate sidebar width

### Responsive Usage

Use Tailwind breakpoint modifiers for responsive behavior:

```html
<!-- Open on large screens and above -->
<div class="drawer lg:drawer-open">

<!-- Open on medium screens and above -->
<div class="drawer md:drawer-open">

<!-- Open on extra-large screens and above -->
<div class="drawer xl:drawer-open">
```

## Combined Mobile + Desktop Pattern (Recommended)

This is the **most common pattern** for responsive applications: mobile overlay + desktop persistent.

### Complete Implementation

```html
<div class="drawer lg:drawer-open">
  <!-- Checkbox for mobile toggle -->
  <input id="app-drawer" type="checkbox" class="drawer-toggle" />
  
  <div class="drawer-content flex flex-col">
    <!-- Navbar with mobile menu button -->
    <div class="navbar bg-base-100 lg:hidden">
      <div class="flex-none">
        <label for="app-drawer" class="btn btn-square btn-ghost">
          <!-- Hamburger icon -->
          <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" class="inline-block w-5 h-5 stroke-current">
            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16"></path>
          </svg>
        </label>
      </div>
      <div class="flex-1">
        <a class="btn btn-ghost text-xl">My App</a>
      </div>
    </div>
    
    <!-- Main content -->
    <div class="flex-1 p-6">
      <h1 class="text-3xl font-bold mb-4">Welcome</h1>
      <p>This is the main content area.</p>
      <p>On mobile (< lg): sidebar is hidden, hamburger menu visible</p>
      <p>On desktop (≥ lg): sidebar is persistent, hamburger menu hidden</p>
    </div>
  </div>
  
  <div class="drawer-side">
    <!-- Overlay only shows on mobile -->
    <label for="app-drawer" aria-label="close sidebar" class="drawer-overlay"></label>
    
    <!-- Sidebar navigation -->
    <aside class="bg-base-200 w-80 min-h-full">
      <!-- Logo/Header area -->
      <div class="p-4 font-bold text-xl border-b border-base-300">
        My App Logo
      </div>
      
      <!-- Navigation menu -->
      <ul class="menu p-4">
        <li><a>
          <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6" />
          </svg>
          Dashboard
        </a></li>
        <li><a>
          <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
          </svg>
          Documents
        </a></li>
        <li><a>
          <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z" />
            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
          </svg>
          Settings
        </a></li>
      </ul>
    </aside>
  </div>
</div>
```

### Behavior Breakdown

#### On Mobile (< 1024px / < lg)
1. Sidebar is hidden by default
2. Hamburger button visible in navbar
3. Clicking hamburger opens sidebar as overlay
4. Clicking overlay or close button closes sidebar
5. Sidebar slides in from left with animation

#### On Desktop (≥ 1024px / ≥ lg)
1. `lg:drawer-open` keeps sidebar permanently visible
2. Hamburger button hidden via `lg:hidden`
3. Sidebar takes up fixed width (320px)
4. Main content area adjusts automatically
5. No overlay, no toggle needed

## Tailwind Breakpoints Reference

```css
/* Default (mobile-first) */
/* < 640px */

sm: /* ≥ 640px */
md: /* ≥ 768px */
lg: /* ≥ 1024px */ ← Common desktop breakpoint
xl: /* ≥ 1280px */
2xl: /* ≥ 1536px */
```

## Key Classes Summary

| Class | Purpose |
|-------|---------|
| `drawer` | Main container |
| `drawer-toggle` | Hidden checkbox for state control |
| `drawer-content` | Main content area |
| `drawer-side` | Sidebar container |
| `drawer-overlay` | Clickable overlay (closes drawer) |
| `drawer-open` | Forces drawer to stay open |
| `drawer-end` | Positions drawer on the right side |
| `lg:drawer-open` | Opens drawer on large screens only |

## Positioning Variants

### Left Side Drawer (Default)

```html
<div class="drawer">
  <!-- Drawer appears on the left -->
</div>
```

### Right Side Drawer

```html
<div class="drawer drawer-end">
  <!-- Drawer appears on the right -->
</div>
```

## Best Practices

### 1. Accessibility
- Always include `aria-label` on overlay: `<label for="drawer" aria-label="close sidebar" class="drawer-overlay"></label>`
- Use semantic HTML (`<nav>`, `<aside>`)
- Ensure keyboard navigation works (native checkbox provides this)

### 2. Responsive Design
- Use `lg:drawer-open` for desktop persistence
- Hide mobile toggle button on desktop: `lg:hidden`
- Adjust sidebar width for mobile if needed: `w-64 md:w-80`

### 3. Performance
- DaisyUI drawer is pure CSS (no JavaScript needed)
- Animations are handled by CSS transitions
- No performance overhead

### 4. Styling
- Use DaisyUI theme colors: `bg-base-200`, `text-base-content`
- Maintain consistent spacing: `p-4`, `gap-2`
- Use DaisyUI menu component for navigation: `<ul class="menu">`

### 5. Content Structure
```html
<div class="drawer-content flex flex-col">
  <!-- Navbar (if needed) -->
  <div class="navbar">...</div>
  
  <!-- Main content with flex-1 to fill space -->
  <div class="flex-1 p-6">
    <!-- Your content -->
  </div>
  
  <!-- Footer (if needed) -->
  <footer>...</footer>
</div>
```

## Common Patterns

### Pattern 1: Drawer with Close Button

```html
<div class="drawer-side">
  <label for="drawer" class="drawer-overlay"></label>
  <aside class="bg-base-200 w-80 min-h-full relative">
    <!-- Close button (mobile only) -->
    <label for="drawer" class="btn btn-sm btn-circle btn-ghost absolute right-2 top-2 lg:hidden">✕</label>
    
    <!-- Sidebar content -->
    <ul class="menu p-4 pt-12">
      <li><a>Item 1</a></li>
    </ul>
  </aside>
</div>
```

### Pattern 2: Drawer with User Profile

```html
<aside class="bg-base-200 w-80 min-h-full flex flex-col">
  <!-- Logo -->
  <div class="p-4 font-bold text-xl">My App</div>
  
  <!-- Navigation (flex-1 to push footer down) -->
  <ul class="menu flex-1 p-4">
    <li><a>Dashboard</a></li>
    <li><a>Settings</a></li>
  </ul>
  
  <!-- User profile footer -->
  <div class="p-4 border-t border-base-300">
    <div class="flex items-center gap-2">
      <div class="avatar">
        <div class="w-10 rounded-full">
          <img src="/avatar.jpg" alt="User" />
        </div>
      </div>
      <div>
        <div class="font-semibold">John Doe</div>
        <div class="text-sm opacity-70">john@example.com</div>
      </div>
    </div>
  </div>
</aside>
```

### Pattern 3: Nested Menu with Submenu

```html
<ul class="menu p-4 w-80 min-h-full bg-base-200">
  <li><a>Dashboard</a></li>
  
  <!-- Submenu -->
  <li>
    <details>
      <summary>Products</summary>
      <ul>
        <li><a>Electronics</a></li>
        <li><a>Clothing</a></li>
        <li><a>Books</a></li>
      </ul>
    </details>
  </li>
  
  <li><a>Settings</a></li>
</ul>
```

## Troubleshooting

### Issue: Drawer doesn't open on mobile
**Solution**: Check that:
1. Checkbox `id` matches label `for` attribute
2. Checkbox has class `drawer-toggle`
3. You're not using `drawer-open` on mobile breakpoints

### Issue: Drawer overlaps content on desktop
**Solution**: 
- Remove `drawer-open` or use responsive variant `lg:drawer-open`
- Ensure you want overlay behavior, not persistent sidebar

### Issue: Overlay not clickable
**Solution**:
- Ensure overlay label has correct `for` attribute
- Check that overlay is not behind other elements (z-index)

### Issue: Content jumps when drawer opens
**Solution**:
- Add `flex flex-col` to `drawer-content`
- Ensure drawer-side width is fixed (e.g., `w-80`)

## Migration from Custom Solutions

If migrating from a custom sidebar implementation:

### Replace custom JavaScript
❌ Before:
```javascript
function toggleDrawer() {
  document.getElementById('sidebar').classList.toggle('open');
}
```

✅ After:
```html
<input id="drawer" type="checkbox" class="drawer-toggle" />
<label for="drawer">Toggle</label>
```

### Replace custom CSS
❌ Before:
```css
.sidebar {
  transform: translateX(-100%);
  transition: transform 0.3s;
}
.sidebar.open {
  transform: translateX(0);
}
```

✅ After:
```html
<div class="drawer">
  <!-- DaisyUI handles all transitions -->
</div>
```

### Replace media query logic
❌ Before:
```css
@media (min-width: 1024px) {
  .sidebar { display: block; }
  .toggle-button { display: none; }
}
```

✅ After:
```html
<div class="drawer lg:drawer-open">
  <label for="drawer" class="lg:hidden">Toggle</label>
</div>
```

## Summary

The DaisyUI drawer pattern provides:

✅ **Zero JavaScript** - Pure CSS solution
✅ **Accessible** - Built-in keyboard support via checkbox
✅ **Responsive** - Easy mobile/desktop variants with Tailwind
✅ **Themeable** - Uses DaisyUI theme colors
✅ **Flexible** - Supports left/right positioning
✅ **Standard** - No custom CSS needed

**Recommended approach**: Use `lg:drawer-open` for desktop with hidden mobile toggle for best responsive experience.


