diff --git a/src/components/KeyboardShortcutPanel.tsx b/src/components/KeyboardShortcutPanel.tsx new file mode 100644 index 00000000..caf07770 --- /dev/null +++ b/src/components/KeyboardShortcutPanel.tsx @@ -0,0 +1,101 @@ +"use client"; + +import { useEffect } from "react"; +import { X } from "lucide-react"; + +interface ShortcutPanelProps { + open: boolean; + onClose: () => void; +} + +const shortcuts = [ + { keys: ["Cmd/Ctrl", "+", "Enter"], action: "Start export" }, + { keys: ["Space"], action: "Play / pause preview" }, + { keys: ["?"], action: "Toggle this shortcut panel" }, + { keys: ["Escape"], action: "Close overlay / cancel" }, + { keys: ["M"], action: "Toggle audio mute" }, +]; + +function ShortcutRow({ keys, action }: { keys: string[]; action: string }) { + return ( +
  • + {action} +
    + {keys.map((key) => ( + + {key} + + ))} +
    +
  • + ); +} + +export default function KeyboardShortcutPanel({ open, onClose }: ShortcutPanelProps) { + useEffect(() => { + if (!open) return; + const onKey = (e: KeyboardEvent) => { + if (e.key === "Escape") onClose(); + }; + + const previousOverflow = document.body.style.overflow; + + document.body.style.overflow = "hidden"; + document.addEventListener("keydown", onKey); + return () => { + document.removeEventListener("keydown", onKey); + document.body.style.overflow = previousOverflow; + }; + }, [open, onClose]); + + if (!open) return null; + + return ( +
    +
    + +
    + ); +} diff --git a/src/components/VideoEditor.tsx b/src/components/VideoEditor.tsx index db5c3793..5f9ffddd 100644 --- a/src/components/VideoEditor.tsx +++ b/src/components/VideoEditor.tsx @@ -16,11 +16,12 @@ import ExportSettings from "./ExportSettings"; import ExportOverlay from "./ExportOverlay"; import DownloadResult from "./DownloadResult"; import ImageOverlay from "./ImageOverlay" +import KeyboardShortcutPanel from "./KeyboardShortcutPanel"; import { cn } from "@/lib/utils"; import { Layers, Crop, Scissors, RotateCw, Volume2, - SlidersHorizontal, Zap, AlertTriangle, Github, Copy + SlidersHorizontal, Zap, AlertTriangle, Copy, HelpCircle } from "lucide-react"; import OnboardingTour from "./OnboardingTour"; import { useKeyboardShortcuts } from "@/hooks/useKeyboardShortcuts"; @@ -50,94 +51,6 @@ function Section({ icon, title, children, delay = 0 }: SectionProps) { ); } -/** Inline keyboard hint badge. */ -function Kbd({ children }: { children: React.ReactNode }) { - return ( - - {children} - - ); -} - -/** Collapsible panel that lists all keyboard shortcuts. */ -function KeyboardShortcutsPanel() { - const [open, setOpen] = useState(false); - - const shortcuts: { keys: React.ReactNode[]; label: string }[] = [ - { - keys: [ - Ctrl, - +, - Shift, - +, - E - ], - label: "Export video", - }, - { - keys: [M], - label: "Toggle audio mute", - }, - { - keys: [R], - label: "Reset all settings", - }, - { - keys: [Esc], - label: "Cancel export", - }, - { - keys: [1, , 9], - label: "Switch preset by index", - }, - { - keys: [?], - label: "Toggle this panel", - }, -]; - - return ( -
    - - - {open && ( - - )} -
    - ); -} - export default function VideoEditor() { const { file, duration, recipe, status, progress, @@ -149,6 +62,7 @@ export default function VideoEditor() { overlayPosition, setOverlayPosition, overlaySize, setOverlaySize, overlayOpacity, setOverlayOpacity, + isShortcutPanelOpen, closeShortcutPanel, toggleShortcutPanel, recommendedPreset, toggleSound, } = useVideoEditor(); @@ -203,6 +117,7 @@ export default function VideoEditor() { return (
    +
    @@ -213,7 +128,7 @@ export default function VideoEditor() {
    -
    +
    -
    - - No login. No ads. 100% private - your video never leaves your device. +
    +
    + + No login. No ads. 100% private - your video never leaves your device. +
    +
    @@ -475,9 +410,6 @@ export default function VideoEditor() {
    - - -