Skip to content

Commit

Permalink
feat: vaul-vue integration (#374)
Browse files Browse the repository at this point in the history
  • Loading branch information
Saeid-Za authored Mar 4, 2024
1 parent 0265b48 commit 64e2f9c
Show file tree
Hide file tree
Showing 29 changed files with 900 additions and 2 deletions.
6 changes: 6 additions & 0 deletions apps/www/.vitepress/theme/config/docs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,12 @@ export const docsConfig: DocsConfig = {
href: '/docs/components/dialog',
items: [],
},
{
title: 'Drawer',
href: '/docs/components/drawer',
items: [],
label: 'New',
},
{
title: 'Dropdown Menu',
href: '/docs/components/dropdown-menu',
Expand Down
2 changes: 1 addition & 1 deletion apps/www/.vitepress/theme/layout/MainLayout.vue
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ watch(() => $route.path, (n) => {
</script>

<template>
<div class="flex min-h-screen flex-col bg-background">
<div vaul-drawer-wrapper class="flex min-h-screen flex-col bg-background">
<header class="sticky z-40 top-0 bg-background/80 backdrop-blur-lg border-b border-border">
<div
class="container flex justify-between h-14 max-w-screen-2xl items-center"
Expand Down
28 changes: 28 additions & 0 deletions apps/www/__registry__/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -402,6 +402,20 @@ export const Index = {
component: () => import("../src/lib/registry/default/example/DialogScrollOverlayDemo.vue").then((m) => m.default),
files: ["../src/lib/registry/default/example/DialogScrollOverlayDemo.vue"],
},
"DrawerDemo": {
name: "DrawerDemo",
type: "components:example",
registryDependencies: ["button","drawer"],
component: () => import("../src/lib/registry/default/example/DrawerDemo.vue").then((m) => m.default),
files: ["../src/lib/registry/default/example/DrawerDemo.vue"],
},
"DrawerDialog": {
name: "DrawerDialog",
type: "components:example",
registryDependencies: ["button","dialog","drawer","label","input"],
component: () => import("../src/lib/registry/default/example/DrawerDialog.vue").then((m) => m.default),
files: ["../src/lib/registry/default/example/DrawerDialog.vue"],
},
"DropdownMenuDemo": {
name: "DropdownMenuDemo",
type: "components:example",
Expand Down Expand Up @@ -1355,6 +1369,20 @@ export const Index = {
component: () => import("../src/lib/registry/new-york/example/DialogScrollOverlayDemo.vue").then((m) => m.default),
files: ["../src/lib/registry/new-york/example/DialogScrollOverlayDemo.vue"],
},
"DrawerDemo": {
name: "DrawerDemo",
type: "components:example",
registryDependencies: ["button","drawer"],
component: () => import("../src/lib/registry/new-york/example/DrawerDemo.vue").then((m) => m.default),
files: ["../src/lib/registry/new-york/example/DrawerDemo.vue"],
},
"DrawerDialog": {
name: "DrawerDialog",
type: "components:example",
registryDependencies: ["button","dialog","drawer","label","input"],
component: () => import("../src/lib/registry/new-york/example/DrawerDialog.vue").then((m) => m.default),
files: ["../src/lib/registry/new-york/example/DrawerDialog.vue"],
},
"DropdownMenuDemo": {
name: "DropdownMenuDemo",
type: "components:example",
Expand Down
1 change: 1 addition & 0 deletions apps/www/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
"radix-vue": "^1.4.9",
"tailwindcss-animate": "^1.0.7",
"v-calendar": "^3.1.2",
"vaul-vue": "^0.1.0",
"vee-validate": "4.12.5",
"vue": "^3.4.21",
"vue-sonner": "^1.1.1",
Expand Down
63 changes: 63 additions & 0 deletions apps/www/src/content/docs/components/drawer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
---
title: Drawer
description: A drawer component for vue.
source: apps/www/src/lib/registry/default/ui/drawer
primitive: https://github.com/radix-vue/vaul-vue
---

<ComponentPreview name="DrawerDemo" />

## About

Drawer is built on top of [Vaul Vue](https://github.com/radix-vue/vaul-vue).

## Installation

```bash
npx shadcn-vue@latest add drawer
```

## Usage

```vue showLineNumbers
<script setup lang="ts">
import {
Drawer,
DrawerClose,
DrawerContent,
DrawerDescription,
DrawerFooter,
DrawerHeader,
DrawerTitle,
DrawerTrigger,
} from '@/components/ui/drawer'
</script>
<template>
<Drawer>
<DrawerTrigger>Open</DrawerTrigger>
<DrawerContent>
<DrawerHeader>
<DrawerTitle>Are you absolutely sure?</DrawerTitle>
<DrawerDescription>This action cannot be undone.</DrawerDescription>
</DrawerHeader>
<DrawerFooter>
<Button>Submit</Button>
<DrawerClose>
<Button variant="outline">
Cancel
</Button>
</DrawerClose>
</DrawerFooter>
</DrawerContent>
</Drawer>
</template>
```

## Examples

### Responsive Dialog

You can combine the `Dialog` and `Drawer` components to create a responsive dialog. This renders a `Dialog` component on desktop and a `Drawer` on mobile.

<ComponentPreview name="DrawerDialog" />
111 changes: 111 additions & 0 deletions apps/www/src/lib/registry/default/example/DrawerDemo.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
<script setup lang="ts">
import { ref } from 'vue'
import { Minus, Plus } from 'lucide-vue-next'
import { VisStackedBar, VisXYContainer } from '@unovis/vue'
import { Button } from '@/lib/registry/default/ui/button'
import {
Drawer,
DrawerClose,
DrawerContent,
DrawerDescription,
DrawerFooter,
DrawerHeader,
DrawerTitle,
DrawerTrigger,
} from '@/lib/registry/default/ui/drawer'
const goal = ref(350)
type Data = typeof data[number]
const data = [
{ goal: 400 },
{ goal: 300 },
{ goal: 200 },
{ goal: 300 },
{ goal: 200 },
{ goal: 278 },
{ goal: 189 },
{ goal: 239 },
{ goal: 300 },
{ goal: 200 },
{ goal: 278 },
{ goal: 189 },
{ goal: 349 },
]
</script>

<template>
<Drawer>
<DrawerTrigger as-child>
<Button variant="outline">
Open Drawer
</Button>
</DrawerTrigger>
<DrawerContent>
<div class="mx-auto w-full max-w-sm">
<DrawerHeader>
<DrawerTitle>Move Goal</DrawerTitle>
<DrawerDescription>Set your daily activity goal.</DrawerDescription>
</DrawerHeader>
<div class="p-4 pb-0">
<div class="flex items-center justify-center space-x-2">
<Button
variant="outline"
size="icon"
class="h-8 w-8 shrink-0 rounded-full"
:disabled="goal <= 200"
@click="goal -= 10"
>
<Minus class="h-4 w-4" />
<span class="sr-only">Decrease</span>
</Button>
<div class="flex-1 text-center">
<div class="text-7xl font-bold tracking-tighter">
{{ goal }}
</div>
<div class="text-[0.70rem] uppercase text-muted-foreground">
Calories/day
</div>
</div>
<Button
variant="outline"
size="icon"
class="h-8 w-8 shrink-0 rounded-full"
:disabled="goal >= 400"
@click="goal += 10"
>
<Plus class="h-4 w-4" />
<span class="sr-only">Increase</span>
</Button>
</div>
<div class="my-3 px-3 h-[120px]">
<VisXYContainer
:data="data"
class="h-[120px]"
:style="{
'opacity': 0.9,
'--theme-primary': `hsl(var(--foreground))`,
}"
>
<VisStackedBar
:x="(d: Data, i :number) => i"
:y="(d: Data) => d.goal"
color="var(--theme-primary)"
:bar-padding="0.1"
:rounded-corners="0"
/>
</VisXYContainer>
</div>
</div>
<DrawerFooter>
<Button>Submit</Button>
<DrawerClose as-child>
<Button variant="outline">
Cancel
</Button>
</DrawerClose>
</DrawerFooter>
</div>
</DrawerContent>
</Drawer>
</template>
90 changes: 90 additions & 0 deletions apps/www/src/lib/registry/default/example/DrawerDialog.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
<script lang="ts" setup>
import { ref } from 'vue'
import { createReusableTemplate, useMediaQuery } from '@vueuse/core'
import { Button } from '@/lib/registry/default/ui/button'
import {
Dialog,
DialogContent,
DialogDescription,
DialogHeader,
DialogTitle,
DialogTrigger,
} from '@/lib/registry/default/ui/dialog'
import {
Drawer,
DrawerClose,
DrawerContent,
DrawerDescription,
DrawerFooter,
DrawerHeader,
DrawerTitle,
DrawerTrigger,
} from '@/lib/registry/default/ui/drawer'
import { Label } from '@/lib/registry/default/ui/label'
import { Input } from '@/lib/registry/default/ui/input'
// Reuse `form` section
const [UseTemplate, GridForm] = createReusableTemplate()
const isDesktop = useMediaQuery('(min-width: 768px)')
const isOpen = ref(false)
</script>

<template>
<UseTemplate>
<form class="grid items-start gap-4 px-4">
<div class="grid gap-2">
<Label html-for="email">Email</Label>
<Input id="email" type="email" default-value="shadcn@example.com" />
</div>
<div class="grid gap-2">
<Label html-for="username">Username</Label>
<Input id="username" default-value="@shadcn" />
</div>
<Button type="submit">
Save changes
</Button>
</form>
</UseTemplate>

<Dialog v-if="isDesktop" v-model:open="isOpen">
<DialogTrigger as-child>
<Button variant="outline">
Edit Profile
</Button>
</DialogTrigger>
<DialogContent class="sm:max-w-[425px]">
<DialogHeader>
<DialogTitle>Edit profile</DialogTitle>
<DialogDescription>
Make changes to your profile here. Click save when you're done.
</DialogDescription>
</DialogHeader>
<GridForm />
</DialogContent>
</Dialog>

<Drawer v-else v-model:open="isOpen">
<DrawerTrigger as-child>
<Button variant="outline">
Edit Profile
</Button>
</DrawerTrigger>
<DrawerContent>
<DrawerHeader class="text-left">
<DrawerTitle>Edit profile</DrawerTitle>
<DrawerDescription>
Make changes to your profile here. Click save when you're done.
</DrawerDescription>
</DrawerHeader>
<GridForm />
<DrawerFooter class="pt-2">
<DrawerClose as-child>
<Button variant="outline">
Cancel
</Button>
</DrawerClose>
</DrawerFooter>
</DrawerContent>
</Drawer>
</template>
19 changes: 19 additions & 0 deletions apps/www/src/lib/registry/default/ui/drawer/Drawer.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
<script lang="ts" setup>
import type { DrawerRootEmits, DrawerRootProps } from 'vaul-vue'
import { DrawerRoot } from 'vaul-vue'
import { useForwardPropsEmits } from 'radix-vue'
const props = withDefaults(defineProps<DrawerRootProps>(), {
shouldScaleBackground: true,
})
const emits = defineEmits<DrawerRootEmits>()
const forwarded = useForwardPropsEmits(props, emits)
</script>

<template>
<DrawerRoot v-bind="forwarded">
<slot />
</DrawerRoot>
</template>
28 changes: 28 additions & 0 deletions apps/www/src/lib/registry/default/ui/drawer/DrawerContent.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<script lang="ts" setup>
import { DrawerContent, DrawerPortal } from 'vaul-vue'
import type { DialogContentEmits, DialogContentProps } from 'radix-vue'
import { useForwardPropsEmits } from 'radix-vue'
import type { HtmlHTMLAttributes } from 'vue'
import DrawerOverlay from './DrawerOverlay.vue'
import { cn } from '@/lib/utils'
const props = defineProps<DialogContentProps & { class?: HtmlHTMLAttributes['class'] }>()
const emits = defineEmits<DialogContentEmits>()
const forwarded = useForwardPropsEmits(props, emits)
</script>

<template>
<DrawerPortal>
<DrawerOverlay />
<DrawerContent
v-bind="forwarded" :class="cn(
'fixed inset-x-0 bottom-0 z-50 mt-24 flex h-auto flex-col rounded-t-[10px] border bg-background',
props.class,
)"
>
<div class="mx-auto mt-4 h-2 w-[100px] rounded-full bg-muted" />
<slot />
</DrawerContent>
</DrawerPortal>
</template>
Loading

0 comments on commit 64e2f9c

Please sign in to comment.