Capítulo 29 de 43

Chapter 29: Select

Core Idea

A button-triggered dropdown for picking one option from a list, with its own scrollable viewport, scroll buttons for long lists, and two distinct positioning strategies — the most structurally complex single-value picker in the library.

Key Concepts

  • Anatomy: RootTrigger (→ Value + Icon), PortalContent (→ ScrollUpButton, ViewportItem (→ ItemText + ItemIndicator) / Group (+ Label) / Separator, ScrollDownButton, Arrow).
  • Two positioning modes: "item-aligned" (default — content overlaps the trigger so the selected item lines up visually with it, like a native <select>) vs. "popper" (behaves like Popover/DropdownMenu — positions relative to the trigger with side/align/collision props). Switch via a prop on Content.
  • Value's placeholder: shown when nothing is selected; Value itself must stay unstyled for positioning to work correctly.
  • ScrollUpButton/ScrollDownButton: appear automatically when the option list overflows Viewport, letting users scroll a long list without a visible native scrollbar.
  • Hidden native select: like Checkbox/RadioGroup, renders automatically for form compatibility; can be decoupled for advanced cases the same way.

Code Examples

<Select.Root>
  <Select.Trigger>
    <Select.Value placeholder="Select a fruit…" />
    <Select.Icon />
  </Select.Trigger>
  <Select.Portal>
    <Select.Content position="popper" sideOffset={5}>
      <Select.Viewport>
        <Select.Item value="apple"><Select.ItemText>Apple</Select.ItemText></Select.Item>
      </Select.Viewport>
    </Select.Content>
  </Select.Portal>
</Select.Root>
  • What it demonstrates: opting into "popper" positioning mode to get Popover-style trigger-relative placement instead of the default item-aligned overlap.

Reference Tables

PartNotable props
Rootvalue/defaultValue, onValueChange, dir, name, disabled, required
Contentpositioning mode + (in popper mode) side, align, collision props
Itemvalue*, disabled, textValue (for typeahead when ItemText content isn't plain text)

Key Takeaways

  1. Default (item-aligned) positioning best mimics a native <select>'s feel; switch to "popper" mode when you need Popover-style trigger-relative placement or collision avoidance near viewport edges.
  2. ScrollUpButton/ScrollDownButton only need to be rendered — Radix shows/hides them automatically based on scroll position, no manual overflow detection required.
  3. Typeahead (type a letter to jump to a matching option) works out of the box; set textValue on Item when its visible content isn't a plain string.

Connects To

  • Dropdown Menu / Popover: share the "popper" positioning mode's API when Select is configured to use it.
  • Combobox-style needs: Select doesn't support free-text filtering — that requires composing with a separate input or a different (non-Radix-core) combobox solution.