From d3204f6cd7772fe63d19ef8892664335d615c9de Mon Sep 17 00:00:00 2001 From: vishesh711 Date: Tue, 15 Jul 2025 12:36:53 -0400 Subject: feat: Add comprehensive keyboard shortcuts system for video editor - Implement industry-standard video editing shortcuts (Space, J/K/L, arrows) - Add playback controls: Space (play/pause), J/K/L (rewind/pause/forward) - Add navigation: arrow keys (frame stepping), Shift+arrows (5s jumps), Home/End - Add editing shortcuts: S (split at playhead), N (toggle snapping) - Add selection shortcuts: Ctrl/Cmd+A (select all), Ctrl/Cmd+D (duplicate) - Add keyboard shortcuts help dialog with categorized shortcuts display - Integrate help button in editor header for discoverability - Add TypeScript type declarations for better development experience - Fix Docker build environment variable validation issues All shortcuts follow professional video editing standards (Avid/Premiere/Final Cut). Context-aware shortcuts that don't interfere with text input fields. Toast notifications provide user feedback for better UX. --- .../web/src/components/keyboard-shortcuts-help.tsx | 220 +++++++++++++++++++++ 1 file changed, 220 insertions(+) create mode 100644 apps/web/src/components/keyboard-shortcuts-help.tsx (limited to 'apps/web/src/components/keyboard-shortcuts-help.tsx') diff --git a/apps/web/src/components/keyboard-shortcuts-help.tsx b/apps/web/src/components/keyboard-shortcuts-help.tsx new file mode 100644 index 00000000..c2087b4a --- /dev/null +++ b/apps/web/src/components/keyboard-shortcuts-help.tsx @@ -0,0 +1,220 @@ +"use client"; + +import { useState } from "react"; +import { Button } from "./ui/button"; +import { + Dialog, + DialogContent, + DialogDescription, + DialogHeader, + DialogTitle, + DialogTrigger, +} from "./ui/dialog"; +import { Badge } from "./ui/badge"; +import { Keyboard, Play, Pause, SkipBack, SkipForward } from "lucide-react"; + +interface Shortcut { + keys: string[]; + description: string; + category: string; + icon?: React.ReactNode; +} + +const shortcuts: Shortcut[] = [ + // Playback Controls + { + keys: ["Space"], + description: "Play/Pause", + category: "Playback", + icon: + }, + { + keys: ["J"], + description: "Rewind 1 second", + category: "Playback", + icon: + }, + { + keys: ["K"], + description: "Play/Pause (alternative)", + category: "Playback", + icon: + }, + { + keys: ["L"], + description: "Fast forward 1 second", + category: "Playback", + icon: + }, + + // Navigation + { + keys: ["←"], + description: "Frame step backward", + category: "Navigation" + }, + { + keys: ["→"], + description: "Frame step forward", + category: "Navigation" + }, + { + keys: ["Shift", "←"], + description: "Jump back 5 seconds", + category: "Navigation" + }, + { + keys: ["Shift", "→"], + description: "Jump forward 5 seconds", + category: "Navigation" + }, + { + keys: ["Home"], + description: "Go to timeline start", + category: "Navigation" + }, + { + keys: ["End"], + description: "Go to timeline end", + category: "Navigation" + }, + + // Editing + { + keys: ["S"], + description: "Split element at playhead", + category: "Editing" + }, + { + keys: ["Delete", "Backspace"], + description: "Delete selected elements", + category: "Editing" + }, + { + keys: ["N"], + description: "Toggle snapping", + category: "Editing" + }, + + // Selection & Organization + { + keys: ["Cmd", "A"], + description: "Select all elements", + category: "Selection" + }, + { + keys: ["Cmd", "D"], + description: "Duplicate selected element", + category: "Selection" + }, + + // History + { + keys: ["Cmd", "Z"], + description: "Undo", + category: "History" + }, + { + keys: ["Cmd", "Shift", "Z"], + description: "Redo", + category: "History" + }, + { + keys: ["Cmd", "Y"], + description: "Redo (alternative)", + category: "History" + } +]; + +const KeyBadge = ({ keyName }: { keyName: string }) => { + // Replace common key names with symbols + const displayKey = keyName + .replace("Cmd", "⌘") + .replace("Shift", "⇧") + .replace("←", "◀") + .replace("→", "▶") + .replace("Space", "⎵"); + + return ( + + {displayKey} + + ); +}; + +const ShortcutItem = ({ shortcut }: { shortcut: Shortcut }) => ( +
+
+ {shortcut.icon && ( +
{shortcut.icon}
+ )} + {shortcut.description} +
+
+ {shortcut.keys.map((key, index) => ( +
+ + {index < shortcut.keys.length - 1 && ( + + + )} +
+ ))} +
+
+); + +export const KeyboardShortcutsHelp = () => { + const [open, setOpen] = useState(false); + + const categories = Array.from(new Set(shortcuts.map(s => s.category))); + + return ( + + + + + + + + + Keyboard Shortcuts + + + Speed up your video editing workflow with these keyboard shortcuts. + Most shortcuts work when the timeline is focused. + + + +
+ {categories.map(category => ( +
+

+ {category} +

+
+ {shortcuts + .filter(shortcut => shortcut.category === category) + .map((shortcut, index) => ( + + ))} +
+
+ ))} +
+ +
+

Tips:

+
    +
  • • Shortcuts work when the editor is focused (not typing in inputs)
  • +
  • • J/K/L are industry-standard video editing shortcuts
  • +
  • • Use arrow keys for frame-perfect positioning
  • +
  • • Hold Shift with arrow keys for larger jumps
  • +
+
+
+
+ ); +}; \ No newline at end of file -- cgit v1.3.1