# Combobox (/docs/combobox)





## API Reference [#api-reference]

<BaseUIReference href="https://base-ui.com/react/components/combobox" />

## Choosing the right component [#choosing-the-right-component]

Use `Combobox` when selection should come from predefined options, but users still need an input to
search or narrow that list.

* Choose &#x2A;*`Combobox`** for searchable selection from a known dataset.
* Choose &#x2A;*`Autocomplete`** when free-form input is valid and suggestions are optional guidance.
* Choose &#x2A;*`Select`** when input typing is unnecessary and a button-triggered list is enough.

## Basic [#basic]

<Preview cssProperties="comboboxPlaygroundCssProperties">
  <ComboboxExample />

  <Preview.Code>
    {`
          import {
            Combobox,
            ComboboxField,
            ComboboxFieldLabel,
            ComboboxInputGroup,
            ComboboxInput,
            ComboboxControlActions,
            ComboboxClear,
            ComboboxTrigger,
            ComboboxContent,
            ComboboxEmpty,
            ComboboxList,
            ComboboxItem,
            ComboboxItemIndicator,
            ComboboxItemText,
          } from "moduix";
          import { useId } from "react";

          export function ComboboxDemo() {
            const id = useId();

            return (
              <Combobox items={fruits} itemToStringLabel={(item) => item.label}>
                <ComboboxField>
                  <ComboboxFieldLabel htmlFor={id}>Choose fruit</ComboboxFieldLabel>
                  <ComboboxInputGroup>
                    <ComboboxInput id={id} placeholder="e.g. Mango" />
                    <ComboboxControlActions>
                      <ComboboxClear aria-label="Clear selection" />
                      <ComboboxTrigger aria-label="Open options" />
                    </ComboboxControlActions>
                  </ComboboxInputGroup>
                </ComboboxField>

                <ComboboxContent>
                  <ComboboxEmpty>No fruits found.</ComboboxEmpty>
                  <ComboboxList>
                    {(item) => (
                      <ComboboxItem key={item.id} value={item}>
                        <ComboboxItemIndicator />
                        <ComboboxItemText>{item.label}</ComboboxItemText>
                      </ComboboxItem>
                    )}
                  </ComboboxList>
                </ComboboxContent>
              </Combobox>
            );
          }
        `}
  </Preview.Code>

  <Preview.Data>
    {`
          const fruits = [
            { id: "apple", label: "Apple", value: "apple" },
            { id: "banana", label: "Banana", value: "banana" },
            { id: "mango", label: "Mango", value: "mango" },
          ];
        `}
  </Preview.Data>

  <Preview.CSSProperties>
    {(context) => <ComboboxCssPropertiesPanel {...context} />}
  </Preview.CSSProperties>

  <Preview.CSSPlayground>
    {(context) => <ComboboxCssPlaygroundPanel {...context} />}
  </Preview.CSSPlayground>
</Preview>

## Anatomy [#anatomy]

`Combobox` combines an input-like control with a popup list. Keep the field parts together
inside `ComboboxField` and keep list-related parts inside `ComboboxContent` so keyboard focus,
selection state, and filtering stay synchronized.

```text
Combobox
├─ ComboboxField
│  ├─ ComboboxFieldLabel
│  └─ ComboboxInputGroup
│     ├─ ComboboxInput
│     └─ ComboboxControlActions
│        ├─ ComboboxClear
│        └─ ComboboxTrigger
└─ ComboboxContent
   ├─ service slots (internal): portal, backdrop, positioner, arrow
   ├─ ComboboxStatus / ComboboxEmpty
   └─ ComboboxList
      ├─ ComboboxGroup / ComboboxCollection
      ├─ ComboboxRow (for grid lists)
      ├─ ComboboxSeparator
      └─ ComboboxItem[value]
         ├─ ComboboxItemIndicator
         └─ ComboboxItemText
```

```tsx
<Combobox items={fruits} itemToStringLabel={(item) => item.label}>
  <ComboboxField>
    <ComboboxFieldLabel htmlFor={id}>Choose fruit</ComboboxFieldLabel>
    <ComboboxInputGroup>
      <ComboboxInput id={id} placeholder="e.g. Mango" />
      <ComboboxControlActions>
        <ComboboxClear aria-label="Clear selection" />
        <ComboboxTrigger aria-label="Open options" />
      </ComboboxControlActions>
    </ComboboxInputGroup>
  </ComboboxField>

  <ComboboxContent>
    <ComboboxEmpty>No fruits found.</ComboboxEmpty>
    <ComboboxList>
      {(item) => (
        <ComboboxItem key={item.id} value={item}>
          <ComboboxItemIndicator />
          <ComboboxItemText>{item.label}</ComboboxItemText>
        </ComboboxItem>
      )}
    </ComboboxList>
  </ComboboxContent>
</Combobox>
```

| Part                     | Role                                                                                                                    |
| ------------------------ | ----------------------------------------------------------------------------------------------------------------------- |
| `Combobox`               | Root state machine. Controls selected value, input text, popup open state, filtering, and keyboard navigation.          |
| `ComboboxField`          | Field wrapper for label and input area. Keep visible form-control pieces here for layout and accessibility semantics.   |
| `ComboboxInput`          | Search/input control. Drives filtering and exposes input events, placeholder, and focus behavior.                       |
| `ComboboxControlActions` | Slot for inline controls such as clear and trigger buttons.                                                             |
| `ComboboxContent`        | Popup surface with list/status/empty content. Also configures internal service layers and popup behavior props.         |
| `ComboboxList`           | Collection renderer for options or grouped options. Contains `ComboboxItem`, `ComboboxGroup`, and `ComboboxCollection`. |
| `ComboboxItem`           | One selectable option. Renders selected state and text/indicator subparts.                                              |
| `ComboboxChips`          | Multiple-selection chip container used with `multiple` and `ComboboxValue`.                                             |

In most cases, keep default popup infrastructure and style the visible parts (`ComboboxInput`,
`ComboboxItem`, `ComboboxItemIndicator`, `ComboboxItemText`, `ComboboxContent`).
Use `ComboboxContent` service-slot props (`classNames`, `portalProps`, `positionerProps`,
`backdropProps`, `arrowProps`, `withBackdrop`, `arrow`) only when you need custom portal,
layering, backdrop, or arrow behavior.

## Composition [#composition]

Use `Combobox` for root state and behavior props such as `value`, `defaultValue`,
`onValueChange`, `inputValue`, `onInputValueChange`, `open`, `onOpenChange`, `multiple`,
`filter`, `filteredItems`, `limit`, `grid`, `virtualized`, `modal`, `openOnInputClick`,
`autoHighlight`, `loopFocus`, `itemToStringLabel`, `itemToStringValue`, and
`isItemEqualToValue`.

The moduix wrapper keeps Base UI behavior available while hiding service elements from the
recommended composition:

| Base UI capability                      | moduix API                                                                                         |
| --------------------------------------- | -------------------------------------------------------------------------------------------------- |
| Root state, filtering, forms, grid mode | Pass Base UI root props directly to `Combobox`.                                                    |
| Flat items                              | Pass `items` to `Combobox` and render items with a function child on `ComboboxList`.               |
| Grouped items                           | Pass grouped `items`, then render `ComboboxGroup`, `ComboboxGroupLabel`, and `ComboboxCollection`. |
| Async or remote search                  | Pass `filter={null}`, manage `items`, and announce progress with `ComboboxStatus`.                 |
| Externally filtered items               | Pass `filteredItems` or combine `useComboboxFilter` with application state.                        |
| Virtualized lists                       | Pass `virtualized`, render custom rows in `ComboboxList`, and read `useComboboxFilteredItems`.     |
| Multiple values                         | Pass `multiple` and render chips through `ComboboxValue`, `ComboboxChips`, and `ComboboxChip`.     |
| Popup placement                         | Pass `side`, `align`, offsets, collision props, and `container` to `ComboboxContent`.              |
| Portal, backdrop, positioner, arrow     | Use `ComboboxContent` props instead of composing those service slots manually.                     |

`className` styles the visible popup. `classNames` styles the internal service slots that are
hidden from the default composition. Use `container`, `portalProps`, `backdropProps`,
`positionerProps`, `arrowProps`, `withBackdrop`, and `arrow` when you need the matching
Base UI escape hatches:

```tsx
<ComboboxContent
  className={styles.popup}
  withArrow
  withBackdrop
  classNames={{
    portal: styles.portal,
    backdrop: styles.backdrop,
    positioner: styles.positioner,
    arrow: styles.arrow,
  }}
/>
```

Every visible part accepts `className` and the Base UI `render` prop where the underlying primitive
supports it, so the component can be styled with CSS Modules, plain CSS, CSS-in-JS, cascade layers,
or design-system wrappers. Default icons are only fallbacks: pass children to `ComboboxTrigger`,
`ComboboxIcon`, `ComboboxClear`, `ComboboxItemIndicator`, and `ComboboxChipRemove` to use your own
icon set.

## Examples [#examples]

### Indicator Right With Icon [#indicator-right-with-icon]

Use `indicator="end"` when the selected indicator should be aligned to the end. Pass children to icon slots to use icons from your application.

<Preview>
  <IndicatorRightComboboxExample />

  <Preview.Code>
    {`
          import {
            Combobox,
            ComboboxField,
            ComboboxFieldLabel,
            ComboboxInputGroup,
            ComboboxInput,
            ComboboxControlActions,
            ComboboxClear,
            ComboboxTrigger,
            ComboboxContent,
            ComboboxList,
            ComboboxItem,
            ComboboxItemText,
            ComboboxItemTextContent,
            ComboboxItemTextIcon,
            InfoIcon,
            ComboboxItemTextLabel,
            ComboboxItemIndicator,
          } from "moduix";
          import { useId } from "react";

          export function IndicatorRightComboboxDemo() {
            const id = useId();

            return (
              <Combobox items={fruits} itemToStringLabel={(item) => item.label}>
                <ComboboxField>
                  <ComboboxFieldLabel htmlFor={id}>Choose fruit</ComboboxFieldLabel>
                  <ComboboxInputGroup>
                    <ComboboxInput id={id} placeholder="e.g. Mango" />
                    <ComboboxControlActions>
                      <ComboboxClear aria-label="Clear selection" />
                      <ComboboxTrigger aria-label="Open options" />
                    </ComboboxControlActions>
                  </ComboboxInputGroup>
                </ComboboxField>

                <ComboboxContent>
                  <ComboboxList>
                    {(item) => (
                      <ComboboxItem key={item.id} value={item} indicator="end">
                        <ComboboxItemText>
                          <ComboboxItemTextContent>
                            <ComboboxItemTextIcon>
                              <InfoIcon />
                            </ComboboxItemTextIcon>
                            <ComboboxItemTextLabel>{item.label}</ComboboxItemTextLabel>
                          </ComboboxItemTextContent>
                        </ComboboxItemText>
                        <ComboboxItemIndicator />
                      </ComboboxItem>
                    )}
                  </ComboboxList>
                </ComboboxContent>
              </Combobox>
            );
          }
        `}
  </Preview.Code>

  <Preview.Data>
    {`
          const fruits = [
            { id: "apple", label: "Apple", value: "apple" },
            { id: "banana", label: "Banana", value: "banana" },
            { id: "mango", label: "Mango", value: "mango" },
          ];
        `}
  </Preview.Data>
</Preview>

### Input Inside Popup [#input-inside-popup]

Render `ComboboxInput` inside the popup when the closed field should behave like a select trigger.

<Preview>
  <InputInsidePopupComboboxExample />

  <Preview.Code>
    {`
          import {
            Combobox,
            ComboboxField,
            ComboboxFieldLabel,
            ComboboxTrigger,
            ComboboxValue,
            ComboboxIcon,
            ComboboxContent,
            ComboboxInlineInputContainer,
            ComboboxInput,
            ComboboxEmpty,
            ComboboxList,
            ComboboxItem,
            ComboboxItemIndicator,
            ComboboxItemText,
          } from "moduix";
          import styles from "./combobox.module.css";

          export function InputInsidePopupComboboxDemo() {
            return (
              <Combobox items={countries} itemToStringLabel={(item) => item.label}>
                <ComboboxField>
                  <ComboboxFieldLabel>Country</ComboboxFieldLabel>
                  <ComboboxTrigger className={styles.triggerField}>
                    <ComboboxValue placeholder="Select country" />
                    <ComboboxIcon />
                  </ComboboxTrigger>
                </ComboboxField>

                <ComboboxContent className={styles.popupWithInlineInput}>
                  <ComboboxInlineInputContainer>
                    <ComboboxInput className={styles.inlineInput} placeholder="Search country" />
                  </ComboboxInlineInputContainer>
                  <ComboboxEmpty>No countries found.</ComboboxEmpty>
                  <ComboboxList className={styles.listWithInlineInput}>
                    {(item) => (
                      <ComboboxItem key={item.id} value={item}>
                        <ComboboxItemIndicator />
                        <ComboboxItemText>{item.label}</ComboboxItemText>
                      </ComboboxItem>
                    )}
                  </ComboboxList>
                </ComboboxContent>
              </Combobox>
            );
          }
        `}
  </Preview.Code>

  <Preview.CSS>
    {`
          .triggerField {
            display: inline-flex;
            width: var(--combobox-width, 16rem);
            min-height: var(--combobox-control-height, var(--size-lg));
            align-items: center;
            justify-content: space-between;
            gap: 0.75rem;
            padding: 0 0.875rem;
            border: var(--border-width-sm) solid var(--combobox-border-color, var(--color-border));
            border-radius: var(--combobox-radius, var(--radius-md));
            background-color: var(--combobox-bg, var(--color-background));
            color: var(--combobox-color, var(--color-foreground));
            transition:
              background-color var(--transition-default),
              border-color var(--transition-default),
              outline-color var(--transition-default);

            &[data-popup-open] {
              background-color: var(--color-muted);
            }

            &:focus-visible {
              border-color: var(--combobox-focus-ring-color, var(--color-ring));
              outline: var(--border-width-sm) solid var(--combobox-focus-ring-color, var(--color-ring));
              outline-offset: calc(var(--border-width-sm) * -1);
            }
          }

          .popupWithInlineInput {
            --combobox-inline-input-container-height: calc(
              var(--combobox-control-height, var(--size-lg)) +
                var(--combobox-inline-input-container-padding-top, var(--spacing-2)) +
                var(--combobox-inline-input-container-padding-bottom, var(--spacing-2)) +
                var(--combobox-inline-input-divider-width, var(--border-width-sm))
            );
          }

          .listWithInlineInput {
            max-height: min(
              calc(
                var(--combobox-list-max-height, var(--combobox-popup-max-height, 24rem)) -
                  var(--combobox-inline-input-container-height, 0px)
              ),
              calc(var(--available-height) - var(--combobox-inline-input-container-height, 0px))
            );
            padding-top: 0.375rem;
            padding-bottom: 0.5rem;
            scroll-padding-top: 0.375rem;
            scroll-padding-bottom: 0.5rem;
          }

          .inlineInput {
            padding-inline: 0.75rem;
            border: var(--border-width-sm) solid var(--combobox-border-color, var(--color-border));
            border-radius: var(--radius-sm);
          }
        `}
  </Preview.CSS>

  <Preview.Data>
    {`
          const countries = [
            { id: "de", label: "Germany", value: "germany" },
            { id: "es", label: "Spain", value: "spain" },
            { id: "fr", label: "France", value: "france" },
          ];
        `}
  </Preview.Data>
</Preview>

### Grouped [#grouped]

Pass grouped data to `Combobox` and render `ComboboxCollection` inside each `ComboboxGroup`.

<Preview>
  <GroupedComboboxExample />

  <Preview.Code>
    {`
          import {
            Combobox,
            ComboboxField,
            ComboboxFieldLabel,
            ComboboxInputGroup,
            ComboboxInput,
            ComboboxControlActions,
            ComboboxClear,
            ComboboxTrigger,
            ComboboxContent,
            ComboboxEmpty,
            ComboboxList,
            ComboboxGroup,
            ComboboxGroupLabel,
            ComboboxCollection,
            ComboboxItem,
            ComboboxItemIndicator,
            ComboboxItemText,
          } from "moduix";
          import { useId } from "react";

          export function GroupedComboboxDemo() {
            const id = useId();

            return (
              <Combobox items={groupedProduce} itemToStringLabel={(item) => item.label}>
                <ComboboxField>
                  <ComboboxFieldLabel htmlFor={id}>Select produce</ComboboxFieldLabel>
                  <ComboboxInputGroup>
                    <ComboboxInput id={id} placeholder="e.g. Spinach" />
                    <ComboboxControlActions>
                      <ComboboxClear aria-label="Clear selection" />
                      <ComboboxTrigger aria-label="Open groups" />
                    </ComboboxControlActions>
                  </ComboboxInputGroup>
                </ComboboxField>

                <ComboboxContent>
                  <ComboboxEmpty>No produce found.</ComboboxEmpty>
                  <ComboboxList>
                    {(group) => (
                      <ComboboxGroup key={group.value} items={group.items}>
                        <ComboboxGroupLabel>{group.value}</ComboboxGroupLabel>
                        <ComboboxCollection>
                          {(item) => (
                            <ComboboxItem key={item.id} value={item}>
                              <ComboboxItemIndicator />
                              <ComboboxItemText>{item.label}</ComboboxItemText>
                            </ComboboxItem>
                          )}
                        </ComboboxCollection>
                      </ComboboxGroup>
                    )}
                  </ComboboxList>
                </ComboboxContent>
              </Combobox>
            );
          }
        `}
  </Preview.Code>

  <Preview.Data>
    {`
          const groupedProduce = [
            {
              value: "Fruits",
              items: [
                { id: "fruit-apple", label: "Apple", value: "apple" },
                { id: "fruit-mango", label: "Mango", value: "mango" },
              ],
            },
            {
              value: "Vegetables",
              items: [
                { id: "veg-carrot", label: "Carrot", value: "carrot" },
                { id: "veg-spinach", label: "Spinach", value: "spinach" },
              ],
            },
          ];
        `}
  </Preview.Data>
</Preview>

### Multiple [#multiple]

Use the `multiple` prop and render chips inside `ComboboxValue`. The input remains the main control, so a separate trigger icon is optional.

<Preview>
  <MultipleComboboxExample />

  <Preview.Code>
    {`
          import {
            Combobox,
            ComboboxField,
            ComboboxFieldLabel,
            ComboboxInputGroup,
            ComboboxChips,
            ComboboxValue,
            ComboboxChip,
            ComboboxChipText,
            ComboboxChipRemove,
            ComboboxChipsInput,
            ComboboxContent,
            ComboboxEmpty,
            ComboboxList,
            ComboboxItem,
            ComboboxItemIndicator,
            ComboboxItemText,
          } from "moduix";
          import { useId } from "react";

          export function MultipleComboboxDemo() {
            const id = useId();

            return (
              <Combobox items={fruits} itemToStringLabel={(item) => item.label} multiple>
                <ComboboxField>
                  <ComboboxFieldLabel htmlFor={id}>Select fruits</ComboboxFieldLabel>
                  <ComboboxInputGroup>
                    <ComboboxChips>
                      <ComboboxValue>
                        {(value) => (
                          <>
                            {value.map((item) => (
                              <ComboboxChip key={item.id} aria-label={item.label}>
                                <ComboboxChipText>{item.label}</ComboboxChipText>
                                <ComboboxChipRemove aria-label={\`Remove \${item.label}\`} />
                              </ComboboxChip>
                            ))}
                            <ComboboxChipsInput
                              id={id}
                              placeholder={value.length === 0 ? "Select..." : ""}
                            />
                          </>
                        )}
                      </ComboboxValue>
                    </ComboboxChips>
                  </ComboboxInputGroup>
                </ComboboxField>

                <ComboboxContent>
                  <ComboboxEmpty>No fruits found.</ComboboxEmpty>
                  <ComboboxList>
                    {(item) => (
                      <ComboboxItem key={item.id} value={item}>
                        <ComboboxItemIndicator />
                        <ComboboxItemText>{item.label}</ComboboxItemText>
                      </ComboboxItem>
                    )}
                  </ComboboxList>
                </ComboboxContent>
              </Combobox>
            );
          }
        `}
  </Preview.Code>

  <Preview.Data>
    {`
          const fruits = [
            { id: "apple", label: "Apple", value: "apple" },
            { id: "banana", label: "Banana", value: "banana" },
            { id: "mango", label: "Mango", value: "mango" },
          ];
        `}
  </Preview.Data>
</Preview>

### Async Search [#async-search]

Disable the built-in filter with `filter={null}` when results are loaded from your application state or a remote API.

<Preview>
  <AsyncSearchComboboxExample />

  <Preview.Code>
    {`
          import {
            Combobox,
            ComboboxField,
            ComboboxFieldLabel,
            ComboboxInputGroup,
            ComboboxInput,
            ComboboxControlActions,
            ComboboxClear,
            ComboboxTrigger,
            ComboboxContent,
            ComboboxStatus,
            ComboboxEmpty,
            ComboboxList,
            ComboboxItem,
            ComboboxItemIndicator,
            ComboboxItemText,
            useComboboxFilter,
          } from "moduix";
          import { useId, useMemo, useRef, useState, useTransition } from "react";

          export function AsyncSearchComboboxDemo() {
            const id = useId();
            const { contains } = useComboboxFilter();
            const [searchResults, setSearchResults] = useState([]);
            const [selectedValue, setSelectedValue] = useState(null);
            const [searchValue, setSearchValue] = useState("");
            const [isPending, startTransition] = useTransition();
            const abortControllerRef = useRef(null);
            const trimmedSearchValue = searchValue.trim();

            const items = useMemo(() => {
              if (!selectedValue || searchResults.some((user) => user.id === selectedValue.id)) {
                return searchResults;
              }

              return [...searchResults, selectedValue];
            }, [searchResults, selectedValue]);

            const status = isPending
              ? "Searching..."
              : trimmedSearchValue === ""
                ? selectedValue ? null : "Start typing to search people..."
                : searchResults.length === 0
                  ? \`No matches for "\${trimmedSearchValue}".\`
                  : null;

            return (
              <Combobox
                items={items}
                itemToStringLabel={(user) => user.name}
                filter={null}
                onValueChange={(nextSelectedValue) => {
                  setSelectedValue(nextSelectedValue);
                  setSearchValue("");
                }}
                onInputValueChange={(nextSearchValue, { reason }) => {
                  setSearchValue(nextSearchValue);

                  if (nextSearchValue === "") {
                    abortControllerRef.current?.abort();
                    setSearchResults([]);
                    return;
                  }

                  if (reason === "item-press") {
                    return;
                  }

                  const controller = new AbortController();
                  abortControllerRef.current?.abort();
                  abortControllerRef.current = controller;

                  startTransition(async () => {
                    await new Promise((resolve) => setTimeout(resolve, 250));

                    if (controller.signal.aborted) {
                      return;
                    }

                    setSearchResults(
                      directoryUsers.filter(
                        (user) =>
                          contains(user.name, nextSearchValue) ||
                          contains(user.username, nextSearchValue) ||
                          contains(user.email, nextSearchValue) ||
                          contains(user.title, nextSearchValue),
                      ),
                    );
                  });
                }}
              >
                <ComboboxField>
                  <ComboboxFieldLabel htmlFor={id}>Assign reviewer</ComboboxFieldLabel>
                  <ComboboxInputGroup>
                    <ComboboxInput id={id} placeholder="e.g. Michael" />
                    <ComboboxControlActions>
                      <ComboboxClear aria-label="Clear selection" />
                      <ComboboxTrigger aria-label="Open options" />
                    </ComboboxControlActions>
                  </ComboboxInputGroup>
                </ComboboxField>

                <ComboboxContent>
                  <ComboboxStatus>{status}</ComboboxStatus>
                  <ComboboxEmpty>
                    {trimmedSearchValue !== "" && !isPending && searchResults.length === 0
                      ? "Try a different search term."
                      : null}
                  </ComboboxEmpty>
                  <ComboboxList>
                    {(user) => (
                      <ComboboxItem key={user.id} value={user}>
                        <ComboboxItemIndicator />
                        <ComboboxItemText>{user.name}</ComboboxItemText>
                      </ComboboxItem>
                    )}
                  </ComboboxList>
                </ComboboxContent>
              </Combobox>
            );
          }
        `}
  </Preview.Code>

  <Preview.Data>
    {`
          const directoryUsers = [
            {
              id: "leslie-alexander",
              name: "Leslie Alexander",
              username: "leslie",
              email: "leslie.alexander@example.com",
              title: "Product Manager",
            },
            {
              id: "michael-foster",
              name: "Michael Foster",
              username: "michael",
              email: "michael.foster@example.com",
              title: "Frontend Engineer",
            },
          ];
        `}
  </Preview.Data>
</Preview>

### Custom Styles [#custom-styles]

Use `ComboboxContent` props for popup infrastructure. `Portal`, `Positioner`, `Backdrop`, and `Arrow` are rendered internally, so application code only configures behavior and service-slot classes.

<Preview>
  <CustomStylesComboboxExample />

  <Preview.Code>
    {`
          import {
            Combobox,
            ComboboxField,
            ComboboxFieldLabel,
            ComboboxInputGroup,
            ComboboxInput,
            ComboboxControlActions,
            ComboboxClear,
            ComboboxTrigger,
            ComboboxContent,
            ComboboxEmpty,
            ComboboxList,
            ComboboxItem,
            ComboboxItemIndicator,
            ComboboxItemText,
          } from "moduix";
          import { useId } from "react";
          import styles from "./combobox.module.css";

          export function CustomStylesComboboxDemo() {
            const id = useId();

            return (
              <Combobox items={fruits} itemToStringLabel={(item) => item.label}>
                <ComboboxField>
                  <ComboboxFieldLabel htmlFor={id}>Choose fruit</ComboboxFieldLabel>
                  <ComboboxInputGroup>
                    <ComboboxInput id={id} placeholder="e.g. Mango" />
                    <ComboboxControlActions>
                      <ComboboxClear aria-label="Clear selection" />
                      <ComboboxTrigger aria-label="Open options" />
                    </ComboboxControlActions>
                  </ComboboxInputGroup>
                </ComboboxField>

                <ComboboxContent
                  className={styles.customPopup}
                  sideOffset={8}
                  withArrow
                  withBackdrop
                  classNames={{
                    portal: styles.portal,
                    backdrop: styles.backdrop,
                    positioner: styles.positioner,
                    arrow: styles.arrow,
                  }}
                >
                  <ComboboxEmpty>No fruits found.</ComboboxEmpty>
                  <ComboboxList>
                    {(item) => (
                      <ComboboxItem key={item.id} value={item}>
                        <ComboboxItemIndicator />
                        <ComboboxItemText>{item.label}</ComboboxItemText>
                      </ComboboxItem>
                    )}
                  </ComboboxList>
                </ComboboxContent>
              </Combobox>
            );
          }
        `}
  </Preview.Code>

  <Preview.CSS>
    {`
          .customPopup {
            --combobox-popup-bg: var(--color-background);
            --combobox-popup-border-color: var(--color-ring);
            --combobox-shadow: var(--shadow-xl);
          }

          .portal {
            isolation: isolate;
          }

          .positioner {
            z-index: var(--z-popup);
          }

          .backdrop {
            --combobox-backdrop-bg: var(--color-overlay);
            --combobox-backdrop-blur: 2px;
          }

          .arrow {
            --combobox-arrow-stroke-color: var(--color-border);
          }
        `}
  </Preview.CSS>

  <Preview.Data>
    {`
          const fruits = [
            { id: "apple", label: "Apple", value: "apple" },
            { id: "banana", label: "Banana", value: "banana" },
            { id: "mango", label: "Mango", value: "mango" },
          ];
        `}
  </Preview.Data>
</Preview>
