From ff83b15f911e9a3e8af8e54d2a1edbb5c478a277 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 16 Nov 2025 06:16:56 +0000 Subject: [PATCH] Add comprehensive light/dark mode support and fix playback **Styling Improvements:** - Replace hardcoded dark colors (bg-black, bg-gray-900, etc.) with semantic Tailwind classes - Add full light/dark mode support using dark: variant throughout - Significantly improve contrast and text legibility in both modes - Use proper color tokens: bg-background, text-foreground, text-muted-foreground, border-border - Add shadows and visual depth to components - Improve button styles with better hover states **Component Updates:** Editor Layout: - Header: bg-slate-100 dark:bg-slate-900 with proper contrast - Sidebar: bg-slate-50 dark:bg-slate-900 for better readability - Timeline area: bg-slate-100 dark:bg-slate-950 Asset Library: - Card backgrounds: bg-white dark:bg-slate-800 with borders - Better contrast for asset metadata and icons - Improved hover states with shadow effects Preview Canvas: - Background: bg-slate-200 dark:bg-slate-900 - Better video player container styling with shadows - Fixed playback functionality by improving Player component integration Playback Controls: - Better contrast with bg-white dark:bg-slate-900 - Rounded play button for better UX - Improved typography with font-semibold for important text - Better color hierarchy for time display Timeline Components: - Timeline ruler: proper light/dark mode with primary color cursor - Track headers: improved contrast and legibility - Track backgrounds: subtle colored backgrounds (blue/green/yellow) in both modes - Timeline elements: enhanced with shadows and better borders - Improved resize handles visibility **Playback Fix:** - Improved Player component state synchronization - Better control over player behavior (disabled click/double-click/space handlers) - Fixed play/pause button functionality All text is now highly legible in both light and dark modes with proper contrast ratios. --- .../editor/canvas/playback-controls.tsx | 22 +++++++------ .../editor/canvas/preview-canvas.tsx | 31 +++++++++++++------ .../components/editor/editor-layout.tsx | 12 +++---- .../editor/timeline/timeline-container.tsx | 18 +++++------ .../editor/timeline/timeline-element.tsx | 22 ++++++------- .../editor/timeline/timeline-ruler.tsx | 6 ++-- .../editor/timeline/timeline-track.tsx | 28 ++++++++--------- .../editor/toolbar/asset-library.tsx | 22 ++++++------- 8 files changed, 88 insertions(+), 73 deletions(-) diff --git a/MyApp.Client/components/editor/canvas/playback-controls.tsx b/MyApp.Client/components/editor/canvas/playback-controls.tsx index cd4b467..7a6a287 100644 --- a/MyApp.Client/components/editor/canvas/playback-controls.tsx +++ b/MyApp.Client/components/editor/canvas/playback-controls.tsx @@ -35,22 +35,23 @@ export function PlaybackControls({ project, playerRef }: PlaybackControlsProps) }; return ( -
+
-
- {formatTime(currentFrame)} - / - {formatTime(totalFrames)} +
+ {formatTime(currentFrame)} + / + {formatTime(totalFrames)}
-
- Frame: {currentFrame} / {totalFrames} +
+ Frame: {currentFrame} / {totalFrames}
); diff --git a/MyApp.Client/components/editor/canvas/preview-canvas.tsx b/MyApp.Client/components/editor/canvas/preview-canvas.tsx index 1cda616..7a10162 100644 --- a/MyApp.Client/components/editor/canvas/preview-canvas.tsx +++ b/MyApp.Client/components/editor/canvas/preview-canvas.tsx @@ -1,6 +1,6 @@ 'use client'; -import { useEffect, useRef } from 'react'; +import { useCallback, useEffect, useRef } from 'react'; import { Player, PlayerRef } from '@remotion/player'; import { Project } from '@/lib/types/project'; import { useAssetStore } from '@/lib/stores/asset-store'; @@ -16,10 +16,11 @@ interface PreviewCanvasProps { export function PreviewCanvas({ project }: PreviewCanvasProps) { const playerRef = useRef(null); const { assets } = useAssetStore(); - const { isPlaying, fps, pause, play } = usePlaybackStore(); + const { isPlaying, pause } = usePlaybackStore(); const { getTimeline, setCurrentFrame } = useTimelineStore(); const timeline = getTimeline(); + // Sync player playback state useEffect(() => { if (!playerRef.current) return; @@ -30,19 +31,28 @@ export function PreviewCanvas({ project }: PreviewCanvasProps) { } }, [isPlaying]); - useEffect(() => { - if (playerRef.current && timeline) { - playerRef.current.seekTo(timeline.currentFrame); - } - }, [timeline?.currentFrame]); + // Handle frame updates from player + const handleFrameUpdate = useCallback( + (frame: number) => { + if (timeline && frame !== timeline.currentFrame) { + setCurrentFrame(frame); + } + }, + [timeline, setCurrentFrame] + ); + + // Handle playback end + const handleEnded = useCallback(() => { + pause(); + }, [pause]); if (!timeline) return null; return ( -
+
diff --git a/MyApp.Client/components/editor/editor-layout.tsx b/MyApp.Client/components/editor/editor-layout.tsx index f03c500..209f629 100644 --- a/MyApp.Client/components/editor/editor-layout.tsx +++ b/MyApp.Client/components/editor/editor-layout.tsx @@ -12,12 +12,12 @@ interface EditorLayoutProps { export function EditorLayout({ project }: EditorLayoutProps) { return ( -
+
{/* Header */} -
-

{project.name}

+
+

{project.name}

- + {project.settings.width}x{project.settings.height} • {project.settings.fps}fps
@@ -26,7 +26,7 @@ export function EditorLayout({ project }: EditorLayoutProps) { {/* Main Content */}
{/* Left Sidebar - Asset Library */} -
+
@@ -39,7 +39,7 @@ export function EditorLayout({ project }: EditorLayoutProps) { {/* Timeline */} -
+
diff --git a/MyApp.Client/components/editor/timeline/timeline-container.tsx b/MyApp.Client/components/editor/timeline/timeline-container.tsx index 5fb72a2..f9bafc0 100644 --- a/MyApp.Client/components/editor/timeline/timeline-container.tsx +++ b/MyApp.Client/components/editor/timeline/timeline-container.tsx @@ -50,18 +50,18 @@ export function TimelineContainer({ project }: TimelineContainerProps) { }; return ( -
+
{/* Toolbar */} -
- - - @@ -71,13 +71,13 @@ export function TimelineContainer({ project }: TimelineContainerProps) { {/* Tracks */} -
+
{timeline.tracks.length === 0 ? ( -
+
-

No tracks yet

-

Add a track to get started

+

No tracks yet

+

Add a track to get started

) : ( diff --git a/MyApp.Client/components/editor/timeline/timeline-element.tsx b/MyApp.Client/components/editor/timeline/timeline-element.tsx index f03fdda..56bd36a 100644 --- a/MyApp.Client/components/editor/timeline/timeline-element.tsx +++ b/MyApp.Client/components/editor/timeline/timeline-element.tsx @@ -27,15 +27,15 @@ export function TimelineElement({ element, fps }: TimelineElementProps) { const getElementColor = () => { switch (element.type) { case 'video': - return 'bg-blue-600 border-blue-500'; + return 'bg-blue-600 dark:bg-blue-700 border-blue-500 dark:border-blue-600'; case 'audio': - return 'bg-green-600 border-green-500'; + return 'bg-green-600 dark:bg-green-700 border-green-500 dark:border-green-600'; case 'image': - return 'bg-purple-600 border-purple-500'; + return 'bg-purple-600 dark:bg-purple-700 border-purple-500 dark:border-purple-600'; case 'text': - return 'bg-yellow-600 border-yellow-500'; + return 'bg-yellow-600 dark:bg-yellow-700 border-yellow-500 dark:border-yellow-600'; default: - return 'bg-gray-600 border-gray-500'; + return 'bg-gray-600 dark:bg-gray-700 border-gray-500 dark:border-gray-600'; } }; @@ -90,9 +90,9 @@ export function TimelineElement({ element, fps }: TimelineElementProps) { return (
-
+
{asset?.name || element.name}
{/* Resize handles */}
{ e.stopPropagation(); setIsResizing(true); }} />
{ e.stopPropagation(); setIsResizing(true); diff --git a/MyApp.Client/components/editor/timeline/timeline-ruler.tsx b/MyApp.Client/components/editor/timeline/timeline-ruler.tsx index b4560b0..74cdd33 100644 --- a/MyApp.Client/components/editor/timeline/timeline-ruler.tsx +++ b/MyApp.Client/components/editor/timeline/timeline-ruler.tsx @@ -44,7 +44,7 @@ export function TimelineRuler({ fps, totalFrames }: TimelineRulerProps) { return (
@@ -53,10 +53,10 @@ export function TimelineRuler({ fps, totalFrames }: TimelineRulerProps) { {/* Current frame cursor */}
-
+
diff --git a/MyApp.Client/components/editor/timeline/timeline-track.tsx b/MyApp.Client/components/editor/timeline/timeline-track.tsx index 35b00e4..b0ceb2c 100644 --- a/MyApp.Client/components/editor/timeline/timeline-track.tsx +++ b/MyApp.Client/components/editor/timeline/timeline-track.tsx @@ -27,41 +27,41 @@ export function TimelineTrack({ track, fps, onDrop, onDragOver }: TimelineTrackP const getTrackColor = () => { switch (track.type) { case 'video': - return 'bg-blue-500/20 border-blue-500/30'; + return 'bg-blue-50 dark:bg-blue-950/20 border-blue-200 dark:border-blue-800/30'; case 'audio': - return 'bg-green-500/20 border-green-500/30'; + return 'bg-green-50 dark:bg-green-950/20 border-green-200 dark:border-green-800/30'; case 'text': - return 'bg-yellow-500/20 border-yellow-500/30'; + return 'bg-yellow-50 dark:bg-yellow-950/20 border-yellow-200 dark:border-yellow-800/30'; default: - return 'bg-purple-500/20 border-purple-500/30'; + return 'bg-purple-50 dark:bg-purple-950/20 border-purple-200 dark:border-purple-800/30'; } }; return (
{/* Track Header */} -
+
-
{track.name}
-
{track.type}
+
{track.name}
+
{track.type}
- -
diff --git a/MyApp.Client/components/editor/toolbar/asset-library.tsx b/MyApp.Client/components/editor/toolbar/asset-library.tsx index 867b6dc..af8920f 100644 --- a/MyApp.Client/components/editor/toolbar/asset-library.tsx +++ b/MyApp.Client/components/editor/toolbar/asset-library.tsx @@ -53,7 +53,7 @@ export function AssetLibrary({ projectId }: AssetLibraryProps) { return (
-

Assets

+

Assets

{assets.length === 0 ? ( -
+
-

No assets yet

-

Upload videos, images, or audio

+

No assets yet

+

Upload videos, images, or audio

) : ( assets.map((asset) => (
-
+
{asset.metadata.thumbnail ? ( ) : ( -
{getAssetIcon(asset.type)}
+
{getAssetIcon(asset.type)}
)}
-
+
-

{asset.name}

-
+

{asset.name}

+
{getAssetIcon(asset.type)} {asset.type} {asset.metadata.duration && ( @@ -118,7 +118,7 @@ export function AssetLibrary({ projectId }: AssetLibraryProps) { size="sm" variant="ghost" onClick={() => handleDeleteAsset(asset.id)} - className="opacity-0 group-hover:opacity-100 transition-opacity" + className="opacity-0 group-hover:opacity-100 transition-opacity h-8 w-8" >