Selecting a value from a dropdown list of options.
The component can be imported via:
To use the Select component, pass in the following props:
label - a string label to render above the select
ariaLabelledby or ariaLabel may be usedvalue - the string value of the currently selected optiononChange - a callback to set the value stateoptions - an array of objects to render in the select dropdown menu. The objects should contain the following keys:
value - a string value, which corresponds to the value proplabel - a string text label to render in the dropdown menudescription - optional, a string with additional descriptive text to display below the labelsearchLabel - optional, a string used for searching the options (if different than the label)icon - a PlumaIcon name to render next to the optionisDisabled - optional, whether this options should be disabled (not selectable)tooltip - optional, a string tooltip to show on hoverwithTruncatedTooltip - optional, automatically show a tooltip when the label is truncatedplaceholder - a placeholder value to show when no option is selectedA Select component can be used to select multiple values, which can be enabled
via the isMulti prop.
When isMulti is true, there are two important differences from the single value case:
value prop is an array of strings (the values of the selected options)onChange callback is called with an array of stringsYou can add descriptive text below an option's label:
Individual options can be disabled:
Enabling isSearchable on the component will render a search input inside the
select dropdown, which allows users to filter the options:
When using a searchable Select, you can allow users to create new options when their search doesn't match any existing options. This is useful for fields like tags, categories, or any user-defined values where the list of options should be dynamic.
Enable this feature with the withCreate and onCreate props:
withCreate - enables the "Create new" option when no exact match is foundonCreate - callback that receives the search value when "Create new" is selectedcreateOptionLabel - optional custom label for the "Create new" option (default: Create "{value}")
canCreateNewOption - optional function to control when the "Create new" option appears
The label shown for the "Create new" option can be customized using the createOptionLabel prop.
It accepts a string or a function that receives the search value:
The canCreateNewOption callback can be used to control whether specific values
should show/not show the "Create new" option, for example if we want to prevent
creation of items that have special names.
You can pass in groups of options to the selects to create breaks between sets of options:
An entire group can be disabled by setting its option entry to isDisabled:
The Select component supports making groups collapsible - where clicking
on the group's header will collapse/expand the group. This is enabled by
including an isCollapsible key on the group's object - when set to true,
that group will be collapsible.
Additionally, the defaultIsCollapsed key can be used to make a group collapsed
by default when first opening the dropdown.
For very long lists of options (hundreds, thousands of items), rendering the dropdown content may become very slow. For these cases, the Select component supports rendering "virtualized" lists, i.e. it will only render a small subset of options within the dropdown, and will update accordingly as users scroll through it.
For virtualization we use the TanStack Virtual library (both in Ember and React).
This option is disabled by default, and can be enabled via the withVirtualizer argument.
Optionally, the virtualizerOptions argument accepts the same options as the library's
Virtualizer class,
allowing you to customize the behavior if necessary.
The Select component accepts valueComponent, optionItemComponent, and optionComponent props,
which can be used to customize how the selected value, and the options in the dropdown,
are rendered.
To use them, you will need to pass in a component as the prop.
valueComponent is the component that will be used to render the selected value
in the Select's trigger. It will be called with the following props:
option - the option object from the options arrayoptionItemComponent is the component that renders each option button in the dropdown.
This needs to be customized carefully, as this is the component to which various
events and props are attached, to support features like keyboard navigation, focus management,
and accessibility via aria props.
Pluma also exports a SelectMenuOptionButton component, which is the one used
internally for these options. When customizing, it is recommended to use this component
as a base to make sure the basic styling and behavior is preserved.
This component is called with:
option - the option object from the options arrayisSelected - whether this is the currently selected option (the value matches this option)isActive - whether this is the currently active option (it's currently hovered or focused via keyboard)isDisabled - whether this option is disabledindex - the index of this option in the listlevel - the nesting level of this optioncollapsibleParentsCount - the number of collapsible parent groups (this, and the one below, are used internally
to apply the correct padding to nested options))nonCollapsibleParentsCount - the number of non-collapsible parent groupslabelRef - (only in React) a ref to an element inside the option that could become
truncated - this is used to detect when an option is truncated to optionally show a tooltipsetLabelElement - (only in Ember) like above, but for Ember - a callback to set the
potentially truncated elementoptionComponent - the component that renders this element's contentsoptionComponent is the content rendered inside the option button (inside optionItemComponent).
It will be called with the following props:
option - the option object from the options arrayisSelected - whether this is the currently selected option (the value matches this option)isActive - whether this is the currently active option (it's currently hovered or focused via keyboard)labelRef - (only in React) a ref to an element inside the option that could become
truncated - this is used to detect when an option is truncated to optionally show a tooltipsetLabelElement - (only in Ember) like above, but for Ember - a callback to set the
potentially truncated element
If you intend to enable withTruncatedTooltip on a customized optionComponent,
it is required to set the labelRef (in React) or call setLabelElement (in Ember)
with the element that might get truncated - otherwise the tooltip won't be able
to detect the truncation.The same component may be used for both valueComponent and optionComponent.
For example, we might define a custom option component like this:
Which could then be used in the Select component:
You may find that customizing the entire option may be too heavy-handed. Instead, you may just need to customize the icon area that prefixes the option.
For such cases, the Select component also accepts an iconComponent prop,
which can be used to customize how the icons next to the options are rendered.
To use iconComponent, you will need to pass in a component as the prop.
iconComponent will be called with the following props:
name - the name of the icon (this value will be the same as icon on the option)isSelected - whether the option this icon is a part of is currently selectedsize - the size of the control (which will either be sm or md, as per the size prop)For example, we might define a custom icon component like this:
Which could then be used in the Select component:
Individual options can display a tooltip on hover by setting the tooltip property
on the option object.
The tooltip placement can be customized with tooltipPlacement
(defaults to 'right'), though it's recommended to avoid using top or bottom
placements, as they would overlap with other options in the dropdown and make it
more difficult to navigate.
When options may have long labels that get truncated by CSS, setting withTruncatedTooltip
to true on the option will automatically show a tooltip only when the label text is
actually truncated. The tooltip content defaults to the option's label, but can be
overridden by also setting tooltip.
When you need tooltips with rich content like links or formatted text, use the
optionItemComponent prop
to wrap the default SelectMenuOptionButton with a custom Tooltip.
The custom optionItemComponent must be a forwardRef component.
When using a custom tooltip, you will also need to combine the external ref with
the tooltip's reference using a utility like useMergeRefs.
The Select component supports loading options data asynchronously. It will display
a loading spinner inside the input when isLoading is true. When performing
filtering through an API, you will also have to control the search input state
via the searchInputValue and onSearchInput props (otherwise the component
will perform filtering internally).
Select also supports infinite scrolling (for paginated APIs), and will call
the onLoadMore callback when scrolling towards the end of the list. The other
props expected for this use case are:
shouldLoadMore - a boolean indicating whether the onLoadMore callback should
be called at all (e.g. when there is a next page of data). Set to false if there
are no more pages/there is no more data to fetchisLoadingMore - whether more data is currently being fetched. While the API call
issued via the onLoadMore callback is running, this should be true, and will
show a loading spinner at the bottom of the listNote: It is up to you to merge the results of the paginated API calls into one
options array, which you pass into the component. The component itself only issues
callbacks when required, but you control the state.
The example below shows a Select that simulates an API with filtering and pagination.
PlumaProvider configurationBy default, the Select component enters and exits with a CSS transition animation (with a duration of 125ms).
The value can be overridden globally with the componentConfig prop on the PlumaProvider component:
This can be used, for example, in tests, to set the transition time to 0.
If a string label is not sufficient, a component can be used to render the label.
In React, the label prop accepts any ReactNode.
If a string description is not sufficient, a component can be used to render the description.
In React, the description prop accepts any ReactNode.
If a string error is not sufficient, a component can be used to render the error.
In React, the error prop accepts any ReactNode.
PlumaSelect accepts an isClearable prop, which renders a "clear" button
when it has a value. When the button is clicked, the onChange callback is called
with null.
PlumaSelect extends BoxAdditional middleware to apply to Floating UI, for example custom middleware for more control. These will be applied after the default middleware.
Element (or elements) that describe the form field. Also used for error messages, as aria-errormessage isn't supported in all assistive technologies: https://a11ysupport.io/tech/aria/aria-errormessage_attribute
String value that labels the form field.
Element (or elements) that label the form field.
The component to render at the header of the menu (after the search input, if present, but before the options list).
Whether a new option with the given value can be created. This can be used to exclude certain values from showing a "Create new" option.
Default:false
Whether the Select can wrap selected values to multiple lines (instead of truncating overflow).
Only applies when isMulti is true.
Default:'Create "{value}"'
The label to show for the "Create new" option. If a function is provided, it will be called with the current search input value.
Whether the select dropdown is open initially (when uncontrolled).
A description for the field, providing additional context or hints.
An error message associated with the form field.
Boolean: Ember-only. If the error named block is used,
this prop can be set to true to indicate an error is present,
which will make the error block render.
The component to render at the header of the menu (before the search input, if present).
The component to render for an option's icon.
An optional id to be assigned to the input element. Also used to generate ids for labels and error messages. If one isn't provided, it will be generated.
Whether the select is clearable.
When the clear button is clicked, the onChange callback
is called with null.
Whether the form field is disabled.
Whether the form field is in an invalid state.
Whether the component should show a loading spinner.
Whether more options are currently being loaded.
Whether multiple options can be selected.
Whether the select dropdown is open. Use this for controlled mode.
Whether the select options should be searchable (via an input inside the options menu).
The label text to show with the form field.
The name attribute is used for HTML forms
Called when the active (currently highlighted, but not necessarily selected) option changes when the dropdown is open.
The callback for when a value is selected.
When isMulti is true, the value in the callback
will be an array of the selected values.
Called when the dropdown finishes closing (after the close animation finishes).
Called when the "Create new" option is selected.
Note: onChange is not called when creating a new option: setting the new value
should also happen within this callback.
Callback for when the end of the dropdown is reached and more options should be loaded.
Called when the dropdown is opened.
Callback when the open state should change.
A handler for the input event on the search text field.
If provided, the Select component won't handle the filtering itself,
and it's up to the developer to filter the options.
The component to render for each option in the menu.
An array of options to render.
Placeholder text to show inside the field.
Default:'Search'
An aria-label to apply to the search field (as it doesn't render with its own label).
A value for the search input. If provided, combine it with onSearchInput to
control filtering of the options.
Default:'Search'
Placeholder text to show inside the search field (if enabled).
Whether to allow browser autofill and password managers. When false (default), adds attributes to disable password managers (1Password, LastPass, Bitwarden, Dashlane). Set to true for fields where autofill is desired (e.g., email, password, address fields).
Whether the generated description id should be included in the input's aria-describedby attribute.
Disable this when a label`` tag surrounds the input as well as it's description text, for example in an OptionCard` component.
Whether the generated label id should be included in the input's aria-labelledby attribute.
Disable this when the label tag surrounds the input as well as it's label text,
for example in an OptionCard component.
Whether the onLoadMore callback should be called when the end of the dropdown is reached. If no more paginated options are available, this should be set to false.
By default, form elements will throw an error if no label or aria-label is provided. Disable this to suppress the error, for example when building a custom form element, and you want to handle labeling yourself.
The size of the input element. medium and small are deprecated, use md and sm instead.
Additional classes to be applied to the description element.
Additional classes to be applied to the error element.
Additional classes to be applied to the field node.
Ember-only: this is used internally to detect whether a label
named block is present, and to ignore empty label props if so.
The initial value inside the search input. Only used in snapshots/tests.
Additional classes to be applied to the input node.
Sets the size attribute on the input element. This controls the visible width of the input in characters.
Whether the component should render with "legacy" styles.
Additional classes to be applied to the label node.
Additional classes to apply on the SelectPopover component (the floating element, not the trigger).
Additional size configuration for the SelectPopover component. Can be used to e.g. restrict the maxWidth of the popover. If the value of one of the keys is a function, it will be called with the default values that PlumaSelect would use (with numbers representing pixel values).
Additional inline styles to apply on the SelectPopover component (the floating element, not the trigger).
The current value. Can be either:
value of the selected option itemoptions array
When isMulti is true, the value is an array of the
above value options.The component to render for the selected value.
Options, or a function that returns options, for the Virtualizer.
Whether to apply the center-baseline variant.
When the Select is searchable, whether it should be possible to create new options if the search input doesn't exactly match any existing options.
Show tooltip only when label is truncated, for all options and group headers. Can be overridden per-option or per-group.
Whether the menu options should render in a virtualized list.