diff --git a/app/(landing)/hero-workflow.tsx b/app/(landing)/hero-workflow.tsx index fa0cfcd198..d05361dbfe 100644 --- a/app/(landing)/hero-workflow.tsx +++ b/app/(landing)/hero-workflow.tsx @@ -1,6 +1,6 @@ 'use client' -import { useCallback, useState } from 'react' +import { useCallback, useEffect, useMemo, useState } from 'react' import ReactFlow, { Background, ConnectionLineType, @@ -14,6 +14,7 @@ import ReactFlow, { } from 'reactflow' import 'reactflow/dist/style.css' import { HeroBlock } from './hero-block' +import { useWindowSize } from './use-window-size' const nodeTypes: NodeTypes = { heroBlock: HeroBlock, @@ -67,8 +68,8 @@ const initialNodes: Node[] = [ }, ] -// Initial edges configuration -const initialEdges: Edge[] = [ +// Consolidated edges configuration +const baseEdges: Edge[] = [ { id: 'api-router', source: 'api', @@ -93,6 +94,10 @@ const initialEdges: Edge[] = [ style: { stroke: '#94a3b8', strokeWidth: 2, strokeDasharray: '5,5' }, className: 'animated-edge', }, +] + +const initialEdges: Edge[] = [ + ...baseEdges, { id: 'router-agent3', source: 'router', @@ -103,9 +108,83 @@ const initialEdges: Edge[] = [ }, ] +// Create mobile node positions +const getMobileNodes = (): Node[] => [ + { + id: 'api', + type: 'heroBlock', + position: { x: -25, y: -150 }, + data: { + type: 'api', + name: 'API Block', + color: '#2F55FF', + }, + dragHandle: '.workflow-drag-handle', + }, + { + id: 'router', + type: 'heroBlock', + position: { x: 0, y: -30 }, + data: { + type: 'router', + name: 'Router', + color: '#28C43F', + }, + dragHandle: '.workflow-drag-handle', + }, + { + id: 'agent1', + type: 'heroBlock', + position: { x: 275, y: -100 }, + data: { + type: 'agent', + name: 'Agent 1', + color: '#7F2FFF', + }, + dragHandle: '.workflow-drag-handle', + }, + { + id: 'agent2', + type: 'heroBlock', + position: { x: 275, y: 0 }, + data: { + type: 'agent', + name: 'Agent 2', + color: '#7F2FFF', + }, + dragHandle: '.workflow-drag-handle', + }, +] + export function HeroWorkflow() { - const [nodes, setNodes, onNodesChange] = useNodesState(initialNodes) - const [edges, setEdges, onEdgesChange] = useEdgesState(initialEdges) + const { width } = useWindowSize() + const isMobile = width ? width <= 768 : false + + const [nodes, setNodes, onNodesChange] = useNodesState(isMobile ? getMobileNodes() : initialNodes) + const [edges, setEdges, onEdgesChange] = useEdgesState(isMobile ? baseEdges : initialEdges) + + // Handle viewport changes with instant update + useEffect(() => { + const targetNodes = isMobile ? getMobileNodes() : initialNodes + const targetEdges = isMobile ? baseEdges : initialEdges + + setNodes((nds) => + nds.map((node) => { + const targetNode = targetNodes.find((n) => n.id === node.id) + if (targetNode) { + return { + ...node, + position: { + x: targetNode.position.x, + y: targetNode.position.y, + }, + } + } + return node + }) + ) + setEdges(targetEdges) + }, [isMobile, setNodes, setEdges]) return (
@@ -151,14 +230,17 @@ export function HeroWorkflow() { selectionOnDrag={false} preventScrolling={true} autoPanOnNodeDrag={false} - nodeExtent={[ - [-190, -130], - [644, 60], - ]} - translateExtent={[ - [-200, -300], - [800, 300], - ]} + nodeExtent={ + isMobile + ? [ + [-50, -200], + [500, 100], + ] + : [ + [-190, -130], + [644, 60], + ] + } />
) diff --git a/app/(landing)/use-window-size.ts b/app/(landing)/use-window-size.ts new file mode 100644 index 0000000000..67e721d4e0 --- /dev/null +++ b/app/(landing)/use-window-size.ts @@ -0,0 +1,34 @@ +import { useEffect, useState } from 'react' + +interface WindowSize { + width: number | undefined + height: number | undefined +} + +export function useWindowSize(): WindowSize { + const [windowSize, setWindowSize] = useState({ + width: undefined, + height: undefined, + }) + + useEffect(() => { + // Handler to call on window resize + function handleResize() { + setWindowSize({ + width: window.innerWidth, + height: window.innerHeight, + }) + } + + // Add event listener + window.addEventListener('resize', handleResize) + + // Call handler right away so state gets updated with initial window size + handleResize() + + // Remove event listener on cleanup + return () => window.removeEventListener('resize', handleResize) + }, []) + + return windowSize +}