Skip to main content

Option groups, separators and disabled options

select, multiselect, search and multisearch accept more than a flat list. Alongside the ->options(['value' => 'Label']) map shorthand, ->option() declares one option at a time and can mark it disabled, and ->heading() and ->separator() add non-selectable structure:

$p->select('profile', 'Install profile')
->heading('Recommended')
->option('standard', 'Standard')
->option('minimal', 'Minimal')
->separator()
->heading('Advanced')
->option('demo_umami', 'Demo Umami', disabled: TRUE, disabled_reason: 'requires PHP 8.4');

Headings, separators and disabled options are visual only: navigation skips them, so the cursor lands only on selectable options, and they can never be highlighted or selected. A disabled option shows its reason beside the label, dimmed. Every kind is theme-driven - override heading(), divider() or disabled() on a theme to restyle it.

Non-selectable rows never leak into the answer: a disabled value is dropped from a multiselect default, absent from the collected value, and excluded from the JSON schema (Tui::schema() lists selectable options only). Supplying a disabled - or otherwise unknown - option value non-interactively (via --prompts JSON or an environment override) fails collection with a clear error naming the value.

A single-choice select with a group heading, a separator and a disabled option (its reason shown beside the dimmed label):

ANSINo ANSI
UnicodeSelect with groups: Unicode + ANSISelect with groups: Unicode + No ANSI
ASCIISelect with groups: ASCII + ANSISelect with groups: ASCII + No ANSI

A multiselect where the cursor and Space skip the separator and the disabled option, which can never be checked:

ANSINo ANSI
UnicodeMultiSelect with groups: Unicode + ANSIMultiSelect with groups: Unicode + No ANSI
ASCIIMultiSelect with groups: ASCII + ANSIMultiSelect with groups: ASCII + No ANSI