Acronis UIKit
Legacy (shadcn-uikit)Components

Combobox

A searchable dropdown for selecting from a list of options.

Usage

import { Combobox } from '@acronis-platform/shadcn-uikit';

Basic

A basic searchable select dropdown.

View source
import * as React from 'react';
import { cn } from '@acronis-platform/shadcn-uikit/react';
import { Button } from '@acronis-platform/shadcn-uikit/react';
import {
  Command,
  CommandEmpty,
  CommandGroup,
  CommandInput,
  CommandItem,
  CommandList,
} from '@acronis-platform/shadcn-uikit/react';
import {
  Popover,
  PopoverContent,
  PopoverTrigger,
} from '@acronis-platform/shadcn-uikit/react';

import { CheckIcon, ChevronUpdownIcon } from '@acronis-platform/shadcn-uikit';
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' },
  { value: 'react', label: 'React' },
  { value: 'vue', label: 'Vue' },
  { value: 'angular', label: 'Angular' },
];

export function ComboboxBasic() {
  const [open, setOpen] = React.useState(false);
  const [value, setValue] = React.useState('');

  return (
    <Popover open={open} onOpenChange={setOpen}>
      <PopoverTrigger
        render={
          <Button
            variant="outline"
            role="combobox"
            aria-expanded={open}
            className="w-[280px] justify-between"
          />
        }
      >
        {value
          ? frameworks.find((framework) => framework.value === value)?.label
          : 'Select framework...'}
        <ChevronUpdownIcon className="ml-2 h-4 w-4 shrink-0 opacity-50" />
      </PopoverTrigger>
      <PopoverContent className="w-[280px] 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) => {
                    setValue(currentValue === value ? '' : currentValue);
                    setOpen(false);
                  }}
                >
                  <CheckIcon
                    className={cn(
                      'mr-2 h-4 w-4',
                      value === framework.value ? 'opacity-100' : 'opacity-0'
                    )}
                  />
                  {framework.label}
                </CommandItem>
              ))}
            </CommandGroup>
          </CommandList>
        </Command>
      </PopoverContent>
    </Popover>
  );
}

Widths

Combobox with different width configurations.

View source
import * as React from 'react';
import { cn } from '@acronis-platform/shadcn-uikit/react';
import { Button } from '@acronis-platform/shadcn-uikit/react';
import {
  Command,
  CommandEmpty,
  CommandGroup,
  CommandInput,
  CommandItem,
  CommandList,
} from '@acronis-platform/shadcn-uikit/react';
import {
  Popover,
  PopoverContent,
  PopoverTrigger,
} from '@acronis-platform/shadcn-uikit/react';

import { CheckIcon, ChevronUpdownIcon } from '@acronis-platform/shadcn-uikit';
const languages = [
  { value: 'javascript', label: 'JavaScript' },
  { value: 'typescript', label: 'TypeScript' },
  { value: 'python', label: 'Python' },
  { value: 'java', label: 'Java' },
  { value: 'csharp', label: 'C#' },
  { value: 'go', label: 'Go' },
  { value: 'rust', label: 'Rust' },
  { value: 'php', label: 'PHP' },
];

const countries = [
  { value: 'us', label: 'United States' },
  { value: 'uk', label: 'United Kingdom' },
  { value: 'ca', label: 'Canada' },
  { value: 'au', label: 'Australia' },
  { value: 'de', label: 'Germany' },
  { value: 'fr', label: 'France' },
  { value: 'jp', label: 'Japan' },
  { value: 'cn', label: 'China' },
];

export function ComboboxWidths() {
  const [languageOpen, setLanguageOpen] = React.useState(false);
  const [languageValue, setLanguageValue] = React.useState('');

  const [countryOpen, setCountryOpen] = React.useState(false);
  const [countryValue, setCountryValue] = React.useState('');

  return (
    <div className="flex flex-wrap gap-4">
      <Popover open={languageOpen} onOpenChange={setLanguageOpen}>
        <PopoverTrigger
          render={
            <Button
              variant="outline"
              role="combobox"
              aria-expanded={languageOpen}
              className="w-[200px] justify-between"
            />
          }
        >
          {languageValue
            ? languages.find((lang) => lang.value === languageValue)?.label
            : 'Select language...'}
          <ChevronUpdownIcon className="ml-2 h-4 w-4 shrink-0 opacity-50" />
        </PopoverTrigger>
        <PopoverContent className="w-[200px] p-0">
          <Command>
            <CommandInput placeholder="Search language..." />
            <CommandList>
              <CommandEmpty>No language found.</CommandEmpty>
              <CommandGroup>
                {languages.map((lang) => (
                  <CommandItem
                    key={lang.value}
                    value={lang.value}
                    onSelect={(currentValue) => {
                      setLanguageValue(
                        currentValue === languageValue ? '' : currentValue
                      );
                      setLanguageOpen(false);
                    }}
                  >
                    <CheckIcon
                      className={cn(
                        'mr-2 h-4 w-4',
                        languageValue === lang.value
                          ? 'opacity-100'
                          : 'opacity-0'
                      )}
                    />
                    {lang.label}
                  </CommandItem>
                ))}
              </CommandGroup>
            </CommandList>
          </Command>
        </PopoverContent>
      </Popover>

      <Popover open={countryOpen} onOpenChange={setCountryOpen}>
        <PopoverTrigger
          render={
            <Button
              variant="outline"
              role="combobox"
              aria-expanded={countryOpen}
              className="w-[320px] justify-between"
            />
          }
        >
          {countryValue
            ? countries.find((country) => country.value === countryValue)?.label
            : 'Select country...'}
          <ChevronUpdownIcon className="ml-2 h-4 w-4 shrink-0 opacity-50" />
        </PopoverTrigger>
        <PopoverContent className="w-[320px] p-0">
          <Command>
            <CommandInput placeholder="Search country..." />
            <CommandList>
              <CommandEmpty>No country found.</CommandEmpty>
              <CommandGroup>
                {countries.map((country) => (
                  <CommandItem
                    key={country.value}
                    value={country.value}
                    onSelect={(currentValue) => {
                      setCountryValue(
                        currentValue === countryValue ? '' : currentValue
                      );
                      setCountryOpen(false);
                    }}
                  >
                    <CheckIcon
                      className={cn(
                        'mr-2 h-4 w-4',
                        countryValue === country.value
                          ? 'opacity-100'
                          : 'opacity-0'
                      )}
                    />
                    {country.label}
                  </CommandItem>
                ))}
              </CommandGroup>
            </CommandList>
          </Command>
        </PopoverContent>
      </Popover>
    </div>
  );
}

Small

A compact combobox variant for tighter layouts.

View source
import * as React from 'react';
import { cn } from '@acronis-platform/shadcn-uikit/react';
import { Button } from '@acronis-platform/shadcn-uikit/react';
import {
  Command,
  CommandEmpty,
  CommandGroup,
  CommandInput,
  CommandItem,
  CommandList,
} from '@acronis-platform/shadcn-uikit/react';
import {
  Popover,
  PopoverContent,
  PopoverTrigger,
} from '@acronis-platform/shadcn-uikit/react';

import { CheckIcon, ChevronUpdownIcon } from '@acronis-platform/shadcn-uikit';
const statuses = [
  { value: 'active', label: 'Active' },
  { value: 'inactive', label: 'Inactive' },
  { value: 'pending', label: 'Pending' },
  { value: 'archived', label: 'Archived' },
];

export function ComboboxSmall() {
  const [open, setOpen] = React.useState(false);
  const [value, setValue] = React.useState('');

  return (
    <Popover open={open} onOpenChange={setOpen}>
      <PopoverTrigger
        render={
          <Button
            variant="outline"
            role="combobox"
            aria-expanded={open}
            className="h-8 w-[200px] justify-between text-sm"
          />
        }
      >
        {value
          ? statuses.find((status) => status.value === value)?.label
          : 'Select status...'}
        <ChevronUpdownIcon className="ml-2 h-3 w-3 shrink-0 opacity-50" />
      </PopoverTrigger>
      <PopoverContent className="w-[200px] p-0">
        <Command>
          <CommandInput placeholder="Search status..." className="h-8" />
          <CommandList>
            <CommandEmpty>No status found.</CommandEmpty>
            <CommandGroup>
              {statuses.map((status) => (
                <CommandItem
                  key={status.value}
                  value={status.value}
                  onSelect={(currentValue) => {
                    setValue(currentValue === value ? '' : currentValue);
                    setOpen(false);
                  }}
                >
                  <CheckIcon
                    className={cn(
                      'mr-2 h-3 w-3',
                      value === status.value ? 'opacity-100' : 'opacity-0'
                    )}
                  />
                  {status.label}
                </CommandItem>
              ))}
            </CommandGroup>
          </CommandList>
        </Command>
      </PopoverContent>
    </Popover>
  );
}

In a form

Combobox integrated with form validation.

Choose the framework you want to use for your project.

Select your preferred programming language.

View source
import * as React from 'react';
import { cn } from '@acronis-platform/shadcn-uikit/react';
import { Button } from '@acronis-platform/shadcn-uikit/react';
import {
  Command,
  CommandEmpty,
  CommandGroup,
  CommandInput,
  CommandItem,
  CommandList,
} from '@acronis-platform/shadcn-uikit/react';
import {
  Popover,
  PopoverContent,
  PopoverTrigger,
} from '@acronis-platform/shadcn-uikit/react';

import { CheckIcon, ChevronUpdownIcon } from '@acronis-platform/shadcn-uikit';
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' },
  { value: 'react', label: 'React' },
  { value: 'vue', label: 'Vue' },
  { value: 'angular', label: 'Angular' },
];

const languages = [
  { value: 'javascript', label: 'JavaScript' },
  { value: 'typescript', label: 'TypeScript' },
  { value: 'python', label: 'Python' },
  { value: 'java', label: 'Java' },
  { value: 'csharp', label: 'C#' },
  { value: 'go', label: 'Go' },
  { value: 'rust', label: 'Rust' },
  { value: 'php', label: 'PHP' },
];

export function ComboboxForm() {
  const [frameworkOpen, setFrameworkOpen] = React.useState(false);
  const [frameworkValue, setFrameworkValue] = React.useState('');

  return (
    <div className="max-w-md space-y-4 rounded-lg border p-6">
      <div className="space-y-2">
        <label htmlFor="framework-select" className="text-sm font-medium">
          Framework
        </label>
        <Popover open={frameworkOpen} onOpenChange={setFrameworkOpen}>
          <PopoverTrigger
            render={
              <Button
                id="framework-select"
                variant="outline"
                role="combobox"
                aria-expanded={frameworkOpen}
                className="w-full justify-between"
              />
            }
          >
            {frameworkValue
              ? frameworks.find(
                  (framework) => framework.value === frameworkValue
                )?.label
              : 'Select framework...'}
            <ChevronUpdownIcon className="ml-2 h-4 w-4 shrink-0 opacity-50" />
          </PopoverTrigger>
          <PopoverContent className="w-full 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) => {
                        setFrameworkValue(
                          currentValue === frameworkValue ? '' : currentValue
                        );
                        setFrameworkOpen(false);
                      }}
                    >
                      <CheckIcon
                        className={cn(
                          'mr-2 h-4 w-4',
                          frameworkValue === framework.value
                            ? 'opacity-100'
                            : 'opacity-0'
                        )}
                      />
                      {framework.label}
                    </CommandItem>
                  ))}
                </CommandGroup>
              </CommandList>
            </Command>
          </PopoverContent>
        </Popover>
        <p className="text-sm text-gray-500">
          Choose the framework you want to use for your project.
        </p>
      </div>

      <div className="space-y-2">
        <label htmlFor="language-select" className="text-sm font-medium">
          Programming Language
        </label>
        <Popover>
          <PopoverTrigger
            render={
              <Button
                id="language-select"
                variant="outline"
                role="combobox"
                className="w-full justify-between"
              />
            }
          >
            Select language...
            <ChevronUpdownIcon className="ml-2 h-4 w-4 shrink-0 opacity-50" />
          </PopoverTrigger>
          <PopoverContent className="w-full p-0">
            <Command>
              <CommandInput placeholder="Search language..." />
              <CommandList>
                <CommandEmpty>No language found.</CommandEmpty>
                <CommandGroup>
                  {languages.map((lang) => (
                    <CommandItem key={lang.value} value={lang.value}>
                      <CheckIcon className="mr-2 h-4 w-4 opacity-0" />
                      {lang.label}
                    </CommandItem>
                  ))}
                </CommandGroup>
              </CommandList>
            </Command>
          </PopoverContent>
        </Popover>
        <p className="text-sm text-gray-500">
          Select your preferred programming language.
        </p>
      </div>
    </div>
  );
}

Disabled state

A disabled combobox that cannot be interacted with.

View source
import { Button } from '@acronis-platform/shadcn-uikit/react';

import { ChevronUpdownIcon } from '@acronis-platform/shadcn-uikit';
export function ComboboxDisabled() {
  return (
    <Button
      variant="outline"
      role="combobox"
      disabled
      className="w-[280px] justify-between"
    >
      Select framework...
      <ChevronUpdownIcon className="ml-2 h-4 w-4 shrink-0 opacity-50" />
    </Button>
  );
}

API Reference

The Combobox is a composition of Command and Popover primitives. It does not export a standalone component with its own Props interface. See the source code for implementation patterns using Command, CommandInput, CommandList, CommandItem, Popover, PopoverTrigger, and PopoverContent.

Edit on GitHub

On this page