diff --git a/src/apps/officer-web/Screens/Dashboard/Layout/Spotlight/Spotlight.tsx b/src/apps/officer-web/Screens/Dashboard/Layout/Spotlight/Spotlight.tsx index 6d5cec5b..e8eaa57e 100644 --- a/src/apps/officer-web/Screens/Dashboard/Layout/Spotlight/Spotlight.tsx +++ b/src/apps/officer-web/Screens/Dashboard/Layout/Spotlight/Spotlight.tsx @@ -11,18 +11,28 @@ import { useSpotlightItems, type SpotlightItem } from './useSpotlightItems'; // // ── Keyboard first, and the trigger ── // -// `ctrl-space`, and ONLY that. It has now been ctrl-space → shift-space → alt-space → ctrl-space, and every -// move was the owner naming a real collision on the machine he uses: +// `shift-space`, and ONLY that. Fifth setting: ctrl-space → shift-space → alt-space → ctrl-space → +// shift-space. Every move was the owner naming a collision, and by now the list is the useful part: // -// shift-space types a space — see below, this was the worst of them -// alt-space the GNOME window menu. He rebound the OS to keep it, disliked what he rebound it TO, and -// asked for the OS binding back — so the app moves rather than the desktop. -// ctrl-space chosen deliberately on the way back. It was ruled out on 2026-08-20 as "focuses the -// address bar in Brave"; that observation was made before anything preventDefault'ed it, and -// the owner would rather rebind a browser than his window manager. +// ctrl-space Brave takes it for the address bar, at the browser level. Tried twice, on the theory that +// preventDefault would win. It does not — the key never reaches this handler. +// alt-space the GNOME window menu. He rebound the desktop to keep it, disliked the replacement, and +// would rather move the app than the window manager. +// shift-space where it lands, with BOTH of its stock behaviours deliberately overridden. // -// If the address bar still steals it, the key never reaches this handler and nothing here can help — the fix -// is in Brave, not in this file. Worth knowing WHICH of the two it is before changing anything. +// ── Shift-space overrides two things, on purpose ── +// +// It types a space in a text field, and it scrolls a page UP when nothing has focus. The owner's judgement, +// and it is his to make: neither is worth a launcher. Page-up-by-shift-space is a fossil nobody reaches for, +// and typing a space is what the unmodified spacebar is for. +// +// The cost, stated once because it is the one that will bite: typing in CAPS by holding shift rather than +// using caps lock puts a shift-space between every word. That opens the launcher mid-sentence. If it turns +// out to be a nuisance, the fix is a guard for text fields only — which this had for a day, and which is +// what made the launcher unopenable from the composer, where it is most wanted. +// +// This is also why the ctrl+? registry names the file that implements each chord: five moves in three days +// is the argument for making them configurable, not for choosing better. // // **Shift-space was never a good choice**, and that is why it did not last a day. It is a real key // combination inside a text field: it types a space, and people hold shift through one more often than @@ -30,7 +40,7 @@ import { useSpotlightItems, type SpotlightItem } from './useSpotlightItems'; // — which is where focus usually is, the chat composer — so opening Spotlight meant clicking out first. // A launcher you have to prepare for is not a launcher. // -// Ctrl-space has no meaning inside a text field, so there is NO focus check at all. The guard shift-space +// There is NO focus check, and here that is a choice with a cost rather than a free one — see above. The guard shift-space // needed was kept for one commit as "belt-and-braces" and was simply the old bug wearing a new hat: focus // is usually in the chat composer, so a launcher that stands down there is a launcher that does not open // when you want it. `preventDefault` on the handler covers the only real risk the guard addressed. @@ -206,18 +216,18 @@ export const Spotlight = () => { // anywhere — including inside a panel that has its own key handling. useEffect(() => { const onKey = (ev: KeyboardEvent) => { - // `ctrlKey` and `code`, not `key`: a modifier+space produces a different `key` on several layouts (and - // nothing at all on some), while the physical key is `Space` everywhere. + // `code`, not `key`: shift+space reports `key: ' '` on most layouts and something else on a few, while + // the physical key is `Space` everywhere. // - // `!ev.shiftKey`, because ctrl+SHIFT+space is the theme browser. Without it one chord would open both, - // which is the bug that took a capture-phase listener to fix on the theme side. + // Every other modifier must be ABSENT. `ctrl+shift+space` is the theme browser, and one chord opening + // both is the bug that took a capture-phase listener to fix on the theme side. // // No focus check. There was one, inherited from shift-space where it was mandatory, and keeping it // "as belt-and-braces" was wrong in the plainest way: focus is usually IN the chat composer, so the // guard meant the launcher did not open from the place it is most often wanted. `preventDefault` // below covers the only thing the guard was protecting against — a layout that would otherwise type // a character. - if (ev.ctrlKey && !ev.shiftKey && !ev.altKey && ev.code === 'Space') { + if (ev.shiftKey && !ev.ctrlKey && !ev.altKey && !ev.metaKey && ev.code === 'Space') { ev.preventDefault(); // Take focus off whatever had it, explicitly, before the overlay mounts. The effect below focuses // this panel's own input, and on paper that is enough — but "on paper" is what produced arrow keys diff --git a/src/apps/officer-web/state/shortcuts.ts b/src/apps/officer-web/state/shortcuts.ts index df522366..cec5013c 100644 --- a/src/apps/officer-web/state/shortcuts.ts +++ b/src/apps/officer-web/state/shortcuts.ts @@ -39,7 +39,7 @@ export const SHORTCUT_SECTIONS: ShortcutSection[] = [ title: 'Navigation', shortcuts: [ { - keys: 'Ctrl+Space', + keys: 'Shift+Space', description: 'Spotlight — go to any screen, plugin or setting by name', implementedIn: 'Layout/Spotlight/Spotlight.tsx', },