docs: adding remaining usages of drawer (#380)

This commit is contained in:
Saeid Zareie 2024-03-05 14:45:30 +03:30 committed by GitHub
parent 3ec55ada1b
commit 75cf9c40c4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 452 additions and 196 deletions

View File

@ -0,0 +1,54 @@
<script lang="ts" setup>
import type { Color } from '../types/colors'
import { useConfigStore } from '@/stores/config'
import { colors } from '@/lib/registry'
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/lib/registry/new-york/ui/tooltip'
import RadixIconsCheck from '~icons/radix-icons/check'
defineProps<{
allColors: Color[]
}>()
const { theme, setTheme } = useConfigStore()
</script>
<template>
<div>
<TooltipProvider
v-for="(color, index) in allColors.slice(0, 5)"
:key="index"
>
<Tooltip>
<TooltipTrigger as-child>
<button
:key="index"
class="flex h-9 w-9 items-center justify-center rounded-full border-2 border-border text-xs"
:class="
color === theme
? 'border-primary'
: 'border-transparent'
"
@click="setTheme(color)"
>
<span
class="flex h-6 w-6 items-center justify-center rounded-full"
:style="{ backgroundColor: colors[color][6].rgb }"
>
<RadixIconsCheck
v-if="color === theme"
class="h-4 w-4 text-white"
/>
</span>
</button>
</TooltipTrigger>
<TooltipContent
align="center"
:side-offset="1"
class="capitalize bg-zinc-900 text-zinc-50"
>
{{ allColors[index] }}
</TooltipContent>
</Tooltip>
</TooltipProvider>
</div>
</template>

View File

@ -0,0 +1,106 @@
<script lang="ts" setup>
import { useData } from 'vitepress'
import type { Color } from '../types/colors'
import { RADII, useConfigStore } from '@/stores/config'
import { Button } from '@/lib/registry/new-york/ui/button'
import { Label } from '@/lib/registry/new-york/ui/label'
import { colors } from '@/lib/registry'
import RadixIconsCheck from '~icons/radix-icons/check'
import RadixIconsSun from '~icons/radix-icons/sun'
import RadixIconsMoon from '~icons/radix-icons/moon'
defineProps<{
allColors: Color[]
}>()
const { theme, radius, setRadius, setTheme } = useConfigStore()
const { isDark } = useData()
</script>
<template>
<div class="p-4">
<div class="grid space-y-1">
<h1 class="text-md text-foreground font-semibold">
Customize
</h1>
<p class="text-xs text-muted-foreground">
Pick a style and color for your components.
</p>
</div>
<div class="space-y-1.5 pt-6">
<Label for="color" class="text-xs"> Color </Label>
<div class="grid grid-cols-3 gap-2 py-1.5">
<Button
v-for="(color, index) in allColors"
:key="index"
variant="outline"
class="h-8 justify-start px-3"
:class="
color === theme
? 'border-foreground border-2'
: ''
"
@click="setTheme(color)"
>
<span
class="h-5 w-5 rounded-full flex items-center justify-center"
:style="{ backgroundColor: colors[color][7].rgb }"
>
<RadixIconsCheck
v-if="color === theme"
class="h-3 w-3 text-white"
/>
</span>
<span class="ml-2 text-xs capitalize">
{{ color }}
</span>
</Button>
</div>
</div>
<div class="space-y-1.5 pt-6">
<Label for="radius" class="text-xs"> Radius </Label>
<div class="grid grid-cols-5 gap-2 py-1.5">
<Button
v-for="(r, index) in RADII"
:key="index"
variant="outline"
class="h-8 justify-center px-3"
:class="
r === radius
? 'border-foreground border-2'
: ''
"
@click="setRadius(r)"
>
<span class="text-xs">
{{ r }}
</span>
</Button>
</div>
</div>
<div class="space-y-1.5 pt-6">
<Label for="theme" class="text-xs"> Theme </Label>
<div class="flex space-x-2 py-1.5">
<Button
class="h-8"
variant="outline"
:class="{ 'border-2 border-foreground': !isDark }"
@click="isDark = false"
>
<RadixIconsSun class="w-4 h-4 mr-2" />
<span class="text-xs">Light</span>
</Button>
<Button
class="h-8"
variant="outline"
:class="{ 'border-2 border-foreground': isDark }"
@click="isDark = true"
>
<RadixIconsMoon class="w-4 h-4 mr-2" />
<span class="text-xs">Dark</span>
</Button>
</div>
</div>
</div>
</template>

View File

@ -1,35 +1,19 @@
<script setup lang="ts"> <script setup lang="ts">
import { onMounted, watch } from 'vue' import { onMounted, watch } from 'vue'
import { Paintbrush } from 'lucide-vue-next' import { Paintbrush } from 'lucide-vue-next'
import { useData } from 'vitepress'
import PageHeader from '../components/PageHeader.vue' import PageHeader from '../components/PageHeader.vue'
import PageHeaderHeading from '../components/PageHeaderHeading.vue' import PageHeaderHeading from '../components/PageHeaderHeading.vue'
import PageHeaderDescription from '../components/PageHeaderDescription.vue' import PageHeaderDescription from '../components/PageHeaderDescription.vue'
import CustomizerCode from '../components/CustomizerCode.vue' import CustomizerCode from '../components/CustomizerCode.vue'
import { RADII, useConfigStore } from '@/stores/config' import type { Color } from '../types/colors'
import { colors } from '@/lib/registry' import ThemeCustomizer from '../components/ThemeCustomizer.vue'
import InlineThemePicker from '../components/InlineThemePicker.vue'
import PageAction from '../components/PageAction.vue'
import { useConfigStore } from '@/stores/config'
import { Button } from '@/lib/registry/new-york/ui/button' import { Button } from '@/lib/registry/new-york/ui/button'
import { Label } from '@/lib/registry/new-york/ui/label'
import { Popover, PopoverContent, PopoverTrigger } from '@/lib/registry/new-york/ui/popover' import { Popover, PopoverContent, PopoverTrigger } from '@/lib/registry/new-york/ui/popover'
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/lib/registry/new-york/ui/tooltip'
import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, DialogTrigger } from '@/lib/registry/new-york/ui/dialog' import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, DialogTrigger } from '@/lib/registry/new-york/ui/dialog'
import RadixIconsCheck from '~icons/radix-icons/check' import { Drawer, DrawerContent, DrawerTrigger } from '@/lib/registry/new-york/ui/drawer'
import RadixIconsSun from '~icons/radix-icons/sun'
import RadixIconsMoon from '~icons/radix-icons/moon'
type Color =
| 'zinc'
| 'slate'
| 'stone'
| 'gray'
| 'neutral'
| 'red'
| 'rose'
| 'orange'
| 'green'
| 'blue'
| 'yellow'
| 'violet'
// Create an array of color values // Create an array of color values
const allColors: Color[] = [ const allColors: Color[] = [
@ -47,8 +31,7 @@ const allColors: Color[] = [
'violet', 'violet',
] ]
const { theme, radius, setRadius, setTheme } = useConfigStore() const { theme, radius } = useConfigStore()
const { isDark } = useData()
// Whenever the component is mounted, update the document class list // Whenever the component is mounted, update the document class list
onMounted(() => { onMounted(() => {
@ -72,173 +55,63 @@ watch(radius, (radius) => {
<template> <template>
<div class="container relative"> <div class="container relative">
<div class="flex justify-between items-center"> <PageHeader>
<div> <PageHeaderHeading class="hidden md:block">
<PageHeader class="page-header pb-8"> Add colors. Make it yours.
<PageHeaderHeading class="hidden md:block"> </PageHeaderHeading>
Make it yours. <PageHeaderHeading class="md:hidden">
</PageHeaderHeading> Make it yours
<PageHeaderDescription> </PageHeaderHeading>
Hand-picked themes that you can copy and paste into your apps. <PageHeaderDescription>
</PageHeaderDescription> Hand-picked themes that you can copy and paste into your apps.
</PageHeader> </PageHeaderDescription>
</div>
<div class="px-4 pb-8 md:ml-auto md:pb-0"> <PageAction>
<div class="flex items-center space-x-2"> <InlineThemePicker class="gap-x-1 me-4 hidden lg:flex" :all-colors="allColors" />
<div class="hidden md:flex">
<div class="mr-4 hidden items-center space-x-1 lg:flex"> <Drawer>
<TooltipProvider <DrawerTrigger as-child>
v-for="(color, index) in allColors.slice(0, 5)" <Button variant="outline" class="md:hidden h-9 rounded-[0.5rem]">
:key="index" <Paintbrush class="w-4 h-4 mr-2" />
> Customize
<Tooltip> </Button>
<TooltipTrigger as-child> </DrawerTrigger>
<button <DrawerContent class="p-6 pt-0">
:key="index" <ThemeCustomizer :all-colors="allColors" />
class="flex h-9 w-9 items-center justify-center rounded-full border-2 border-border text-xs" </DrawerContent>
:class=" </Drawer>
color === theme
? 'border-primary' <Popover>
: 'border-transparent' <PopoverTrigger as-child>
" <Button variant="outline" class="hidden md:flex h-9 rounded-[0.5rem]">
@click="setTheme(color)" <Paintbrush class="w-4 h-4 mr-2" />
> Customize
<span </Button>
class="flex h-6 w-6 items-center justify-center rounded-full" </PopoverTrigger>
:style="{ backgroundColor: colors[color][6].rgb }" <PopoverContent :side-offset="8" align="end" class="w-96">
> <ThemeCustomizer :all-colors="allColors" />
<RadixIconsCheck </PopoverContent>
v-if="color === theme" </Popover>
class="h-4 w-4 text-white"
/> <Dialog>
</span> <DialogTrigger as-child>
</button> <Button class="h-9 ml-2 rounded-[0.5rem]">
</TooltipTrigger> Copy code
<TooltipContent </Button>
align="center" </DialogTrigger>
:side-offset="1" <DialogContent class="sm:max-w-[625px]">
class="capitalize bg-zinc-900 text-zinc-50" <DialogHeader>
> <DialogTitle>Theme</DialogTitle>
{{ allColors[index] }} <DialogDescription>
</TooltipContent> Copy and paste the following code into your CSS file.
</Tooltip> </DialogDescription>
</TooltipProvider> </DialogHeader>
</div> <CustomizerCode />
<Popover> </DialogContent>
<PopoverTrigger as-child> </Dialog>
<Button variant="outline" class="h-9 rounded-[0.5rem]"> </PageAction>
<Paintbrush class="w-4 h-4 mr-2" /> </PageHeader>
Customize
</Button>
</PopoverTrigger>
<PopoverContent :side-offset="8" align="end" class="w-96">
<div class="p-4">
<div class="grid space-y-1">
<h1 class="text-md text-foreground font-semibold">
Customize
</h1>
<p class="text-xs text-muted-foreground">
Pick a style and color for your components.
</p>
</div>
<div class="space-y-1.5 pt-6">
<Label for="color" class="text-xs"> Color </Label>
<div class="grid grid-cols-3 gap-2 py-1.5">
<Button
v-for="(color, index) in allColors"
:key="index"
variant="outline"
class="h-8 justify-start px-3"
:class="
color === theme
? 'border-foreground border-2'
: ''
"
@click="setTheme(color)"
>
<span
class="h-5 w-5 rounded-full flex items-center justify-center"
:style="{ backgroundColor: colors[color][7].rgb }"
>
<RadixIconsCheck
v-if="color === theme"
class="h-3 w-3 text-white"
/>
</span>
<span class="ml-2 text-xs capitalize">
{{ color }}
</span>
</Button>
</div>
</div>
<div class="space-y-1.5 pt-6">
<Label for="radius" class="text-xs"> Radius </Label>
<div class="grid grid-cols-5 gap-2 py-1.5">
<Button
v-for="(r, index) in RADII"
:key="index"
variant="outline"
class="h-8 justify-center px-3"
:class="
r === radius
? 'border-foreground border-2'
: ''
"
@click="setRadius(r)"
>
<span class="text-xs">
{{ r }}
</span>
</Button>
</div>
</div>
<div class="space-y-1.5 pt-6">
<Label for="theme" class="text-xs"> Theme </Label>
<div class="flex space-x-2 py-1.5">
<Button
class="h-8"
variant="outline"
:class="{ 'border-2 border-foreground': !isDark }"
@click="isDark = false"
>
<RadixIconsSun class="w-4 h-4 mr-2" />
<span class="text-xs">Light</span>
</Button>
<Button
class="h-8"
variant="outline"
:class="{ 'border-2 border-foreground': isDark }"
@click="isDark = true"
>
<RadixIconsMoon class="w-4 h-4 mr-2" />
<span class="text-xs">Dark</span>
</Button>
</div>
</div>
</div>
</PopoverContent>
</Popover>
<Dialog>
<DialogTrigger as-child>
<Button class="h-9 ml-2 rounded-[0.5rem]">
Copy code
</Button>
</DialogTrigger>
<DialogContent class="sm:max-w-[625px]">
<DialogHeader>
<DialogTitle>Theme</DialogTitle>
<DialogDescription>
Copy and paste the following code into your CSS file.
</DialogDescription>
</DialogHeader>
<CustomizerCode />
</DialogContent>
</Dialog>
</div>
</div>
</div>
</div>
<section> <section>
<slot /> <slot />
</section> </section>

View File

@ -0,0 +1,13 @@
export type Color =
| 'zinc'
| 'slate'
| 'stone'
| 'gray'
| 'neutral'
| 'red'
| 'rose'
| 'orange'
| 'green'
| 'blue'
| 'yellow'
| 'violet'

View File

@ -4,7 +4,7 @@ import { dependencies as deps } from '../../../package.json'
import { Index as demoIndex } from '../../../../www/__registry__' import { Index as demoIndex } from '../../../../www/__registry__'
import tailwindConfigRaw from '../../../tailwind.config?raw' import tailwindConfigRaw from '../../../tailwind.config?raw'
import cssRaw from '../../../../../packages/cli/test/fixtures/nuxt/assets/css/tailwind.css?raw' import cssRaw from '../../../../../packages/cli/test/fixtures/nuxt/assets/css/tailwind.css?raw'
import { type Style } from '@/lib/registry/styles' import type { Style } from '@/lib/registry/styles'
export function makeCodeSandboxParams(componentName: string, style: Style, sources: Record<string, string>) { export function makeCodeSandboxParams(componentName: string, style: Style, sources: Record<string, string>) {
let files: Record<string, any> = {} let files: Record<string, any> = {}
@ -54,7 +54,7 @@ export default defineConfig({
<title>Vite + Vue + TS</title> <title>Vite + Vue + TS</title>
</head> </head>
<body> <body>
<div id="app"></div> <div vaul-drawer-wrapper id="app"></div>
<script type="module" src="/src/main.ts"></script> <script type="module" src="/src/main.ts"></script>
</body> </body>
</html> </html>
@ -90,6 +90,9 @@ function constructFiles(componentName: string, style: Style, sources: Record<str
[iconPackage]: 'latest', [iconPackage]: 'latest',
'shadcn-vue': 'latest', 'shadcn-vue': 'latest',
'typescript': 'latest', 'typescript': 'latest',
'vaul-vue': 'latest',
'@unovis/vue': 'latest',
'@unovis/ts': 'latest',
} }
const devDependencies = { const devDependencies = {

View File

@ -297,6 +297,13 @@ export const Index = {
component: () => import("../src/lib/registry/default/example/ComboboxPopover.vue").then((m) => m.default), component: () => import("../src/lib/registry/default/example/ComboboxPopover.vue").then((m) => m.default),
files: ["../src/lib/registry/default/example/ComboboxPopover.vue"], files: ["../src/lib/registry/default/example/ComboboxPopover.vue"],
}, },
"ComboboxResponsive": {
name: "ComboboxResponsive",
type: "components:example",
registryDependencies: ["button","command","drawer","popover"],
component: () => import("../src/lib/registry/default/example/ComboboxResponsive.vue").then((m) => m.default),
files: ["../src/lib/registry/default/example/ComboboxResponsive.vue"],
},
"CommandDemo": { "CommandDemo": {
name: "CommandDemo", name: "CommandDemo",
type: "components:example", type: "components:example",
@ -1278,6 +1285,13 @@ export const Index = {
component: () => import("../src/lib/registry/new-york/example/ComboboxPopover.vue").then((m) => m.default), component: () => import("../src/lib/registry/new-york/example/ComboboxPopover.vue").then((m) => m.default),
files: ["../src/lib/registry/new-york/example/ComboboxPopover.vue"], files: ["../src/lib/registry/new-york/example/ComboboxPopover.vue"],
}, },
"ComboboxResponsive": {
name: "ComboboxResponsive",
type: "components:example",
registryDependencies: ["button","command","drawer","popover"],
component: () => import("../src/lib/registry/new-york/example/ComboboxResponsive.vue").then((m) => m.default),
files: ["../src/lib/registry/new-york/example/ComboboxResponsive.vue"],
},
"CommandDemo": { "CommandDemo": {
name: "CommandDemo", name: "CommandDemo",
type: "components:example", type: "components:example",

View File

@ -1,9 +1,9 @@
--- ---
title: Combobox title: Combobox
description: Autocomplete input and command palette with a list of suggestions. description: Autocomplete input and command palette with a list of suggestions.
--- ---
<ComponentPreview name="ComboboxDemo" /> <ComponentPreview name="ComboboxDemo" />
<br> <br>
<Callout title="Note" class="bg-destructive"> <Callout title="Note" class="bg-destructive">
@ -11,14 +11,13 @@ description: Autocomplete input and command palette with a list of suggestions.
[Radix Vue](https://github.com/radix-vue/radix-vue/releases/tag/v1.2.0) introduced a breaking change. You will need to wrap `ComboboxGroup` and `ComboboxItem` inside of `ComboboxList` now. [Radix Vue](https://github.com/radix-vue/radix-vue/releases/tag/v1.2.0) introduced a breaking change. You will need to wrap `ComboboxGroup` and `ComboboxItem` inside of `ComboboxList` now.
</Callout> </Callout>
## Installation ## Installation
The Combobox is built using a composition of the `<Popover />` and the `<Command />` components. The Combobox is built using a composition of the `<Popover />` and the `<Command />` components.
See installation instructions for the [Popover](/docs/components/popover#installation) and the [Command](/docs/components/command#installation) components. See installation instructions for the [Popover](/docs/components/popover#installation) and the [Command](/docs/components/command#installation) components.
## Usage ## Usage
```vue ```vue
@ -110,6 +109,12 @@ const value = ref({})
<ComponentPreview name="ComboboxDropdownMenu" /> <ComponentPreview name="ComboboxDropdownMenu" />
### Responsive
You can create a responsive combobox by using the `<Popover />` on desktop and the `<Drawer />` components on mobile.
<ComponentPreview name="ComboboxResponsive" />
### Form ### Form
<ComponentPreview name="ComboboxForm" /> <ComponentPreview name="ComboboxForm" />

View File

@ -0,0 +1,94 @@
<script lang="ts" setup>
import { createReusableTemplate, useMediaQuery } from '@vueuse/core'
import { ref } from 'vue'
import { Button } from '@/lib/registry/default/ui/button'
import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList } from '@/lib/registry/default/ui/command'
import { Drawer, DrawerContent, DrawerTrigger } from '@/lib/registry/default/ui/drawer'
import { Popover, PopoverContent, PopoverTrigger } from '@/lib/registry/default/ui/popover'
interface Status {
value: string
label: string
}
const statuses: Status[] = [
{
value: 'backlog',
label: 'Backlog',
},
{
value: 'todo',
label: 'Todo',
},
{
value: 'in progress',
label: 'In Progress',
},
{
value: 'done',
label: 'Done',
},
{
value: 'canceled',
label: 'Canceled',
},
]
const [UseTemplate, StatusList] = createReusableTemplate()
const isDesktop = useMediaQuery('(min-width: 768px)')
const isOpen = ref(false)
const selectedStatus = ref<Status | null>(null)
function onStatusSelect(status: Status) {
selectedStatus.value = status
isOpen.value = false
}
</script>
<template>
<div>
<UseTemplate>
<Command>
<CommandInput placeholder="Filter status..." />
<CommandList>
<CommandEmpty>No results found.</CommandEmpty>
<CommandGroup>
<CommandItem
v-for="status of statuses"
:key="status.value"
:value="status.value"
@select="onStatusSelect(status)"
>
{{ status.label }}
</CommandItem>
</CommandGroup>
</CommandList>
</Command>
</UseTemplate>
<Popover v-if="isDesktop" v-model:open="isOpen">
<PopoverTrigger as-child>
<Button variant="outline" class="w-[150px] justify-start">
{{ selectedStatus ? selectedStatus.label : "+ Set status" }}
</Button>
</PopoverTrigger>
<PopoverContent class="w-[200px] p-0" align="start">
<StatusList />
</PopoverContent>
</Popover>
<Drawer v-else :open="isOpen" @update:open="(newOpenValue) => isOpen = newOpenValue">
<DrawerTrigger as-child>
<Button variant="outline" class="w-[150px] justify-start">
{{ selectedStatus ? selectedStatus.label : "+ Set status" }}
</Button>
</DrawerTrigger>
<DrawerContent>
<div class="mt-4 border-t">
<StatusList />
</div>
</DrawerContent>
</Drawer>
</div>
</template>

View File

@ -0,0 +1,94 @@
<script lang="ts" setup>
import { createReusableTemplate, useMediaQuery } from '@vueuse/core'
import { ref } from 'vue'
import { Button } from '@/lib/registry/new-york/ui/button'
import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList } from '@/lib/registry/new-york/ui/command'
import { Drawer, DrawerContent, DrawerTrigger } from '@/lib/registry/new-york/ui/drawer'
import { Popover, PopoverContent, PopoverTrigger } from '@/lib/registry/new-york/ui/popover'
interface Status {
value: string
label: string
}
const statuses: Status[] = [
{
value: 'backlog',
label: 'Backlog',
},
{
value: 'todo',
label: 'Todo',
},
{
value: 'in progress',
label: 'In Progress',
},
{
value: 'done',
label: 'Done',
},
{
value: 'canceled',
label: 'Canceled',
},
]
const [UseTemplate, StatusList] = createReusableTemplate()
const isDesktop = useMediaQuery('(min-width: 768px)')
const isOpen = ref(false)
const selectedStatus = ref<Status | null>(null)
function onStatusSelect(status: Status) {
selectedStatus.value = status
isOpen.value = false
}
</script>
<template>
<div>
<UseTemplate>
<Command>
<CommandInput placeholder="Filter status..." />
<CommandList>
<CommandEmpty>No results found.</CommandEmpty>
<CommandGroup>
<CommandItem
v-for="status of statuses"
:key="status.value"
:value="status.value"
@select="onStatusSelect(status)"
>
{{ status.label }}
</CommandItem>
</CommandGroup>
</CommandList>
</Command>
</UseTemplate>
<Popover v-if="isDesktop" v-model:open="isOpen">
<PopoverTrigger as-child>
<Button variant="outline" class="w-[150px] justify-start">
{{ selectedStatus ? selectedStatus.label : "+ Set status" }}
</Button>
</PopoverTrigger>
<PopoverContent class="w-[200px] p-0" align="start">
<StatusList />
</PopoverContent>
</Popover>
<Drawer v-else v-model:open="isOpen">
<DrawerTrigger as-child>
<Button variant="outline" class="w-[150px] justify-start">
{{ selectedStatus ? selectedStatus.label : "+ Set status" }}
</Button>
</DrawerTrigger>
<DrawerContent>
<div class="mt-4 border-t">
<StatusList />
</div>
</DrawerContent>
</Drawer>
</div>
</template>