Blueprint Select provides a comprehensive set of utilities, types, and helper functions that support all select components.
Pre-defined CSS class constants for styling select components.
/**
* CSS classes namespace containing all component styles
*/
namespace Classes {
/** Multi-select component class */
const MULTISELECT: string;
/** Multi-select popover class */
const MULTISELECT_POPOVER: string;
/** Multi-select popover with default width */
const MULTISELECT_POPOVER_DEFAULT_WIDTH: string;
/** Multi-select popover tag input margin */
const MULTISELECT_POPOVER_TAG_INPUT_MARGIN: string;
/** Multi-select tag input element */
const MULTISELECT_TAG_INPUT_INPUT: string;
/** Omnibar component class */
const OMNIBAR: string;
/** Omnibar overlay class */
const OMNIBAR_OVERLAY: string;
/** Select popover class */
const SELECT_POPOVER: string;
/** Suggest popover class */
const SUGGEST_POPOVER: string;
}
// Import as namespace from the package
import { Classes } from "@blueprintjs/select";Usage Examples:
import { Classes } from "@blueprintjs/select";
// Using namespace import (recommended)
const CustomSelect = () => (
<div className={`${Classes.SELECT_POPOVER} my-custom-select`}>
{/* Select component */}
</div>
);
// Multi-select example
const CustomMultiSelect = () => (
<div className={`${Classes.MULTISELECT_POPOVER} my-custom-multi-select`}>
{/* MultiSelect component */}
</div>
);
// Target specific elements with CSS
const styles = `
.${Classes.MULTISELECT_POPOVER} {
min-width: 300px;
}
.${Classes.OMNIBAR_OVERLAY} {
background-color: rgba(0, 0, 0, 0.9);
}
`;Utilities for managing "create new item" functionality.
/**
* Branded interface for create new item markers
*/
interface CreateNewItem {
__blueprintCreateNewItemBrand: "blueprint-create-new-item";
}
/**
* Creates a marker object representing "create new item" option
* @returns CreateNewItem marker object
*/
function getCreateNewItem(): CreateNewItem;
/**
* Type guard to check if an item is a CreateNewItem marker
* @param item - Item to check
* @returns True if item is a CreateNewItem marker
*/
function isCreateNewItem<T>(item: T | CreateNewItem | null | undefined): item is CreateNewItem;
/**
* Extracts the actual item from a potentially CreateNewItem value
* @param activeItem - Item that might be a CreateNewItem marker
* @returns The actual item or null if it was a CreateNewItem marker
*/
function getActiveItem<T>(activeItem: T | CreateNewItem | null | undefined): T | null;Usage Examples:
import { getCreateNewItem, isCreateNewItem, getActiveItem } from "@blueprintjs/select";
// Usage in a custom item renderer
const renderItemWithCreate: ItemRenderer<string> = (item, props) => {
if (isCreateNewItem(item)) {
return (
<div onClick={props.handleClick} style={{ padding: "8px", fontStyle: "italic" }}>
Create "{props.query}"
</div>
);
}
return (
<div onClick={props.handleClick} style={{ padding: "8px" }}>
{item}
</div>
);
};
// Usage in active item handling
const handleActiveItemChange = (activeItem: string | CreateNewItem | null) => {
const actualItem = getActiveItem(activeItem);
if (actualItem) {
console.log("Real item active:", actualItem);
} else if (isCreateNewItem(activeItem)) {
console.log("Create new item option is active");
} else {
console.log("No item active");
}
};
// Creating a new item marker
const createMarker = getCreateNewItem();
console.log(isCreateNewItem(createMarker)); // true
console.log(getActiveItem(createMarker)); // nullFunctions for comparing items for equality in select components.
/**
* Function type for comparing two items for equality
*/
type ItemsEqualComparator<T> = (itemA: T, itemB: T) => boolean;
/**
* Either a comparator function or a property key for equality checking
*/
type ItemsEqualProp<T> = ItemsEqualComparator<T> | keyof T;
/**
* Executes item equality comparison using the provided equality prop
* @param itemsEqualProp - Comparator function or property key
* @param itemA - First item to compare
* @param itemB - Second item to compare
* @returns True if items are considered equal
*/
function executeItemsEqual<T>(
itemsEqualProp: ItemsEqualProp<T> | undefined,
itemA: T | null | undefined,
itemB: T | null | undefined,
): boolean;Usage Examples:
import { executeItemsEqual, ItemsEqualComparator } from "@blueprintjs/select";
interface User {
id: number;
name: string;
email: string;
}
const users: User[] = [
{ id: 1, name: "Alice", email: "alice@example.com" },
{ id: 2, name: "Bob", email: "bob@example.com" },
];
// Using property key for equality
const user1 = users[0];
const user2 = { ...users[0] }; // Different object, same data
console.log(executeItemsEqual("id", user1, user2)); // true (same id)
console.log(executeItemsEqual("email", user1, user2)); // true (same email)
// Using custom comparator function
const userComparator: ItemsEqualComparator<User> = (a, b) => {
return a.id === b.id && a.email === b.email;
};
console.log(executeItemsEqual(userComparator, user1, user2)); // true
// Usage in select components
const UserSelect = () => (
<Select<User>
items={users}
itemRenderer={renderUser}
itemsEqual="id" // Use ID for equality comparison
onItemSelect={(user) => console.log("Selected:", user.name)}
/>
);
// Custom equality for complex objects
interface ComplexItem {
data: { nested: { value: string } };
metadata: Record<string, any>;
}
const complexComparator: ItemsEqualComparator<ComplexItem> = (a, b) => {
return a.data.nested.value === b.data.nested.value;
};
const ComplexItemSelect = () => (
<Select<ComplexItem>
items={complexItems}
itemRenderer={renderComplexItem}
itemsEqual={complexComparator}
onItemSelect={handleComplexItemSelect}
/>
);Default implementation for rendering filtered item lists.
/**
* Props passed to item list renderers
*/
interface ItemListRendererProps<T> {
/** Currently active item */
activeItem: T | CreateNewItem | null;
/** Items after filtering */
filteredItems: T[];
/** All items before filtering */
items: T[];
/** Current query string */
query: string;
/** Ref for the items container element */
itemsParentRef: React.Ref<HTMLUListElement>;
/** Props for the menu container */
menuProps?: React.HTMLAttributes<HTMLUListElement>;
/** Function to render each individual item */
renderItem: (item: T, index: number) => React.JSX.Element | null;
/** Function to render the create new item option */
renderCreateItem: () => React.JSX.Element | null | undefined;
}
/**
* Function type for rendering the entire list of items
*/
type ItemListRenderer<T> = (itemListProps: ItemListRendererProps<T>) => React.JSX.Element | null;
/**
* Default implementation for rendering filtered items with optional empty states
* @param props - Item list renderer props
* @param noResults - Content to show when no items match the filter
* @param initialContent - Content to show when no query is entered
* @returns Rendered item list
*/
function renderFilteredItems(
props: ItemListRendererProps<any>,
noResults?: React.ReactNode,
initialContent?: React.ReactNode | null,
): React.ReactNode;Usage Examples:
import { renderFilteredItems, ItemListRenderer } from "@blueprintjs/select";
// Custom item list renderer using the default implementation
const customItemListRenderer: ItemListRenderer<string> = (props) => {
const noResults = <div style={{ padding: "8px", textAlign: "center" }}>No items found</div>;
const initialContent = <div style={{ padding: "8px", color: "#666" }}>Start typing to search...</div>;
return (
<div>
{renderFilteredItems(props, noResults, initialContent)}
</div>
);
};
// More complex custom renderer with sections
const sectionedItemListRenderer: ItemListRenderer<Task> = (props) => {
const { filteredItems, renderItem } = props;
if (filteredItems.length === 0) {
return <div style={{ padding: "16px", textAlign: "center" }}>No tasks found</div>;
}
// Group by priority
const grouped = filteredItems.reduce((acc, item, index) => {
const priority = item.priority;
if (!acc[priority]) acc[priority] = [];
acc[priority].push({ item, index });
return acc;
}, {} as Record<string, Array<{ item: Task; index: number }>>);
return (
<div>
{Object.entries(grouped).map(([priority, items]) => (
<div key={priority}>
<div style={{ padding: "8px", background: "#f5f5f5", fontWeight: "bold" }}>
{priority.toUpperCase()} PRIORITY
</div>
{items.map(({ item, index }) => renderItem(item, index))}
</div>
))}
</div>
);
};
// Using the custom renderer in a Select component
const SectionedTaskSelect = () => (
<Select<Task>
items={tasks}
itemRenderer={renderTask}
itemListRenderer={sectionedItemListRenderer}
onItemSelect={(task) => console.log("Selected:", task.title)}
/>
);Shared type definitions used across all select components.
/**
* Function to render individual items in lists
*/
type ItemRenderer<T> = (item: T, itemProps: ItemRendererProps) => React.JSX.Element | null;
/**
* Properties passed to item renderers
*/
interface ItemRendererProps<T extends HTMLElement = HTMLLIElement> {
/** Ref for the item element */
ref?: React.Ref<T>;
/** Click handler for item selection */
handleClick: React.MouseEventHandler<HTMLElement>;
/** Focus handler (optional) */
handleFocus?: () => void;
/** Item index in the list */
index: number;
/** Item state modifiers */
modifiers: ItemModifiers;
/** Current search query */
query: string;
}
/**
* State flags for individual items
*/
interface ItemModifiers {
/** Whether this item is currently active/highlighted */
active: boolean;
/** Whether this item is disabled */
disabled: boolean;
/** Whether this item matches the current search predicate */
matchesPredicate: boolean;
}
/**
* Function to filter individual items
*/
type ItemPredicate<T> = (query: string, item: T, index?: number, exactMatch?: boolean) => boolean;
/**
* Function to filter and transform entire item lists
*/
type ItemListPredicate<T> = (query: string, items: T[]) => T[];
/**
* Configuration for popover behavior in select components
*/
interface SelectPopoverProps {
/** Props for popover content container */
popoverContentProps?: React.HTMLAttributes<HTMLDivElement>;
/** Props for Blueprint Popover component */
popoverProps?: Partial<Omit<PopoverProps, "content" | "defaultIsOpen" | "fill" | "renderTarget">>;
/** Ref for accessing popover instance */
popoverRef?: React.RefObject<Popover<DefaultPopoverTargetHTMLProps>>;
/** Props for popover target element */
popoverTargetProps?: React.HTMLAttributes<HTMLElement>;
}Legacy component names and types maintained for backward compatibility.
/** @deprecated Use MultiSelect instead */
const MultiSelect2 = MultiSelect;
/** @deprecated Use MultiSelectProps instead */
type MultiSelect2Props<T> = MultiSelectProps<T>;
/** @deprecated Use Select instead */
const Select2 = Select;
/** @deprecated Use SelectProps instead */
type Select2Props<T> = SelectProps<T>;
/** @deprecated Use Suggest instead */
const Suggest2 = Suggest;
/** @deprecated Use SuggestProps instead */
type Suggest2Props<T> = SuggestProps<T>;Migration Examples:
// Old (deprecated) usage
import { Select2, MultiSelect2, Suggest2 } from "@blueprintjs/select";
const OldSelect = () => <Select2 items={[]} itemRenderer={() => null} onItemSelect={() => {}} />;
// New (recommended) usage
import { Select, MultiSelect, Suggest } from "@blueprintjs/select";
const NewSelect = () => <Select items={[]} itemRenderer={() => null} onItemSelect={() => {}} />;