Forge
markdowndeeb25a2
1# ADR 0070: Command Palette как прямой overlay surface, маршрутизируемый в активный TopLevel
2
3**Статус:** Accepted · Implemented
4**Дата:** 2026-04-19
5
6## Связанные ADR
7
8| ADR | Роль |
9|-----|------|
10| [0013](0013-command-surface-and-discoverability.md) | палитра и discoverability |
11| [0017](0017-multi-window-workspace-and-agent-surfaces.md) | несколько `TopLevel` и фокус |
12| [0021](0021-pfd-mfd-cockpit-attention-model.md) | модель внимания |
13| [0060](0060-keyboard-chord-stack-fms-tactical-strategic.md) | keyboard-first и overlay-подсказки |
14| [0066](0066-cockpit-ui-vs-ide-presentation-layer.md) | shell chrome vs cockpit UI |
15
16## Резюме
17
18- Command Palette — **прямой overlay** в host, не `ModalOverlay` baseline.
19- Маршрутизация в активный `TopLevel`; связь с [0112](0112-command-palette-query-modes-strategy.md).
20
21
22---
23## Контекст
24
25Командная палитра уже была канонической surface в [0013](0013-command-surface-and-discoverability.md), но её конкретный render-host оставался незафиксированным. Практика показала, что композиция через общий `ModalOverlay` оказалась хрупкой для multi-window topology:
26
271. overlay мог не материализоваться в нужном `TopLevel`, хотя хоткей и состояние VM уже сработали;
282. при мультиоконности палитра могла визуально появляться не в том хосте или дублироваться;
293. keyboard-first UX ломался именно в критическом месте discoverability: у пользователя создавалось ощущение, что `Ctrl+Q` ничего не делает.
30
31Проблема оказалась не в самой палитре как продуктовой идее, а в фундаменте surface: общий модальный compose-path был слишком неявным для keyboard-first overlay, который обязан быть привязан к активному окну и фокусу.
32
33---
34
35## Решение
36
37<a id="adr0070-p1"></a>
38
39### 1. Базовый surface палитры
40
41Command Palette рендерится как **прямой overlay surface** внутри конкретного host view, а не как обязательная композиция через общий `ModalOverlay`.
42
43Это означает:
44
45- корневой визуал палитры сам содержит dimmer/panel;
46- палитра сама управляет видимостью, фокусом и keyboard routing;
47- `ModalOverlay` остаётся общей UI-инфраструктурой, но больше **не считается каноническим фундаментом** для палитры.
48
49<a id="adr0070-p2"></a>
50
51### 2. Маршрутизация в активный TopLevel
52
53При открытии палитра должна быть видима **ровно в одном активном host window**:
54
55- `MainWindow`
56- `PfdHostWindow`
57- `MfdHostWindow`
58
59Источник истины для выбора host — состояние shell/VM, отражающее активный `TopLevel` и источник последнего keyboard entry. Overlay не должен “угадывать” по глобальному статическому состоянию вне текущего окна.
60
61<a id="adr0070-p3"></a>
62
63### 3. Keyboard-first инварианты
64
65Для палитры обязательны следующие инварианты:
66
67- открытие по хоткею должно работать из дочерних контролов и редактора;
68- при открытии фокус переходит в строку поиска;
69- при закрытии фокус возвращается в предыдущий элемент текущего host;
70- `Esc`, `Enter`, `Up/Down`, `PageUp/PageDown` обрабатываются на уровне самой палитры;
71- overlay не должен зависеть от того, есть ли в конкретной раскладке дополнительные chrome/composition wrappers.
72
73<a id="adr0070-p4"></a>
74
75### 4. Граница решения
76
77Этот ADR фиксирует только baseline surface для **Command Palette**.
78
79Он **не** означает, что:
80
81- любой modal/dimmer в IDE должен быть переписан под ту же схему;
82- `ModalOverlay` запрещён;
83- overlay-подсказки chord-системы из [0060](0060-keyboard-chord-stack-fms-tactical-strategic.md) обязаны использовать тот же visual tree.
84
85Но для палитры правило по умолчанию теперь однозначно: **прямой overlay в нужном host**.
86
87---
88
89## Последствия
90
91- Поведение палитры становится предсказуемым в multi-window topology.
92- Тесты должны страховать не только hotkey routing, но и host routing: палитра видна только в ожидаемом `TopLevel`.
93- Документация по keyboard-first теперь может опираться на конкретный baseline, а не на “историческую” реализацию через `ModalOverlay`.
94
95---
96
97## Отклонённые альтернативы
98
991. **Оставить `ModalOverlay` каноном и чинить частные баги вокруг него.**
100 Отклонено: причина поломки не локальная, а архитектурная для multi-window keyboard-first surface.
101
1022. **Глобальный singleton-overlay поверх всех окон.**
103 Отклонено: нарушает модель фокуса и внимания из [0017](0017-multi-window-workspace-and-agent-surfaces.md) и [0021](0021-pfd-mfd-cockpit-attention-model.md).
104
1053. **Привязывать палитру только к `MainWindow`, а host-окна заставлять проксировать ввод назад.**
106 Отклонено: пользователь ожидает, что discoverability surface появится именно там, где сейчас работает.
107
View only · write via MCP/CIDE