> ## Documentation Index
> Fetch the complete documentation index at: https://anvil.servicetitan.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Combobox – Code

> Comboboxes are form elements that allow users to filter and select a value from a list.

export const LiveCode = ({children, customHeight, clickToLoad, example, fullWidth, fullHeight, hideCodeInLiveCode, screenshot, screenshotOnly, showCode: showCodeProp}) => {
  const SCREENSHOTS_BASE = "https://servicetitan.github.io/anvil2-docs-live-code/screenshots";
  const STACKBLITZ_BASE = "https://stackblitz.com/github/servicetitan/anvil2-docs-live-code/tree/main/examples";
  const [showCodeBlock, setShowCodeBlock] = useState(showCodeProp ?? false);
  const [isLocalOverride, setIsLocalOverride] = useState(false);
  useEffect(() => {
    const examplePath = `/images/live-code-screenshots-tmp/${example}.png`;
    fetch(examplePath, {
      method: "HEAD"
    }).then(r => {
      if (r.ok) setIsLocalOverride(true);
    }).catch(() => {});
  }, [example]);
  const screenshotBase = isLocalOverride ? "/images/live-code-screenshots-tmp" : SCREENSHOTS_BASE;
  if (screenshotOnly) {
    return <Frame className="flex flex-col">
        <div className="flex dark:hidden" style={{
      justifyContent: "center",
      alignItems: "center",
      width: fullWidth ? "100%" : "50%",
      minHeight: fullHeight ? "284px" : undefined,
      background: "#FFFFFF"
    }}>
          <img srcset={`${screenshotBase}/${example}.png, ${screenshotBase}/${example}-2x.png 2x`} src={`${screenshotBase}/${example}.png`} alt={example} noZoom />
        </div>
        <div className="hidden dark:flex" style={{
      justifyContent: "center",
      alignItems: "center",
      width: fullWidth ? "100%" : "50%",
      minHeight: fullHeight ? "284px" : undefined,
      background: "#141414"
    }}>
          <img srcset={`${screenshotBase}/${example}-dark.png, ${screenshotBase}/${example}-dark-2x.png 2x`} src={`${screenshotBase}/${example}-dark.png`} alt={example} noZoom />
        </div>
      </Frame>;
  }
  if (screenshot) {
    return <Frame className="flex flex-col -mb-2">
        <div className="flex dark:hidden bg-white dark:bg-codeblock border border-gray-950/10 dark:border-white/10 dark:twoslash-dark rounded-2xl overflow-hidden" style={{
      justifyContent: "center",
      alignItems: "center",
      width: fullWidth ? "100%" : "50%",
      minHeight: fullHeight ? "284px" : undefined
    }}>
          <img srcset={`${screenshotBase}/${example}.png, ${screenshotBase}/${example}-2x.png 2x`} src={`${screenshotBase}/${example}.png`} alt={example} noZoom />
        </div>

        <div className="hidden dark:flex bg-white dark:bg-codeblock border border-gray-950/10 dark:border-white/10 dark:twoslash-dark rounded-2xl overflow-hidden" style={{
      background: "#141414",
      justifyContent: "center",
      alignItems: "center",
      width: fullWidth ? "100%" : "50%",
      minHeight: fullHeight ? "284px" : undefined
    }}>
          <img srcset={`${screenshotBase}/${example}-dark.png, ${screenshotBase}/${example}-dark-2x.png 2x`} src={`${screenshotBase}/${example}-dark.png`} alt={example} noZoom />
        </div>

        <div className="flex justify-end items-center text-xs py-2 px-1 gap-4">
          {!showCodeProp ? <button className="inline-flex justify-end items-center text-gray-700 dark:text-gray-50 hover:text-blue-500 dark:hover:text-blue-300 transition-colors group self-end gap-1 cursor-pointer" onClick={() => setShowCodeBlock(!showCodeBlock)} style={{
      appearance: "none"
    }}>
              <Icon icon="code" size="12px" className="group-hover:bg-blue-500 dark:group-hover:bg-blue-300" />
              <span>{showCodeBlock ? "Hide code" : "Show code"}</span>
            </button> : null}

          <a className="inline-flex justify-end items-center hover:text-blue-500 dark:hover:text-blue-300 transition-colors group self-end gap-1" href={`${STACKBLITZ_BASE}/${example}?file=src/App.tsx`} target="_blank" rel="noreferrer">
            <Icon icon="bolt" size="12px" className="group-hover:bg-blue-500 dark:group-hover:bg-blue-300" />
            <span>StackBlitz demo</span>
          </a>
        </div>

        <div className="grid transition-[grid-template-rows] duration-300 ease-in-out overflow-auto overflow-y-hidden overflow-x-auto" style={showCodeBlock ? {
      gridTemplateRows: "1fr"
    } : {
      gridTemplateRows: "0fr"
    }}>
          <div style={{
      minHeight: 0,
      overflowX: "auto",
      overflowY: "hidden",
      marginBlockStart: "-1.25rem",
      marginBlockEnd: "-1.5rem"
    }}>
            {children}
          </div>
        </div>
      </Frame>;
  } else {
    return <div style={{
      display: "flex",
      width: fullWidth ? "100%" : "50%",
      minHeight: customHeight ? customHeight : "316px",
      resize: "vertical",
      overflow: "auto"
    }}>
        <iframe title={example} style={{
      flex: 1,
      width: fullWidth ? "100%" : "50%",
      minHeight: customHeight ? customHeight : "316px"
    }} src={`${STACKBLITZ_BASE}/${example}?embed=1&hideNavigation=1&hideExplorer=1&terminalHeight=0&file=src/App.tsx${clickToLoad ? "&ctl=1" : ""}${hideCodeInLiveCode ? "&view=preview" : ""}`} allow="accelerometer; ambient-light-sensor; camera; encrypted-media; geolocation; gyroscope; hid; microphone; midi; payment; usb; vr; xr-spatial-tracking" sandbox="allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts" />
      </div>;
  }
};

<Note>
  The [SelectField](/docs/web/components/select-field/code) and [MultiSelectField](/docs/web/components/multi-select-field/code) beta components cover many common use cases for Combobox. These components are actively receiving updates with new features and will be the recommended components for Anvil2 consumers in the future.
</Note>

<Tabs>
  <Tab title="Implementation">
    <LiveCode showCode example="combobox-playground" fullWidth screenshot>
      ```tsx lines expandable theme={null}
      import { Combobox } from "@servicetitan/anvil2";
      import { useState } from "react";

      type Item = {
        id: number;
        name: string;
      };

      const items = [
        { id: 1, name: "First item" },
        { id: 2, name: "Second item" },
        { id: 3, name: "Third item" },
        { id: 4, name: "Fourth item" },
        { id: 5, name: "Fifth item" },
        { id: 6, name: "Sixth item" },
        { id: 7, name: "Seventh item" },
        { id: 8, name: "Eighth item" },
        { id: 9, name: "Ninth item" },
        { id: 10, name: "Tenth item" },
      ];

      function App() {
        const [selectedItems, setSelectedItems] = useState<Item[] | null>([]);

        return (
          <div style={{ minWidth: "384px", minHeight: "284px" }}>
            <Combobox
              multiple
              items={items}
              itemToString={(item) => (item ? item.name : "")}
              itemToKey={(item) => (item ? item.id : null)}
              selectedItems={selectedItems ?? []}
              onChange={setSelectedItems}
              filterOptions={{ keys: ["name"] }}
              defaultIsOpen
            >
              <Combobox.SearchField
                label="Label"
                placeholder="Placeholder"
                description="Description"
                moreInfo="More info!"
              />
              <Combobox.Content>
                {({ items }) => (
                  <Combobox.List>
                    {items.map((item, i) => (
                      <Combobox.Item key={item.id} item={item} index={i}>
                        {item.name}
                      </Combobox.Item>
                    ))}
                  </Combobox.List>
                )}
              </Combobox.Content>
            </Combobox>
          </div>
        );
      }

      export default App;
      ```
    </LiveCode>

    ## Common Examples

    ```tsx theme={null}
    import { useState } from "react";
    import { Combobox } from "@servicetitan/anvil2";

    const items = [
      { id: 1, name: "First item" },
      // ...more items...
    ];

    const ExampleComponent = () => {
      const [selectedItem, setSelectedItem] = useState();

      return (
        <Combobox
          items={items}
          itemToString={(item) => item ? item.name : ""}
          itemToKey={(item) => item ? item.id : null}
          selectedItem={selectedItem}
          onChange={setSelectedItem}
          filterOptions={{ keys: ["name"] }}
        >
          <Combobox.SearchField label="Label" />
          <Combobox.Content>
            {({ items }) => (
              <Combobox.List>
                {items.map((item, i) => (
                  <Combobox.Item
                    key={item.id}
                    item={item}
                    index={i}
                  >
                    {item.name}
                  </Combobox.Item>
                ))}
              </Combobox.List>
            )}
          </Combobox.Content>
        </Combobox>
      );
    ```

    ### Combobox components

    The Anvil2 combobox is made up of a `Combobox` component and a few sub-components that can be used together to build simple or complex select drop-downs.

    * `Combobox`: the parent component to configure comboboxes.
    * `Combobox.SearchField`: used to create a searchable select input to use with a combobox list in a drop-down.
    * `Combobox.Content`: popover that passes an `items` array to its `children` to construct combobox items.
    * `Combobox.List`: organizes combobox items in the drop-down list.
    * `Combobox.Item`: used to construct the items within the combobox drop-down.
    * `Combobox.Empty`: optionally used to customize empty results message.

    ### Multi-selects

    To allow the user to select multiple items, set the `multiple` prop of the `Combobox` to `true`. In addition, props such as `selectedItem` will be replaced with `selectedItems` (note the "s" at the end) and will expect an array.

    <LiveCode showCode example="combobox-playground" screenshot fullWidth>
      ```tsx lines expandable theme={null}
      import { Combobox } from "@servicetitan/anvil2";
      import { useState } from "react";

      type Item = {
        id: number;
        name: string;
      };

      const items = [
        { id: 1, name: "First item" },
        { id: 2, name: "Second item" },
        { id: 3, name: "Third item" },
        { id: 4, name: "Fourth item" },
        { id: 5, name: "Fifth item" },
        { id: 6, name: "Sixth item" },
        { id: 7, name: "Seventh item" },
        { id: 8, name: "Eighth item" },
        { id: 9, name: "Ninth item" },
        { id: 10, name: "Tenth item" },
      ];

      function App() {
        const [selectedItems, setSelectedItems] = useState<Item[] | null>([]);

        return (
          <div style={{ minWidth: "384px", minHeight: "284px" }}>
            <Combobox
              multiple
              items={items}
              itemToString={(item) => (item ? item.name : "")}
              itemToKey={(item) => (item ? item.id : null)}
              selectedItems={selectedItems ?? []}
              onChange={setSelectedItems}
              filterOptions={{ keys: ["name"] }}
              defaultIsOpen
            >
              <Combobox.SearchField
                label="Label"
                placeholder="Placeholder"
                description="Description"
                moreInfo="More info!"
              />
              <Combobox.Content>
                {({ items }) => (
                  <Combobox.List>
                    {items.map((item, i) => (
                      <Combobox.Item key={item.id} item={item} index={i}>
                        {item.name}
                      </Combobox.Item>
                    ))}
                  </Combobox.List>
                )}
              </Combobox.Content>
            </Combobox>
          </div>
        );
      }

      export default App;
      ```
    </LiveCode>

    ### Select all for multi-selects

    To add a "Select All" option at the top of a multi-select combobox dropdown, use the `selectAll` prop. This prop accepts an object with `label`, `onSelection`, and `isChecked` properties. The `onSelection` callback is called when the user clicks the Select All option, and `isChecked` controls whether the checkbox appears checked.

    Note: The "Select All" option does not automatically select all items when the combobox is opened. It is up to the developer to handle the selection of all items when the "Select All" option is clicked. This means it is incompatible with using `Combobox` in an uncontrolled way.

    <LiveCode showCode example="combobox-selectall" screenshot fullWidth>
      ```tsx lines expandable theme={null}
      import { Combobox } from "@servicetitan/anvil2";
      import { useState } from "react";

      type Item = {
        id: number;
        name: string;
      };

      const items: Item[] = [
        { id: 1, name: "Apple" },
        { id: 2, name: "Banana" },
        { id: 3, name: "Blueberry" },
        { id: 4, name: "Grapefruit" },
        { id: 5, name: "Orange" },
        { id: 6, name: "Peach" },
        { id: 7, name: "Pomegranate" },
        { id: 8, name: "Raspberry" },
        { id: 9, name: "Strawberry" },
        { id: 10, name: "Watermelon" },
      ];

      function App() {
        const [selectedItems, setSelected] = useState<Item[] | null>();

        return (
          <div style={{ minWidth: "384px", minHeight: "300px" }}>
            <Combobox
              items={items}
              itemToString={(item) => (item ? item.name : "")}
              onChange={setSelected}
              filterOptions={{ keys: ["name"] }}
              selectAll={{
                label: "Select All",
                onSelection: () => {
                  setSelected(items);
                },
                isChecked: selectedItems?.length === items.length,
              }}
              selectedItems={selectedItems ?? undefined}
              multiple
              defaultIsOpen
            >
              <Combobox.SearchField label="Select Fruit" />
              <Combobox.Content>
                {({ items }) => (
                  <Combobox.List>
                    {items.map((item, i) => (
                      <Combobox.Item key={item.id} item={item} index={i}>
                        {item.name}
                      </Combobox.Item>
                    ))}
                  </Combobox.List>
                )}
              </Combobox.Content>
            </Combobox>
          </div>
        );
      }

      export default App;
      ```
    </LiveCode>

    ```tsx theme={null}
    import { useState } from "react";
    import { Combobox } from "@servicetitan/anvil2";

    const items = [
      { id: 1, name: "First item" },
      { id: 2, name: "Second item" },
      { id: 3, name: "Third item" },
      { id: 4, name: "Fourth item" },
      { id: 5, name: "Fifth item" },
    ];

    const ExampleComponent = () => {
      const [selectedItems, setSelectedItems] = useState([]);

      return (
        <Combobox
          multiple
          items={items}
          itemToString={(item) => item?.name ?? ""}
          itemToKey={(item) => item?.id ?? null}
          selectedItems={selectedItems}
          onChange={setSelectedItems}
          filterOptions={{ keys: ["name"] }}
          selectAll={{
            // Customize the label of the "Select All" option
            label: "Select All",
            // Callback function to handle the selection of all items
            onSelection: () => {
              // This is up to the developer to implement based on their use case
              setSelectedItems((prev) =>
                prev.length === items.length ? [] : items
              );
            },
            // Control whether the "Select All" option appears checked
            isChecked: selectedItems.length === items.length,
          }}
        >
          <Combobox.SearchField label="Label" />
          <Combobox.Content>
            {({ items }) => (
              <Combobox.List>
                {items.map((item, i) => (
                  <Combobox.Item key={item.id} item={item} index={i}>
                    {item.name}
                  </Combobox.Item>
                ))}
              </Combobox.List>
            )}
          </Combobox.Content>
        </Combobox>
      );
    };
    ```

    ### Building selects

    The Anvil2 `Combobox` component is versatile due to its flexibility and robust set of sub-components. It can be used in place of the `Select` component from the original Anvil library to create a searchable select component.

    <LiveCode showCode example="combobox-multiple-false" screenshot fullWidth>
      ```tsx lines expandable theme={null}
      import { Combobox } from "@servicetitan/anvil2";
      import { useState } from "react";

      type Item = {
        id: number;
        name: string;
      };

      const items: Item[] = [
        { id: 1, name: "Casey Maxwell" },
        { id: 2, name: "Giovanni Saunders" },
        { id: 3, name: "Harper Gonzalez" },
        { id: 4, name: "Jane Doe" },
        { id: 5, name: "Meadow Hunter" },
      ];

      function App() {
        const [, setSelected] = useState<Item | null>();

        return (
          <div style={{ minWidth: "384px", minHeight: "284px" }}>
            <Combobox
              items={items}
              itemToString={(item) => (item ? item.name : "")}
              onChange={setSelected}
              filterOptions={{ keys: ["name"] }}
              defaultIsOpen
            >
              <Combobox.SearchField label="Select Teammate" />
              <Combobox.Content>
                {({ items }) => (
                  <Combobox.List>
                    {items.map((item, i) => (
                      <Combobox.Item key={item.id} item={item} index={i}>
                        {item.name}
                      </Combobox.Item>
                    ))}
                  </Combobox.List>
                )}
              </Combobox.Content>
            </Combobox>
          </div>
        );
      }

      export default App;
      ```
    </LiveCode>

    #### Notes for building selects

    * The `itemToString` prop passes an `item` object and expects a `string` return type. This is used to format the text of each combobox item within the search field input (after selecting an item) based on the provided `item` object type.
    * The `itemToKey` prop passes an `item` object and expects something that can be used to identify the item, such as an `id`. This is used for identity comparisons, so if this prop is omitted, the `item`s will be compared by reference equality instead.
    * The `filterOptions` prop is used to filter the items using the [match-sorter](https://github.com/kentcdodds/match-sorter?tab=readme-ov-file) library. See [their docs](https://github.com/kentcdodds/match-sorter?tab=readme-ov-file#advanced-options) for more info on the options that can be provided.
    * The `selectedItem`/`selectedItems` props allow the `Combobox` to be used as a controlled component.
    * For easily managing the selected item state, the `onChange` prop accepts a `setState` function, which is the second item in the array that a `useState` function returns:

    ```tsx theme={null}
    const ExampleComponent = () => {
      const [selected, setSelected] = useState();
      return <Combobox {...} onChange={setSelected} />
    }
    ```

    #### Compare using `itemToKey` or reference equality

    The `itemToKey` prop is used to compare `items` using a unique identifier. By default, the `Combobox` component does searches and comparisons using reference equality. That means that the `Combobox` may not behave how you expect if your code is generating new references for your `items` on every render:

    ```tsx theme={null}
    const items = [
      { id: 1, name: "First item" },
      { id: 2, name: "Second item" },
      { id: 3, name: "Third item" },
      { id: 4, name: "Fourth item" },
      { id: 5, name: "Fifth item" },
    ];

    const ExampleComponent = () => {
      const [selected, setSelected] = useState();

      // WARNING! This will create a new reference for every item on every render!
      const newItems = items.map(item => { ...item, someChange: Math.random() });

      return (
        <Combobox
          items={newItems}
        >
          {...}
        </Combobox>
      )
    }
    ```

    Some ways have stable references might be to perform the reference modifications outside of React's render cycle or to use `React.useMemo` to memoize computations on `items` and only update the references when something has meaningfully changed.

    However, in cases like this, it's probably more likely you'd prefer to have your `items` compared by a specific key in your object rather than by reference equality. And so you can do that by passing in an `itemToKey` function that takes an item and returns a unique key:

    ```tsx theme={null}
    const items = [
      { id: 1, name: "First item" },
      { id: 2, name: "Second item" },
      { id: 3, name: "Third item" },
      { id: 4, name: "Fourth item" },
      { id: 5, name: "Fifth item" },
    ];

    const ExampleComponent = () => {
      const [selected, setSelected] = useState();

      const newItems = items.map(item => { ...item, someChange: Math.random() });

      return (
        <Combobox
          items={newItems}
          itemToKey={(item) => item?.id}
        >
          {...}
        </Combobox>
      )
    }
    ```

    #### Passing filtered items through the combobox components

    The `items` array passed to the `Combobox` is automatically filtered based on the user typing in the search input and the `keys` in the `filterOption` prop. After filtering, it is passed through the `Combobox.Content` as a parameter used to generate the `children`.

    ```tsx theme={null}
    // objects in items array can have any type
    const items = [
      { id: 1, label: "First item", alias: "one" },
      { id: 2, label: "Second item", alias: "two" },
      { id: 3, label: "Third item", alias: "three" },
    ];

    const ExampleComponent = () => {
      const [selectedItems, setSelectedItems] = useState([]);

      return (
        <Combobox
          multiple
          items={items}
          itemToString={(item) => item?.label ?? ""}
          itemToKey={(item) => item?.id ?? null}
          selectedItems={selectedItems}
          onChange={setSelectedItems}
          /* strings in keys array should match the 
             searchable fields in items objects */
          filterOptions={{ keys: ["label", "alias"] }}
        >
          <Combobox.SearchField {...searchFieldProps} />
          <Combobox.Content>
            {/* matches items array, with filtering */}
            {({ items }) => (
              <Combobox.List>
                {items.map((item, index) => (
                  <Combobox.Item key={item.id} item={item} index={index}>
                    {item.label}
                  </Combobox.Item>
                ))}
              </Combobox.List>
            )}
          </Combobox.Content>
        </Combobox>
      );
    };
    ```

    ### Adding a new item when there is no exact match

    To allow the user to add a new item when their search returns no exact matches, use the `Combobox.ItemAddNew` component. This component provides an `onSelection` callback, and that callback will need to be used to update both your list of items and your selected item.

    Your `onSelection` callback will need to both update the list of items and update the `selectedItem`/`selectedItems`, so we recommend that you use a controlled `Combobox` when you need the ability to add a new item:

    <LiveCode showCode example="combobox-itemaddnew" screenshot fullWidth>
      ```tsx lines expandable theme={null}
      import { Combobox, Text } from "@servicetitan/anvil2";
      import { useState } from "react";

      type Item = {
        id: number;
        name: string;
      };

      function App() {
        const [items, setItems] = useState<Item[]>([
          { id: 1, name: "First item" },
          { id: 2, name: "Second item" },
          { id: 3, name: "Third item" },
          { id: 4, name: "Fourth item" },
          { id: 5, name: "Fifth item" },
          { id: 6, name: "Sixth item" },
          { id: 7, name: "Seventh item" },
          { id: 8, name: "Eighth item" },
          { id: 9, name: "Ninth item" },
          { id: 10, name: "Tenth item" },
        ]);

        const [selectedItems, setSelectedItems] = useState<Item[] | null>([]);

        const handleAddNew = (inputValue: string) => {
          const newItem = { id: items.length + 1, name: inputValue };
          setItems((prevItems) => [...prevItems, newItem]);
          setSelectedItems((prevItems) =>
            prevItems != null ? [...prevItems, newItem] : [newItem],
          );
        };

        return (
          <div style={{ minWidth: "384px", minHeight: "284px" }}>
            <Combobox
              multiple
              items={items}
              itemToString={(item) => (item ? item.name : "")}
              itemToKey={(item) => (item ? item.id : null)}
              selectedItems={selectedItems ?? []}
              onChange={setSelectedItems}
              defaultIsOpen
              defaultInputValue="New item"
            >
              <Combobox.SearchField
                label="Select an item"
                description="Add a new item"
              />
              <Combobox.Content>
                {({ items, inputValue }) => (
                  <Combobox.List>
                    {items.map((item, i) => (
                      <Combobox.Item key={item.id} item={item} index={i}>
                        {item.name}
                      </Combobox.Item>
                    ))}

                    <Combobox.Empty>
                      <div
                        style={{
                          padding: "0.5rem 1rem",
                          textTransform: "uppercase",
                        }}
                      >
                        <Text subdued size="small">
                          No match found
                        </Text>
                      </div>
                    </Combobox.Empty>

                    <Combobox.ItemAddNew onSelection={handleAddNew}>
                      + &nbsp; Add &ldquo;{inputValue}&rdquo;
                    </Combobox.ItemAddNew>
                  </Combobox.List>
                )}
              </Combobox.Content>
            </Combobox>
          </div>
        );
      }

      export default App;
      ```
    </LiveCode>

    ### Select-only comboboxes

    By default, comboboxes include a text input for searching and filtering items. To create a select-only combobox that acts similarly to an HTML select, use the `Combobox.Select` and `Combobox.SelectTrigger` instead of `Combobox` and `Combobox.SearchField`.

    <LiveCode showCode example="comboboxselect" screenshot fullWidth>
      ```tsx lines expandable theme={null}
      import { Combobox } from "@servicetitan/anvil2";
      import { useState } from "react";

      type Item = {
        id: number;
        name: string;
      };

      const items = [
        { id: 1, name: "First item" },
        { id: 2, name: "Second item" },
        { id: 3, name: "Third item" },
        { id: 4, name: "Fourth item" },
        { id: 5, name: "Fifth item" },
        { id: 6, name: "Sixth item" },
        { id: 7, name: "Seventh item" },
        { id: 8, name: "Eighth item" },
        { id: 9, name: "Ninth item" },
        { id: 10, name: "Tenth item" },
      ];

      function App() {
        const [selectedItem, setSelectedItem] = useState<Item | null>();

        return (
          <div style={{ minWidth: "384px", minHeight: "284px" }}>
            <Combobox.Select
              items={items}
              itemToString={(item) => (item ? item.name : "")}
              itemToKey={(item) => (item ? item.id : null)}
              selectedItem={selectedItem}
              onChange={setSelectedItem}
              defaultIsOpen
            >
              <Combobox.SelectTrigger
                label="Select an item"
                description="This is a Combobox.SelectTrigger"
              />
              <Combobox.Content>
                {({ items }) => (
                  <Combobox.List>
                    {items.map((item, i) => (
                      <Combobox.Item key={item.id} item={item} index={i}>
                        {item.name}
                      </Combobox.Item>
                    ))}
                  </Combobox.List>
                )}
              </Combobox.Content>
            </Combobox.Select>
          </div>
        );
      }

      export default App;
      ```
    </LiveCode>

    #### Disable clearing selection on select-only combobox

    To remove the "x" button that clears a selection in a select-only combobox, use the `disableClearSelection` prop.

    **Note**: this does not work when `multiple` is `true`, due to the nature of clearing options in multi-select comboboxes.

    <LiveCode showCode example="comboboxselect-disableclearselection" screenshot fullWidth>
      ```tsx lines expandable theme={null}
      import { Combobox } from "@servicetitan/anvil2";
      import { useState } from "react";

      type Item = {
        id: number;
        name: string;
      };

      const items = [
        { id: 1, name: "First item" },
        { id: 2, name: "Second item" },
        { id: 3, name: "Third item" },
        { id: 4, name: "Fourth item" },
        { id: 5, name: "Fifth item" },
        { id: 6, name: "Sixth item" },
        { id: 7, name: "Seventh item" },
        { id: 8, name: "Eighth item" },
        { id: 9, name: "Ninth item" },
        { id: 10, name: "Tenth item" },
      ];

      function App() {
        const [selectedItem, setSelectedItem] = useState<Item | null>(items[1]);

        return (
          <div style={{ minWidth: "384px", minHeight: "284px" }}>
            <Combobox.Select
              disableClearSelection
              items={items}
              itemToString={(item) => (item ? item.name : "")}
              itemToKey={(item) => (item ? item.id : null)}
              selectedItem={selectedItem}
              onChange={setSelectedItem}
              defaultIsOpen
            >
              <Combobox.SelectTrigger
                label="Select an item"
                description="This is a Combobox.SelectTrigger"
              />
              <Combobox.Content>
                {({ items }) => (
                  <Combobox.List>
                    {items.map((item, i) => (
                      <Combobox.Item key={item.id} item={item} index={i}>
                        {item.name}
                      </Combobox.Item>
                    ))}
                  </Combobox.List>
                )}
              </Combobox.Content>
            </Combobox.Select>
          </div>
        );
      }

      export default App;
      ```
    </LiveCode>

    ### Sorting combobox options

    By default, Comboboxes sort options based on the order that they are provided via the `items` prop.

    <LiveCode showCode example="combobox-sort" screenshot fullWidth>
      ```tsx lines expandable theme={null}
      import { Combobox } from "@servicetitan/anvil2";
      import { useState } from "react";

      type Item = {
        id: number;
        name: string;
      };

      const items = [
        { id: 1, name: "First item" },
        { id: 2, name: "Second item" },
        { id: 3, name: "Third item" },
        { id: 4, name: "Fourth item" },
        { id: 5, name: "Fifth item" },
        { id: 6, name: "Sixth item" },
        { id: 7, name: "Seventh item" },
        { id: 8, name: "Eighth item" },
        { id: 9, name: "Ninth item" },
        { id: 10, name: "Tenth item" },
      ];

      const reversedItems = items.reverse();

      function App() {
        const [selectedItems, setSelectedItems] = useState<Item[] | null>([]);

        return (
          <div style={{ minWidth: "384px", minHeight: "284px" }}>
            <Combobox
              multiple
              items={reversedItems}
              itemToString={(item) => (item ? item.name : "")}
              itemToKey={(item) => (item ? item.id : null)}
              selectedItems={selectedItems ?? []}
              onChange={setSelectedItems}
              filterOptions={{ keys: ["name"] }}
              defaultIsOpen
            >
              <Combobox.SearchField
                label="Select an item"
                description="This is a Combobox.SearchField"
              />
              <Combobox.Content>
                {({ items }) => (
                  <Combobox.List>
                    {items.map((item, i) => (
                      <Combobox.Item key={item.id} item={item} index={i}>
                        {item.name}
                      </Combobox.Item>
                    ))}
                  </Combobox.List>
                )}
              </Combobox.Content>
            </Combobox>
          </div>
        );
      }

      export default App;
      ```
    </LiveCode>

    ### Controlled combobox

    Comboboxes can be used uncontrolled by default, or can be used in a fully-controlled way by setting the `selectedItem` prop (or by using the `selectedItems` prop when used with `multiple` select):

    <LiveCode showCode example="combobox-controlled" screenshot fullWidth>
      ```tsx lines expandable theme={null}
      import { Combobox, Flex, Button } from "@servicetitan/anvil2";
      import { useState } from "react";

      type Item = {
        id: number;
        name: string;
      };

      const items = [
        { id: 1, name: "First item" },
        { id: 2, name: "Second item" },
        { id: 3, name: "Third item" },
        { id: 4, name: "Fourth item" },
        { id: 5, name: "Fifth item" },
        { id: 6, name: "Sixth item" },
        { id: 7, name: "Seventh item" },
        { id: 8, name: "Eighth item" },
        { id: 9, name: "Ninth item" },
        { id: 10, name: "Tenth item" },
      ];

      function App() {
        const [selectedItem, setSelectedItem] = useState<Item | null>();

        return (
          <div style={{ minWidth: "384px", minHeight: "284px" }}>
            <Flex gap={8}>
              <Flex grow={1} direction="column" alignItems="center" gap={4}>
                <Button onClick={() => setSelectedItem(items[0])}>
                  Set First Item
                </Button>
                <Button onClick={() => setSelectedItem(items[1])}>
                  Set Second Item
                </Button>
                <Button onClick={() => setSelectedItem(items[2])}>
                  Set Third Item
                </Button>
                <Button onClick={() => setSelectedItem(items[3])}>
                  Set Fourth Item
                </Button>
                <Button onClick={() => setSelectedItem(items[4])}>
                  Set Fifth Item
                </Button>
              </Flex>

              <Combobox
                items={items}
                itemToString={(item) => (item ? item.name : "")}
                itemToKey={(item) => (item ? item.id : null)}
                selectedItem={selectedItem}
                onChange={setSelectedItem}
                filterOptions={{ keys: ["name"] }}
                style={{ width: "50vw", maxWidth: "50%" }}
                defaultIsOpen
              >
                <Combobox.SearchField
                  label="Select an item (single)"
                  description="This is a Combobox.SearchField"
                />
                <Combobox.Content>
                  {({ items }) => (
                    <Combobox.List>
                      {items.map((item, i) => (
                        <Combobox.Item key={item.id} item={item} index={i}>
                          {item.name}
                        </Combobox.Item>
                      ))}
                    </Combobox.List>
                  )}
                </Combobox.Content>
              </Combobox>
            </Flex>
          </div>
        );
      }

      export default App;
      ```
    </LiveCode>

    <LiveCode showCode example="combobox-controlled-multiple" screenshot fullWidth>
      ```tsx lines expandable theme={null}
      import { Combobox, Flex, Button } from "@servicetitan/anvil2";
      import { useState } from "react";

      type Item = {
        id: number;
        name: string;
      };

      const items = [
        { id: 1, name: "First item" },
        { id: 2, name: "Second item" },
        { id: 3, name: "Third item" },
        { id: 4, name: "Fourth item" },
        { id: 5, name: "Fifth item" },
        { id: 6, name: "Sixth item" },
        { id: 7, name: "Seventh item" },
        { id: 8, name: "Eighth item" },
        { id: 9, name: "Ninth item" },
        { id: 10, name: "Tenth item" },
      ];

      function App() {
        const [selectedItems, setSelectedItems] = useState<Item[] | null>([]);

        return (
          <div style={{ minWidth: "384px", minHeight: "284px" }}>
            <Flex gap={8}>
              <Flex grow={1} direction="column" alignItems="center" gap={4}>
                <Button onClick={() => setSelectedItems([items[0]])}>
                  Set First Item
                </Button>
                <Button onClick={() => setSelectedItems([items[1], items[2]])}>
                  Set Second and Third Items
                </Button>
                <Button
                  onClick={() => setSelectedItems([items[7], items[8], items[9]])}
                >
                  Set Last Three Items
                </Button>
                <Button onClick={() => setSelectedItems([])}>Set Empty Array</Button>
              </Flex>

              <Combobox
                multiple
                items={items}
                itemToString={(item) => (item ? item.name : "")}
                itemToKey={(item) => (item ? item.id : null)}
                selectedItems={selectedItems ?? []}
                onChange={setSelectedItems}
                filterOptions={{ keys: ["name"] }}
                style={{ width: "50vw", maxWidth: "50%" }}
                defaultIsOpen
              >
                <Combobox.SearchField
                  label="Select an item (multiple)"
                  description="This is a Combobox.SearchField"
                />
                <Combobox.Content>
                  {({ items }) => (
                    <Combobox.List>
                      {items.map((item, i) => (
                        <Combobox.Item key={item.id} item={item} index={i}>
                          {item.name}
                        </Combobox.Item>
                      ))}
                    </Combobox.List>
                  )}
                </Combobox.Content>
              </Combobox>
            </Flex>
          </div>
        );
      }

      export default App;
      ```
    </LiveCode>

    ### Default combobox selection

    When using a Combobox in an uncontrolled way, Comboboxes can set an item as a default by using the `defaultSelectedItem` prop (or by using the `defaultSelectedItems` prop when used with `multiple` select):

    <LiveCode showCode example="combobox-defaultselecteditem" screenshot fullWidth>
      ```tsx lines expandable theme={null}
      import { Combobox } from "@servicetitan/anvil2";
      import { useState } from "react";

      type Item = {
        id: number;
        name: string;
      };

      const items: Item[] = [
        { id: 1, name: "Casey Maxwell" },
        { id: 2, name: "Giovanni Saunders" },
        { id: 3, name: "Harper Gonzalez" },
        { id: 4, name: "Jane Doe" },
        { id: 5, name: "Meadow Hunter" },
      ];
      const defaultItem = items[0];

      function App() {
        const [, setSelected] = useState<Item | null>();

        return (
          <Combobox
            items={items}
            itemToString={(item) => (item ? item.name : "")}
            onChange={setSelected}
            filterOptions={{ keys: ["name"] }}
            defaultSelectedItem={defaultItem}
            style={{ minWidth: "260px" }}
          >
            <Combobox.SearchField label="Select Teammate" />
            <Combobox.Content>
              {({ items }) => (
                <Combobox.List>
                  {items.map((item, i) => (
                    <Combobox.Item key={item.id} item={item} index={i}>
                      {item.name}
                    </Combobox.Item>
                  ))}
                </Combobox.List>
              )}
            </Combobox.Content>
          </Combobox>
        );
      }

      export default App;
      ```
    </LiveCode>

    <LiveCode showCode example="combobox-defaultselecteditems" screenshot fullWidth>
      ```tsx lines expandable theme={null}
      import { Combobox } from "@servicetitan/anvil2";
      import { useState } from "react";

      type Item = {
        id: number;
        name: string;
      };

      const items: Item[] = [
        { id: 1, name: "Casey Maxwell" },
        { id: 2, name: "Giovanni Saunders" },
        { id: 3, name: "Harper Gonzalez" },
        { id: 4, name: "Jane Doe" },
        { id: 5, name: "Meadow Hunter" },
      ];
      const defaultItems = [items[1], items[4]];

      function App() {
        const [, setSelected] = useState<Item[] | null>();

        return (
          <Combobox
            items={items}
            itemToString={(item) => (item ? item.name : "")}
            onChange={setSelected}
            filterOptions={{ keys: ["name"] }}
            multiple
            defaultSelectedItems={defaultItems}
          >
            <Combobox.SearchField label="Select Teammate" />
            <Combobox.Content>
              {({ items }) => (
                <Combobox.List>
                  {items.map((item, i) => (
                    <Combobox.Item key={item.id} item={item} index={i}>
                      {item.name}
                    </Combobox.Item>
                  ))}
                </Combobox.List>
              )}
            </Combobox.Content>
          </Combobox>
        );
      }

      export default App;
      ```
    </LiveCode>

    ### Selected item customization

    `Combobox`es with `multiple` select can customize the selected state of an item using the `selectedItemProps` prop on the `Combobox.SearchField`. This prop accepts a function that will pass the selected item as an parameter to allow for things like customizing the display color:

    <LiveCode showCode example="combobox-selecteditemprops" screenshot fullWidth>
      ```tsx lines expandable theme={null}
      import { Combobox } from "@servicetitan/anvil2";
      import { useState } from "react";

      type Item = {
        id: number;
        name: string;
        color: string;
      };

      const items = [
        { id: 1, name: "Red", color: "red" },
        { id: 2, name: "Purple", color: "purple" },
        { id: 3, name: "Black", color: "black" },
        { id: 4, name: "Gray", color: "gray" },
        { id: 5, name: "Gold", color: "gold" },
        { id: 6, name: "Cyan", color: "cyan" },
        { id: 7, name: "Pink", color: "pink" },
        { id: 8, name: "Blue", color: "blue" },
        { id: 9, name: "Green", color: "green" },
      ];

      function App() {
        const [, setSelectedItems] = useState<Item[] | null>([
          items[4],
          items[5],
          items[6],
        ]);

        return (
          <div style={{ minWidth: "384px", minHeight: "284px" }}>
            <Combobox
              multiple
              items={items}
              itemToString={(item) => (item ? item.name : "")}
              itemToKey={(item) => (item ? item.id : null)}
              defaultSelectedItems={[items[4], items[5], items[6]]}
              onChange={setSelectedItems}
              filterOptions={{ keys: ["name"] }}
              defaultIsOpen
            >
              <Combobox.SearchField
                label="Select a color"
                description="This is an example of color customization"
                selectedItemProps={(item) => ({
                  color: item.color,
                })}
              />
              <Combobox.Content>
                {({ items }) => (
                  <Combobox.List>
                    {items.map((item, i) => (
                      <Combobox.Item key={item.id} item={item} index={i}>
                        {item.name}
                      </Combobox.Item>
                    ))}
                  </Combobox.List>
                )}
              </Combobox.Content>
            </Combobox>
          </div>
        );
      }

      export default App;
      ```
    </LiveCode>

    ### Disabling combobox popovers

    Comboboxes can be used to create searchable select lists without a drop-down. If `disablePopover` is set to `true` on the `Combobox.Content`, the list will always render. This is especially useful if the combobox exists within a custom [popover](/docs/web/components/popover/design).

    <LiveCode showCode example="combobox-disablepopover" screenshot fullWidth>
      ```tsx lines expandable theme={null}
      import { Combobox, Popover } from "@servicetitan/anvil2";
      import { useState } from "react";

      type Item = {
        id: string;
        name: string;
      };

      const technicians = [
        { id: "cs-0", name: "Cory Sparks" },
        { id: "jb-1", name: "Jessica Brees" },
        { id: "jc-2", name: "Johnny Carpenter" },
        { id: "rp-3", name: "Rusty Pipes" },
        { id: "sp-4", name: "Silvia Plomería" },
      ];

      function App() {
        const [selectedItems, setSelectedItems] = useState<Item[] | null>([]);

        return (
          <div style={{ minHeight: "284px", paddingInlineEnd: "18rem" }}>
            <Popover placement="right-start" defaultOpen>
              <Popover.Button>Add technician(s)</Popover.Button>
              <Popover.Content>
                <Combobox
                  multiple
                  items={technicians}
                  itemToString={(item) => (item ? item.name : "")}
                  itemToKey={(item) => (item ? item.id : null)}
                  selectedItems={selectedItems ?? []}
                  onChange={setSelectedItems}
                  filterOptions={{ keys: ["name"] }}
                  style={{ width: "15rem" }}
                >
                  <Combobox.SearchField label="Label" />
                  <Combobox.Content disablePopover>
                    {({ items }) => (
                      <Combobox.List>
                        {items.map((item, i) => (
                          <Combobox.Item key={item.id} item={item} index={i}>
                            {item.name}
                          </Combobox.Item>
                        ))}
                      </Combobox.List>
                    )}
                  </Combobox.Content>
                </Combobox>
              </Popover.Content>
            </Popover>
          </div>
        );
      }

      export default App;
      ```
    </LiveCode>

    ### Custom combobox empty state

    By default, if no items exist in the filtered combobox results, a simple "No results found" message is displayed. To customize this, use the `Combobox.Empty` component.

    <LiveCode showCode example="combobox-empty" screenshot fullWidth>
      ```tsx lines expandable theme={null}
      import { Combobox, Flex, Text } from "@servicetitan/anvil2";
      import { useState } from "react";

      type Item = {
        id: number;
        name: string;
      };

      const items = [
        { id: 1, name: "First item" },
        { id: 2, name: "Second item" },
        { id: 3, name: "Third item" },
        { id: 4, name: "Fourth item" },
        { id: 5, name: "Fifth item" },
        { id: 6, name: "Sixth item" },
        { id: 7, name: "Seventh item" },
        { id: 8, name: "Eighth item" },
        { id: 9, name: "Ninth item" },
        { id: 10, name: "Tenth item" },
      ];

      function App() {
        const [selectedItem, setSelectedItem] = useState<Item | null>();

        return (
          <div style={{ minWidth: "384px", minHeight: "284px" }}>
            <Combobox
              items={items}
              itemToString={(item) => (item ? item.name : "")}
              itemToKey={(item) => (item ? item.id : null)}
              selectedItem={selectedItem}
              onChange={setSelectedItem}
              filterOptions={{ keys: ["name"] }}
              defaultIsOpen
              defaultInputValue="XYZ"
            >
              <Combobox.SearchField label="Select an item" />
              <Combobox.Content>
                {({ items }) => (
                  <>
                    <Combobox.Empty>
                      <Flex
                        gap="1"
                        alignItems="center"
                        justifyContent="center"
                        direction="column"
                        style={{ padding: "var(--size-2)" }}
                      >
                        <Text variant="headline" el="h3" size="medium">
                          😕 No matches
                        </Text>
                        <Text>Please try again.</Text>
                      </Flex>
                    </Combobox.Empty>
                    <Combobox.List>
                      {items.map((item, i) => (
                        <Combobox.Item key={item.id} item={item} index={i}>
                          {item.name}
                        </Combobox.Item>
                      ))}
                    </Combobox.List>
                  </>
                )}
              </Combobox.Content>
            </Combobox>
          </div>
        );
      }

      export default App;
      ```
    </LiveCode>

    ### Combobox virtualization example

    `Combobox.Content` renders a function that passes down the list of filtered items as children, allowing the `Combobox.List` component to be used with virtualization libraries, which often require an additional wrapper component around the items being virtualized. The following example uses `react-window`'s `FixedSizeList` component for virtualizing the list of items:

    ```tsx theme={null}
    import { useState } from "react";
    import { Combobox } from "@servicetitan/anvil2";
    import { FixedSizeList as List } from "react-window";

    const items = [
      { id: 1, name: "First item" },
      // ...more items...
    ];

    const ExampleComponent = () => {
      const [selectedItem, setSelectedItem] = useState();

      return (
        <Combobox
          items={items}
          itemToString={(item) => (item ? item.name : "")}
          itemToKey={(item) => (item ? item.id : null)}
          onChange={setSelectedItem}
          filterOptions={{ keys: ["name"] }}
        >
          <Combobox.SearchField label="Virtualization" />
          <Combobox.Content>
            {({ items }) => (
              <List
                height={Math.min(640, 34 * items.length)}
                width="100%"
                itemCount={items.length}
                itemSize={34}
                innerElementType={Combobox.List}
              >
                {({ index, style }) => (
                  <Combobox.Item
                    key={index}
                    item={items[index]}
                    index={index}
                    style={style}
                  >
                    {items[index].name}
                  </Combobox.Item>
                )}
              </List>
            )}
          </Combobox.Content>
        </Combobox>
      );
    };
    ```
  </Tab>

  <Tab title="Combobox and Combobox.Select Props">
    ```tsx theme={null}
    <Combobox
      items={items}
      itemToString={(item) => item?.name ?? ""}
      itemToKey={(item) => item?.id ?? null}
      multiple={false}
      onChange={setSelectedItem}
      filterOptions={{ keys: ["name"] }}
    />
    ```

    ## `Combobox` and `Combobox.Select` Props

    In addition to the props listed below, the `Combobox` and `Combobox.Select` components can accept any valid HTML `div` props.

    * The default `Combobox` also accepts the props listed in the [downshift UseComboboxProps type](https://github.com/downshift-js/downshift/blob/v8.5.0/typings/index.d.ts#L537).

    * The `Combobox.Select` component alternatively extends the [downshift UseSelectProps type](https://github.com/downshift-js/downshift/blob/v8.5.0/typings/index.d.ts#L340). Note: Props related to the input are not included for Combobox.Select, since there is no search field. (`defaultInputValue, inputId`, etc.)

    <ParamField path="defaultSelectedItem" type="Item">
      The default selected item for single-select combobox.
    </ParamField>

    <ParamField path="defaultSelectedItems" type="Item[]">
      The default selected item(s) for multi-select combobox.
    </ParamField>

    <ParamField path="disabled" type="boolean" default="false">
      Disables the combobox, preventing user interaction.
    </ParamField>

    <ParamField path="disableClearInputValueOnSelectItem" type="boolean">
      Prevent input from clearing when item is selected. **Note:** Only works with
      `Combobox` with `multiple={true}`
    </ParamField>

    <ParamField path="disableClearSelection" type="boolean" default="false">
      Remove the clear button to disable user clearing the input after selecting.
      **Note:** Only works with `Combobox.Select` with `multiple` is not `true`
    </ParamField>

    <ParamField path="disableCloseOnClickOutside" type="boolean" default="false">
      Prevent the drop-down popover from closing when the user clicks outside of it.
    </ParamField>

    <ParamField path="disableCloseOnSelectItem" type="boolean">
      Prevent the drop-down from closing when item is selected. **Note:** Only works
      with `Combobox` with `multiple={true}`
    </ParamField>

    <ParamField path="filterOptions" type="MatchSorterOptions">
      See the [match-sorter MatchSorterOptions
      type](https://github.com/kentcdodds/match-sorter/blob/v6.3.4/src/index.ts#L50)
      **Note:** Not available on `Combobox.Select`
    </ParamField>

    <ParamField path="groupBy" type="string">
      Name of the property on each item to group by. When provided, items are organized into labeled sections in the dropdown based on the value of this property.
    </ParamField>

    <ParamField path="groupSorter" type="(a: ComboboxGroupByValue, b: ComboboxGroupByValue) => number" default="(a, b) => String(a).localeCompare(String(b))">
      Function to compare two group values for sorting. Must return a negative number if `a` should appear before `b`, and a positive number if `b` should appear before `a`. `ComboboxGroupByValue` is `string | number`.
    </ParamField>

    <ParamField path="groupToString" type="(groupByValue: ComboboxGroupByValue) => string | null">
      Function to convert group values to display labels. When not provided, the raw group key value is used as the label. `ComboboxGroupByValue` is `string | number`.
    </ParamField>

    <ParamField path="multiple" type="boolean" default="false" />

    <ParamField path="onChange" type="(item: Item | null) => void | (items: Item[]) => void">
      Callback when selection changes. For single-select, receives the selected item or null. For multi-select, receives an array of selected items.
    </ParamField>

    <ParamField path="open" type="boolean" default="false" />

    <ParamField path="readOnly" type="boolean" default="false">
      Makes the combobox read-only, allowing focus but preventing changes.
    </ParamField>

    <ParamField path="selectAll" type="{ label?: string; onSelection: () => void; isChecked: boolean }">
      Configuration for "Select All" option in multi-select comboboxes. When provided, adds a "Select All"
      option at the top of the dropdown list. Only available when `multiple={true}`.
    </ParamField>
  </Tab>

  <Tab title="Combobox.SearchField and Combobox.SelectTrigger Props">
    ```tsx theme={null}
    <Combobox.SearchField
      id="combobox-1"
      label="Select an item"
      required={true}
      moreInfo="Additional information"
      prefix={{ icon: SearchIcon }}
    />
    ```

    ## `Combobox.SearchField` and `Combobox.SelectTrigger` Props

    <ParamField path="id" type="string" />

    <ParamField path="moreInfo" type="string" />

    <ParamField path="moreInfoOpen" type="boolean" default="false">
      Control opening the `moreInfo` tooltip.
    </ParamField>

    <ParamField path="prefix" type="string | { icon: IconProps }">
      Prefix content displayed before the input.
    </ParamField>

    <ParamField path="required" type="boolean" default="false" />

    <ParamField path="selectedItemProps" type="(Item) => ChipProps">
      This function passes the selected item as a parameter and returns an object to
      merge into the selected item `Chip` props.
    </ParamField>
  </Tab>

  <Tab title="Combobox.Content Props">
    ```tsx theme={null}
    <Combobox.Content disablePopover={false}>
      {({ items }) => (
        <Combobox.List>
          {items.map((item, index) => (
            <Combobox.Item key={item.id} item={item} index={index}>
              {item.name}
            </Combobox.Item>
          ))}
        </Combobox.List>
      )}
    </Combobox.Content>
    ```

    ## `Combobox.Content` Props

    <ParamField path="children" type="({ items, inputValue }) => ReactNode" />

    <ParamField path="disablePopover" type="boolean" default="false" />
  </Tab>

  <Tab title="Combobox.List Props">
    ```tsx theme={null}
    <Combobox.List>
      {items.map((item, index) => (
        <Combobox.Item key={item.id} item={item} index={index}>
          {item.name}
        </Combobox.Item>
      ))}
    </Combobox.List>
    ```

    ## `Combobox.List` Props

    <ParamField path="children" type="ReactNode" />
  </Tab>

  <Tab title="Combobox.Item Props">
    ```tsx theme={null}
    <Combobox.Item index={0} item={items[0]} disabled={false}>
      Item content
    </Combobox.Item>
    ```

    ## `Combobox.Item` Props

    <ParamField path="index" type="number" required />

    <ParamField path="item" type="Item" required />

    <ParamField path="children" type="ReactNode" />

    <ParamField path="disabled" type="boolean" />
  </Tab>

  <Tab title="Combobox.ItemAddNew Props">
    ```tsx theme={null}
    <Combobox.ItemAddNew onSelection={(inputValue) => console.log(inputValue)}>
      Add new item
    </Combobox.ItemAddNew>
    ```

    ## `Combobox.ItemAddNew` Props

    <ParamField path="children" type="ReactNode" />

    <ParamField path="onSelection" type="(inputValue) => void" />
  </Tab>

  <Tab title="Combobox.Empty Props">
    ```tsx theme={null}
    <Combobox.Empty>No results found</Combobox.Empty>
    ```

    ## `Combobox.Empty` Props

    <ParamField path="children" type="ReactNode" />
  </Tab>
</Tabs>
