Drawer
A drawer component for Svelte, built on Vaul Svelte.
Loading preview…
1<script lang="ts">
2 import MinusIcon from '@lucide/svelte/icons/minus';
3 import PlusIcon from '@lucide/svelte/icons/plus';
4 import { buttonVariants } from '../button/button.variants.js';
5 import Button from '../button/button.svelte';
6 import * as Drawer from './index.js';
7
8 let goal = $state(350);
9
10 function handleClick(adjustment: number) {
11 goal = Math.max(200, Math.min(400, goal + adjustment));
12 }
13</script>
14
15<Drawer.Root>
16 <Drawer.Trigger class={buttonVariants({ variant: 'outline' })}>Open Drawer</Drawer.Trigger>
17 <Drawer.Content>
18 <div class="mx-auto w-full max-w-sm">
19 <Drawer.Header>
20 <Drawer.Title>Move Goal</Drawer.Title>
21 <Drawer.Description>Set your daily activity goal.</Drawer.Description>
22 </Drawer.Header>
23 <div class="p-4 pb-0">
24 <div class="flex items-center justify-center space-x-2">
25 <Button
26 variant="outline"
27 size="icon"
28 class="size-8 shrink-0 rounded-full"
29 onclick={() => handleClick(-10)}
30 disabled={goal <= 200}
31 >
32 <MinusIcon />
33 <span class="sr-only">Decrease</span>
34 </Button>
35 <div class="flex-1 text-center">
36 <div class="text-7xl font-bold tracking-tighter">
37 {goal}
38 </div>
39 <div class="text-[0.70rem] text-muted-foreground uppercase">Calories/day</div>
40 </div>
41 <Button
42 variant="outline"
43 size="icon"
44 class="size-8 shrink-0 rounded-full"
45 onclick={() => handleClick(10)}
46 disabled={goal >= 400}
47 >
48 <PlusIcon />
49 <span class="sr-only">Increase</span>
50 </Button>
51 </div>
52 </div>
53 <Drawer.Footer>
54 <Button>Submit</Button>
55 <Drawer.Close class={buttonVariants({ variant: 'outline' })}>Cancel</Drawer.Close>
56 </Drawer.Footer>
57 </div>
58 </Drawer.Content>
59</Drawer.Root>
60Installation
1. Install dependencies
2. Copy these files into your project
- ~/components/drawer/index.ts
- ~/components/drawer/drawer.svelte
- ~/components/drawer/drawer-trigger.svelte
- ~/components/drawer/drawer-portal.svelte
- ~/components/drawer/drawer-overlay.svelte
- ~/components/drawer/drawer-content.svelte
- ~/components/drawer/drawer-header.svelte
- ~/components/drawer/drawer-footer.svelte
- ~/components/drawer/drawer-title.svelte
- ~/components/drawer/drawer-description.svelte
- ~/components/drawer/drawer-close.svelte
- ~/components/drawer/drawer-nested.svelte
Usage
Use drawer for bottom (or edge) panels on mobile and secondary flows. Compose with trigger,
content, header, and footer. Set direction on Drawer.Root to top, right, bottom, or left.
1<script lang="ts">
2 import * as Drawer from '~/components/drawer';
3 import { Button, buttonVariants } from '~/components/button';
4</script>
5
6<Drawer.Root>
7 <Drawer.Trigger class={buttonVariants({ variant: 'outline' })}>Open</Drawer.Trigger>
8 <Drawer.Content>
9 <Drawer.Header>
10 <Drawer.Title>Are you absolutely sure?</Drawer.Title>
11 <Drawer.Description>This action cannot be undone.</Drawer.Description>
12 </Drawer.Header>
13 <Drawer.Footer>
14 <Button>Submit</Button>
15 <Drawer.Close class={buttonVariants({ variant: 'outline' })}>Cancel</Drawer.Close>
16 </Drawer.Footer>
17 </Drawer.Content>
18</Drawer.Root>