Browse Source

fix: unify video handle, label, and edge colors to pink (#ec4899)

Video handles/edges/labels were inconsistent — using white, green, blue,
and hardcoded purple across different files. Standardize all to pink and
use the CSS variable var(--handle-color-video) for labels. Also adds the
missing .react-flow__handle[data-handletype="video"] CSS rule.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
handoff-20260429-1057
shrimbly 3 months ago
parent
commit
ea8eb8a8d7
  1. 7
      src/app/globals.css
  2. 2
      src/components/edges/EditableEdge.tsx
  3. 2
      src/components/edges/SharedEdgeGradients.tsx
  4. 4
      src/components/nodes/EaseCurveNode.tsx
  5. 4
      src/components/nodes/GenerateAudioNode.tsx
  6. 2
      src/components/nodes/GenerateImageNode.tsx
  7. 4
      src/components/nodes/GenerateVideoNode.tsx
  8. 2
      src/components/nodes/OutputGalleryNode.tsx
  9. 2
      src/components/nodes/RouterNode.tsx
  10. 2
      src/components/nodes/SwitchNode.tsx
  11. 2
      src/components/nodes/VideoFrameGrabNode.tsx
  12. 4
      src/components/nodes/VideoStitchNode.tsx
  13. 4
      src/components/nodes/VideoTrimNode.tsx

7
src/app/globals.css

@ -12,7 +12,7 @@
--handle-color-text: #3b82f6; --handle-color-text: #3b82f6;
--handle-color-3d: #f97316; --handle-color-3d: #f97316;
--handle-color-audio: #a855f7; --handle-color-audio: #a855f7;
--handle-color-video: #a855f7; --handle-color-video: #ec4899;
} }
html { html {
@ -125,6 +125,11 @@ body {
background: #a855f7; background: #a855f7;
} }
/* Video handles - pink */
.react-flow__handle[data-handletype="video"] {
background: #ec4899;
}
/* 3D handles - orange */ /* 3D handles - orange */
.react-flow__handle[data-handletype="3d"] { .react-flow__handle[data-handletype="3d"] {
background: #f97316; background: #f97316;

2
src/components/edges/EditableEdge.tsx

@ -24,7 +24,7 @@ const EDGE_COLORS: Record<string, string> = {
default: "#64748b", // Gray for unknown default: "#64748b", // Gray for unknown
pause: "#ea580c", // Orange for paused edges pause: "#ea580c", // Orange for paused edges
reference: "#52525b", // Gray for reference connections reference: "#52525b", // Gray for reference connections
video: "#a855f7", // Purple for video connections video: "#ec4899", // Pink for video connections
audio: "#f97316", // Orange for audio connections audio: "#f97316", // Orange for audio connections
text: "#2563eb", // Blue for text connections text: "#2563eb", // Blue for text connections
"3d": "#06b6d4", // Cyan for 3D connections "3d": "#06b6d4", // Cyan for 3D connections

2
src/components/edges/SharedEdgeGradients.tsx

@ -10,7 +10,7 @@ const EDGE_COLORS: Record<string, string> = {
default: "#64748b", default: "#64748b",
pause: "#ea580c", pause: "#ea580c",
reference: "#52525b", reference: "#52525b",
video: "#a855f7", video: "#ec4899",
audio: "#f97316", audio: "#f97316",
text: "#2563eb", text: "#2563eb",
"3d": "#06b6d4", "3d": "#06b6d4",

4
src/components/nodes/EaseCurveNode.tsx

@ -57,7 +57,7 @@ export function EaseCurveNode({ id, data, selected }: NodeProps<EaseCurveNodeTyp
isConnectable={true} isConnectable={true}
style={{ top: "35%" }} style={{ top: "35%" }}
/> />
<HandleLabel label="Video In" side="target" color="rgb(168, 85, 247)" top="calc(35% - 7px)" visible={showLabels} /> <HandleLabel label="Video In" side="target" color="var(--handle-color-video)" top="calc(35% - 7px)" visible={showLabels} />
{/* Video Out (source, right, 35%) */} {/* Video Out (source, right, 35%) */}
<Handle <Handle
@ -68,7 +68,7 @@ export function EaseCurveNode({ id, data, selected }: NodeProps<EaseCurveNodeTyp
isConnectable={true} isConnectable={true}
style={{ top: "35%" }} style={{ top: "35%" }}
/> />
<HandleLabel label="Video Out" side="source" color="rgb(168, 85, 247)" top="calc(35% - 7px)" visible={showLabels} /> <HandleLabel label="Video Out" side="source" color="var(--handle-color-video)" top="calc(35% - 7px)" visible={showLabels} />
{/* Settings In (target, left, 75%) */} {/* Settings In (target, left, 75%) */}
<Handle <Handle

4
src/components/nodes/GenerateAudioNode.tsx

@ -248,7 +248,7 @@ export function GenerateAudioNode({ id, data, selected }: NodeProps<GenerateAudi
</React.Fragment> </React.Fragment>
); );
}); });
}, [nodeData.inputSchema]); }, [nodeData.inputSchema, showLabels]);
return ( return (
<> <>
@ -429,7 +429,7 @@ export function GenerateAudioNode({ id, data, selected }: NodeProps<GenerateAudi
{/* Download button */} {/* Download button */}
<button <button
onClick={() => downloadMedia(nodeData.outputAudio!, "audio")} onClick={() => downloadMedia(nodeData.outputAudio!, "audio").catch(() => {})}
className="absolute top-1 right-7 w-5 h-5 bg-black/60 hover:bg-black/80 text-white rounded text-xs opacity-0 group-hover:opacity-100 transition-opacity flex items-center justify-center" className="absolute top-1 right-7 w-5 h-5 bg-black/60 hover:bg-black/80 text-white rounded text-xs opacity-0 group-hover:opacity-100 transition-opacity flex items-center justify-center"
title="Download audio" title="Download audio"
> >

2
src/components/nodes/GenerateImageNode.tsx

@ -782,7 +782,7 @@ export function GenerateImageNode({ id, data, selected }: NodeProps<NanoBananaNo
{/* Download + Clear buttons */} {/* Download + Clear buttons */}
<div className="absolute top-1 right-1 flex items-center gap-0.5"> <div className="absolute top-1 right-1 flex items-center gap-0.5">
<button <button
onClick={() => downloadMedia(nodeData.outputImage!, "image")} onClick={() => downloadMedia(nodeData.outputImage!, "image").catch(() => {})}
className="w-5 h-5 bg-neutral-900/80 hover:bg-neutral-700 rounded flex items-center justify-center text-neutral-400 hover:text-white transition-colors" className="w-5 h-5 bg-neutral-900/80 hover:bg-neutral-700 rounded flex items-center justify-center text-neutral-400 hover:text-white transition-colors"
title="Download image" title="Download image"
> >

4
src/components/nodes/GenerateVideoNode.tsx

@ -644,7 +644,7 @@ export function GenerateVideoNode({ id, data, selected }: NodeProps<GenerateVide
style={{ zIndex: 10 }} style={{ zIndex: 10 }}
/> />
{/* Output label */} {/* Output label */}
<HandleLabel label="Video" side="source" color="var(--handle-color-image)" visible={showLabels} /> <HandleLabel label="Video" side="source" color="var(--handle-color-video)" visible={showLabels} />
<div className="relative w-full h-full min-h-0 overflow-hidden rounded-lg"> <div className="relative w-full h-full min-h-0 overflow-hidden rounded-lg">
{/* Preview area */} {/* Preview area */}
@ -735,7 +735,7 @@ export function GenerateVideoNode({ id, data, selected }: NodeProps<GenerateVide
{/* Download + Clear buttons */} {/* Download + Clear buttons */}
<div className="absolute top-1 right-1 flex items-center gap-0.5"> <div className="absolute top-1 right-1 flex items-center gap-0.5">
<button <button
onClick={() => downloadMedia(nodeData.outputVideo!, "video")} onClick={() => downloadMedia(nodeData.outputVideo!, "video").catch(() => {})}
className="w-5 h-5 bg-neutral-900/80 hover:bg-neutral-700 rounded flex items-center justify-center text-neutral-400 hover:text-white transition-colors" className="w-5 h-5 bg-neutral-900/80 hover:bg-neutral-700 rounded flex items-center justify-center text-neutral-400 hover:text-white transition-colors"
title="Download video" title="Download video"
> >

2
src/components/nodes/OutputGalleryNode.tsx

@ -197,7 +197,7 @@ export function OutputGalleryNode({ id, data, selected }: NodeProps<OutputGaller
data-handletype="video" data-handletype="video"
style={{ top: "60%" }} style={{ top: "60%" }}
/> />
<HandleLabel label="Video" side="target" color="rgb(168, 85, 247)" top="calc(60% - 18px)" visible={showLabels} /> <HandleLabel label="Video" side="target" color="var(--handle-color-video)" top="calc(60% - 18px)" visible={showLabels} />
{displayMedia.length > 0 && ( {displayMedia.length > 0 && (
<div className="flex items-center justify-between px-2 py-1"> <div className="flex items-center justify-between px-2 py-1">

2
src/components/nodes/RouterNode.tsx

@ -11,7 +11,7 @@ const ALL_HANDLE_TYPES = ["image", "text", "video", "audio", "3d", "easeCurve"]
const HANDLE_COLORS: Record<(typeof ALL_HANDLE_TYPES)[number], string> = { const HANDLE_COLORS: Record<(typeof ALL_HANDLE_TYPES)[number], string> = {
image: "#10b981", // emerald — matches globals.css image: "#10b981", // emerald — matches globals.css
text: "#3b82f6", // blue — matches globals.css text: "#3b82f6", // blue — matches globals.css
video: "#ffffff", // white — default handle style video: "#ec4899", // pink — video handle style
audio: "rgb(167, 139, 250)", // violet — matches GenerateAudioNode/OutputNode audio: "rgb(167, 139, 250)", // violet — matches GenerateAudioNode/OutputNode
"3d": "#f97316", // orange — matches globals.css "3d": "#f97316", // orange — matches globals.css
easeCurve: "#ffffff", // white — default handle style easeCurve: "#ffffff", // white — default handle style

2
src/components/nodes/SwitchNode.tsx

@ -9,7 +9,7 @@ import type { WorkflowNode, SwitchNodeData, HandleType } from "@/types";
const HANDLE_COLORS: Record<HandleType, string> = { const HANDLE_COLORS: Record<HandleType, string> = {
image: "#10b981", // emerald — matches globals.css image: "#10b981", // emerald — matches globals.css
text: "#3b82f6", // blue — matches globals.css text: "#3b82f6", // blue — matches globals.css
video: "#ffffff", // white — default handle style video: "#ec4899", // pink — video handle style
audio: "rgb(167, 139, 250)", // violet — matches GenerateAudioNode/OutputNode audio: "rgb(167, 139, 250)", // violet — matches GenerateAudioNode/OutputNode
"3d": "#f97316", // orange — matches globals.css "3d": "#f97316", // orange — matches globals.css
easeCurve: "#ffffff", // white — default handle style easeCurve: "#ffffff", // white — default handle style

2
src/components/nodes/VideoFrameGrabNode.tsx

@ -59,7 +59,7 @@ export function VideoFrameGrabNode({ id, data, selected }: NodeProps<VideoFrameG
isConnectable={true} isConnectable={true}
style={{ top: "50%" }} style={{ top: "50%" }}
/> />
<HandleLabel label="Video In" side="target" color="rgb(168, 85, 247)" top="calc(50% - 7px)" visible={showLabels} /> <HandleLabel label="Video In" side="target" color="var(--handle-color-video)" top="calc(50% - 7px)" visible={showLabels} />
{/* Image Out (source, right, 50%) */} {/* Image Out (source, right, 50%) */}
<Handle <Handle

4
src/components/nodes/VideoStitchNode.tsx

@ -315,7 +315,7 @@ export function VideoStitchNode({ id, data, selected }: NodeProps<VideoStitchNod
isConnectable={true} isConnectable={true}
style={{ top: `${topPercent}%` }} style={{ top: `${topPercent}%` }}
/> />
<HandleLabel label={`Video ${index + 1}`} side="target" color="rgb(96, 165, 250)" top={`calc(${topPercent}% - 9px)`} visible={showLabels} /> <HandleLabel label={`Video ${index + 1}`} side="target" color="var(--handle-color-video)" top={`calc(${topPercent}% - 9px)`} visible={showLabels} />
</React.Fragment> </React.Fragment>
); );
})} })}
@ -339,7 +339,7 @@ export function VideoStitchNode({ id, data, selected }: NodeProps<VideoStitchNod
data-handletype="video" data-handletype="video"
isConnectable={true} isConnectable={true}
/> />
<HandleLabel label="Output" side="source" color="rgb(96, 165, 250)" top="calc(50% - 9px)" visible={showLabels} /> <HandleLabel label="Output" side="source" color="var(--handle-color-video)" top="calc(50% - 9px)" visible={showLabels} />
</> </>
); );

4
src/components/nodes/VideoTrimNode.tsx

@ -176,7 +176,7 @@ export function VideoTrimNode({ id, data, selected }: NodeProps<VideoTrimNodeTyp
isConnectable={true} isConnectable={true}
style={{ top: "50%" }} style={{ top: "50%" }}
/> />
<HandleLabel label="Video In" side="target" color="rgb(168, 85, 247)" top="calc(50% - 7px)" visible={showLabels} /> <HandleLabel label="Video In" side="target" color="var(--handle-color-video)" top="calc(50% - 7px)" visible={showLabels} />
{/* Video Out (source, right, 50%) */} {/* Video Out (source, right, 50%) */}
<Handle <Handle
@ -187,7 +187,7 @@ export function VideoTrimNode({ id, data, selected }: NodeProps<VideoTrimNodeTyp
isConnectable={true} isConnectable={true}
style={{ top: "50%" }} style={{ top: "50%" }}
/> />
<HandleLabel label="Video Out" side="source" color="rgb(168, 85, 247)" top="calc(50% - 7px)" visible={showLabels} /> <HandleLabel label="Video Out" side="source" color="var(--handle-color-video)" top="calc(50% - 7px)" visible={showLabels} />
</> </>
); );

Loading…
Cancel
Save