docs: adding remaining usages of drawer (#380)
This commit is contained in:
parent
3ec55ada1b
commit
75cf9c40c4
54
apps/www/.vitepress/theme/components/InlineThemePicker.vue
Normal file
54
apps/www/.vitepress/theme/components/InlineThemePicker.vue
Normal 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>
|
||||
106
apps/www/.vitepress/theme/components/ThemeCustomizer.vue
Normal file
106
apps/www/.vitepress/theme/components/ThemeCustomizer.vue
Normal 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>
|
||||
|
|
@ -1,35 +1,19 @@
|
|||
<script setup lang="ts">
|
||||
import { onMounted, watch } from 'vue'
|
||||
import { Paintbrush } from 'lucide-vue-next'
|
||||
import { useData } from 'vitepress'
|
||||
import PageHeader from '../components/PageHeader.vue'
|
||||
import PageHeaderHeading from '../components/PageHeaderHeading.vue'
|
||||
import PageHeaderDescription from '../components/PageHeaderDescription.vue'
|
||||
import CustomizerCode from '../components/CustomizerCode.vue'
|
||||
import { RADII, useConfigStore } from '@/stores/config'
|
||||
import { colors } from '@/lib/registry'
|
||||
import type { Color } from '../types/colors'
|
||||
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 { Label } from '@/lib/registry/new-york/ui/label'
|
||||
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 RadixIconsCheck from '~icons/radix-icons/check'
|
||||
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'
|
||||
import { Drawer, DrawerContent, DrawerTrigger } from '@/lib/registry/new-york/ui/drawer'
|
||||
|
||||
// Create an array of color values
|
||||
const allColors: Color[] = [
|
||||
|
|
@ -47,8 +31,7 @@ const allColors: Color[] = [
|
|||
'violet',
|
||||
]
|
||||
|
||||
const { theme, radius, setRadius, setTheme } = useConfigStore()
|
||||
const { isDark } = useData()
|
||||
const { theme, radius } = useConfigStore()
|
||||
|
||||
// Whenever the component is mounted, update the document class list
|
||||
onMounted(() => {
|
||||
|
|
@ -72,173 +55,63 @@ watch(radius, (radius) => {
|
|||
|
||||
<template>
|
||||
<div class="container relative">
|
||||
<div class="flex justify-between items-center">
|
||||
<div>
|
||||
<PageHeader class="page-header pb-8">
|
||||
<PageHeaderHeading class="hidden md:block">
|
||||
Make it yours.
|
||||
</PageHeaderHeading>
|
||||
<PageHeaderDescription>
|
||||
Hand-picked themes that you can copy and paste into your apps.
|
||||
</PageHeaderDescription>
|
||||
</PageHeader>
|
||||
</div>
|
||||
<div class="px-4 pb-8 md:ml-auto md:pb-0">
|
||||
<div class="flex items-center space-x-2">
|
||||
<div class="hidden md:flex">
|
||||
<div class="mr-4 hidden items-center space-x-1 lg:flex">
|
||||
<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>
|
||||
<Popover>
|
||||
<PopoverTrigger as-child>
|
||||
<Button variant="outline" class="h-9 rounded-[0.5rem]">
|
||||
<Paintbrush class="w-4 h-4 mr-2" />
|
||||
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>
|
||||
<PageHeader>
|
||||
<PageHeaderHeading class="hidden md:block">
|
||||
Add colors. Make it yours.
|
||||
</PageHeaderHeading>
|
||||
<PageHeaderHeading class="md:hidden">
|
||||
Make it yours
|
||||
</PageHeaderHeading>
|
||||
<PageHeaderDescription>
|
||||
Hand-picked themes that you can copy and paste into your apps.
|
||||
</PageHeaderDescription>
|
||||
|
||||
<PageAction>
|
||||
<InlineThemePicker class="gap-x-1 me-4 hidden lg:flex" :all-colors="allColors" />
|
||||
|
||||
<Drawer>
|
||||
<DrawerTrigger as-child>
|
||||
<Button variant="outline" class="md:hidden h-9 rounded-[0.5rem]">
|
||||
<Paintbrush class="w-4 h-4 mr-2" />
|
||||
Customize
|
||||
</Button>
|
||||
</DrawerTrigger>
|
||||
<DrawerContent class="p-6 pt-0">
|
||||
<ThemeCustomizer :all-colors="allColors" />
|
||||
</DrawerContent>
|
||||
</Drawer>
|
||||
|
||||
<Popover>
|
||||
<PopoverTrigger as-child>
|
||||
<Button variant="outline" class="hidden md:flex h-9 rounded-[0.5rem]">
|
||||
<Paintbrush class="w-4 h-4 mr-2" />
|
||||
Customize
|
||||
</Button>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent :side-offset="8" align="end" class="w-96">
|
||||
<ThemeCustomizer :all-colors="allColors" />
|
||||
</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>
|
||||
</PageAction>
|
||||
</PageHeader>
|
||||
|
||||
<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>
|
||||
<slot />
|
||||
</section>
|
||||
|
|
|
|||
13
apps/www/.vitepress/theme/types/colors.ts
Normal file
13
apps/www/.vitepress/theme/types/colors.ts
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
export type Color =
|
||||
| 'zinc'
|
||||
| 'slate'
|
||||
| 'stone'
|
||||
| 'gray'
|
||||
| 'neutral'
|
||||
| 'red'
|
||||
| 'rose'
|
||||
| 'orange'
|
||||
| 'green'
|
||||
| 'blue'
|
||||
| 'yellow'
|
||||
| 'violet'
|
||||
|
|
@ -4,7 +4,7 @@ import { dependencies as deps } from '../../../package.json'
|
|||
import { Index as demoIndex } from '../../../../www/__registry__'
|
||||
import tailwindConfigRaw from '../../../tailwind.config?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>) {
|
||||
let files: Record<string, any> = {}
|
||||
|
|
@ -54,7 +54,7 @@ export default defineConfig({
|
|||
<title>Vite + Vue + TS</title>
|
||||
</head>
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<div vaul-drawer-wrapper id="app"></div>
|
||||
<script type="module" src="/src/main.ts"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -90,6 +90,9 @@ function constructFiles(componentName: string, style: Style, sources: Record<str
|
|||
[iconPackage]: 'latest',
|
||||
'shadcn-vue': 'latest',
|
||||
'typescript': 'latest',
|
||||
'vaul-vue': 'latest',
|
||||
'@unovis/vue': 'latest',
|
||||
'@unovis/ts': 'latest',
|
||||
}
|
||||
|
||||
const devDependencies = {
|
||||
|
|
|
|||
|
|
@ -297,6 +297,13 @@ export const Index = {
|
|||
component: () => import("../src/lib/registry/default/example/ComboboxPopover.vue").then((m) => m.default),
|
||||
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": {
|
||||
name: "CommandDemo",
|
||||
type: "components:example",
|
||||
|
|
@ -1278,6 +1285,13 @@ export const Index = {
|
|||
component: () => import("../src/lib/registry/new-york/example/ComboboxPopover.vue").then((m) => m.default),
|
||||
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": {
|
||||
name: "CommandDemo",
|
||||
type: "components:example",
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
---
|
||||
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>
|
||||
<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.
|
||||
|
||||
</Callout>
|
||||
|
||||
|
||||
## Installation
|
||||
|
||||
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.
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
```vue
|
||||
|
|
@ -110,6 +109,12 @@ const value = ref({})
|
|||
|
||||
<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
|
||||
|
||||
<ComponentPreview name="ComboboxForm" />
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
@ -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>
|
||||
Loading…
Reference in New Issue
Block a user