| 1 | <!-- English translation of adr/0070-command-palette-direct-overlay-surface.md. Canonical Russian: ../../adr/0070-command-palette-direct-overlay-surface.md --> |
| 2 | |
| 3 | # ADR 0070: Command Palette as direct overlay surface, routed to active TopLevel |
| 4 | |
| 5 | **Status:** Accepted · Implemented |
| 6 | **Date:** 2026-04-19 |
| 7 | |
| 8 | ## Related ADRs |
| 9 | |
| 10 | | ADR | Role | |
| 11 | |-----|------| |
| 12 | | [0013](0013-command-surface-and-discoverability.md) | palette and discoverability | |
| 13 | | [0017](0017-multi-window-workspace-and-agent-surfaces.md) | several `TopLevel` and focus | |
| 14 | | [0021](0021-pfd-mfd-cockpit-attention-model.md) | attention model | |
| 15 | | [0060](0060-keyboard-chord-stack-fms-tactical-strategic.md) | keyboard-first and overlay-tips | |
| 16 | | [0066](0066-cockpit-ui-vs-ide-presentation-layer.md) | shell chrome vs cockpit UI | |
| 17 | |
| 18 | ## Summary |
| 19 | |
| 20 | - Command Palette - **direct overlay** in host, not `ModalOverlay` baseline. |
| 21 | - Routing to active `TopLevel`; communication with [0112](0112-command-palette-query-modes-strategy.md). |
| 22 | |
| 23 | |
| 24 | --- |
| 25 | ## Context |
| 26 | |
| 27 | The command palette was already a canonical surface in [0013](0013-command-surface-and-discoverability.md), but its specific render-host remained unfixed. Practice has shown that composition through a common `ModalOverlay` turned out to be fragile for multi-window topology: |
| 28 | |
| 29 | 1. overlay might not materialize in the desired `TopLevel`, although the hotkey and VM state have already worked; |
| 30 | 2. with multi-windows, the palette could visually appear in the wrong host or be duplicated; |
| 31 | 3. keyboard-first UX broke down precisely at the critical point of discoverability: the user got the feeling that `Ctrl+Q` does nothing. |
| 32 | |
| 33 | The problem turned out to be not in the palette itself as a product idea, but in the foundation of the surface: the general modal compose-path was too implicit for the keyboard-first overlay, which must be bound to the active window and focus. |
| 34 | |
| 35 | --- |
| 36 | |
| 37 | ## Solution |
| 38 | |
| 39 | <a id="adr0070-p1"></a> |
| 40 | |
| 41 | ### 1. Basic surface palette |
| 42 | |
| 43 | The Command Palette is rendered as a **direct overlay surface** within a specific host view, and not as a mandatory composition through a generic `ModalOverlay`. |
| 44 | |
| 45 | This means: |
| 46 | |
| 47 | - the root visual of the palette itself contains a dimmer/panel; |
| 48 | - the palette itself controls visibility, focus and keyboard routing; |
| 49 | - `ModalOverlay` remains a common UI framework, but is no longer **considered the canonical foundation** for the palette. |
| 50 | |
| 51 | <a id="adr0070-p2"></a> |
| 52 | |
| 53 | ### 2. Routing to active TopLevel |
| 54 | |
| 55 | When opened, the palette should be visible **in exactly one active host window**: |
| 56 | |
| 57 | - `MainWindow` |
| 58 | - `PfdHostWindow` |
| 59 | - `MfdHostWindow` |
| 60 | |
| 61 | The source of truth for host selection is the shell/VM state, reflecting the active `TopLevel` and the source of the last keyboard entry. Overlay should not “guess” from the global static state outside the current window. |
| 62 | |
| 63 | <a id="adr0070-p3"></a> |
| 64 | |
| 65 | ### 3. Keyboard-first invariants |
| 66 | |
| 67 | The following invariants are required for the palette: |
| 68 | |
| 69 | - opening by hotkey should work from child controls and the editor; |
| 70 | - when opened, focus goes to the search bar; |
| 71 | - when closing, focus returns to the previous element of the current host; |
| 72 | - `Esc`, `Enter`, `Up/Down`, `PageUp/PageDown` are processed at the level of the palette itself; |
| 73 | - overlay should not depend on whether a particular layout has additional chrome/composition wrappers. |
| 74 | |
| 75 | <a id="adr0070-p4"></a> |
| 76 | |
| 77 | ### 4. Decision boundary |
| 78 | |
| 79 | This ADR captures only the baseline surface for the **Command Palette**. |
| 80 | |
| 81 | It **doesn't** mean that: |
| 82 | |
| 83 | - any modal/dimmer in the IDE must be rewritten to fit the same scheme; |
| 84 | - `ModalOverlay` is prohibited; |
| 85 | - overlay chord system hints from [0060](0060-keyboard-chord-stack-fms-tactical-strategic.md) must use the same visual tree. |
| 86 | |
| 87 | But for the palette the default rule is now unambiguous: **direct overlay in the desired host**. |
| 88 | |
| 89 | --- |
| 90 | |
| 91 | ## Consequences |
| 92 | |
| 93 | - The behavior of the palette becomes predictable in multi-window topology. |
| 94 | - Tests must cover not only hotkey routing, but also host routing: the palette is visible only in the expected `TopLevel`. |
| 95 | - Documentation for keyboard-first can now rely on a specific baseline, rather than the “historical” implementation via `ModalOverlay`. |
| 96 | |
| 97 | --- |
| 98 | |
| 99 | ## Rejected alternatives |
| 100 | |
| 101 | 1. **Keep `ModalOverlay` canon and fix private bugs around it.** |
| 102 | Rejected: the cause of the failure is not local, but architectural for multi-window keyboard-first surface. |
| 103 | |
| 104 | 2. **Global singleton-overlay on top of all windows.** |
| 105 | Rejected: violates the focus and attention model from [0017](0017-multi-window-workspace-and-agent-surfaces.md) and [0021](0021-pfd-mfd-cockpit-attention-model.md). |
| 106 | |
| 107 | 3. **Bind the palette only to `MainWindow`, and force the host window to proxy input back.** |
| 108 | Rejected: The user expects the discoverability surface to appear exactly where it is currently working. |