Skip to content
Components

Listbox

Keep choices visible with clear selection and keyboard movement.

TS
import { … } from "@fungi.computer/caps/components/listbox";

Hero

TSX
import { useState } from "react";
import { Listbox } from "@fungi.computer/caps/components/listbox";
type Spot = { id: string; name: string };
const spots: Spot[] = [
{ id: "oak-hollow", name: "Oak hollow" },
{ id: "mossy-ridge", name: "Mossy ridge" },
{ id: "creek-bend", name: "Creek bend" },
];
export default function Hero() {
const [value, setValue] = useState<string | null>("mossy-ridge");
return (
<Listbox
aria-label="Foraging spots"
getKey={(item) => item.id}
getLabel={(item) => item.name}
items={spots}
onValueChange={setValue}
value={value}
/>
);
}

Multiple

TSX
import { useState } from "react";
import { Listbox } from "@fungi.computer/caps/components/listbox";
type Tag = { id: string; name: string };
const tags: Tag[] = [
{ id: "edible", name: "Edible" },
{ id: "medicinal", name: "Medicinal" },
{ id: "toxic", name: "Toxic" },
];
export default function Multiple() {
const [value, setValue] = useState<string[]>(["edible"]);
return (
<Listbox
aria-label="Tag this mushroom"
getKey={(item) => item.id}
getLabel={(item) => item.name}
items={tags}
multiple
onValueChange={setValue}
value={value}
/>
);
}

Disabled and empty

TSX
import { useState } from "react";
import { Listbox } from "@fungi.computer/caps/components/listbox";
type Spot = { id: string; name: string; closed?: boolean };
const spots: Spot[] = [
{ id: "oak-hollow", name: "Oak hollow" },
{ id: "flooded-field", name: "Flooded field", closed: true },
];
export default function DisabledAndEmpty() {
const [value, setValue] = useState<string | null>(null);
return (
<div className="flex w-full max-w-sm gap-3">
<Listbox
aria-label="Open spots"
getKey={(item) => item.id}
getLabel={(item) => item.name}
isDisabled={(item) => Boolean(item.closed)}
items={spots}
onValueChange={setValue}
value={value}
/>
<Listbox
aria-label="Saved spots"
getKey={(item: Spot) => item.id}
getLabel={(item: Spot) => item.name}
items={[]}
/>
</div>
);
}

Props

ListboxProps

PropTypeDescription
emptyMessage?ReactNode
getKey()(item) => stringReturns the stable key used for focus and selection.
getLabel()(item) => stringReturns the accessible label used for an item.
isDisabled()?(item) => booleanDetermines whether an item can receive focus or selection.
itemsreadonly T[]
rootRef?React.Ref<HTMLDivElement>Receives the selection control's root div.
renderItem()?(item, active, state) => ReactNodeRenders an item with its intrinsic focus and selection state.
  • emptyMessage?ReactNode
  • getKey()(item) => string

    Returns the stable key used for focus and selection.

  • getLabel()(item) => string

    Returns the accessible label used for an item.

  • isDisabled()?(item) => boolean

    Determines whether an item can receive focus or selection.

  • itemsreadonly T[]
  • rootRef?React.Ref<HTMLDivElement>

    Receives the selection control's root div.

  • renderItem()?(item, active, state) => ReactNode

    Renders an item with its intrinsic focus and selection state.

ListboxProps

PropTypeDescription
T-
Multiple extends booleanfalse
  • T-
  • Multiple extends booleanfalse

Full types: API reference.