The Select component allows users to choose one item from a dropdown list with optional filtering capabilities.
React component for single item selection from a dropdown list.
/**
* Select component for choosing one item from a dropdown list
* @template T - Type of items in the list
*/
class Select<T> extends React.Component<SelectProps<T>, SelectState> {
/** Generic factory method for type inference */
static ofType<U>(): new (props: SelectProps<U>) => Select<U>;
/** Reference to the input element */
inputElement: HTMLInputElement | null;
}
interface SelectProps<T> extends ListItemsProps<T>, SelectPopoverProps {
/** Child element that triggers the popover (typically a button) */
children?: React.ReactNode;
/** Whether the select is disabled */
disabled?: boolean;
/** Whether the select should fill its container */
fill?: boolean;
/** Whether to show a filter input in the dropdown */
filterable?: boolean;
/** Props for the filter input when filterable is true */
inputProps?: Partial<Omit<InputGroupProps, "value" | "onChange">>;
/** Props for the dropdown menu container */
menuProps?: React.HTMLAttributes<HTMLUListElement>;
/** Placeholder text for the filter input */
placeholder?: string;
/** Whether to reset the query when the popover closes */
resetOnClose?: boolean;
}
interface SelectState {
/** Whether the dropdown is currently open */
isOpen: boolean;
}Usage Examples:
import React, { useState } from "react";
import { Select, ItemRenderer } from "@blueprintjs/select";
import { Button, MenuItem } from "@blueprintjs/core";
interface City {
name: string;
country: string;
population: number;
}
const cities: City[] = [
{ name: "New York", country: "USA", population: 8400000 },
{ name: "London", country: "UK", population: 9000000 },
{ name: "Tokyo", country: "Japan", population: 14000000 },
];
const renderCity: ItemRenderer<City> = (city, { handleClick, modifiers, query }) => (
<MenuItem
key={`${city.name}-${city.country}`}
text={`${city.name}, ${city.country}`}
label={city.population.toLocaleString()}
onClick={handleClick}
active={modifiers.active}
disabled={modifiers.disabled}
/>
);
const CitySelect = () => {
const [selectedCity, setSelectedCity] = useState<City | null>(null);
return (
<Select<City>
items={cities}
itemRenderer={renderCity}
onItemSelect={setSelectedCity}
noResults={<MenuItem disabled text="No cities found." />}
filterable
resetOnClose
>
<Button
text={selectedCity ? `${selectedCity.name}, ${selectedCity.country}` : "Select a city..."}
rightIcon="caret-down"
/>
</Select>
);
};
// With custom filtering
const cityPredicate = (query: string, city: City) => {
return (
city.name.toLowerCase().includes(query.toLowerCase()) ||
city.country.toLowerCase().includes(query.toLowerCase())
);
};
const FilteredCitySelect = () => (
<Select<City>
items={cities}
itemRenderer={renderCity}
itemPredicate={cityPredicate}
onItemSelect={(city) => console.log("Selected:", city)}
>
<Button text="Select city with custom filter..." rightIcon="caret-down" />
</Select>
);Select components support extensive popover customization through SelectPopoverProps.
interface SelectPopoverProps {
/** Props passed to the popover content container */
popoverContentProps?: React.HTMLAttributes<HTMLDivElement>;
/** Props passed to the Blueprint Popover component */
popoverProps?: Partial<Omit<PopoverProps, "content" | "defaultIsOpen" | "fill" | "renderTarget">>;
/** Ref to access the popover instance */
popoverRef?: React.RefObject<Popover>;
/** Props passed to the popover target element */
popoverTargetProps?: React.HTMLAttributes<HTMLElement>;
}Usage Examples:
import { Select } from "@blueprintjs/select";
import { Button } from "@blueprintjs/core";
// Customize popover positioning and behavior
const CustomPopoverSelect = () => (
<Select<string>
items={["Option 1", "Option 2", "Option 3"]}
itemRenderer={(item, { handleClick, modifiers }) => (
<div onClick={handleClick} style={{ padding: "8px" }}>
{item}
</div>
)}
onItemSelect={(item) => console.log(item)}
popoverProps={{
position: "bottom-left",
minimal: true,
modifiers: {
preventOverflow: { enabled: true },
},
}}
popoverContentProps={{
style: { minWidth: "200px" },
}}
>
<Button text="Custom popover..." />
</Select>
);Select supports both item-level and list-level filtering predicates.
// From common types
type ItemPredicate<T> = (query: string, item: T, index?: number, exactMatch?: boolean) => boolean;
type ItemListPredicate<T> = (query: string, items: T[]) => T[];Usage Examples:
// Item predicate - filters individual items
const itemPredicate: ItemPredicate<City> = (query, city, index, exactMatch) => {
if (exactMatch) {
return city.name.toLowerCase() === query.toLowerCase();
}
return (
city.name.toLowerCase().includes(query.toLowerCase()) ||
city.country.toLowerCase().includes(query.toLowerCase())
);
};
// List predicate - custom sorting and filtering
const itemListPredicate: ItemListPredicate<City> = (query, cities) => {
if (!query) return cities;
const filtered = cities.filter(city =>
city.name.toLowerCase().includes(query.toLowerCase()) ||
city.country.toLowerCase().includes(query.toLowerCase())
);
// Sort by relevance
return filtered.sort((a, b) => {
const aStartsWithQuery = a.name.toLowerCase().startsWith(query.toLowerCase());
const bStartsWithQuery = b.name.toLowerCase().startsWith(query.toLowerCase());
if (aStartsWithQuery && !bStartsWithQuery) return -1;
if (!aStartsWithQuery && bStartsWithQuery) return 1;
return a.name.localeCompare(b.name);
});
};
const AdvancedFilterSelect = () => (
<Select<City>
items={cities}
itemRenderer={renderCity}
itemListPredicate={itemListPredicate}
onItemSelect={(city) => console.log("Selected:", city)}
filterable
>
<Button text="Advanced filtering..." />
</Select>
);