summaryrefslogtreecommitdiff
path: root/apps/web/src/components/editor/timeline-zoom-control.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'apps/web/src/components/editor/timeline-zoom-control.tsx')
-rw-r--r--apps/web/src/components/editor/timeline-zoom-control.tsx126
1 files changed, 126 insertions, 0 deletions
diff --git a/apps/web/src/components/editor/timeline-zoom-control.tsx b/apps/web/src/components/editor/timeline-zoom-control.tsx
new file mode 100644
index 00000000..ab9c57a5
--- /dev/null
+++ b/apps/web/src/components/editor/timeline-zoom-control.tsx
@@ -0,0 +1,126 @@
+import { useState } from "react";
+import { Button } from "../ui/button";
+import { Slider } from "../ui/slider";
+import {
+ Tooltip,
+ TooltipContent,
+ TooltipTrigger,
+} from "../ui/tooltip";
+import { ZoomIn, ZoomOut, Maximize2 } from "lucide-react";
+
+interface TimelineZoomControlProps {
+ zoomLevel: number;
+ onZoomChange: (zoom: number) => void;
+ onFitToWindow?: () => void;
+ className?: string;
+}
+
+export function TimelineZoomControl({
+ zoomLevel,
+ onZoomChange,
+ onFitToWindow,
+ className,
+}: TimelineZoomControlProps) {
+ // Convert zoom level to percentage for display
+ const zoomPercentage = Math.round(zoomLevel * 100);
+
+ const handleZoomIn = () => {
+ onZoomChange(Math.min(10, zoomLevel + 0.2));
+ };
+
+ const handleZoomOut = () => {
+ onZoomChange(Math.max(0.1, zoomLevel - 0.2));
+ };
+
+ const handleReset = () => {
+ if (onFitToWindow) {
+ onFitToWindow();
+ } else {
+ onZoomChange(1);
+ }
+ };
+
+ const handleSliderChange = (value: number[]) => {
+ onZoomChange(value[0]);
+ };
+
+ return (
+ <div className={`flex items-center gap-1 ${className || ""}`}>
+ {/* Zoom Out Button */}
+ <Tooltip>
+ <TooltipTrigger asChild>
+ <Button
+ variant="outline"
+ size="sm"
+ onClick={handleZoomOut}
+ disabled={zoomLevel <= 0.1}
+ className="h-7 w-7 p-0"
+ >
+ <ZoomOut className="h-3 w-3" />
+ </Button>
+ </TooltipTrigger>
+ <TooltipContent>
+ <p>Zoom out</p>
+ <p className="text-xs text-muted-foreground">Ctrl + - / Ctrl + Wheel</p>
+ </TooltipContent>
+ </Tooltip>
+
+ {/* Zoom Slider */}
+ <div className="flex items-center gap-2 w-20">
+ <Slider
+ value={[zoomLevel]}
+ onValueChange={handleSliderChange}
+ min={0.1}
+ max={5}
+ step={0.1}
+ className="flex-1"
+ />
+ </div>
+
+ {/* Zoom In Button */}
+ <Tooltip>
+ <TooltipTrigger asChild>
+ <Button
+ variant="outline"
+ size="sm"
+ onClick={handleZoomIn}
+ disabled={zoomLevel >= 5}
+ className="h-7 w-7 p-0"
+ >
+ <ZoomIn className="h-3 w-3" />
+ </Button>
+ </TooltipTrigger>
+ <TooltipContent>
+ <p>Zoom in</p>
+ <p className="text-xs text-muted-foreground">Ctrl + + / Ctrl + Wheel</p>
+ </TooltipContent>
+ </Tooltip>
+
+ {/* Fit to Window / Reset Button */}
+ <Tooltip>
+ <TooltipTrigger asChild>
+ <Button
+ variant="outline"
+ size="sm"
+ onClick={handleReset}
+ className="h-7 px-2 min-w-[60px] flex items-center gap-1"
+ >
+ {onFitToWindow ? (
+ <>
+ <Maximize2 className="h-3 w-3" />
+ </>
+ ) : (
+ <span className="text-xs font-mono">{zoomPercentage}%</span>
+ )}
+ </Button>
+ </TooltipTrigger>
+ <TooltipContent>
+ <p>{onFitToWindow ? "Fit to Window" : "Reset Zoom"}</p>
+ <p className="text-xs text-muted-foreground">
+ {onFitToWindow ? "Show all track content" : "Ctrl + 0"}
+ </p>
+ </TooltipContent>
+ </Tooltip>
+ </div>
+ );
+}