mirror of
https://github.com/alkimake/paperclip.git
synced 2026-06-15 18:30:39 +09:00
feat: polish inbox and issue list workflows
This commit is contained in:
parent
548721248e
commit
dab95740be
37 changed files with 1674 additions and 411 deletions
|
|
@ -10,12 +10,15 @@ import { useKeyboardShortcuts } from "./useKeyboardShortcuts";
|
|||
|
||||
function TestHarness({
|
||||
onNewIssue,
|
||||
onSearch,
|
||||
}: {
|
||||
onNewIssue: () => void;
|
||||
onSearch?: () => void;
|
||||
}) {
|
||||
useKeyboardShortcuts({
|
||||
enabled: true,
|
||||
onNewIssue,
|
||||
onSearch,
|
||||
});
|
||||
|
||||
return <div>keyboard shortcuts test</div>;
|
||||
|
|
@ -55,4 +58,52 @@ describe("useKeyboardShortcuts", () => {
|
|||
root.unmount();
|
||||
});
|
||||
});
|
||||
|
||||
it("focuses the current page search target on slash", () => {
|
||||
const root = createRoot(container);
|
||||
const onSearch = vi.fn();
|
||||
const input = document.createElement("input");
|
||||
input.setAttribute("data-page-search-target", "true");
|
||||
vi.spyOn(input, "getClientRects").mockReturnValue([{}] as unknown as DOMRectList);
|
||||
document.body.appendChild(input);
|
||||
|
||||
act(() => {
|
||||
root.render(<TestHarness onNewIssue={vi.fn()} onSearch={onSearch} />);
|
||||
});
|
||||
|
||||
document.dispatchEvent(new KeyboardEvent("keydown", {
|
||||
key: "/",
|
||||
bubbles: true,
|
||||
cancelable: true,
|
||||
}));
|
||||
|
||||
expect(document.activeElement).toBe(input);
|
||||
expect(onSearch).not.toHaveBeenCalled();
|
||||
|
||||
act(() => {
|
||||
root.unmount();
|
||||
});
|
||||
input.remove();
|
||||
});
|
||||
|
||||
it("falls back to quick search when the page has no search target", () => {
|
||||
const root = createRoot(container);
|
||||
const onSearch = vi.fn();
|
||||
|
||||
act(() => {
|
||||
root.render(<TestHarness onNewIssue={vi.fn()} onSearch={onSearch} />);
|
||||
});
|
||||
|
||||
document.dispatchEvent(new KeyboardEvent("keydown", {
|
||||
key: "/",
|
||||
bubbles: true,
|
||||
cancelable: true,
|
||||
}));
|
||||
|
||||
expect(onSearch).toHaveBeenCalledTimes(1);
|
||||
|
||||
act(() => {
|
||||
root.unmount();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,9 +1,14 @@
|
|||
import { useEffect } from "react";
|
||||
import { isKeyboardShortcutTextInputTarget } from "../lib/keyboardShortcuts";
|
||||
import {
|
||||
focusPageSearchShortcutTarget,
|
||||
hasBlockingShortcutDialog,
|
||||
isKeyboardShortcutTextInputTarget,
|
||||
} from "../lib/keyboardShortcuts";
|
||||
|
||||
interface ShortcutHandlers {
|
||||
enabled?: boolean;
|
||||
onNewIssue?: () => void;
|
||||
onSearch?: () => void;
|
||||
onToggleSidebar?: () => void;
|
||||
onTogglePanel?: () => void;
|
||||
onShowShortcuts?: () => void;
|
||||
|
|
@ -12,6 +17,7 @@ interface ShortcutHandlers {
|
|||
export function useKeyboardShortcuts({
|
||||
enabled = true,
|
||||
onNewIssue,
|
||||
onSearch,
|
||||
onToggleSidebar,
|
||||
onTogglePanel,
|
||||
onShowShortcuts,
|
||||
|
|
@ -29,6 +35,19 @@ export function useKeyboardShortcuts({
|
|||
return;
|
||||
}
|
||||
|
||||
// / → Page search when available, otherwise quick search
|
||||
if (e.key === "/" && !e.metaKey && !e.ctrlKey && !e.altKey) {
|
||||
if (hasBlockingShortcutDialog()) {
|
||||
return;
|
||||
}
|
||||
|
||||
e.preventDefault();
|
||||
if (!focusPageSearchShortcutTarget()) {
|
||||
onSearch?.();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// ? → Show keyboard shortcuts cheatsheet
|
||||
if (e.key === "?" && !e.metaKey && !e.ctrlKey && !e.altKey) {
|
||||
e.preventDefault();
|
||||
|
|
@ -57,5 +76,5 @@ export function useKeyboardShortcuts({
|
|||
|
||||
document.addEventListener("keydown", handleKeyDown);
|
||||
return () => document.removeEventListener("keydown", handleKeyDown);
|
||||
}, [enabled, onNewIssue, onToggleSidebar, onTogglePanel, onShowShortcuts]);
|
||||
}, [enabled, onNewIssue, onSearch, onToggleSidebar, onTogglePanel, onShowShortcuts]);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue