- useListNavigation: shared j/k/arrows/Home/End/Enter keyboard spine, container or window scope, input guard, roving tabindex. Replaces ProposalsRoute's bespoke window listener (one pattern app-wide). - VirtualizedList over @tanstack/react-virtual composing the hook; evidence lists render O(viewport). - Panel: standard header/toolbar/body chrome for routes. - Inspector resize: Shell center cell becomes SplitPane(main, inspector) when open; width persists via guarded storage (SplitPane id). - Palette action verbs: Command gains kind (navigate|action); Shell registers Toggle inspector + Copy evidence link; EvalsRoute registers 'Run eval lane <lane>' per read-only lane (same POST /evals/run). - shortcutRegistry: binding sites register what they handle while mounted; KeyboardHelp renders FROM the registry — advertising an unbound shortcut is structurally impossible. j/k, /, Enter rows (removed in R0a as false) return as live registry entries. - Kbd primitive (front-loaded from R1); SearchInput registers '/'; SearchInput wired into Proposals + Replay lists with client filters. - Preview entries for Kbd/Panel/VirtualizedList. Verified: build green; vitest 33 files / 245 tests EXIT=0 (~5.5s); playwright 12/12.
41 lines
1.6 KiB
TypeScript
41 lines
1.6 KiB
TypeScript
import { render, screen } from "@testing-library/react";
|
|
import { describe, expect, it } from "vitest";
|
|
import { KeyboardHelp } from "./KeyboardHelp";
|
|
import { useRegisterShortcuts } from "./shortcutRegistry";
|
|
import { useListNavigation } from "../design/hooks/useListNavigation";
|
|
|
|
function HostWithBinding() {
|
|
useRegisterShortcuts([
|
|
{ id: "test-binding", keys: "⌘T", action: "Test verb", order: 1 },
|
|
]);
|
|
return <KeyboardHelp open onOpenChange={() => {}} />;
|
|
}
|
|
|
|
function HostWithList() {
|
|
useListNavigation({ itemCount: 3 });
|
|
return <KeyboardHelp open onOpenChange={() => {}} />;
|
|
}
|
|
|
|
describe("KeyboardHelp (registry-driven)", () => {
|
|
it("renders rows from the shortcut registry, not a hand-maintained list", () => {
|
|
render(<HostWithBinding />);
|
|
expect(screen.getByText("Test verb")).toBeInTheDocument();
|
|
expect(screen.getByText("⌘T")).toBeInTheDocument();
|
|
});
|
|
|
|
it("shows nothing for shortcuts no mounted component binds", () => {
|
|
render(<KeyboardHelp open onOpenChange={() => {}} />);
|
|
// No binder mounted in this render — the overlay cannot advertise j/k.
|
|
expect(screen.queryByText("Navigate lists")).not.toBeInTheDocument();
|
|
});
|
|
|
|
it("list-navigation rows appear exactly while a navigable list is mounted", () => {
|
|
const { unmount } = render(<HostWithList />);
|
|
expect(screen.getByText("Navigate lists")).toBeInTheDocument();
|
|
expect(screen.getByText("Open selected item")).toBeInTheDocument();
|
|
unmount();
|
|
|
|
render(<KeyboardHelp open onOpenChange={() => {}} />);
|
|
expect(screen.queryByText("Navigate lists")).not.toBeInTheDocument();
|
|
});
|
|
});
|