Combobox

Enables users to pick from a list of options displayed in a dropdown.

llms.txt
	<script lang="ts">
  import { Combobox } from "bits-ui";
  import CaretUpDown from "phosphor-svelte/lib/CaretUpDown";
  import Check from "phosphor-svelte/lib/Check";
  import OrangeSlice from "phosphor-svelte/lib/OrangeSlice";
  import CaretDoubleUp from "phosphor-svelte/lib/CaretDoubleUp";
  import CaretDoubleDown from "phosphor-svelte/lib/CaretDoubleDown";
 
  const fruits = [
    { value: "mango", label: "Mango" },
    { value: "watermelon", label: "Watermelon" },
    { value: "apple", label: "Apple" },
    { value: "pineapple", label: "Pineapple" },
    { value: "orange", label: "Orange" },
    { value: "grape", label: "Grape" },
    { value: "strawberry", label: "Strawberry" },
    { value: "banana", label: "Banana" },
    { value: "kiwi", label: "Kiwi" },
    { value: "peach", label: "Peach" },
    { value: "cherry", label: "Cherry" },
    { value: "blueberry", label: "Blueberry" },
    { value: "raspberry", label: "Raspberry" },
    { value: "blackberry", label: "Blackberry" },
    { value: "plum", label: "Plum" },
    { value: "apricot", label: "Apricot" },
    { value: "pear", label: "Pear" },
    { value: "grapefruit", label: "Grapefruit" }
  ];
 
  let searchValue = $state("");
 
  const filteredFruits = $derived(
    searchValue === ""
      ? fruits
      : fruits.filter((fruit) =>
          fruit.label.toLowerCase().includes(searchValue.toLowerCase())
        )
  );
</script>
 
<Combobox.Root
  type="multiple"
  name="favoriteFruit"
  onOpenChange={(o) => {
    if (!o) searchValue = "";
  }}
>
  <div class="relative">
    <OrangeSlice
      class="text-muted-foreground absolute start-3 top-1/2 size-6 -translate-y-1/2"
    />
    <Combobox.Input
      oninput={(e) => (searchValue = e.currentTarget.value)}
      class="h-input rounded-9px border-border-input bg-background placeholder:text-foreground-alt/50 focus:ring-foreground focus:ring-offset-background focus:outline-hidden inline-flex w-[296px] touch-none truncate border px-11 text-base transition-colors focus:ring-2 focus:ring-offset-2 sm:text-sm"
      placeholder="Search a fruit"
      aria-label="Search a fruit"
    />
    <Combobox.Trigger
      class="absolute end-3 top-1/2 size-6 -translate-y-1/2 touch-none"
    >
      <CaretUpDown class="text-muted-foreground size-6" />
    </Combobox.Trigger>
  </div>
  <Combobox.Portal>
    <Combobox.Content
      class="focus-override border-muted bg-background shadow-popover 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 outline-hidden z-50 h-96 max-h-[var(--bits-combobox-content-available-height)] w-[var(--bits-combobox-anchor-width)] min-w-[var(--bits-combobox-anchor-width)] select-none rounded-xl border px-1 py-3 data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1"
      sideOffset={10}
    >
      <Combobox.ScrollUpButton
        class="flex w-full items-center justify-center py-1"
      >
        <CaretDoubleUp class="size-3" />
      </Combobox.ScrollUpButton>
      <Combobox.Viewport class="p-1">
        {#each filteredFruits as fruit, i (i + fruit.value)}
          <Combobox.Item
            class="rounded-button data-highlighted:bg-muted outline-hidden flex h-10 w-full select-none items-center py-3 pl-5 pr-1.5 text-sm capitalize"
            value={fruit.value}
            label={fruit.label}
          >
            {#snippet children({ selected })}
              {fruit.label}
              {#if selected}
                <div class="ml-auto">
                  <Check />
                </div>
              {/if}
            {/snippet}
          </Combobox.Item>
        {:else}
          <span class="block px-5 py-2 text-sm text-muted-foreground">
            No results found, try again.
          </span>
        {/each}
      </Combobox.Viewport>
      <Combobox.ScrollDownButton
        class="flex w-full items-center justify-center py-1"
      >
        <CaretDoubleDown class="size-3" />
      </Combobox.ScrollDownButton>
    </Combobox.Content>
  </Combobox.Portal>
</Combobox.Root>

Overview

The Combobox component combines the functionality of an input field with a dropdown list of selectable options. It provides users with the ability to search, filter, and select from a predefined set of choices.

Key Features

  • Keyboard Navigation: Full support for keyboard interactions, allowing users to navigate and select options without using a mouse.
  • Customizable Rendering: Flexible architecture for rendering options, including support for grouped items.
  • Accessibility: Built with ARIA attributes and keyboard interactions to ensure screen reader compatibility and accessibility standards.
  • Portal Support: Ability to render the dropdown content in a portal, preventing layout issues in complex UI structures.

Architecture

The Combobox component is composed of several sub-components, each with a specific role:

  • Root: The main container component that manages the state and context for the combobox.
  • Input: The input field that allows users to enter search queries.
  • Trigger: The button or element that opens the dropdown list.
  • Portal: Responsible for portalling the dropdown content to the body or a custom target.
  • Group: A container for grouped items, used to group related items.
  • GroupHeading: A heading for a group of items, providing a descriptive label for the group.
  • Item: An individual item within the list.
  • Separator: A visual separator between items.
  • Content: The dropdown container that displays the items. It uses Floating UI to position the content relative to the trigger.
  • ContentStatic: An alternative to the Content component, that enables you to opt-out of Floating UI and position the content yourself.
  • Viewport: The visible area of the dropdown content, used to determine the size and scroll behavior.
  • ScrollUpButton: A button that scrolls the content up when the content is larger than the viewport.
  • ScrollDownButton: A button that scrolls the content down when the content is larger than the viewport.
  • Arrow: An arrow element that points to the trigger when using the Combobox.Content component.

Structure

Here's an overview of how the Combobox component is structured in code:

	<script lang="ts">
  import { Combobox } from "bits-ui";
</script>
 
<Combobox.Root>
  <Combobox.Input />
  <Combobox.Trigger />
  <Combobox.Portal>
    <Combobox.Content>
      <Combobox.Group>
        <Combobox.GroupHeading />
        <Combobox.Item />
      </Combobox.Group>
      <Combobox.Item />
    </Combobox.Content>
  </Combobox.Portal>
</Combobox.Root>

Reusable Components

It's recommended to use the Combobox primitives to build your own custom combobox component that can be reused throughout your application.

CustomCombobox.svelte
	<script lang="ts">
  import { Combobox, type WithoutChildrenOrChild, mergeProps } from "bits-ui";
 
  type Props = Combobox.RootProps & {
    inputProps?: WithoutChildrenOrChild<Combobox.InputProps>;
    contentProps?: WithoutChildrenOrChild<Combobox.ContentProps>;
  };
 
  let {
    items = [],
    value = $bindable(),
    open = $bindable(false),
    inputProps,
    contentProps,
    type,
    ...restProps
  }: Props = $props();
 
  let searchValue = $state("");
 
  const filteredItems = $derived.by(() => {
    if (searchValue === "") return items;
    return items.filter((item) =>
      item.label.toLowerCase().includes(searchValue.toLowerCase())
    );
  });
 
  function handleInput(e: Event & { currentTarget: HTMLInputElement }) {
    searchValue = e.currentTarget.value;
  }
 
  function handleOpenChange(newOpen: boolean) {
    if (!newOpen) searchValue = "";
  }
 
  const mergedRootProps = $derived(
    mergeProps(restProps, { onOpenChange: handleOpenChange })
  );
  const mergedInputProps = $derived(
    mergeProps(inputProps, { oninput: handleInput })
  );
</script>
 
<!--
Destructuring (required for bindable) and discriminated unions don't play well together,
so we cast the value to `never` to avoid type errors here. However, on the consumer
side, the component will still be type-checked correctly.
-->
<Combobox.Root
  {type}
  {items}
  bind:value={value as never}
  bind:open
  {...mergedRootProps}
>
  <Combobox.Input {...mergedInputProps} />
  <Combobox.Trigger>Open</Combobox.Trigger>
  <Combobox.Portal>
    <Combobox.Content {...contentProps}>
      {#each filteredItems as item, i (i + item.value)}
        <Combobox.Item {...item}>
          {#snippet children({ selected })}
            {item.label}
            {selected ? "✅" : ""}
          {/snippet}
        </Combobox.Item>
      {:else}
        <span> No results found </span>
      {/each}
    </Combobox.Content>
  </Combobox.Portal>
</Combobox.Root>
+page.svelte
	<script lang="ts">
  import { CustomCombobox } from "$lib/components";
 
  const items = [
    { value: "mango", label: "Mango" },
    { value: "watermelon", label: "Watermelon" },
    { value: "apple", label: "Apple" },
    // ...
  ];
</script>
 
<CustomCombobox type="single" {items} />

Managing Value State

This section covers how to manage the value state of the Combobox.

Two-Way Binding

Use bind:value for simple, automatic state synchronization:

	<script lang="ts">
  import { Combobox } from "bits-ui";
  let myValue = $state("");
</script>
 
<button onclick={() => (myValue = "A")}> Select A </button>
 
<Combobox.Root type="single" bind:value={myValue}>
  <!-- ... -->
</Combobox.Root>

Fully Controlled

Use a Function Binding for complete control over the state's reads and writes.

	<script lang="ts">
  import { Combobox } from "bits-ui";
  let myValue = $state("");
 
  function getValue() {
    return myValue;
  }
 
  function setValue(newValue: string) {
    myValue = newValue;
  }
</script>
 
<Combobox.Root type="single" bind:value={getValue, setValue}>
  <!-- ... -->
</Combobox.Root>

Managing Open State

This section covers how to manage the open state of the Combobox.

Two-Way Binding

Use bind:open for simple, automatic state synchronization:

	<script lang="ts">
  import { Combobox } from "bits-ui";
  let myOpen = $state(false);
</script>
 
<button onclick={() => (myOpen = true)}> Open </button>
 
<Combobox.Root bind:open={myOpen}>
  <!-- ... -->
</Combobox.Root>

Fully Controlled

Use a Function Binding for complete control over the state's reads and writes.

	<script lang="ts">
  import { Combobox } from "bits-ui";
  let myOpen = $state(false);
 
  function getOpen() {
    return myOpen;
  }
 
  function setOpen(newOpen: boolean) {
    myOpen = newOpen;
  }
</script>
 
<Combobox.Root type="single" bind:open={getOpen, setOpen}>
  <!-- ... -->
</Combobox.Root>

Opt-out of Floating UI

When you use the Combobox.Content component, Bits UI uses Floating UI to position the content relative to the trigger, similar to other popover-like components.

You can opt-out of this behavior by instead using the Combobox.ContentStatic component.

	<Combobox.Root>
  <Combobox.Trigger />
  <Combobox.Input />
  <Combobox.Portal>
    <Combobox.ContentStatic>
      <Combobox.ScrollUpButton />
      <Combobox.Viewport>
        <Combobox.Item />
        <Combobox.Group>
          <Combobox.GroupHeading />
          <Combobox.Item />
        </Combobox.Group>
      </Combobox.Viewport>
      <Combobox.ScrollDownButton />
    </Combobox.ContentStatic>
  </Combobox.Portal>
</Combobox.Root>

When using this component, you'll need to handle the positioning of the content yourself. Keep in mind that using Combobox.Portal alongside Combobox.ContentStatic may result in some unexpected positioning behavior, feel free to not use the portal or work around it.

Custom Anchor

By default, the Combobox.Content is anchored to the Combobox.Input component, which determines where the content is positioned.

If you wish to instead anchor the content to a different element, you can pass either a selector string or an HTMLElement to the customAnchor prop of the Combobox.Content component.

	<script lang="ts">
  import { Combobox } from "bits-ui";
 
  let customAnchor = $state<HTMLElement>(null!);
</script>
 
<div bind:this={customAnchor}></div>
 
<Combobox.Root>
  <Combobox.Trigger />
  <Combobox.Input />
  <Combobox.Content {customAnchor}>
    <!-- ... -->
  </Combobox.Content>
</Combobox.Root>

What is the Viewport?

The Combobox.Viewport component is used to determine the size of the content in order to determine whether or not the scroll up and down buttons should be rendered.

If you wish to set a minimum/maximum height for the select content, you should apply it to the Combobox.Viewport component.

Scroll Up/Down Buttons

The Combobox.ScrollUpButton and Combobox.ScrollDownButton components are used to render the scroll up and down buttons when the select content is larger than the viewport.

You must use the Combobox.Viewport component when using the scroll buttons.

Custom Scroll Delay

The initial and subsequent scroll delays can be controlled using the delay prop on the buttons.

For example, we can use the cubicOut easing function from Svelte to create a smooth scrolling effect that speeds up over time.

	<script lang="ts">
  import { Combobox } from "bits-ui";
  import CaretUpDown from "phosphor-svelte/lib/CaretUpDown";
  import Check from "phosphor-svelte/lib/Check";
  import OrangeSlice from "phosphor-svelte/lib/OrangeSlice";
  import CaretDoubleUp from "phosphor-svelte/lib/CaretDoubleUp";
  import CaretDoubleDown from "phosphor-svelte/lib/CaretDoubleDown";
  import { cubicOut } from "svelte/easing";
 
  const fruits = [
    { value: "mango", label: "Mango" },
    { value: "watermelon", label: "Watermelon" },
    { value: "apple", label: "Apple" },
    { value: "pineapple", label: "Pineapple" },
    { value: "orange", label: "Orange" },
    { value: "grape", label: "Grape" },
    { value: "strawberry", label: "Strawberry" },
    { value: "banana", label: "Banana" },
    { value: "kiwi", label: "Kiwi" },
    { value: "peach", label: "Peach" },
    { value: "cherry", label: "Cherry" },
    { value: "blueberry", label: "Blueberry" },
    { value: "raspberry", label: "Raspberry" },
    { value: "blackberry", label: "Blackberry" },
    { value: "plum", label: "Plum" },
    { value: "apricot", label: "Apricot" },
    { value: "pear", label: "Pear" },
    { value: "grapefruit", label: "Grapefruit" }
  ];
 
  // Duplicate the menu items a couple of times to show off scrolling a big list
  const baseFruits = [...fruits];
  for (let i = 0; i < 10; i++) {
    for (let baseTheme of baseFruits) {
      fruits.push({ ...baseTheme, value: baseTheme.value + i });
    }
  }
 
  let searchValue = $state("");
 
  const filteredFruits = $derived(
    searchValue === ""
      ? fruits
      : fruits.filter((fruit) =>
          fruit.label.toLowerCase().includes(searchValue.toLowerCase())
        )
  );
 
  function autoScrollDelay(tick: number) {
    const maxDelay = 200;
    const minDelay = 25;
    const steps = 30;
 
    const progress = Math.min(tick / steps, 1);
    // Use the cubicOut easing function from svelte/easing
    return maxDelay - (maxDelay - minDelay) * cubicOut(progress);
  }
</script>
 
<Combobox.Root
  type="multiple"
  name="favoriteFruit"
  onOpenChange={(o) => {
    if (!o) searchValue = "";
  }}
>
  <div class="relative">
    <OrangeSlice
      class="text-muted-foreground absolute start-3 top-1/2 size-6 -translate-y-1/2"
    />
    <Combobox.Input
      oninput={(e) => (searchValue = e.currentTarget.value)}
      class="h-input rounded-9px border-border-input bg-background placeholder:text-foreground-alt/50 focus:ring-foreground focus:ring-offset-background focus:outline-hidden inline-flex w-[296px] truncate border px-11 text-base transition-colors focus:ring-2 focus:ring-offset-2 sm:text-sm"
      placeholder="Search a fruit"
      aria-label="Search a fruit"
    />
    <Combobox.Trigger class="absolute end-3 top-1/2 size-6 -translate-y-1/2">
      <CaretUpDown class="text-muted-foreground size-6" />
    </Combobox.Trigger>
  </div>
  <Combobox.Portal>
    <Combobox.Content
      class="focus-override border-muted bg-background shadow-popover 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 outline-hidden z-50 h-96 max-h-[var(--bits-combobox-content-available-height)] w-[var(--bits-combobox-anchor-width)] min-w-[var(--bits-combobox-anchor-width)] select-none rounded-xl border px-1 py-3 data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1"
      sideOffset={10}
    >
      <Combobox.ScrollUpButton
        class="flex w-full items-center justify-center py-1"
        delay={autoScrollDelay}
      >
        <CaretDoubleUp class="size-3" />
      </Combobox.ScrollUpButton>
      <Combobox.Viewport class="p-1">
        {#each filteredFruits as fruit, i (i + fruit.value)}
          <Combobox.Item
            class="rounded-button data-highlighted:bg-muted outline-hidden flex h-10 w-full select-none items-center py-3 pl-5 pr-1.5 text-sm capitalize"
            value={fruit.value}
            label={fruit.label}
          >
            {#snippet children({ selected })}
              {fruit.label}
              {#if selected}
                <div class="ml-auto">
                  <Check />
                </div>
              {/if}
            {/snippet}
          </Combobox.Item>
        {:else}
          <span class="block px-5 py-2 text-sm text-muted-foreground">
            No results found, try again.
          </span>
        {/each}
      </Combobox.Viewport>
      <Combobox.ScrollDownButton
        class="flex w-full items-center justify-center py-1"
        delay={autoScrollDelay}
      >
        <CaretDoubleDown class="size-3" />
      </Combobox.ScrollDownButton>
    </Combobox.Content>
  </Combobox.Portal>
</Combobox.Root>

Native Scrolling/Overflow

If you don't want to use the scroll buttons and prefer to use the standard scrollbar/overflow behavior, you can omit the Combobox.Scroll[Up|Down]Button components and the Combobox.Viewport component.

You'll need to set a height on the Combobox.Content component and appropriate overflow styles to enable scrolling.

Scroll Lock

To prevent the user from scrolling outside of the Combobox.Content component when open, you can set the preventScroll prop to true.

	<Combobox.Content preventScroll={true}>
  <!-- ... -->
</Combobox.Content>

Highlighted Items

The Combobox component follows the WAI-ARIA descendant pattern for highlighting items. This means that the Combobox.Input retains focus the entire time, even when navigating with the keyboard, and items are highlighted as the user navigates them.

Styling Highlighted Items

You can use the data-highlighted attribute on the Combobox.Item component to style the item differently when it is highlighted.

onHighlight / onUnhighlight

To trigger side effects when an item is highlighted or unhighlighted, you can use the onHighlight and onUnhighlight props.

	<Combobox.Item onHighlight={() => console.log('I am highlighted!')} onUnhighlight={() => console.log('I am unhighlighted!')} />
<!-- ... -->
</Combobox.Item>

Svelte Transitions

You can use the forceMount prop along with the child snippet to forcefully mount the Combobox.Content component to use Svelte Transitions or another animation library that requires more control.

	<script lang="ts">
  import { Combobox } from "bits-ui";
  import { fly } from "svelte/transition";
</script>
 
<Combobox.Content forceMount>
  {#snippet child({ wrapperProps, props, open })}
    {#if open}
      <div {...wrapperProps}>
        <div {...props} transition:fly>
          <!-- ... -->
        </div>
      </div>
    {/if}
  {/snippet}
</Combobox.Content>

Of course, this isn't the prettiest syntax, so it's recommended to create your own reusable content component that handles this logic if you intend to use this approach. For more information on using transitions with Bits UI components, see the Transitions documentation.

	<script lang="ts">
  import { Combobox } from "bits-ui";
  import CaretUpDown from "phosphor-svelte/lib/CaretUpDown";
  import Check from "phosphor-svelte/lib/Check";
  import OrangeSlice from "phosphor-svelte/lib/OrangeSlice";
  import CaretDoubleUp from "phosphor-svelte/lib/CaretDoubleUp";
  import CaretDoubleDown from "phosphor-svelte/lib/CaretDoubleDown";
  import { fly } from "svelte/transition";
 
  const fruits = [
    { value: "mango", label: "Mango" },
    { value: "watermelon", label: "Watermelon" },
    { value: "apple", label: "Apple" },
    { value: "pineapple", label: "Pineapple" },
    { value: "orange", label: "Orange" },
    { value: "grape", label: "Grape" },
    { value: "strawberry", label: "Strawberry" },
    { value: "banana", label: "Banana" },
    { value: "kiwi", label: "Kiwi" },
    { value: "peach", label: "Peach" },
    { value: "cherry", label: "Cherry" },
    { value: "blueberry", label: "Blueberry" },
    { value: "raspberry", label: "Raspberry" },
    { value: "blackberry", label: "Blackberry" },
    { value: "plum", label: "Plum" },
    { value: "apricot", label: "Apricot" },
    { value: "pear", label: "Pear" },
    { value: "grapefruit", label: "Grapefruit" }
  ];
 
  let searchValue = $state("");
 
  const filteredFruits = $derived(
    searchValue === ""
      ? fruits
      : fruits.filter((fruit) =>
          fruit.label.toLowerCase().includes(searchValue.toLowerCase())
        )
  );
</script>
 
<Combobox.Root
  type="single"
  name="favoriteFruit"
  onOpenChange={(o) => {
    if (!o) searchValue = "";
  }}
>
  <div class="relative">
    <OrangeSlice
      class="text-muted-foreground absolute start-3 top-1/2 size-6 -translate-y-1/2"
    />
    <Combobox.Input
      oninput={(e) => (searchValue = e.currentTarget.value)}
      class="h-input rounded-9px border-border-input bg-background placeholder:text-foreground-alt/50 focus:ring-foreground focus:ring-offset-background focus:outline-hidden inline-flex w-[296px] truncate border px-11 text-base transition-colors focus:ring-2 focus:ring-offset-2 sm:text-sm"
      placeholder="Search a fruit"
      aria-label="Search a fruit"
    />
    <Combobox.Trigger class="absolute end-3 top-1/2 size-6 -translate-y-1/2">
      <CaretUpDown class="text-muted-foreground size-6" />
    </Combobox.Trigger>
  </div>
  <Combobox.Portal>
    <Combobox.Content
      class="border-muted bg-background shadow-popover outline-hidden h-96 max-h-[var(--bits-combobox-content-available-height)] w-[var(--bits-combobox-anchor-width)] min-w-[var(--bits-combobox-anchor-width)] rounded-xl border px-1 py-3"
      sideOffset={10}
      forceMount
    >
      {#snippet child({ wrapperProps, props, open })}
        {#if open}
          <div {...wrapperProps}>
            <div {...props} transition:fly={{ duration: 300 }}>
              <Combobox.ScrollUpButton
                class="flex w-full items-center justify-center"
              >
                <CaretDoubleUp class="size-3" />
              </Combobox.ScrollUpButton>
              <Combobox.Viewport class="p-1">
                {#each filteredFruits as fruit, i (i + fruit.value)}
                  <Combobox.Item
                    class="rounded-button data-highlighted:bg-muted outline-hidden flex h-10 w-full select-none items-center py-3 pl-5 pr-1.5 text-sm  capitalize"
                    value={fruit.value}
                    label={fruit.label}
                  >
                    {#snippet children({ selected })}
                      {fruit.label}
                      {#if selected}
                        <div class="ml-auto">
                          <Check />
                        </div>
                      {/if}
                    {/snippet}
                  </Combobox.Item>
                {:else}
                  <span class="block px-5 py-2 text-sm text-muted-foreground">
                    No results found, try again.
                  </span>
                {/each}
              </Combobox.Viewport>
              <Combobox.ScrollDownButton
                class="flex w-full items-center justify-center"
              >
                <CaretDoubleDown class="size-3" />
              </Combobox.ScrollDownButton>
            </div>
          </div>
        {/if}
      {/snippet}
    </Combobox.Content>
  </Combobox.Portal>
</Combobox.Root>

API Reference

Combobox.Root

The root combobox component which manages & scopes the state of the combobox.

Property Details
type
value
onValueChange
open
onOpenChange
onOpenChangeComplete
disabled
name
required
scrollAlignment
loop
allowDeselect
items
inputValue
children
Data Attribute Details

Combobox.Trigger

A button which toggles the combobox's open state.

Property Details
ref
children
child
Data Attribute Details
data-state
data-disabled
data-combobox-trigger

Combobox.Viewport

An optional element to track the scroll position of the combobox for rendering the scroll up/down buttons.

Property Details
ref
children
child
Data Attribute Details
data-combobox-viewport

Combobox.Content

The element which contains the combobox's items.

Property Details
side
sideOffset
align
alignOffset
arrowPadding
avoidCollisions
collisionBoundary
collisionPadding
sticky
hideWhenDetached
updatePositionStrategy
strategy
preventScroll
customAnchor
onEscapeKeydown
escapeKeydownBehavior
onInteractOutside
onFocusOutside
interactOutsideBehavior
preventOverflowTextSelection
dir
loop
forceMount
ref
children
child
Data Attribute Details
data-state
data-combobox-content
CSS Variable Details
--bits-combobox-content-transform-origin
--bits-combobox-content-available-width
--bits-combobox-content-available-height
--bits-combobox-anchor-width
--bits-combobox-anchor-height

Combobox.ContentStatic

The element which contains the combobox's items. (Static/No Floating UI)

Property Details
onEscapeKeydown
escapeKeydownBehavior
onInteractOutside
onFocusOutside
interactOutsideBehavior
onOpenAutoFocus
onCloseAutoFocus
trapFocus
preventScroll
preventOverflowTextSelection
dir
loop
forceMount
ref
children
child
Data Attribute Details
data-state
data-combobox-content

Combobox.Portal

When used, will render the combobox content into the body or custom to element when open

Property Details
to
disabled
children
Data Attribute Details

Combobox.Item

A combobox item, which must be a child of the Combobox.Content component.

Property Details
value
label
disabled
onHighlight
onUnhighlight
ref
children
child
Data Attribute Details
data-value
data-label
data-disabled
data-highlighted
data-selected
data-combobox-item

Combobox.Input

A representation of the combobox input element, which is typically displayed in the content.

Property Details
defaultValue
clearOnDeselect
ref
children
child
Data Attribute Details
data-state
data-disabled
data-combobox-input

Combobox.Group

A group of related combobox items.

Property Details
ref
children
child
Data Attribute Details
data-combobox-group

Combobox.GroupHeading

A heading for the parent combobox group. This is used to describe a group of related combobox items.

Property Details
ref
children
child
Data Attribute Details
data-combobox-group-heading

Combobox.ScrollUpButton

An optional scroll up button element to improve the scroll experience within the combobox. Should be used in conjunction with the Combobox.Viewport component.

Property Details
delay
ref
children
child
Data Attribute Details
data-combobox-scroll-up-button

Combobox.ScrollDownButton

An optional scroll down button element to improve the scroll experience within the combobox. Should be used in conjunction with the Combobox.Viewport component.

Property Details
delay
ref
children
child
Data Attribute Details
data-combobox-scroll-down-button

Combobox.Arrow

An optional arrow element which points to the content when open.

Property Details
width
height
ref
children
child
Data Attribute Details
data-arrow