Keyboard shortcuts: - **Ctrl/Cmd + O**: Open file dialog - **Ctrl/Cmd + Enter**: Start conversion - **Ctrl/Cmd + S**: Download results (ZIP if multiple) - **Ctrl/Cmd + R**: Reset converter - **Ctrl/Cmd + /**: Show keyboard shortcuts help - **?**: Show keyboard shortcuts help - **Escape**: Close shortcuts modal Implementation: - Created useKeyboardShortcuts custom hook - Platform-aware keyboard handling (Cmd on Mac, Ctrl elsewhere) - KeyboardShortcutsModal component with beautiful UI - Floating keyboard icon button (bottom-right) - Visual shortcut display with kbd tags - Context-aware shortcut execution (respects disabled states) - Prevents default browser behavior for shortcuts User experience: - Floating help button always accessible - Clean modal with shortcut descriptions - Platform-specific key symbols (⌘ on Mac) - Shortcuts disabled when modal is open - Clear visual feedback for shortcuts - Non-intrusive button placement Features: - Smart ref forwarding to FileUpload component - Conditional shortcut execution based on app state - Professional kbd styling for key combinations - Responsive modal with backdrop - Smooth animations 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
66 lines
1.7 KiB
TypeScript
66 lines
1.7 KiB
TypeScript
import { useEffect } from 'react';
|
|
|
|
export interface KeyboardShortcut {
|
|
key: string;
|
|
ctrl?: boolean;
|
|
alt?: boolean;
|
|
shift?: boolean;
|
|
description: string;
|
|
action: () => void;
|
|
}
|
|
|
|
/**
|
|
* Hook for managing keyboard shortcuts
|
|
*/
|
|
export function useKeyboardShortcuts(shortcuts: KeyboardShortcut[], enabled: boolean = true) {
|
|
useEffect(() => {
|
|
if (!enabled) return;
|
|
|
|
const handleKeyDown = (event: KeyboardEvent) => {
|
|
// Find matching shortcut
|
|
const shortcut = shortcuts.find((s) => {
|
|
const keyMatch = s.key.toLowerCase() === event.key.toLowerCase();
|
|
const ctrlMatch = s.ctrl ? (event.ctrlKey || event.metaKey) : !event.ctrlKey && !event.metaKey;
|
|
const altMatch = s.alt ? event.altKey : !event.altKey;
|
|
const shiftMatch = s.shift ? event.shiftKey : !event.shiftKey;
|
|
|
|
return keyMatch && ctrlMatch && altMatch && shiftMatch;
|
|
});
|
|
|
|
if (shortcut) {
|
|
event.preventDefault();
|
|
shortcut.action();
|
|
}
|
|
};
|
|
|
|
window.addEventListener('keydown', handleKeyDown);
|
|
return () => window.removeEventListener('keydown', handleKeyDown);
|
|
}, [shortcuts, enabled]);
|
|
}
|
|
|
|
/**
|
|
* Format shortcut key combination for display
|
|
*/
|
|
export function formatShortcut(shortcut: KeyboardShortcut): string {
|
|
const parts: string[] = [];
|
|
|
|
// Use Cmd on Mac, Ctrl on others
|
|
const isMac = typeof window !== 'undefined' && /Mac|iPhone|iPod|iPad/.test(navigator.platform);
|
|
|
|
if (shortcut.ctrl) {
|
|
parts.push(isMac ? '⌘' : 'Ctrl');
|
|
}
|
|
|
|
if (shortcut.alt) {
|
|
parts.push(isMac ? '⌥' : 'Alt');
|
|
}
|
|
|
|
if (shortcut.shift) {
|
|
parts.push(isMac ? '⇧' : 'Shift');
|
|
}
|
|
|
|
parts.push(shortcut.key.toUpperCase());
|
|
|
|
return parts.join(' + ');
|
|
}
|