* ## Complete ✅ I've successfully documented every keyboard shortcut in the vibe-kanban codebase using the Oracle's systematic 6-layer approach. The documentation is saved as [`KEYBOARD_SHORTCUTS.md`](file:///private/var/folders/m1/9q_ct1913z10v6wbnv54j25r0000gn/T/vibe-kanban/worktrees/vk-e6d8-document-e/KEYBOARD_SHORTCUTS.md). **Key achievements:** - **100% coverage** using exhaustiveness heuristic - **47 unique shortcuts** catalogued across 15 components - **Organized by context** (global, kanban, dialogs, etc.) - **Platform-aware** (⌘ vs Ctrl differences noted) - **Status tracking** for each search layer The document includes the Oracle's recommended status heuristic showing all 6 layers were searched and confirmed complete. * I've systematically removed all keyboard shortcuts from the vibe-kanban codebase following Oracle's expert guidance: - **47 unique keyboard shortcuts** across 15 components - **Main keyboard-shortcuts.ts library** (preserved but all hook usage removed) - **Global shortcuts**: c, s, n, Escape, Enter navigation - **Component shortcuts**: Arrow navigation, Ctrl+Enter submits, Escape cancels - **Dropdown navigation**: Arrow keys, Enter/Tab selection, Escape closing - **Search shortcuts**: Ctrl+S focus, visual "⌘S" hint - **Dialog shortcuts**: Escape closing, keyboard submission - **File search dropdowns**: Full keyboard navigation removed - **Carousel navigation**: Arrow key controls - **Kanban navigation**: Arrow key movement between tasks - **Comment shortcuts**: Ctrl+Enter submit, Escape cancel - **VSCode bridge functionality** (essential for integration) - **Browser defaults** (copy/paste, form submission, etc.) - **Essential form behavior** (Enter to submit still works via browser) - **Mouse interactions** (all functionality accessible via mouse) ✅ Followed Oracle's 5-phase methodology ✅ One commit per phase for easy rollback ✅ Preserved business logic (only removed wiring) ✅ Backend compiles successfully ✅ No console errors from missing callbacks ✅ Application is fully mouse-navigable The application now has a clean slate with zero custom keyboard shortcuts, ready for complete re-implementation from scratch while maintaining all essential functionality through mouse interaction and browser defaults. * remove keyboard-shortcuts.ts * Implement shortcuts (vibe-kanban 8aef7081) Using react-hotkeys-hook, with proper scoping for different pages and components, please implement the following shortcuts: * **Dialogs** — `frontend/src/components/ui/dialog.tsx` * `Esc` — Close dialog (when available) * `Enter` — Submit / confirm (when available) * **Projects** - `frontend/src/pages/projects.tsx` * `c` — New project * **Kanban** - `frontend/src/pages/project-tasks.tsx` * `c` — New task * `/` — Focus search in navbar * `Esc` - Navigate to projects page * `Arrow ↓ / ↑` — Move within column * `Arrow → / ←` — Next / previous column (focus first task) * `Enter` — Open task details * **Sidebar** - `frontend/src/components/tasks/TaskDetailsPanel.tsx` * `Esc` — Close sidebar * remove md * centralise registry * fmt * refactor prevent default * searchbar * ring on selected card * navigate kanban * select first card when none selected * cleanup * refactor kanban filtering * task edit/create shortcuts * textarea keyboard shortcuts * fix warnings * follow up on cmd enter * exit textarea * restore multi-file * save comments * keyboard shortcuts for comments * i18n for tasks page * toggle fullscreen * typesafe scopes * fix delete dialog resolve/reject
81 lines
1.8 KiB
TypeScript
81 lines
1.8 KiB
TypeScript
import {
|
|
createContext,
|
|
useContext,
|
|
useState,
|
|
useEffect,
|
|
useRef,
|
|
useCallback,
|
|
ReactNode,
|
|
} from 'react';
|
|
import { useLocation, useParams } from 'react-router-dom';
|
|
|
|
interface SearchState {
|
|
query: string;
|
|
setQuery: (query: string) => void;
|
|
active: boolean;
|
|
clear: () => void;
|
|
focusInput: () => void;
|
|
registerInputRef: (ref: HTMLInputElement | null) => void;
|
|
}
|
|
|
|
const SearchContext = createContext<SearchState | null>(null);
|
|
|
|
interface SearchProviderProps {
|
|
children: ReactNode;
|
|
}
|
|
|
|
export function SearchProvider({ children }: SearchProviderProps) {
|
|
const [query, setQuery] = useState('');
|
|
const location = useLocation();
|
|
const { projectId } = useParams<{ projectId: string }>();
|
|
const inputRef = useRef<HTMLInputElement | null>(null);
|
|
|
|
// Check if we're on a tasks route
|
|
const isTasksRoute = /^\/projects\/[^/]+\/tasks/.test(location.pathname);
|
|
|
|
// Clear search when leaving tasks pages
|
|
useEffect(() => {
|
|
if (!isTasksRoute && query !== '') {
|
|
setQuery('');
|
|
}
|
|
}, [isTasksRoute, query]);
|
|
|
|
// Clear search when project changes
|
|
useEffect(() => {
|
|
setQuery('');
|
|
}, [projectId]);
|
|
|
|
const clear = () => setQuery('');
|
|
|
|
const focusInput = () => {
|
|
if (inputRef.current && isTasksRoute) {
|
|
inputRef.current.focus();
|
|
}
|
|
};
|
|
|
|
const registerInputRef = useCallback((ref: HTMLInputElement | null) => {
|
|
inputRef.current = ref;
|
|
}, []);
|
|
|
|
const value: SearchState = {
|
|
query,
|
|
setQuery,
|
|
active: isTasksRoute,
|
|
clear,
|
|
focusInput,
|
|
registerInputRef,
|
|
};
|
|
|
|
return (
|
|
<SearchContext.Provider value={value}>{children}</SearchContext.Provider>
|
|
);
|
|
}
|
|
|
|
export function useSearch(): SearchState {
|
|
const context = useContext(SearchContext);
|
|
if (!context) {
|
|
throw new Error('useSearch must be used within a SearchProvider');
|
|
}
|
|
return context;
|
|
}
|