feat: add comprehensive keyboard shortcuts system

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>
This commit is contained in:
2025-11-17 13:34:11 +01:00
parent 6b0bda05db
commit 3f4fcf39bc
4 changed files with 220 additions and 2 deletions

View File

@@ -0,0 +1,65 @@
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(' + ');
}