chore: add combobox demo
This commit is contained in:
parent
34f0786b0c
commit
893427b0d2
|
|
@ -618,12 +618,12 @@ export const Index = {
|
||||||
component: () => import('../src/lib/registry/default/example/TabsDemo.vue').then(m => m.default),
|
component: () => import('../src/lib/registry/default/example/TabsDemo.vue').then(m => m.default),
|
||||||
files: ['../src/lib/registry/default/example/TabsDemo.vue'],
|
files: ['../src/lib/registry/default/example/TabsDemo.vue'],
|
||||||
},
|
},
|
||||||
TagsInputComboDemo: {
|
TagsInputComboboxDemo: {
|
||||||
name: 'TagsInputComboDemo',
|
name: 'TagsInputComboboxDemo',
|
||||||
type: 'components:example',
|
type: 'components:example',
|
||||||
registryDependencies: ['utils', 'button', 'command', 'popover', 'tags-input'],
|
registryDependencies: ['command', 'tags-input'],
|
||||||
component: () => import('../src/lib/registry/default/example/TagsInputComboDemo.vue').then(m => m.default),
|
component: () => import('../src/lib/registry/default/example/TagsInputComboboxDemo.vue').then(m => m.default),
|
||||||
files: ['../src/lib/registry/default/example/TagsInputComboDemo.vue'],
|
files: ['../src/lib/registry/default/example/TagsInputComboboxDemo.vue'],
|
||||||
},
|
},
|
||||||
TagsInputDemo: {
|
TagsInputDemo: {
|
||||||
name: 'TagsInputDemo',
|
name: 'TagsInputDemo',
|
||||||
|
|
@ -1537,12 +1537,12 @@ export const Index = {
|
||||||
component: () => import('../src/lib/registry/new-york/example/TabsDemo.vue').then(m => m.default),
|
component: () => import('../src/lib/registry/new-york/example/TabsDemo.vue').then(m => m.default),
|
||||||
files: ['../src/lib/registry/new-york/example/TabsDemo.vue'],
|
files: ['../src/lib/registry/new-york/example/TabsDemo.vue'],
|
||||||
},
|
},
|
||||||
TagsInputComboDemo: {
|
TagsInputComboboxDemo: {
|
||||||
name: 'TagsInputComboDemo',
|
name: 'TagsInputComboboxDemo',
|
||||||
type: 'components:example',
|
type: 'components:example',
|
||||||
registryDependencies: ['utils', 'button', 'command', 'popover', 'tags-input'],
|
registryDependencies: ['command', 'tags-input'],
|
||||||
component: () => import('../src/lib/registry/new-york/example/TagsInputComboDemo.vue').then(m => m.default),
|
component: () => import('../src/lib/registry/new-york/example/TagsInputComboboxDemo.vue').then(m => m.default),
|
||||||
files: ['../src/lib/registry/new-york/example/TagsInputComboDemo.vue'],
|
files: ['../src/lib/registry/new-york/example/TagsInputComboboxDemo.vue'],
|
||||||
},
|
},
|
||||||
TagsInputDemo: {
|
TagsInputDemo: {
|
||||||
name: 'TagsInputDemo',
|
name: 'TagsInputDemo',
|
||||||
|
|
|
||||||
|
|
@ -18,4 +18,4 @@ npx shadcn-vue@latest add tags-input
|
||||||
|
|
||||||
### Multiple Combobox
|
### Multiple Combobox
|
||||||
|
|
||||||
<ComponentPreview name="TagsInputComboDemo" />
|
<ComponentPreview name="TagsInputComboboxDemo" />
|
||||||
|
|
|
||||||
|
|
@ -1,74 +0,0 @@
|
||||||
<script setup lang="ts">
|
|
||||||
import { ref } from 'vue'
|
|
||||||
import { Check, ChevronsUpDown } from 'lucide-vue-next'
|
|
||||||
|
|
||||||
import { cn } from '@/lib/utils'
|
|
||||||
import { Button } from '@/lib/registry/default/ui/button'
|
|
||||||
import {
|
|
||||||
Command,
|
|
||||||
CommandEmpty,
|
|
||||||
CommandGroup,
|
|
||||||
CommandInput,
|
|
||||||
CommandItem,
|
|
||||||
CommandList,
|
|
||||||
} from '@/lib/registry/default/ui/command'
|
|
||||||
import {
|
|
||||||
Popover,
|
|
||||||
PopoverContent,
|
|
||||||
PopoverTrigger,
|
|
||||||
} from '@/lib/registry/default/ui/popover'
|
|
||||||
import { TagsInput, TagsInputItem, TagsInputItemDelete, TagsInputItemText } from '@/lib/registry/default/ui/tags-input'
|
|
||||||
|
|
||||||
const frameworks = [
|
|
||||||
{ value: 'next.js', label: 'Next.js' },
|
|
||||||
{ value: 'sveltekit', label: 'SvelteKit' },
|
|
||||||
{ value: 'nuxt.js', label: 'Nuxt.js' },
|
|
||||||
{ value: 'remix', label: 'Remix' },
|
|
||||||
{ value: 'astro', label: 'Astro' },
|
|
||||||
]
|
|
||||||
|
|
||||||
const open = ref(false)
|
|
||||||
const value = ref([])
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<Popover v-model:open="open">
|
|
||||||
<PopoverTrigger as-child>
|
|
||||||
<Button
|
|
||||||
variant="outline"
|
|
||||||
role="combobox"
|
|
||||||
:aria-expanded="open"
|
|
||||||
class="w-[200px] justify-between"
|
|
||||||
>
|
|
||||||
qwe
|
|
||||||
<ChevronsUpDown class="ml-2 h-4 w-4 shrink-0 opacity-50" />
|
|
||||||
</Button>
|
|
||||||
</PopoverTrigger>
|
|
||||||
<PopoverContent class="w-[200px] p-0">
|
|
||||||
<Command>
|
|
||||||
<CommandInput class="h-9" placeholder="Search framework..." />
|
|
||||||
<CommandEmpty>No framework found.</CommandEmpty>
|
|
||||||
<CommandList>
|
|
||||||
<CommandGroup>
|
|
||||||
<CommandItem
|
|
||||||
v-for="framework in frameworks"
|
|
||||||
:key="framework.value"
|
|
||||||
:value="framework"
|
|
||||||
@select="(ev) => {
|
|
||||||
console.log(ev.detail.value)
|
|
||||||
// if (typeof ev.detail.value === 'string') {
|
|
||||||
// value = ev.detail.value
|
|
||||||
// }
|
|
||||||
open = true
|
|
||||||
}"
|
|
||||||
>
|
|
||||||
{{ framework.label }}
|
|
||||||
<!-- <Check
|
|
||||||
/> -->
|
|
||||||
</CommandItem>
|
|
||||||
</CommandGroup>
|
|
||||||
</CommandList>
|
|
||||||
</Command>
|
|
||||||
</PopoverContent>
|
|
||||||
</Popover>
|
|
||||||
</template>
|
|
||||||
|
|
@ -0,0 +1,58 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { computed, ref } from 'vue'
|
||||||
|
import { ComboboxAnchor, ComboboxInput, ComboboxPortal, ComboboxRoot } from 'radix-vue'
|
||||||
|
import { CommandGroup, CommandItem, CommandList } from '@/lib/registry/default/ui/command'
|
||||||
|
import { TagsInput, TagsInputInput, TagsInputItem, TagsInputItemDelete, TagsInputItemText } from '@/lib/registry/default/ui/tags-input'
|
||||||
|
|
||||||
|
const frameworks = [
|
||||||
|
{ value: 'next.js', label: 'Next.js' },
|
||||||
|
{ value: 'sveltekit', label: 'SvelteKit' },
|
||||||
|
{ value: 'nuxt.js', label: 'Nuxt.js' },
|
||||||
|
{ value: 'remix', label: 'Remix' },
|
||||||
|
{ value: 'astro', label: 'Astro' },
|
||||||
|
]
|
||||||
|
|
||||||
|
const modelValue = ref<string[]>([])
|
||||||
|
const open = ref(false)
|
||||||
|
const searchTerm = ref('')
|
||||||
|
|
||||||
|
const filteredFrameworks = computed(() => frameworks.filter(i => !modelValue.value.includes(i.label)))
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<TagsInput :model-value="modelValue">
|
||||||
|
<TagsInputItem v-for="item in modelValue" :key="item" :value="item">
|
||||||
|
<TagsInputItemText />
|
||||||
|
<TagsInputItemDelete />
|
||||||
|
</TagsInputItem>
|
||||||
|
|
||||||
|
<ComboboxRoot v-model="modelValue" v-model:open="open" v-model:searchTerm="searchTerm">
|
||||||
|
<ComboboxAnchor>
|
||||||
|
<ComboboxInput placeholder="Framework..." as-child>
|
||||||
|
<TagsInputInput @keydown.enter.prevent />
|
||||||
|
</ComboboxInput>
|
||||||
|
</ComboboxAnchor>
|
||||||
|
|
||||||
|
<ComboboxPortal>
|
||||||
|
<CommandList :position="'popper'" class="w-48 rounded-md mt-2 border bg-popover text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2">
|
||||||
|
<CommandGroup>
|
||||||
|
<CommandItem
|
||||||
|
v-for="framework in filteredFrameworks"
|
||||||
|
:key="framework.value"
|
||||||
|
:value="framework.label"
|
||||||
|
@select.prevent="(ev) => {
|
||||||
|
if (typeof ev.detail.value === 'string') {
|
||||||
|
searchTerm = ''
|
||||||
|
modelValue.push(ev.detail.value)
|
||||||
|
open = false
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
{{ framework.label }}
|
||||||
|
</CommandItem>
|
||||||
|
</CommandGroup>
|
||||||
|
</CommandList>
|
||||||
|
</ComboboxPortal>
|
||||||
|
</ComboboxRoot>
|
||||||
|
</TagsInput>
|
||||||
|
</template>
|
||||||
|
|
@ -1,73 +0,0 @@
|
||||||
<script setup lang="ts">
|
|
||||||
import { ref } from 'vue'
|
|
||||||
import { Check, ChevronsUpDown } from 'lucide-vue-next'
|
|
||||||
|
|
||||||
import { cn } from '@/lib/utils'
|
|
||||||
import { Button } from '@/lib/registry/default/ui/button'
|
|
||||||
import {
|
|
||||||
Command,
|
|
||||||
CommandEmpty,
|
|
||||||
CommandGroup,
|
|
||||||
CommandInput,
|
|
||||||
CommandItem,
|
|
||||||
CommandList,
|
|
||||||
} from '@/lib/registry/default/ui/command'
|
|
||||||
import {
|
|
||||||
Popover,
|
|
||||||
PopoverContent,
|
|
||||||
PopoverTrigger,
|
|
||||||
} from '@/lib/registry/default/ui/popover'
|
|
||||||
import { TagsInput, TagsInputItem, TagsInputItemDelete, TagsInputItemText } from '@/lib/registry/default/ui/tags-input'
|
|
||||||
|
|
||||||
const frameworks = [
|
|
||||||
{ value: 'next.js', label: 'Next.js' },
|
|
||||||
{ value: 'sveltekit', label: 'SvelteKit' },
|
|
||||||
{ value: 'nuxt.js', label: 'Nuxt.js' },
|
|
||||||
{ value: 'remix', label: 'Remix' },
|
|
||||||
{ value: 'astro', label: 'Astro' },
|
|
||||||
]
|
|
||||||
|
|
||||||
const open = ref(false)
|
|
||||||
const value = ref([])
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<template>
|
|
||||||
<Popover v-model:open="open">
|
|
||||||
<PopoverTrigger as-child>
|
|
||||||
<Button
|
|
||||||
variant="outline"
|
|
||||||
role="combobox"
|
|
||||||
:aria-expanded="open"
|
|
||||||
class="w-[200px] justify-between"
|
|
||||||
>
|
|
||||||
qwe
|
|
||||||
<ChevronsUpDown class="ml-2 h-4 w-4 shrink-0 opacity-50" />
|
|
||||||
</Button>
|
|
||||||
</PopoverTrigger>
|
|
||||||
<PopoverContent class="w-[200px] p-0">
|
|
||||||
<Command>
|
|
||||||
<CommandInput class="h-9" placeholder="Search framework..." />
|
|
||||||
<CommandEmpty>No framework found.</CommandEmpty>
|
|
||||||
<CommandList>
|
|
||||||
<CommandGroup>
|
|
||||||
<CommandItem
|
|
||||||
v-for="framework in frameworks"
|
|
||||||
:key="framework.value"
|
|
||||||
:value="frameworks"
|
|
||||||
@select="(ev) => {
|
|
||||||
// if (typeof ev.detail.value === 'string') {
|
|
||||||
// value = ev.detail.value
|
|
||||||
// }
|
|
||||||
open = false
|
|
||||||
}"
|
|
||||||
>
|
|
||||||
{{ framework.label }}
|
|
||||||
<!-- <Check
|
|
||||||
/> -->
|
|
||||||
</CommandItem>
|
|
||||||
</CommandGroup>
|
|
||||||
</CommandList>
|
|
||||||
</Command>
|
|
||||||
</PopoverContent>
|
|
||||||
</Popover>
|
|
||||||
</template>
|
|
||||||
|
|
@ -0,0 +1,58 @@
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { computed, ref } from 'vue'
|
||||||
|
import { ComboboxAnchor, ComboboxInput, ComboboxPortal, ComboboxRoot } from 'radix-vue'
|
||||||
|
import { CommandGroup, CommandItem, CommandList } from '@/lib/registry/new-york/ui/command'
|
||||||
|
import { TagsInput, TagsInputInput, TagsInputItem, TagsInputItemDelete, TagsInputItemText } from '@/lib/registry/new-york/ui/tags-input'
|
||||||
|
|
||||||
|
const frameworks = [
|
||||||
|
{ value: 'next.js', label: 'Next.js' },
|
||||||
|
{ value: 'sveltekit', label: 'SvelteKit' },
|
||||||
|
{ value: 'nuxt.js', label: 'Nuxt.js' },
|
||||||
|
{ value: 'remix', label: 'Remix' },
|
||||||
|
{ value: 'astro', label: 'Astro' },
|
||||||
|
]
|
||||||
|
|
||||||
|
const modelValue = ref<string[]>([])
|
||||||
|
const open = ref(false)
|
||||||
|
const searchTerm = ref('')
|
||||||
|
|
||||||
|
const filteredFrameworks = computed(() => frameworks.filter(i => !modelValue.value.includes(i.label)))
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<TagsInput :model-value="modelValue">
|
||||||
|
<TagsInputItem v-for="item in modelValue" :key="item" :value="item">
|
||||||
|
<TagsInputItemText />
|
||||||
|
<TagsInputItemDelete />
|
||||||
|
</TagsInputItem>
|
||||||
|
|
||||||
|
<ComboboxRoot v-model="modelValue" v-model:open="open" v-model:searchTerm="searchTerm">
|
||||||
|
<ComboboxAnchor>
|
||||||
|
<ComboboxInput placeholder="Framework..." as-child>
|
||||||
|
<TagsInputInput @keydown.enter.prevent />
|
||||||
|
</ComboboxInput>
|
||||||
|
</ComboboxAnchor>
|
||||||
|
|
||||||
|
<ComboboxPortal>
|
||||||
|
<CommandList :position="'popper'" class="w-48 rounded-md mt-2 border bg-popover text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2">
|
||||||
|
<CommandGroup>
|
||||||
|
<CommandItem
|
||||||
|
v-for="framework in filteredFrameworks"
|
||||||
|
:key="framework.value"
|
||||||
|
:value="framework.label"
|
||||||
|
@select.prevent="(ev) => {
|
||||||
|
if (typeof ev.detail.value === 'string') {
|
||||||
|
searchTerm = ''
|
||||||
|
modelValue.push(ev.detail.value)
|
||||||
|
open = false
|
||||||
|
}
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
{{ framework.label }}
|
||||||
|
</CommandItem>
|
||||||
|
</CommandGroup>
|
||||||
|
</CommandList>
|
||||||
|
</ComboboxPortal>
|
||||||
|
</ComboboxRoot>
|
||||||
|
</TagsInput>
|
||||||
|
</template>
|
||||||
Loading…
Reference in New Issue
Block a user