Selection and options
Controlled and uncontrolled covers how the value flows between the components and your state; this page covers what sits on both ends of that value — the option data contract shared by the Select family. It applies to:
- Selection lists:
Select,OutlineSelect,TabSelect,ButtonSelect,ButtonMenuSelectWidget - Tag inputs:
TagMultiselect,MenuTagMultiselect - Form fields:
DropdownInput,RadioSelectInput,CheckboxMultiselectInput - Inputs with candidates:
ComboBoxInput,SearchWidget(its result set)
Each component only adds its own props on top of this contract (such as OutlineSelect levels or tag fixing); see the component pages for specifics.
Option data
options is an array of option objects:
- Items with a
valueare selectable options.valueis always astring | number, and doubles as the selected-state match key and the list key. - Items without a
valuerender as group headings (not selectable, skipped by keyboard navigation), supported by the components that have a group form (Select,OutlineSelect,Dropdown,ButtonMenuSelectWidget, etc.). - Option text goes in
children; tag inputs uselabel, see below. - The selected state is never declared in the options — the component derives it from
valueand the current value, keeping the option data pure data.
The Berries item above has no value, so it renders as a group heading.
Options of tag inputs
The options of TagMultiselect / MenuTagMultiselect serve as both the tag itself and the menu candidates. The contract matches the previous section, plus three dedicated fields:
labelaccepts aReactNode(matching the original's rich content support), and defaults to displayingvalue. Tag options uselabelrather thanchildren.labelTextis the plain-text form oflabel, used for filtering menu candidates by typed prefix and for backfilling the input when a tag is selected or edited. Whenlabelis a string it defaults to the string itself; for rich content you must providelabelTextexplicitly — without it the option does not participate in prefix filtering (backfill falls back toString(value)), and a development warning is emitted once.datacarries an arbitrary payload. A tag's identity is always the scalarvalue(keeping the controlled array serializable and diffable), andonChangereturns scalar values too; when you need an object to travel with a tag, put it indataand look it back up byvaluein your ownoptionsarray.- Tags with
fixed: trueare fixed (no close button, cannot be removed), and drag-to-reorder never moves them before the fixed block.
Disabled
- An option's own
disableddisables that single item. - Component-level
disabledlands in two different places: list/group forms (Select,TabSelect,ButtonSelect,RadioSelect,CheckboxMultiselect) disable every option in the group as well, and the group state wins — an option cannot opt back in inside a disabled group; popup trigger forms (Dropdown,ComboBoxInput,ButtonMenuSelectWidget) disable the trigger (nothing opens, keyboard is off), while each item inside the menu is governed by its owndisabled.
Icons and flags
Option forms with icon slots (menu/outline/button options and group headings) support icon and flags: icon takes an icon name (see Icon), and flags tint the icon (progressive, destructive, etc.). Plain-text options (the items of TabSelect, RadioSelect, CheckboxMultiselect) have no icon slot and do not support these fields.
Keyboard and focus
- Arrow keys move between options: direct-select forms (
TabSelect,ButtonSelect,RadioSelect) select on keypress; menu forms (the menus ofDropdownetc.) move the highlight, and Enter / Space choose. - Home / End / PageUp / PageDown jump to the ends or page through: enabled by default in menu forms, available on a standalone
SelectviahandleNavigationKeys;listWrapsAroundcontrols whether navigation wraps at the ends. - Prefix jump: typing characters jumps by option text prefix (1.5 s buffer); tag inputs filter candidates by prefix.
- Focus never enters the list: focus stays on the control (or trigger element), with the highlighted item linked via
aria-activedescendant; the list root is not in the Tab order by default — the same listbox pattern as the original OOUI. Exception: the direct-select forms (TabSelect,ButtonSelect) keep their group root in the Tab order (focus rests on the whole group), and a click moves focus into the group root automatically (the original leaves focus where it was, leaving the arrow keys dead — this library follows the ARIA APG instead). - Direct-select forms (
TabSelect,ButtonSelect) pointaria-activedescendantat the selected item from the first frame when an initial value is present (the original only writes the attribute on the first re-selection). - Direct-select forms (
TabSelect,ButtonSelect) pointaria-activedescendantat the selected item from the first frame when an initial value is present (the original only writes the attribute on the first re-selection). - During input method composition, the confirming Enter and arrow keys for candidate selection never trigger selection, opening or submission by mistake.
See also
- What happens when the controlled value is not among the options: Controlled and uncontrolled
- The division of labor between
onChangeandonChoose(fired on every choice): Controlled and uncontrolled