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):
| ANSI | No ANSI | |
| Unicode | ||
| ASCII |
A multiselect where the cursor and Space skip the separator and the disabled
option, which can never be checked:
| ANSI | No ANSI | |
| Unicode | ||
| ASCII |