Components
MultiSelect
A multi-select dropdown composed of Popover and CheckboxGroup — flat or grouped options, keyboard navigation, controlled value
Installation
$npx litefy@latest add multi-select
$pnpm dlx litefy@latest add multi-select
$yarn dlx litefy@latest add multi-select
$bun --bun litefy@latest add multi-select
Usage
Basic
Selected: -
"use client";
import { useState } from "react";
import { MultiSelect, type CheckboxOptionConfig } from "@/ui";
const options: CheckboxOptionConfig[] = [
{ label: "Electronics", value: "electronics" },
{ label: "Clothing", value: "clothing" },
{ label: "Books", value: "books" },
{ label: "Sports", value: "sports" },
];
export default function Demo() {
const [values, setValues] = useState<string[]>([]);
return (
<div className="flex flex-col items-center gap-3">
<MultiSelect
options={options}
value={values}
onChange={setValues}
placeholder="Categories"
className="w-56"
classNames={{ content: "w-56" }}
/>
<p className="text-sm text-muted-foreground">
Selected: {values.length > 0 ? values.join(", ") : "-"}
</p>
</div>
);
}
Grouped
options also accepts { group, options } items for titled groups.
Fruits
Vegetables
Selected: -
"use client";
import { useState } from "react";
import { MultiSelect, type CheckboxOptionGroup } from "@/ui";
const groups: CheckboxOptionGroup[] = [
{
group: "Fruits",
options: [
{ label: "Apple", value: "apple" },
{ label: "Banana", value: "banana" },
{ label: "Cherry", value: "cherry" },
],
},
{
group: "Vegetables",
options: [
{ label: "Carrot", value: "carrot" },
{ label: "Potato", value: "potato" },
{ label: "Tomato", value: "tomato" },
],
},
];
export default function Demo() {
const [values, setValues] = useState<string[]>([]);
return (
<div className="flex flex-col items-center gap-3">
<MultiSelect
options={groups}
value={values}
onChange={setValues}
placeholder="Categories"
className="w-56"
classNames={{ content: "w-56" }}
/>
<p className="text-sm text-muted-foreground">
Selected: {values.length > 0 ? values.join(", ") : "-"}
</p>
</div>
);
}
Notes
- MultiSelect is composed internally from Popover and CheckboxGroup — installing via CLI resolves them automatically.
- The trigger always shows the selection count (e.g.
Categories (3)) to keep width stable and avoid layout shift. - Panel clicks never close it — only outside mousedown or Escape does — so users can toggle freely.
ArrowDown/ArrowUp(orArrowRight/ArrowLeft) cycle through checkboxes, skipping disabled items;Spacetoggles;Escapecloses the panel.
API Reference
MultiSelect
| Prop | Type | Default | Description |
|---|---|---|---|
options | (CheckboxOptionConfig | CheckboxOptionGroup)[] | - | Flat or grouped checkbox options |
value / defaultValue | string[] | [] | Selected values (controlled / uncontrolled) |
onChange | (values: string[]) => void | - | Fired when selection changes |
trigger | React.ReactNode | - | Custom trigger node (defaults to placeholder (count)) |
placeholder | string | "Select options" | Label shown when no custom trigger is provided |
className | ClassNameValue | - | Custom classes on the trigger button |
classNames | { content? } | - | Custom classes for the panel content |