A combobox componente for Chakra UI.
npm install chakra-comboboxchakra-combobox is a library based on Chakra UI that provides an asynchronous Combobox component with support for option virtualization, dynamic data loading, and multiple selection.
Before using chakra-combobox, install the necessary dependencies:
``sh`
pnpm add @chakra-ui/react @emotion/react
If using npm or yarn:
`sh`
npm install @chakra-ui/react @emotion/react
or
`sh`
yarn add @chakra-ui/react @emotion/react
`tsx
import { AsyncCombobox } from "chakra-combobox";
import { useState } from "react";
import { useInfiniteQuery } from "@tanstack/react-query";
import { getDogBreeds } from "../api/dogs";
const initialPage = 1;
export const BasicAsyncCombobox = () => {
const [search, setSearch] = useState("");
const {
data: dogs,
fetchNextPage,
hasNextPage,
isLoading,
isFetchingNextPage,
isSuccess,
} = useInfiniteQuery({
queryKey: ["dogs", search],
queryFn: ({ pageParam = 0 }) =>
getDogBreeds({ page: pageParam + 1, limit: 10, search }),
initialPageParam: initialPage - 1,
getNextPageParam: (data, _, page) => {
if (data.hasNextPage) return page + 1;
return;
},
});
const parsedDogsData = isSuccess
? dogs?.pages.map(page => page.data).flat()
: [];
const [value, setValue] = useState
return (
fetchNextPage={fetchNextPage}
getOptionLabel={option => option.name}
getOptionValue={option => option.id.toString()}
onSearchChange={value => setSearch(value)}
isLoading={isLoading}
isFetchingNextPage={isFetchingNextPage}
placeholder="Select a dog"
hasNextPage={hasNextPage}
value={value}
onSelect={setValue}
/>
);
};
`
`tsx
import { AsyncCombobox } from "chakra-combobox";
import { useState } from "react";
import { useInfiniteQuery } from "@tanstack/react-query";
import { getDogBreeds } from "../api/dogs";
const initialPage = 1;
export const MultipleSelectionCombobox = () => {
const [search, setSearch] = useState("");
const {
data: dogs,
fetchNextPage,
hasNextPage,
isLoading,
isFetchingNextPage,
isSuccess,
} = useInfiniteQuery({
queryKey: ["dogs", search],
queryFn: ({ pageParam = 0 }) =>
getDogBreeds({ page: pageParam + 1, limit: 10, search }),
initialPageParam: initialPage - 1,
getNextPageParam: (data, _, page) => {
if (data.hasNextPage) return page + 1;
return;
},
});
const parsedDogsData = isSuccess
? dogs?.pages.map(page => page.data).flat()
: [];
const [value, setValue] = useState
return (
fetchNextPage={fetchNextPage}
getOptionLabel={option => option.name}
getOptionValue={option => option.nameWithId}
onSearchChange={value => setSearch(value)}
isLoading={isLoading}
isFetchingNextPage={isFetchingNextPage}
placeholder="Select dogs"
hasNextPage={hasNextPage}
value={value}
onSelect={setValue}
withCheckmark
listboxProps={{
Root: {
selectionMode: "multiple",
},
}}
/>
);
};
`
Props| Property | Type | Description |
| ------------------------ | ----------------------------------------- | ----------------------------------------------------------- |
| options | OptionType[] | List of available options. |value
| | string[] \| undefined | Selected values (array for multiple selection). |onSelect
| | (option: string[] \| undefined) => void | Function triggered when options are selected. |getOptionLabel
| | (option: OptionType) => string | Function returning the option label. |getOptionValue
| | (option: OptionType) => string | Function returning the option value. |placeholder
| | string | Input placeholder text. |onSearchChange
| | (search: string) => void | Function called when typing in the search input. |isLoading
| | boolean | Indicates if data is being loaded. |isFetchingNextPage
| | boolean | Indicates if the next page is being loaded. |hasNextPage
| | boolean | Indicates if there are more options to load. |fetchNextPage
| | () => void | Function to load more options. |isClearable
| | boolean (optional) | Indicates whether the combobox is clearable. |insideDialog
| | boolean (optional) | Set to false when inside dialogs to prevent z-index issues. |closeOnSelect
| | boolean (optional) | Close the dropdown when an option is selected. |dropdownIndicator
| | ElementType (optional) | Custom component to render the dropdown indicator. |loadingElement
| | ReactNode (optional) | Custom loading message element. |emptyElement
| | ReactNode (optional) | Custom empty message element. |searchInputPlaceholder
| | string (optional) | Custom placeholder for the search input. |chakraStyles
| | AsyncComboboxChakraStyles (optional) | Customize the component styles. |listboxProps
| | ListboxProps (optional) | Custom props for the listbox component. |withIndicator
| | boolean (optional) | Whether to show the dropdown indicator. |withCheckmark
| | boolean (optional) | Whether to show checkmarks for selected items. |
To enable multiple selection, configure the listboxProps:
`tsx`
listboxProps={{
Root: {
selectionMode: "multiple",
},
}}
withCheckmark // Shows checkmarks for selected items
/>
When using the combobox inside dialogs or modals, set insideDialog to prevent z-index issues:
`tsx`
insideDialog
/>
chakra-combobox allows style customization via the chakraStyles property. The library exports the AsyncComboboxChakraStyles type, which you can use to ensure type safety when defining your custom styles:
`tsx
import { AsyncCombobox, type AsyncComboboxChakraStyles } from "chakra-combobox";
// ... other imports and component code
const customStyles: AsyncComboboxChakraStyles = {
control: base => ({ ...base, borderColor: "blue.500" }),
popoverContentCss: base => ({ ...base, background: "gray.50" }),
option: base => ({ ...base, color: "black" }),
};
chakraStyles={customStyles}
/>;
`
The component uses react-virtual to render only visible elements on the screen, improving performance when dealing with large lists.
For a full demonstration and detailed documentation, visit the Storybook Documentation.
- Breaking Change: Added support for multiple selection
- Breaking Change: value prop now expects string[] | undefined instead of a single optiononSelect
- Breaking Change: callback now receives string[] | undefinedlistboxProps
- New: Added for configuring the underlying listbox componentwithCheckmark
- New: Added prop to show selection indicatorswithIndicator
- New: Added prop to control dropdown indicator visibilityisClearable
- New: Added prop for clearable functionalityinsideDialog
- Improved: Better TypeScript support with generic types
- Improved: Enhanced dialog/modal support with prop
chakra-combobox` is a flexible solution for creating highly customizable asynchronous dropdowns with multiple selection support, optimized for performance and seamlessly integrated with Chakra UI.