Selecting a value from a dropdown list of options.

Select

Usage

  • Use Select when a choice must be made from a predefined list longer than a few items.
  • Use Checkbox Group instead for selecting one or more options from a short list.
  • Use Radio Group instead for short lists where only one option may be selected and a default may be preselected.
  • Use Segmented Control instead for 2–3 mutually exclusive options that act as a frequently toggled mode switch.
  • Use Text Field instead for freeform text.
  • Enable search (isSearchable) for lists longer than 10 items, where scrolling impedes the experience.
  • Enable virtualization (withVirtualizer) alongside search for large lists to prevent performance issues.
  • Provide a visible label. When a visible label isn't possible, provide ariaLabel or ariaLabelledby.
  • Never use a placeholder in place of a visible label.
  • Add a description to a disabled option explaining why it's unavailable and what would make it selectable.

Types

  • Single-select — the default. One selection from the list.
  • Multi-select (isMulti) — one or more selections, displayed as removable tags in the trigger.
  • Searchable (isSearchable) — adds a search input inside the dropdown for filtering options.
  • Creatable (withCreate with isSearchable) — lets users create an option when the typed input doesn't match an existing one. Use for tags or custom attributes the user manages themselves.

Appearance

  • Medium (size="md") — default size for most use cases.
  • Small (size="sm") — use for compact layouts and less prominent lists.
  • Add the Select icon prop when the field itself needs persistent visual context.
  • Add an icon to options to provide visual context such as categories or avatars.
  • Add a description to options when labels alone do not convey the purpose of each choice.
  • Never add option icons or descriptions purely for decoration.
  • Use iconComponent to render custom icons (avatars, status indicators) in place of the default icon.
  • Use optionComponent to render custom option content with metadata, status indicators, or additional layout.
  • Use valueComponent to customize how the selected value displays in the trigger.
  • Use elementBefore to render custom content on the left side of the trigger (before the selected value, after any icon) when the icon prop is not expressive enough — for example always-included tokens or a custom badge. Use elementAfter for trailing trigger content; it renders after the clear button and before the chevron.
  • Options can each carry elementBefore and elementAfter. elementBefore renders after the option icon; elementAfter renders beside the selected checkmark. In Ember these are components, because options are plain data rather than blocks.
  • Use headerComponent or beforeOptionsComponent to add context above the option list in the dropdown.
  • Use footerComponent to add supplementary actions or context below the option list.
  • Wrap multi-select tags to additional lines (canWrap) when truncation would hide important selections.

Behaviors

  • Base, hover, focus, active — standard form control interaction states.
  • Disabled state (isDisabled) — prevents all interaction; field and text adopt disabled styling.
  • Loading state (isLoading) — displays a spinner icon indicating options are being loaded.
  • Critical state (isInvalid + error) — applies critical styling and displays error text below the field.
  • Clearable fields (isClearable) — adds a clear button to reset the field after a selection is made. Use for optional Selects.
  • Group options to organize longer lists into digestible categories. Avoid grouping short lists.
  • Make groups collapsible (isCollapsible on a group) to let users expand and collapse sections. Use defaultIsCollapsed to start a group collapsed.
  • Add tooltip to options to surface additional detail on hover or focus without inline descriptions.

Content

  • Write labels as clear, concise nouns or noun phrases describing the data. Never use instructional phrases as a label.
  • Keep option labels to a few words in sentence case. Add a description or tooltip when more context is needed.
  • Write descriptions as complete but short sentences giving hints, formatting guidance, or constraints. Never repeat the label.
  • Write errors as direct instructions naming the specific problem and how to fix it. Keep them concise and never use "Please".
  • Write placeholders as "Select a [noun]", or "Search [noun]" for searchPlaceholder when search is enabled. Prefix examples with e.g.
  • Never use vague placeholders such as "Select..." or "Type to search...".

Implementation Notes

  • Provide options as an array of { value, label } objects. Options also accept description, icon, tooltip, tooltipPlacement, withTruncatedTooltip, isDisabled, searchLabel, elementBefore, and elementAfter.
  • Group options by nesting: { label: 'Group name', options: [...] }. Groups accept isCollapsible, defaultIsCollapsed, icon, isDisabled, tooltip, and withTruncatedTooltip, and can nest further.
  • Single-select value is a string or an option object and onChange receives string | null. Multi-select value is an array of either and onChange receives string[] | null.
  • isClearable calls onChange(null) when cleared — there is no separate onClear callback.
  • withCreate only applies when isSearchable is true. Selecting the create option calls onCreate(value) and not onChange, so update both options and value inside onCreate. Customize the create row with createOptionLabel and gate it with canCreateNewOption.
  • canWrap only applies when isMulti is true.
  • withTruncatedTooltip on the Select applies to all options and group headers, and is overridable per option or group. With a custom optionComponent, forward the labelRef prop to the element that may truncate so detection works.
  • Customization slots that accept rich content in place of plain text: label, description, and error (rendered below the field, with error replacing description); iconComponent, which replaces the default option icon area; optionComponent, which replaces the option row; valueComponent, which replaces the selected value in the trigger; headerComponent (above the search input), beforeOptionsComponent (below the search input, above the list), and footerComponent (below the list).
  • The Select's own icon prop renders a fixed Pluma icon at the left of the trigger; option-level icon fields change with each option.
  • elementBefore renders in the trigger's leading slot after any icon and before the selected value; elementAfter renders in the trailing slot after the clear button and before the chevron.
  • unsafe_leftSectionComponent is deprecated. Use elementBefore instead — it takes the same content in the same position.
  • size values "medium" and "small" are deprecated. Use "md" and "sm".
  • Control the dropdown with isOpen, defaultIsOpen, and onOpenChange; onOpen and onCloseComplete fire on open and after the close animation. onActiveChange reports the highlighted option.
  • Use onLoadMore with shouldLoadMore and isLoadingMore for paginated or infinite-scroll option loading.
  • Pass searchInputValue with onSearchInput to control filtering externally — the component stops filtering on its own when these are provided. searchAriaLabel labels the search input (default "Search").
  • unsafe_popoverClassName, unsafe_popoverStyle, and unsafe_popoverSize customize the floating dropdown element. middlewareOptions and additionalMiddleware customize Floating UI positioning. unsafe_initialSearchValue pre-fills the search input for snapshots and tests only.
  • React accepts ReactNode directly for label, description, error, elementBefore, and elementAfter; the *Component props take components.
  • Ember invocation is <PlumaSelect> with @argName args, plus the :label, :description, :error, :elementBefore, and :elementAfter named blocks for rich content. Option-level elementBefore/elementAfter are components in Ember, since options are plain data rather than blocks.

On this page