laif-ds
Version:
Design System di Laif con componenti React basati su principi di Atomic Design
128 lines (104 loc) • 4.92 kB
Markdown
# Drawer
## Overview
Sliding panel component (top/right/bottom/left) built on Vaul. Supports modal behavior, background scaling, snap points, and full keyboard accessibility.
---
## Props
### Drawer (Root)
| Prop | Type | Default | Description |
| -------------------- | ------------------------------------- | ----------- | ------------------------------------------------------------------ |
| `open` | `boolean` | `undefined` | Controlled open state. |
| `onOpenChange` | `(open: boolean) => void` | `undefined` | Called when open state changes. |
| `direction` | `"top" | "right" | "bottom" | "left"` | `"bottom"` | Drawer opening direction. |
| `modal` | `boolean` | `true` | Modal behavior (trap focus, block background interaction). |
| `shouldScaleBackground` | `boolean` | `true` | Scales the background when the drawer is open. |
| `snapPoints` | `number[]` | `[]` | Optional snap points (fractions of viewport: e.g., `0.4`, `0.6`). |
| `activeSnapPoint` | `number | string` | `undefined` | The active snap point index/value. |
| `closeThreshold` | `number` | `undefined` | Threshold to trigger close on drag. |
### Subcomponents
- `DrawerTrigger`: Element that opens the drawer (supports `asChild`).
- `DrawerPortal` / `DrawerOverlay`: Portal root and backdrop.
- `DrawerContent`: Panel container; includes a grab handle in bottom direction.
- `DrawerHeader` / `DrawerFooter`: Layout helpers for content.
- `DrawerTitle` / `DrawerDescription`: Header title and description.
- `DrawerClose`: Close button helper to wrap an element.
---
## Behavior
- **Directions**: Open from any side via `direction` prop.
- **Snap points**: Provide a list of fractional heights; control active point via `activeSnapPoint`.
- **Modal**: When `modal` is true, interaction outside is blocked and overlay is shown.
- **Accessibility**: Focus trapping and keyboard navigation handled by the underlying library.
---
## Examples
### Interactive Drawer
```tsx
import { Button } from "laif-ds";
import {
Drawer,
DrawerTrigger,
DrawerContent,
DrawerHeader,
DrawerTitle,
DrawerDescription,
DrawerFooter,
DrawerClose,
} from "laif-ds";
import { Input } from "laif-ds";
export function InteractiveDrawer() {
return (
<Drawer direction="bottom" modal shouldScaleBackground>
<DrawerTrigger asChild>
<Button variant="outline">Apri Drawer</Button>
</DrawerTrigger>
<DrawerContent>
<DrawerHeader>
<DrawerTitle>Drawer di Esempio</DrawerTitle>
<DrawerDescription>
Personalizza contenuti e comportamento tramite le props.
</DrawerDescription>
</DrawerHeader>
<div className="space-y-4 p-4">
<Input label="Nome" placeholder="Inserisci il tuo nome" />
<Input label="Email" type="email" placeholder="Inserisci la tua email" />
</div>
<DrawerFooter>
<Button>Salva modifiche</Button>
<DrawerClose asChild>
<Button variant="outline">Annulla</Button>
</DrawerClose>
</DrawerFooter>
</DrawerContent>
</Drawer>
);
}
```
### With Snap Points
```tsx
import { Button } from "laif-ds";
import { Drawer, DrawerTrigger, DrawerContent, DrawerHeader, DrawerTitle, DrawerDescription, DrawerFooter, DrawerClose } from "laif-ds";
export function DrawerWithSnapPoints() {
const snapPoints = [0.4, 0.6, 0.9];
return (
<Drawer snapPoints={snapPoints} activeSnapPoint={0}>
<DrawerTrigger asChild>
<Button variant="outline">Drawer con Snap Points</Button>
</DrawerTrigger>
<DrawerContent>
<DrawerHeader>
<DrawerTitle>Drawer con Snap Points</DrawerTitle>
<DrawerDescription>Snap a 40%, 60% e 90% dell'altezza.</DrawerDescription>
</DrawerHeader>
<DrawerFooter>
<DrawerClose asChild>
<Button variant="outline">Chiudi</Button>
</DrawerClose>
</DrawerFooter>
</DrawerContent>
</Drawer>
);
}
```
---
## Notes
- **Handle**: A grab handle is visible for bottom direction.
- **Layout**: Use `DrawerHeader`/`DrawerFooter` and your own content in between.
- **Styling**: Customize via `className` on `DrawerContent`.