Skip to content
Components

Combobox

Search a longer list without losing keyboard selection or a clear current value.

TS
import { … } from "@fungi.computer/caps/components/combobox";
TSX
import { useState } from "react";
import { Combobox } from "@fungi.computer/caps/components/combobox";
type Mushroom = { id: string; name: string };
const mushrooms: Mushroom[] = [
{ id: "chanterelle", name: "Chanterelle" },
{ id: "morel", name: "Morel" },
{ id: "lions-mane", name: "Lion's mane" },
];
export default function InlineSearch() {
const [value, setValue] = useState<string | null>("morel");
return (
<Combobox
aria-label="Find a mushroom"
getKey={(item) => item.id}
getLabel={(item) => item.name}
items={mushrooms}
onValueChange={setValue}
placeholder="Search mushrooms…"
value={value}
/>
);
}

Trigger popup

TSX
import { useState } from "react";
import {
Combobox,
ComboboxTrigger,
} from "@fungi.computer/caps/components/combobox";
type Spot = { id: string; name: string; biome: string };
const spots: Spot[] = [
{ id: "oak-hollow", name: "Oak hollow", biome: "Deciduous" },
{ id: "mossy-ridge", name: "Mossy ridge", biome: "Conifer" },
{ id: "creek-bend", name: "Creek bend", biome: "Riparian" },
];
export default function TriggerPopup() {
const [value, setValue] = useState<string | null>("mossy-ridge");
const current = spots.find((spot) => spot.id === value);
return (
<Combobox
aria-label="Choose a foraging spot"
defaultOpen
getKey={(item) => item.id}
getLabel={(item) => item.name}
groupBy={(item) => item.biome}
items={spots}
onValueChange={setValue}
trigger={
<ComboboxTrigger>{current?.name ?? "Choose a spot"}</ComboboxTrigger>
}
value={value}
/>
);
}

Multiple selection

TSX
import { useState } from "react";
import { Combobox } from "@fungi.computer/caps/components/combobox";
type Tag = { id: string; name: string };
const tags: Tag[] = [
{ id: "edible", name: "Edible" },
{ id: "medicinal", name: "Medicinal" },
{ id: "toxic", name: "Toxic" },
{ id: "unknown", name: "Unknown" },
];
export default function MultipleSelection() {
const [value, setValue] = useState<string[]>(["edible"]);
return (
<div className="flex w-full max-w-sm flex-col gap-2">
<Combobox
aria-label="Tag this mushroom"
getKey={(item) => item.id}
getLabel={(item) => item.name}
items={tags}
multiple
onValueChange={setValue}
value={value}
/>
<p className="text-xs text-base-content">
{value.length ? value.join(", ") : "No tags yet"}
</p>
</div>
);
}

Props

ComboboxProps

PropTypeDescription
T
  • T

ComboboxBaseProps

PropTypeDescription
activeTone?"neutral" | "primary"Color intent for the locally active option.
container?BasePopover.Portal.Props["container"]Native portal destination. Use an unclipped themed container for nested themes.
contentClassName?string
emptyMessage?ReactNode
getKey()(item) => stringReturns the stable identity used to track and compare items.
getLabel()(item) => stringReturns the text shown for an item in the trigger and the list.
getSearchText()?(item) => stringReturns the text matched against caller input; defaults to the item's label.
groupBy()?(item) => stringReturns the heading an item is grouped under in the list.
id?stringIdentifies the popup trigger or inline input for native label association.
inputProps?Omit<React.InputHTMLAttributes<HTMLInputElement>, "defaultValue" | "value">
inputRef?React.Ref<HTMLInputElement>
rootRef?React.Ref<HTMLDivElement>Receives the selection control's root div.
isDisabled()?(item) => booleanReturns whether an item is unselectable.
itemsreadonly T[]
placeholder?string
renderItem()?(item, active, state) => ReactNodeRenders one item's content; defaults to its label.
  • activeTone?"neutral" | "primary"

    Color intent for the locally active option.

  • container?BasePopover.Portal.Props["container"]

    Native portal destination. Use an unclipped themed container for nested themes.

  • contentClassName?string
  • emptyMessage?ReactNode
  • getKey()(item) => string

    Returns the stable identity used to track and compare items.

  • getLabel()(item) => string

    Returns the text shown for an item in the trigger and the list.

  • getSearchText()?(item) => string

    Returns the text matched against caller input; defaults to the item's label.

  • groupBy()?(item) => string

    Returns the heading an item is grouped under in the list.

  • id?string

    Identifies the popup trigger or inline input for native label association.

  • inputProps?Omit<React.InputHTMLAttributes<HTMLInputElement>, "defaultValue" | "value">
  • inputRef?React.Ref<HTMLInputElement>
  • rootRef?React.Ref<HTMLDivElement>

    Receives the selection control's root div.

  • isDisabled()?(item) => boolean

    Returns whether an item is unselectable.

  • itemsreadonly T[]
  • placeholder?string
  • renderItem()?(item, active, state) => ReactNode

    Renders one item's content; defaults to its label.

ComboboxBaseProps

PropTypeDescription
T
  • T

ComboboxPopupProps

PropTypeDescription
defaultOpen?boolean
onOpenChange()?(open) => voidCalled after the popup's open state changes.
open?never
triggerReactElement<ButtonHTMLAttributes<HTMLButtonElement>>
triggerRef?React.Ref<HTMLButtonElement>
  • defaultOpen?boolean
  • onOpenChange()?(open) => void

    Called after the popup's open state changes.

  • open?never
  • triggerReactElement<ButtonHTMLAttributes<HTMLButtonElement>>
  • triggerRef?React.Ref<HTMLButtonElement>

ComboboxPopupProps

PropTypeDescription
defaultOpen?never
onOpenChange()?(open) => voidCalled after the popup's open state changes.
openboolean
triggerReactElement<ButtonHTMLAttributes<HTMLButtonElement>>
triggerRef?React.Ref<HTMLButtonElement>
  • defaultOpen?never
  • onOpenChange()?(open) => void

    Called after the popup's open state changes.

  • openboolean
  • triggerReactElement<ButtonHTMLAttributes<HTMLButtonElement>>
  • triggerRef?React.Ref<HTMLButtonElement>

ComboboxValueProps

PropTypeDescription
T
  • T

ComboboxValueProps

PropTypeDescription
multipletrue
valuereadonly string[]
defaultValue?never
onValueChange()?(value, items) => voidCalled with the newly selected keys and items.
  • multipletrue
  • valuereadonly string[]
  • defaultValue?never
  • onValueChange()?(value, items) => void

    Called with the newly selected keys and items.

Full types: API reference.