<!-- source-hash: 2221d7f0d18b72b3da12ead1872e85f9 -->
A client-side drawer component built on Radix UI's Dialog primitive, providing animated slide-in panels from any viewport edge with optional drag-to-resize and localStorage persistence.

## Key Components

| Export | Type | Description |
|--------|------|-------------|
| `Drawer` | Component | Root dialog primitive (alias for `DialogPrimitive.Root`) |
| `DrawerTrigger` | Component | Trigger element to open the drawer |
| `DrawerClose` | Component | Button/element to close the drawer |
| `DrawerPortal` | Component | Renders drawer outside the DOM tree |
| `DrawerOverlay` | Component | Semi-transparent backdrop with fade animations |
| `DrawerContent` | Component | Main panel with slide animations, resize handle, and variant support |
| `drawerVariants` | CVA | Wrapper positioning variants (`side`, `flush`) |
| `drawerPanelVariants` | CVA | Panel chrome variants (rounded corners, border, padding) |
| `DrawerResizeHandle` | Internal | Drag/keyboard-accessible resize handle rendered as panel sibling |
| `useResizableSize` | Hook | Manages clamped panel size with viewport awareness and localStorage |

**`DrawerContent` Props:**

| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `side` | `"right" \| "left" \| "top" \| "bottom"` | `"right"` | Slide-in direction |
| `flush` | `boolean` | `false` | Full-bleed mode (removes padding/border/rounded on mobile) |
| `resizable` | `boolean` | — | Enables drag-to-resize handle |
| `minSize` | `number` | — | Minimum resize size in px |
| `maxSize` | `number` | — | Maximum resize size in px (also clamped by viewport) |
| `defaultSize` | `number` | — | Initial size in px when no localStorage entry exists |
| `storageKey` | `string` | — | localStorage key for persisting size across sessions |
| `mobileBreakpoint` | `number` | — | Px breakpoint below which resizing is disabled |
| `overlayClassName` | `string` | — | Additional classes for the overlay |
| `resizeAriaLabel` | `string` | — | Accessible label for the resize handle |

## Usage Example

```typescript
import {
  Drawer,
  DrawerTrigger,
  DrawerClose,
  DrawerContent,
} from "@/components/ui/drawer"

// Basic drawer from the right
function BasicDrawer() {
  return (
    <Drawer>
      <DrawerTrigger asChild>
        <button>Open Panel</button>
      </DrawerTrigger>
      <DrawerContent side="right">
        <p>Drawer content here</p>
        <DrawerClose asChild>
          <button>Close</button>
        </DrawerClose>
      </DrawerContent>
    </Drawer>
  )
}

// Resizable flush chat panel persisted across sessions
function ChatDrawer() {
  return (
    <Drawer>
      <DrawerTrigger asChild>
        <button>Open Chat</button>
      </DrawerTrigger>
      <DrawerContent
        side="right"
        flush
        resizable
        minSize={280}
        maxSize={800}
        defaultSize={400}
        storageKey="chat-panel-width"
        mobileBreakpoint={768}
        resizeAriaLabel="Resize chat panel"
      >
        <p>Chat content</p>
      </DrawerContent>
    </Drawer>
  )
}
```

> **Resize handle accessibility:** The handle supports keyboard navigation — `ArrowLeft`/`ArrowRight` (or `ArrowUp`/`ArrowDown`) resize in 16px steps; hold `Shift` for 40px steps. `Home`/`End` jump to `minSize`/`maxSize`.