Skip to main content

Overview

The select menu family includes two components for different use cases:
  • SelectMenu — For async data loading with support for pagination (page-based, offset-based, or group-based lazy loading)
    • Includes automatic debouncing of the search input (configurable via the debounceMs prop)
    • Includes automatic caching of the search input (configurable via the cache prop)
  • SelectMenuSync — For client-side filtering of static option arrays
Both components attach a searchable dropdown to any trigger element via a trigger render prop. The menu closes after an option is selected. Use SelectMenu when you need selection behavior outside of a form field context — for example, attaching a dropdown to a button, icon, or custom element.
Looking for a form field with a built-in label, error state, and input? Use SelectField instead.

SelectMenuSync (Static Options)

Use SelectMenuSync when you have a static list of options that can be filtered client-side.

Filtering and Sorting

By default, SelectMenuSync uses match-sorter to filter options by their label and searchText fields. Results are also ranked by match quality, so the best matches appear first. Before any search is performed, options appear in the order they are supplied. You can customize this behavior in two ways:

Using match-sorter options

Pass a match-sorter options object to customize the default filtering and sorting behavior (e.g., change which keys are matched or adjust ranking):

Using a custom filter function

Pass a function for full control over both filtering and sort order. The returned array determines the exact order options appear in the dropdown:

SelectMenu (Async Loading)

Use SelectMenu when options need to be fetched from an API or when dealing with large datasets that require server-side filtering.

Basic Async Loading

Lazy Loading Modes

SelectMenu supports three lazy loading modes for paginated data:

Page-based Pagination

Offset-based Pagination

Group-based Loading

For loading grouped options incrementally:

Display Modes

Control how the options menu is displayed using the displayMenuAs prop:

Popover Width

Control the width of the popover using the width prop:

Caching

SelectMenu caches loadOptions results by default. Configure caching behavior:

Clearing the Cache

Use a ref to imperatively clear the cache:

Invalidating Options

Call invalidate() to clear the cache and reload options from the data source. Use this when the underlying data has changed and the component needs to reflect the update:
SelectMenuSync handles this automatically when its options prop changes.

Initial Load Behavior

Control when options are first loaded with the initialLoad prop:
Pass disableSearch to remove the search input from inside the menu. The menu renders only the option list, and keyboard focus moves directly to the list container.This is useful when the option list is short and well-known or you are integrating with an API that does not support search.

Disabled Options

Individual options can be disabled by setting disabled: true on the option:

Pinned Options

Pin frequently used or suggested options above the list using the pinned prop. Each pinned section requires a label and an options value, which can be a static array or a dynamic loader function.

Static Pinned Options

Pass an object with label and a static options array:

Dynamic Pinned Options

Pass a function as options to compute pinned options based on the current search value:
By default, the loader re-runs whenever the search value changes. Set searchReactive: false to call the loader once and reuse the result across all search values:

Multiple Pinned Sections

Pass an array of pinned section objects:

Grouping Options

Options can be organized into visual groups by adding a group property to each option. Groups appear as labeled sections in the dropdown.

Basic Grouping

Add a group property to options and provide a groupToString function to display group labels:

Group Sorting

Use groupSorter to control the order of groups. By default, groups appear in the order they are first encountered in the options array.This prop is available on SelectMenuSync and non-lazy SelectMenu:
Avoid using groupSorter with lazy="group". When groups load incrementally from the server and get re-sorted, the menu content shifts unexpectedly, creating a disorienting user experience. Instead, have your server return groups in the desired order.

Virtualization

By default, all dropdown options render to the DOM at once. This works well for typical lists but degrades performance with very large option sets. Pass virtualize to enable windowed rendering, which only renders the items currently visible in the scroll viewport plus a small overscan buffer.Consider enabling virtualize when the dropdown feels sluggish to open or keyboard navigation becomes laggy. These symptoms typically appear around 200-500 items depending on device performance and item complexity.

Clear Button

Pass a clear config to render a “Clear” button in the menu footer. Clicking Clear fires the provided onClick handler and closes the menu; consumers typically use it to reset their selection state.
The footer layout adapts automatically when other footer affordances are present:
  • Clear alone — full-width row.
  • Clear + Add new — Add-new stacks full-width above Clear.

Adding New Items

Provide an onAddNewItem handler to render an “Add new item” button below the option list. This affordance lets users create a value that does not exist yet — a new category, tag, or job type — quickly from the menu.The button sits in a footer region inside the menu. Clicking or activating it via keyboard closes the menu and invokes the onAddNewItem handler with the current search text.From here, it is your responsibility to launch a Dialog (or Drawer, or any other overlay) for collecting the new item’s details, append the result to the option source, invalidate the cache, and update selection state.You may pair onAddNewItem with addItemLabel to control the button text. The label accepts a static node or a function of the current search text — for example, returning Add "foo" when the user has typed foo.When addItemLabel is a function, return null (or undefined) to hide the button for the current search text. Use this when the affordance should only appear for valid input — for example, showing “Add email” only after a well-formed address is typed:
Call invalidate() on the imperative handle after appending the new option. This clears the cached search results and forces a refetch the next time the menu opens, so the new item appears immediately. clearCache() alone wipes the cache but keeps the previously displayed options on screen until something else triggers a reload.
Last modified on July 13, 2026