Component Library
Browse and explore components
Combobox
A Combobox is a UI component that combines a text input with a dropdown list of selectable options.
Basic Combobox
Component Code
Copy Code
import React from 'react'
import { Check, ChevronsUpDown } from 'lucide-react'
import { cn } from '@/lib/utils'
import { Button } from '@/components/ui/button'
import {
Command,
CommandEmpty,
CommandGroup,
CommandInput,
CommandItem,
CommandList,
} from '@/components/ui/command'
import {
Popover,
PopoverContent,
PopoverTrigger,
} from '@/components/ui/popover'
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 BasicComboboxCode = () => {
const [open, setOpen] = React.useState(false)
const [value, setValue] = React.useState('')
return (
<>
<div className='flex flex-wrap items-center gap-3 mt-4 max-w-sm'>
<Popover open={open} onOpenChange={setOpen}>
<PopoverTrigger asChild>
<Button
variant='outline'
role='combobox'
aria-expanded={open}
className='w-full justify-between'>
{value
? frameworks.find((framework) => framework.value === value)
?.label
: 'Select framework...'}
<ChevronsUpDown className='opacity-50' />
</Button>
</PopoverTrigger>
<PopoverContent className=' p-0 '>
<Command>
<CommandInput placeholder='Search framework...' />
<CommandList>
<CommandEmpty>No framework found.</CommandEmpty>
<CommandGroup>
{frameworks.map((framework) => (
<CommandItem
key={framework.value}
value={framework.value}
onSelect={(
currentValue: React.SetStateAction<string>
) => {
setValue(currentValue === value ? '' : currentValue)
setOpen(false)
}}>
{framework.label}
<Check
className={cn(
'ml-auto',
value === framework.value
? 'opacity-100'
: 'opacity-0'
)}
/>
</CommandItem>
))}
</CommandGroup>
</CommandList>
</Command>
</PopoverContent>
</Popover>
</div>
</>
)
}
export default BasicComboboxCode
Popover Combobox
Status
Component Code
Copy Code
import React from 'react'
import {
ArrowUpCircle,
CheckCircle2,
Circle,
HelpCircle,
LucideIcon,
XCircle,
} from 'lucide-react'
import { cn } from '@/lib/utils'
import { Button } from '@/components/ui/button'
import {
Command,
CommandEmpty,
CommandGroup,
CommandInput,
CommandItem,
CommandList,
} from '@/components/ui/command'
import {
Popover,
PopoverContent,
PopoverTrigger,
} from '@/components/ui/popover'
type Status = {
value: string
label: string
icon: LucideIcon
}
const statuses: Status[] = [
{
value: 'backlog',
label: 'Backlog',
icon: HelpCircle,
},
{
value: 'todo',
label: 'Todo',
icon: Circle,
},
{
value: 'in progress',
label: 'In Progress',
icon: ArrowUpCircle,
},
{
value: 'done',
label: 'Done',
icon: CheckCircle2,
},
{
value: 'canceled',
label: 'Canceled',
icon: XCircle,
},
]
const PopovercomboCode = () => {
const [open, setOpen] = React.useState(false)
const [selectedStatus, setSelectedStatus] = React.useState<Status | null>(
null
)
return (
<>
<div className='flex items-center gap-3 mt-4 max-w-sm'>
<p className='text-sm text-ld'>Status</p>
<Popover open={open} onOpenChange={setOpen}>
<PopoverTrigger asChild>
<Button
variant='outline'
size='sm'
className='w-full justify-start'>
{selectedStatus ? (
<>
<selectedStatus.icon className='mr-2 h-4 w-4 shrink-0' />
{selectedStatus.label}
</>
) : (
<>+ Set status</>
)}
</Button>
</PopoverTrigger>
<PopoverContent className='p-0' side='right' align='start'>
<Command>
<CommandInput placeholder='Change status...' />
<CommandList>
<CommandEmpty>No results found.</CommandEmpty>
<CommandGroup>
{statuses.map((status) => (
<CommandItem
key={status.value}
value={status.value}
onSelect={(value: string) => {
setSelectedStatus(
statuses.find(
(priority) => priority.value === value
) || null
)
setOpen(false)
}}>
<status.icon
className={cn(
'mr-2 h-4 w-4',
status.value === selectedStatus?.value
? 'opacity-100'
: 'opacity-40'
)}
/>
<span>{status.label}</span>
</CommandItem>
))}
</CommandGroup>
</CommandList>
</Command>
</PopoverContent>
</Popover>
</div>
</>
)
}
export default PopovercomboCode
Dropdown Combobox
feature
Component Code
Copy Code
import { SetStateAction, useState } from 'react'
import { Calendar, MoreHorizontal, Tags, Trash, User } from 'lucide-react'
import { Button } from '@/components/ui/button'
import {
Command,
CommandEmpty,
CommandGroup,
CommandInput,
CommandItem,
CommandList,
} from '@/components/ui/command'
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuGroup,
DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuSeparator,
DropdownMenuShortcut,
DropdownMenuSub,
DropdownMenuSubContent,
DropdownMenuSubTrigger,
DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu'
const labels = [
'feature',
'bug',
'enhancement',
'documentation',
'design',
'question',
'maintenance',
]
const DropdownComboCode = () => {
const [label, setLabel] = useState('feature')
const [open, setOpen] = useState(false)
return (
<>
<div>
<div className='flex flex-col items-start justify-between rounded-md border border-ld px-2 mt-4 sm:flex-row sm:items-center max-w-sm'>
<p className='text-sm font-medium leading-none'>
<span className='mr-2 rounded-lg bg-primary px-2 py-1 text-xs text-white'>
{label}
</span>
</p>
<DropdownMenu open={open} onOpenChange={setOpen}>
<DropdownMenuTrigger asChild>
<Button variant='ghost' size='sm'>
<MoreHorizontal />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align='end' className='w-[200px]'>
<DropdownMenuLabel>Actions</DropdownMenuLabel>
<DropdownMenuGroup>
<DropdownMenuItem>
<User />
Assign to...
</DropdownMenuItem>
<DropdownMenuItem>
<Calendar />
Set due date...
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuSub>
<DropdownMenuSubTrigger>
<Tags />
Apply label
</DropdownMenuSubTrigger>
<DropdownMenuSubContent className='p-0'>
<Command>
<CommandInput
placeholder='Filter label...'
autoFocus={true}
/>
<CommandList>
<CommandEmpty>No label found.</CommandEmpty>
<CommandGroup>
{labels.map((label) => (
<CommandItem
key={label}
value={label}
onSelect={(value: SetStateAction<string>) => {
setLabel(value)
setOpen(false)
}}>
{label}
</CommandItem>
))}
</CommandGroup>
</CommandList>
</Command>
</DropdownMenuSubContent>
</DropdownMenuSub>
<DropdownMenuSeparator />
<DropdownMenuItem className='text-error'>
<Trash />
Delete
<DropdownMenuShortcut>⌘⌫</DropdownMenuShortcut>
</DropdownMenuItem>
</DropdownMenuGroup>
</DropdownMenuContent>
</DropdownMenu>
</div>
</div>
</>
)
}
export default DropdownComboCode
Form Combobox
Component Code
Copy Code
'use client'
import { zodResolver } from '@hookform/resolvers/zod'
import { Check, ChevronsUpDown } from 'lucide-react'
import { useForm } from 'react-hook-form'
import { z } from 'zod'
import { cn } from '@/lib/utils'
import { toast } from '@/app/hooks/use-toast'
import { Button } from '@/components/ui/button'
import {
Command,
CommandEmpty,
CommandGroup,
CommandInput,
CommandItem,
CommandList,
} from '@/components/ui/command'
import {
Form,
FormControl,
FormDescription,
FormField,
FormItem,
FormLabel,
FormMessage,
} from '@/components/ui/form'
import {
Popover,
PopoverContent,
PopoverTrigger,
} from '@/components/ui/popover'
const languages = [
{ label: 'English', value: 'en' },
{ label: 'French', value: 'fr' },
{ label: 'German', value: 'de' },
{ label: 'Spanish', value: 'es' },
{ label: 'Portuguese', value: 'pt' },
{ label: 'Russian', value: 'ru' },
{ label: 'Japanese', value: 'ja' },
{ label: 'Korean', value: 'ko' },
{ label: 'Chinese', value: 'zh' },
] as const
const FormSchema = z.object({
language: z.string().min(1, 'Please select a language.'),
})
const FormComboCode = () => {
const form = useForm<z.infer<typeof FormSchema>>({
resolver: zodResolver(FormSchema),
})
function onSubmit(data: z.infer<typeof FormSchema>) {
toast({
title: 'You submitted the following values:',
description: (
<pre className='mt-2 w-[340px] rounded-md bg-slate-950 p-4'>
<code className='text-white'>{JSON.stringify(data, null, 2)}</code>
</pre>
),
})
}
return (
<>
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className='space-y-6'>
<FormField
control={form.control}
name='language'
render={({ field }) => (
<FormItem className='flex flex-col'>
<FormLabel>Language</FormLabel>
<Popover>
<PopoverTrigger asChild>
<FormControl>
<Button
variant='outline'
role='combobox'
className={cn(
'w-full justify-between',
!field.value && 'text-muted-foreground'
)}>
{field.value
? languages.find(
(language) => language.value === field.value
)?.label
: 'Select language'}
<ChevronsUpDown className='ml-2 h-4 w-4 shrink-0 opacity-50' />
</Button>
</FormControl>
</PopoverTrigger>
<PopoverContent className='w-full p-0'>
<Command>
<CommandInput placeholder='Search language...' />
<CommandList>
<CommandEmpty>No language found.</CommandEmpty>
<CommandGroup>
{languages.map((language) => (
<CommandItem
value={language.label}
key={language.value}
onSelect={() => {
form.setValue('language', language.value)
}}>
{language.label}
<Check
className={cn(
'ml-auto',
language.value === field.value
? 'opacity-100'
: 'opacity-0'
)}
/>
</CommandItem>
))}
</CommandGroup>
</CommandList>
</Command>
</PopoverContent>
</Popover>
<FormDescription>
This is the language that will be used in the dashboard.
</FormDescription>
<FormMessage />
</FormItem>
)}
/>
<Button type='submit'>Submit</Button>
</form>
</Form>
</>
)
}
export default FormComboCode