feat(nexus): add CmdKButton shim for layout overhaul (phase 8)
Top-strip button that renders the ⌘K glyph and opens the existing CommandPalette by dispatching a synthetic Meta+K keydown on document, which CommandPalette.tsx already listens for at its useEffect (lines 42-51). This is explicitly a Phase 8 shim; Phase 14 of docs/specs/2026-04-11-nexus-layout-overhaul.md replaces it with a proper command-palette context when globalizing the palette's search index. Part of Phase 8 of the Nexus layout overhaul (task 3 of 7). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
1de78f855f
commit
c1647e70d7
2 changed files with 99 additions and 0 deletions
62
ui/src/components/frame/CmdKButton.test.tsx
Normal file
62
ui/src/components/frame/CmdKButton.test.tsx
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
// @vitest-environment jsdom
|
||||
|
||||
import { act } from "react";
|
||||
import { createRoot } from "react-dom/client";
|
||||
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { CmdKButton } from "./CmdKButton";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
(globalThis as any).IS_REACT_ACT_ENVIRONMENT = true;
|
||||
|
||||
describe("CmdKButton", () => {
|
||||
let container: HTMLDivElement;
|
||||
let root: ReturnType<typeof createRoot> | null = null;
|
||||
|
||||
beforeEach(() => {
|
||||
container = document.createElement("div");
|
||||
document.body.appendChild(container);
|
||||
root = null;
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
if (root) {
|
||||
act(() => { root!.unmount(); });
|
||||
root = null;
|
||||
}
|
||||
if (container.parentNode) container.remove();
|
||||
});
|
||||
|
||||
function renderButton() {
|
||||
root = createRoot(container);
|
||||
act(() => {
|
||||
root!.render(<CmdKButton />);
|
||||
});
|
||||
return {
|
||||
getButton: () => container.querySelector("button[aria-label='Open command palette']") as HTMLButtonElement,
|
||||
getKbd: () => container.querySelector("kbd")?.textContent?.trim(),
|
||||
};
|
||||
}
|
||||
|
||||
it("renders a button with the ⌘K kbd glyph", () => {
|
||||
const { getButton, getKbd } = renderButton();
|
||||
expect(getButton()).not.toBeNull();
|
||||
expect(getKbd()).toBe("⌘K");
|
||||
});
|
||||
|
||||
it("dispatches a Meta+K keydown on document when clicked", () => {
|
||||
const listener = vi.fn();
|
||||
document.addEventListener("keydown", listener);
|
||||
|
||||
const { getButton } = renderButton();
|
||||
act(() => {
|
||||
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);
|
||||
});
|
||||
});
|
||||
37
ui/src/components/frame/CmdKButton.tsx
Normal file
37
ui/src/components/frame/CmdKButton.tsx
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
/**
|
||||
* CmdKButton — Phase 8 shim for the top-strip command palette trigger.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
export function CmdKButton() {
|
||||
const handleClick = () => {
|
||||
const event = new KeyboardEvent("keydown", {
|
||||
key: "k",
|
||||
metaKey: true,
|
||||
bubbles: true,
|
||||
cancelable: true,
|
||||
});
|
||||
document.dispatchEvent(event);
|
||||
};
|
||||
|
||||
return (
|
||||
<button
|
||||
type="button"
|
||||
onClick={handleClick}
|
||||
aria-label="Open command palette"
|
||||
title="Open command palette (⌘K)"
|
||||
className="inline-flex h-8 items-center gap-2 rounded-[4px] border border-border bg-card px-2 text-[12px] font-medium text-muted-foreground transition-colors hover:text-primary hover:border-primary focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-primary focus-visible:ring-offset-2 focus-visible:ring-offset-background"
|
||||
>
|
||||
<kbd className="font-mono text-[12px]">⌘K</kbd>
|
||||
</button>
|
||||
);
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue