diff options
Diffstat (limited to 'apps/web/src/components/editor/timeline-zoom-control.tsx')
| -rw-r--r-- | apps/web/src/components/editor/timeline-zoom-control.tsx | 126 |
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> + ); +} |
