Browse Source

refactor: make SplitGridNode full-bleed with overlay controls

Switch to fullBleed BaseNode so the image preview fills the entire
node area. Move grid config, Settings, and Split controls into an
absolute-positioned overlay at the bottom with backdrop blur,
matching the pattern used by PromptConstructorNode and other
full-bleed nodes.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
handoff-20260429-1057
shrimbly 4 months ago
parent
commit
6a6dc82ad9
  1. 122
      src/components/nodes/SplitGridNode.tsx

122
src/components/nodes/SplitGridNode.tsx

@ -36,36 +36,39 @@ export function SplitGridNode({ id, data, selected }: NodeProps<SplitGridNodeTyp
}, [id, regenerateNode]);
return (
<BaseNode
id={id}
selected={selected}
hasError={nodeData.status === "error"}
>
{/* Image input handle */}
<Handle
type="target"
position={Position.Left}
id="image"
data-handletype="image"
/>
<>
<BaseNode
id={id}
selected={selected}
hasError={nodeData.status === "error"}
fullBleed
>
{/* Image input handle */}
<Handle
type="target"
position={Position.Left}
id="image"
data-handletype="image"
style={{ zIndex: 10 }}
/>
{/* Reference output handle for visual links to child nodes */}
<Handle
type="source"
position={Position.Right}
id="reference"
data-handletype="reference"
className="!bg-gray-500"
/>
{/* Reference output handle for visual links to child nodes */}
<Handle
type="source"
position={Position.Right}
id="reference"
data-handletype="reference"
className="!bg-gray-500"
style={{ zIndex: 10 }}
/>
<div className="flex-1 flex flex-col min-h-0 gap-2">
{/* Preview/Status area */}
{/* Full-bleed preview area */}
{nodeData.sourceImage ? (
<div className="relative w-full flex-1 min-h-0">
<div className="relative w-full h-full">
<img
src={nodeData.sourceImage}
alt="Source grid"
className="w-full h-full object-contain rounded"
className="w-full h-full object-cover rounded-lg"
/>
{/* Grid overlay visualization */}
<div
@ -85,7 +88,7 @@ export function SplitGridNode({ id, data, selected }: NodeProps<SplitGridNodeTyp
</div>
{/* Loading overlay */}
{nodeData.status === "loading" && (
<div className="absolute inset-0 bg-neutral-900/70 rounded flex items-center justify-center">
<div className="absolute inset-0 bg-neutral-900/70 rounded-lg flex items-center justify-center">
<svg className="w-6 h-6 animate-spin text-white" fill="none" viewBox="0 0 24 24">
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="3" />
<path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z" />
@ -94,7 +97,7 @@ export function SplitGridNode({ id, data, selected }: NodeProps<SplitGridNodeTyp
)}
</div>
) : (
<div className="w-full flex-1 min-h-[112px] border border-dashed border-neutral-600 rounded flex flex-col items-center justify-center">
<div className="w-full h-full min-h-[112px] bg-neutral-900/40 flex flex-col items-center justify-center rounded-lg">
{nodeData.status === "error" ? (
<span className="text-[10px] text-red-400 text-center px-2">
{nodeData.error || "Error"}
@ -117,40 +120,43 @@ export function SplitGridNode({ id, data, selected }: NodeProps<SplitGridNodeTyp
</div>
)}
{/* Config summary */}
<div className="flex items-center justify-between text-[10px] text-neutral-400 shrink-0">
<span>{nodeData.gridRows}x{nodeData.gridCols} grid ({nodeData.targetCount} images)</span>
<button
onClick={handleOpenSettings}
className="text-blue-400 hover:text-blue-300 transition-colors"
>
Settings
</button>
</div>
{/* Controls overlay pinned at bottom */}
<div className="absolute bottom-0 left-0 right-0 z-10 px-3 py-2 bg-neutral-900/80 backdrop-blur-sm rounded-b-lg space-y-1">
{/* Config summary */}
<div className="flex items-center justify-between text-[10px] text-neutral-400">
<span>{nodeData.gridRows}x{nodeData.gridCols} grid ({nodeData.targetCount} images)</span>
<button
onClick={handleOpenSettings}
className="nodrag nopan text-blue-400 hover:text-blue-300 transition-colors"
>
Settings
</button>
</div>
{/* Child node count / status */}
<div className="flex items-center justify-between shrink-0">
{nodeData.isConfigured ? (
<div className="text-[10px] text-neutral-500">
{nodeData.childNodeIds.length} generate sets created
</div>
) : (
<div className="text-[10px] text-amber-400">
Not configured - click Settings
</div>
)}
{/* Child node count / status */}
<div className="flex items-center justify-between">
{nodeData.isConfigured ? (
<div className="text-[10px] text-neutral-500">
{nodeData.childNodeIds.length} generate sets created
</div>
) : (
<div className="text-[10px] text-amber-400">
Not configured - click Settings
</div>
)}
{/* Split button */}
<button
onClick={handleSplit}
disabled={isRunning || !nodeData.isConfigured}
className="px-2 py-0.5 text-[10px] border border-white hover:bg-white hover:text-neutral-900 disabled:border-neutral-600 disabled:text-neutral-600 disabled:cursor-not-allowed text-white rounded transition-colors"
title={!nodeData.isConfigured ? "Configure node first" : "Split grid"}
>
Split
</button>
{/* Split button */}
<button
onClick={handleSplit}
disabled={isRunning || !nodeData.isConfigured}
className="nodrag nopan px-2 py-0.5 text-[10px] border border-white hover:bg-white hover:text-neutral-900 disabled:border-neutral-600 disabled:text-neutral-600 disabled:cursor-not-allowed text-white rounded transition-colors"
title={!nodeData.isConfigured ? "Configure node first" : "Split grid"}
>
Split
</button>
</div>
</div>
</div>
</BaseNode>
{/* Settings Modal */}
{showSettings && (
@ -160,6 +166,6 @@ export function SplitGridNode({ id, data, selected }: NodeProps<SplitGridNodeTyp
onClose={handleCloseSettings}
/>
)}
</BaseNode>
</>
);
}

Loading…
Cancel
Save