summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaze Winther <mazewinther@gmail.com>2025-07-21 23:07:23 +0200
committerMaze Winther <mazewinther@gmail.com>2025-07-21 23:07:23 +0200
commit2bc3df5383815791547d61f60d26c8c7c910ac85 (patch)
tree71b1a05913866d703d479e812ee08019caefcb2a
parentc06ff9249dba4adc35bb3d1647b22efb49dbcd7d (diff)
downloadopencut-2bc3df5383815791547d61f60d26c8c7c910ac85.tar.gz
Merge pull request [#388](https://github.com/mazeincoding/AppCut/issues/388)
-rw-r--r--apps/web/src/components/editor/timeline/index.tsx44
1 files changed, 40 insertions, 4 deletions
diff --git a/apps/web/src/components/editor/timeline/index.tsx b/apps/web/src/components/editor/timeline/index.tsx
index 3ca561c5..993aa6ad 100644
--- a/apps/web/src/components/editor/timeline/index.tsx
+++ b/apps/web/src/components/editor/timeline/index.tsx
@@ -18,6 +18,8 @@ import {
Lock,
LockOpen,
Link,
+ ZoomIn,
+ ZoomOut,
} from "lucide-react";
import {
Tooltip,
@@ -56,6 +58,7 @@ import {
TIMELINE_CONSTANTS,
snapTimeToFrame,
} from "@/constants/timeline-constants";
+import { Slider } from "@/components/ui/slider";
export function Timeline() {
// Timeline shows all tracks (video, audio, effects) and their elements.
@@ -504,7 +507,7 @@ export function Timeline() {
onMouseEnter={() => setIsInTimeline(true)}
onMouseLeave={() => setIsInTimeline(false)}
>
- <TimelineToolbar />
+ <TimelineToolbar zoomLevel={zoomLevel} setZoomLevel={setZoomLevel} />
{/* Timeline Container */}
<div
@@ -778,7 +781,13 @@ function TrackIcon({ track }: { track: TimelineTrack }) {
);
}
-function TimelineToolbar() {
+function TimelineToolbar({
+ zoomLevel,
+ setZoomLevel,
+}: {
+ zoomLevel: number;
+ setZoomLevel: (zoom: number) => void;
+}) {
const {
tracks,
addTrack,
@@ -797,8 +806,6 @@ function TimelineToolbar() {
toggleRippleEditing,
} = useTimelineStore();
const { currentTime, duration, isPlaying, toggle } = usePlaybackStore();
- const { activeProject } = useProjectStore();
- const { mediaItems, addMediaItem } = useMediaStore();
// Action handlers
const handleSplitSelected = () => {
@@ -915,6 +922,19 @@ function TimelineToolbar() {
});
clearSelectedElements();
};
+
+ // Zoom handlers
+ const handleZoomIn = () => {
+ setZoomLevel(Math.min(4, zoomLevel + 0.25));
+ };
+
+ const handleZoomOut = () => {
+ setZoomLevel(Math.max(0.25, zoomLevel - 0.25));
+ };
+
+ const handleZoomSliderChange = (values: number[]) => {
+ setZoomLevel(values[0]);
+ };
return (
<div className="border-b flex items-center justify-between px-2 py-1">
<div className="flex items-center gap-1 w-full">
@@ -1077,6 +1097,22 @@ function TimelineToolbar() {
</TooltipContent>
</Tooltip>
</TooltipProvider>
+ <div className="flex items-center gap-1">
+ <Button variant="text" size="icon" onClick={handleZoomOut}>
+ <ZoomOut className="h-4 w-4" />
+ </Button>
+ <Slider
+ className="w-24"
+ value={[zoomLevel]}
+ onValueChange={handleZoomSliderChange}
+ min={0.25}
+ max={4}
+ step={0.25}
+ />
+ <Button variant="text" size="icon" onClick={handleZoomIn}>
+ <ZoomIn className="h-4 w-4" />
+ </Button>
+ </div>
</div>
</div>
);