ADR 0070: Command Palette как прямой overlay surface, маршрутизируемый в активный TopLevel¶
Статус: Accepted · Implemented
Дата: 2026-04-19
Связанные ADR¶
| ADR | Роль |
|---|---|
| 0013 | палитра и discoverability |
| 0017 | несколько TopLevel и фокус |
| 0021 | модель внимания |
| 0060 | keyboard-first и overlay-подсказки |
| 0066 | shell chrome vs cockpit UI |
Резюме¶
- Command Palette — прямой overlay в host, не
ModalOverlaybaseline. - Маршрутизация в активный
TopLevel; связь с 0112.
Контекст¶
Командная палитра уже была канонической surface в 0013, но её конкретный render-host оставался незафиксированным. Практика показала, что композиция через общий ModalOverlay оказалась хрупкой для multi-window topology:
- overlay мог не материализоваться в нужном
TopLevel, хотя хоткей и состояние VM уже сработали; - при мультиоконности палитра могла визуально появляться не в том хосте или дублироваться;
- keyboard-first UX ломался именно в критическом месте discoverability: у пользователя создавалось ощущение, что
Ctrl+Qничего не делает.
Проблема оказалась не в самой палитре как продуктовой идее, а в фундаменте surface: общий модальный compose-path был слишком неявным для keyboard-first overlay, который обязан быть привязан к активному окну и фокусу.
Решение¶
1. Базовый surface палитры¶
Command Palette рендерится как прямой overlay surface внутри конкретного host view, а не как обязательная композиция через общий ModalOverlay.
Это означает:
- корневой визуал палитры сам содержит dimmer/panel;
- палитра сама управляет видимостью, фокусом и keyboard routing;
ModalOverlayостаётся общей UI-инфраструктурой, но больше не считается каноническим фундаментом для палитры.
2. Маршрутизация в активный TopLevel¶
При открытии палитра должна быть видима ровно в одном активном host window:
MainWindowPfdHostWindowMfdHostWindow
Источник истины для выбора host — состояние shell/VM, отражающее активный TopLevel и источник последнего keyboard entry. Overlay не должен “угадывать” по глобальному статическому состоянию вне текущего окна.
3. Keyboard-first инварианты¶
Для палитры обязательны следующие инварианты:
- открытие по хоткею должно работать из дочерних контролов и редактора;
- при открытии фокус переходит в строку поиска;
- при закрытии фокус возвращается в предыдущий элемент текущего host;
Esc,Enter,Up/Down,PageUp/PageDownобрабатываются на уровне самой палитры;- overlay не должен зависеть от того, есть ли в конкретной раскладке дополнительные chrome/composition wrappers.
4. Граница решения¶
Этот ADR фиксирует только baseline surface для Command Palette.
Он не означает, что:
- любой modal/dimmer в IDE должен быть переписан под ту же схему;
ModalOverlayзапрещён;- overlay-подсказки chord-системы из 0060 обязаны использовать тот же visual tree.
Но для палитры правило по умолчанию теперь однозначно: прямой overlay в нужном host.
Последствия¶
- Поведение палитры становится предсказуемым в multi-window topology.
- Тесты должны страховать не только hotkey routing, но и host routing: палитра видна только в ожидаемом
TopLevel. - Документация по keyboard-first теперь может опираться на конкретный baseline, а не на “историческую” реализацию через
ModalOverlay.
Отклонённые альтернативы¶
-
Оставить
ModalOverlayканоном и чинить частные баги вокруг него.
Отклонено: причина поломки не локальная, а архитектурная для multi-window keyboard-first surface. -
Глобальный singleton-overlay поверх всех окон.
Отклонено: нарушает модель фокуса и внимания из 0017 и 0021. -
Привязывать палитру только к
MainWindow, а host-окна заставлять проксировать ввод назад.
Отклонено: пользователь ожидает, что discoverability surface появится именно там, где сейчас работает.