van-select
v0.1.13
Published
`VanSelect` is a VanJS select component with a controlled `van.state` API, built in TypeScript and styled with CSS variables.
Downloads
97
Readme
VanSelect
VanSelect is a VanJS select component with a controlled van.state API, built in TypeScript and styled with CSS variables.
Install
van-select depends on vanjs-core as a peer dependency, so install both packages in your app.
Using Bun:
bun add van-select vanjs-coreUsing npm:
npm install van-select vanjs-coreDevelopment
bun run devThis starts the demo app in demo, which imports the library from local source.
Verification
bun run checkUseful commands:
bun run lint
bun run typecheck
bun run test
bun run build
bun run formatLibrary
The public package is van-select. It exports a single Select component and the supporting types:
SelectOptionSelectOptionGroupSelectOptionInputSelectOptionFormatLabelSelectOptionLabelContextSelectProps
Example
import van from "vanjs-core";
import { Select } from "van-select";
import type { SelectOption } from "van-select";
import "van-select/styles.css";
const options: SelectOption<string>[] = [
{ value: "sprinter", label: "Mercedes Sprinter" },
{ value: "transit", label: "Ford Transit" },
{ value: "ducato", label: "Fiat Ducato" },
];
const value = van.state<SelectOption<string> | null>(null);
const inputValue = van.state("");
van.add(
Select({
options,
value,
inputValue,
clearable: true,
placeholder: "Choose a van",
}),
);Multi Select
const value = van.state<SelectOption<string>[]>([]);
const inputValue = van.state("");
van.add(
Select({
multiple: true,
options,
value,
inputValue,
maxVisibleSelections: 2,
placeholder: "Add vans",
}),
);Async lookup
Pass loadOptions(query) for remote search.
Select({
options: [],
value,
inputValue,
debounceMs: 180,
loadOptions: async (query) => fetch(`/api/vans?q=${encodeURIComponent(query)}`).then((r) => r.json()),
loadingText: "Searching remote inventory...",
noOptionsText: "No matches found",
errorText: (message) => `Search failed: ${message}`,
});Reactive option labels
formatOptionLabel receives reactive metadata for each dropdown item. Use it for checkmarks, badges, or other stateful adornments.
const { span } = van.tags;
Select({
multiple: true,
options,
value,
inputValue,
formatOptionLabel: (option, meta) =>
span(
{ class: "van-option" },
span({ class: "van-option__check" }, () =>
meta.selected.val ? "✓" : "",
),
span(option.label),
),
});Props
optionsvalueinputValue?multiple?clearable?disabled?autocomplete?placeholder?themeClass?debounceMs?loadOptions?loadingText?emptyText?noOptionsText?maxVisibleSelections?focusOnOpen?errorText?onOpenChange?onSearch?formatOptionLabel?formatValueLabel?
Set focusOnOpen: false to open the menu without focusing the input. This avoids opening the virtual keyboard on the first tap; after the menu is open, tapping the input still focuses it for search.
formatOptionLabel(option, meta) receives reactive selected and highlighted states for each dropdown item.
Theming
Import the default styles with import "van-select/styles.css";. The stylesheet is also exposed at src/ui/styles.css in the source tree. Override CSS variables or add a themeClass.
Demo
The demo in demo includes scenarios for:
- local single select
- local multi select
- grouped options
- disabled state
- clearable state
- async search
- loading, empty, and error states
- custom theming
Testing
Library tests live in tests.
