Implement quick-add registry (task 21)
- Add url field to QuickAddAction; make action optional - Add getQuickAdds() + SerializedQuickAddItem to registry so quick-add data can cross the server→client RSC boundary without serializing fns - Update calendar/lists/notes manifests with navigation URLs - QuickAddProvider wraps root layout: holds sheet/palette open state and global cmd/ctrl+k shortcut - QuickAddSheet: bottom drawer on mobile, right-side popover on desktop, actions grouped by module - CommandPalette: cmdk-powered modal with fuzzy filter and full keyboard nav (arrows + enter + esc) - QuickAddFab: client button replacing the plain + stub in the dashboard - Add .claude/** to ESLint ignores to prevent stale worktree artifacts from failing lint All 4 E2E specs pass; typecheck, lint, and build clean. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
b9d3cce73a
commit
1133fa8aac
@@ -0,0 +1,57 @@
|
||||
"use client";
|
||||
|
||||
import { createContext, useCallback, useContext, useEffect, useState } from "react";
|
||||
import type { SerializedQuickAddItem } from "@/modules/_core";
|
||||
|
||||
type QuickAddState = {
|
||||
sheetOpen: boolean;
|
||||
paletteOpen: boolean;
|
||||
openSheet: () => void;
|
||||
closeSheet: () => void;
|
||||
openPalette: () => void;
|
||||
closePalette: () => void;
|
||||
actions: SerializedQuickAddItem[];
|
||||
};
|
||||
|
||||
const QuickAddContext = createContext<QuickAddState | null>(null);
|
||||
|
||||
export function useQuickAdd() {
|
||||
const ctx = useContext(QuickAddContext);
|
||||
if (!ctx) throw new Error("useQuickAdd must be used inside QuickAddProvider");
|
||||
return ctx;
|
||||
}
|
||||
|
||||
export function QuickAddProvider({
|
||||
children,
|
||||
actions,
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
actions: SerializedQuickAddItem[];
|
||||
}) {
|
||||
const [sheetOpen, setSheetOpen] = useState(false);
|
||||
const [paletteOpen, setPaletteOpen] = useState(false);
|
||||
|
||||
const openSheet = useCallback(() => setSheetOpen(true), []);
|
||||
const closeSheet = useCallback(() => setSheetOpen(false), []);
|
||||
const openPalette = useCallback(() => setPaletteOpen(true), []);
|
||||
const closePalette = useCallback(() => setPaletteOpen(false), []);
|
||||
|
||||
useEffect(() => {
|
||||
function onKeyDown(e: KeyboardEvent) {
|
||||
if ((e.metaKey || e.ctrlKey) && e.key === "k") {
|
||||
e.preventDefault();
|
||||
setPaletteOpen((prev) => !prev);
|
||||
}
|
||||
}
|
||||
document.addEventListener("keydown", onKeyDown);
|
||||
return () => document.removeEventListener("keydown", onKeyDown);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<QuickAddContext.Provider
|
||||
value={{ sheetOpen, paletteOpen, openSheet, closeSheet, openPalette, closePalette, actions }}
|
||||
>
|
||||
{children}
|
||||
</QuickAddContext.Provider>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user