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") — the default size for most use cases.
  • Small (size="sm") — for compact layouts, smaller viewports, and less prominent lists.
  • Option icons (icon on an option) — use to give visual context such as categories or user avatars.
  • Option descriptions (description on an option) — add when the label alone doesn't convey the option's purpose. Keep them concise.
  • Never add option icons or descriptions purely for decoration.

Behaviors

  • Base, hover, focus, and active states follow standard form-control styling; the active treatment also applies while the dropdown is open.
  • Disabled state (isDisabled) — blocks all interaction and applies disabled field and text styling.
  • Loading state (isLoading) — shows a spinner indicating options are being loaded.
  • Danger state (isInvalid with error) — applies danger styling and renders error text below the field.
  • Clear button (isClearable) — resets the field to its empty state after a selection. Use for optional Selects.
  • Grouping — nest options under a group to organize longer lists into categories. Never group lists short enough to scan without categories.
  • Collapsible groups (isCollapsible on a group) — let users expand and collapse sections. Use defaultIsCollapsed to start a group collapsed.
  • Option tooltips (tooltip on an option) — surface extra detail on hover or focus when inline descriptions are unwanted.

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