spotlight opens on alt-space, and on nothing else
Third chord in a day, and each move was the owner naming a collision on the machine he actually uses: ctrl-space is Brave's address bar, shift-space types a space, alt-space is the window menu — and he rebound that rather than give up the chord. Shift-space was the worst of the three and it is worth saying why, because it read as the safe choice. It is a real key combination inside a text field: it types a space, and people hold shift through one more often than they think while typing capitals. So it had to stand down whenever focus was in an input — which is where focus usually is, the chat composer — and a launcher you have to click out of a field to reach is not a launcher. Alt-space means nothing in a text field, so the isTyping guard stops being the thing holding the feature up and becomes belt-and-braces. Kept anyway: two lines against some layout delivering alt-space as a literal character, which is cheap to prevent and expensive to discover. `altKey` with `ev.code`, not `ev.key` — alt-space produces a different `key` on several layouts and nothing at all on others, while the physical key is `Space` everywhere. No second chord. Two triggers for one thing means two things to collide with, and this one has moved twice. The TODO item's id still says ctrl-space. Ids are stable by design, so it stays; its body now records all three moves and which guard was load-bearing for which. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -11,17 +11,25 @@ import { useSpotlightItems, type SpotlightItem } from './useSpotlightItems';
|
||||
//
|
||||
// ── Keyboard first, and the trigger ──
|
||||
//
|
||||
// `shift-space`. The two obvious chords were both taken: `ctrl-space` focuses the address bar in Brave,
|
||||
// and `alt-space` is load-bearing for the owner elsewhere. `cmd-k` belongs to the browser on some
|
||||
// platforms and to text fields on others.
|
||||
// `alt-space`, and ONLY that. It went ctrl-space → shift-space → alt-space, and each move was the owner
|
||||
// telling us what the chord actually collides with on the machine he uses:
|
||||
//
|
||||
// **Shift-space is a real key combination inside a text field** — it types a space, and people hold shift
|
||||
// through one more often than they think while typing capitals. So the trigger is IGNORED when focus is
|
||||
// in an input, a textarea or anything contenteditable, and the space is typed as normal.
|
||||
// ctrl-space focuses the address bar in Brave
|
||||
// shift-space types a space — see below, this was the real problem
|
||||
// alt-space taken by the window menu, and the owner rebound it rather than give up the chord
|
||||
//
|
||||
// The cost of that is worth stating: focus usually IS in the chat composer, so opening Spotlight from
|
||||
// there means clicking out first. If that turns out to be the common case, a double-tap of shift is the
|
||||
// escape hatch — it conflicts with nothing anywhere.
|
||||
// **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
|
||||
// they think while typing capitals. Guarding it meant IGNORING the trigger whenever focus was in an input
|
||||
// — 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.
|
||||
//
|
||||
// Alt-space has no meaning inside a text field, so the guard is now belt-and-braces rather than the thing
|
||||
// holding the feature together. It stays: alt-space reaching a composer as a literal character on some
|
||||
// layout is cheap to prevent and expensive to discover.
|
||||
//
|
||||
// Nothing else opens it. There is deliberately no second chord — two triggers for one thing means two
|
||||
// things to collide with, and this one moved twice already.
|
||||
//
|
||||
// Escape closes, arrows move, enter goes. The mouse works, but nothing here is designed around it.
|
||||
|
||||
@@ -41,9 +49,11 @@ import { useSpotlightItems, type SpotlightItem } from './useSpotlightItems';
|
||||
/**
|
||||
* Is the user typing into something?
|
||||
*
|
||||
* `shift-space` types a space in any text field, so the trigger has to stand down there or it eats a
|
||||
* keystroke people make by accident all day. `isContentEditable` covers the editor and any rich input a
|
||||
* panel brings with it.
|
||||
* Kept after the trigger moved to `alt-space`, where it is no longer load-bearing. It was written for
|
||||
* `shift-space`, which types a space in any text field and so HAD to stand down or it ate a keystroke
|
||||
* people make by accident all day. Alt-space means nothing in a text field — but a layout that delivers it
|
||||
* as a literal character exists somewhere, and this is two lines. `isContentEditable` covers the editor
|
||||
* and any rich input a panel brings with it.
|
||||
*/
|
||||
function isTyping(target: EventTarget | null): boolean {
|
||||
const el = target as HTMLElement | null;
|
||||
@@ -175,7 +185,9 @@ export const Spotlight = () => {
|
||||
// anywhere — including inside a panel that has its own key handling.
|
||||
useEffect(() => {
|
||||
const onKey = (ev: KeyboardEvent) => {
|
||||
if (ev.shiftKey && ev.code === 'Space' && !isTyping(ev.target)) {
|
||||
// `altKey` and `code`, not `key`: alt-space produces a different `key` on several layouts (and
|
||||
// nothing at all on some), while the physical key is `Space` everywhere.
|
||||
if (ev.altKey && ev.code === 'Space' && !isTyping(ev.target)) {
|
||||
ev.preventDefault();
|
||||
setOpen((wasOpen) => !wasOpen);
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user