diff --git a/ui/src/components/frame/CmdKButton.test.tsx b/ui/src/components/frame/CmdKButton.test.tsx index a5c94f8d..10ed947c 100644 --- a/ui/src/components/frame/CmdKButton.test.tsx +++ b/ui/src/components/frame/CmdKButton.test.tsx @@ -2,8 +2,12 @@ import { act } from "react"; import { createRoot } from "react-dom/client"; -import { afterEach, beforeEach, describe, expect, it, vi } from "vitest"; +import { afterEach, beforeEach, describe, expect, it } from "vitest"; import { CmdKButton } from "./CmdKButton"; +import { + CommandPaletteProvider, + useCommandPalette, +} from "../../context/CommandPaletteContext"; // eslint-disable-next-line @typescript-eslint/no-explicit-any (globalThis as any).IS_REACT_ACT_ENVIRONMENT = true; @@ -20,20 +24,42 @@ describe("CmdKButton", () => { afterEach(() => { if (root) { - act(() => { root!.unmount(); }); + act(() => { + root!.unmount(); + }); root = null; } if (container.parentNode) container.remove(); }); function renderButton() { + let captured: ReturnType | null = null; + const CaptureState: React.FC = () => { + captured = useCommandPalette(); + return ( + {captured.open ? "open" : "closed"} + ); + }; + root = createRoot(container); act(() => { - root!.render(); + root!.render( + + + + , + ); }); + return { - getButton: () => container.querySelector("button[aria-label='Open command palette']") as HTMLButtonElement, + getButton: () => + container.querySelector( + "button[aria-label='Open command palette']", + ) as HTMLButtonElement, getKbd: () => container.querySelector("kbd")?.textContent?.trim(), + getState: () => + container.querySelector("[data-testid='state']")?.textContent ?? null, + getCtx: () => captured, }; } @@ -43,8 +69,22 @@ describe("CmdKButton", () => { expect(getKbd()).toBe("⌘K"); }); - it("dispatches a Meta+K keydown on document when clicked", () => { - const listener = vi.fn(); + it("calls setOpen(true) on click — no synthetic keydown", () => { + const { getButton, getState } = renderButton(); + expect(getState()).toBe("closed"); + + act(() => { + getButton().click(); + }); + + expect(getState()).toBe("open"); + }); + + it("does not dispatch a document-level keydown as a side-effect", () => { + let sawKeydown = false; + const listener = () => { + sawKeydown = true; + }; document.addEventListener("keydown", listener); const { getButton } = renderButton(); @@ -52,11 +92,7 @@ describe("CmdKButton", () => { getButton().click(); }); - expect(listener).toHaveBeenCalledTimes(1); - const event = listener.mock.calls[0]![0] as KeyboardEvent; - expect(event.key).toBe("k"); - expect(event.metaKey).toBe(true); - document.removeEventListener("keydown", listener); + expect(sawKeydown).toBe(false); }); }); diff --git a/ui/src/components/frame/CmdKButton.tsx b/ui/src/components/frame/CmdKButton.tsx index 3e6398c7..ace3c283 100644 --- a/ui/src/components/frame/CmdKButton.tsx +++ b/ui/src/components/frame/CmdKButton.tsx @@ -1,27 +1,17 @@ +import { useCommandPalette } from "../../context/CommandPaletteContext"; + /** - * CmdKButton — Phase 8 shim for the top-strip command palette trigger. + * CmdKButton — top-strip trigger for the command palette. * - * Renders the ⌘K keyboard glyph and, when clicked, dispatches a synthetic - * Meta+K keydown event on `document`. The existing CommandPalette component - * in ui/src/components/CommandPalette.tsx installs a document-level keydown - * listener for Meta+K (see its useEffect at lines 42-51) and opens itself - * when that key is pressed, so the synthetic event reaches it without - * needing a refactor to share state. - * - * Phase 14 of docs/specs/2026-04-11-nexus-layout-overhaul.md replaces this - * shim with a proper command-palette context and globalizes the palette's - * search index. This file will either be deleted or gutted at that point. + * Phase 14 landed the real wiring: clicking the button calls + * `useCommandPalette().setOpen(true)` directly. The Phase 8 synthetic + * Meta+K keydown shim has been retired along with the accompanying + * document-level listener inside CommandPalette (the provider now owns + * the global keyboard shortcut). */ export function CmdKButton() { - const handleClick = () => { - const event = new KeyboardEvent("keydown", { - key: "k", - metaKey: true, - bubbles: true, - cancelable: true, - }); - document.dispatchEvent(event); - }; + const { setOpen } = useCommandPalette(); + const handleClick = () => setOpen(true); return (