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 00000000..3477a188 Binary files /dev/null and b/apps/web/public/platform-guides/tiktok-blueprint.png differ 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)} + /> + +
+ ))} +
+
+
+