From 9ec5a022520aa3a2d1e18b4e3b4056f2ff5dcd35 Mon Sep 17 00:00:00 2001 From: Maze Winther Date: Mon, 4 Aug 2025 17:17:48 +0200 Subject: [PATCH] feat: layout guide for tiktok --- .../platform-guides/tiktok-blueprint.png | Bin 0 -> 32525 bytes .../editor/layout-guide-overlay.tsx | 27 +++++++ .../src/components/editor/preview-panel.tsx | 68 +++++++++++++++++- apps/web/src/components/icons.tsx | 30 ++++++++ apps/web/src/stores/editor-store.ts | 32 +++++++++ 5 files changed, 155 insertions(+), 2 deletions(-) create mode 100644 apps/web/public/platform-guides/tiktok-blueprint.png create mode 100644 apps/web/src/components/editor/layout-guide-overlay.tsx diff --git a/apps/web/public/platform-guides/tiktok-blueprint.png b/apps/web/public/platform-guides/tiktok-blueprint.png new file mode 100644 index 0000000000000000000000000000000000000000..3477a188a9571b365ee69872a31cfbbcc468ffed GIT binary patch literal 32525 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 O1R5&u-d4W02>pMnSc&}r literal 0 HcmV?d00001 diff --git a/apps/web/src/components/editor/layout-guide-overlay.tsx b/apps/web/src/components/editor/layout-guide-overlay.tsx new file mode 100644 index 00000000..ff4cde57 --- /dev/null +++ b/apps/web/src/components/editor/layout-guide-overlay.tsx @@ -0,0 +1,27 @@ +"use client"; + +import { useEditorStore } from "@/stores/editor-store"; +import Image from "next/image"; + +function TikTokGuide() { + return ( +
+ TikTok layout guide +
+ ); +} + +export function LayoutGuideOverlay() { + const { layoutGuide } = useEditorStore(); + + if (layoutGuide.platform === null) return null; + if (layoutGuide.platform === "tiktok") return ; + + return null; +} diff --git a/apps/web/src/components/editor/preview-panel.tsx b/apps/web/src/components/editor/preview-panel.tsx index b9c03382..f4cd2016 100644 --- a/apps/web/src/components/editor/preview-panel.tsx +++ b/apps/web/src/components/editor/preview-panel.tsx @@ -8,7 +8,14 @@ import { useEditorStore } from "@/stores/editor-store"; import { VideoPlayer } from "@/components/ui/video-player"; import { AudioPlayer } from "@/components/ui/audio-player"; import { Button } from "@/components/ui/button"; -import { Play, Pause, Expand, SkipBack, SkipForward } from "lucide-react"; +import { + Play, + Pause, + Expand, + SkipBack, + SkipForward, + LayoutGrid, +} from "lucide-react"; import { useState, useRef, useEffect, useCallback } from "react"; import { cn } from "@/lib/utils"; import { formatTimeCode } from "@/lib/time"; @@ -16,6 +23,16 @@ import { EditableTimecode } from "@/components/ui/editable-timecode"; import { FONT_CLASS_MAP } from "@/lib/font-config"; import { useProjectStore } from "@/stores/project-store"; import { TextElementDragState } from "@/types/editor"; +import { + Popover, + PopoverContent, + PopoverTrigger, +} from "@/components/ui/popover"; +import { Checkbox } from "@/components/ui/checkbox"; +import { LayoutGuideOverlay } from "./layout-guide-overlay"; +import { Label } from "../ui/label"; +import { SocialsIcon } from "../icons"; +import { PLATFORM_LAYOUTS, type PlatformLayout } from "@/stores/editor-store"; interface ActiveElement { element: TimelineElement; @@ -496,6 +513,7 @@ export function PreviewPanel() { renderElement(elementData, index) ) )} + {activeProject?.backgroundType === "blur" && blurBackgroundElements.length === 0 && activeElements.length > 0 && ( @@ -758,6 +776,7 @@ function FullscreenPreview({ renderElement(elementData, index) ) )} + {activeProject?.backgroundType === "blur" && blurBackgroundElements.length === 0 && activeElements.length > 0 && ( @@ -799,6 +818,7 @@ function PreviewToolbar({ getTotalDuration: () => number; }) { const { isPlaying } = usePlaybackStore(); + const { layoutGuide, toggleLayoutGuide } = useEditorStore(); if (isExpanded) { return ( @@ -818,9 +838,53 @@ function PreviewToolbar({ return (
+ + + + + +
+
+

Layout guide

+

+ Show platform-specific layout guides to help align your + content with interface elements like profile pictures, + usernames, and interaction buttons. +

+
+
+
+ toggleLayoutGuide(layoutGuide.platform || "tiktok")} + /> + +
+ {Object.entries(PLATFORM_LAYOUTS).map(([platform, label]) => ( +
+ toggleLayoutGuide(platform as PlatformLayout)} + /> + +
+ ))} +
+
+
+