@@ -3,6 +3,7 @@ import type {
33 Edge as ReactFlowEdge ,
44 Node as ReactFlowNode ,
55} from "@xyflow/react" ;
6+ import ChevronDownIcon from "lucide-react/icons/chevron-down" ;
67import Eye from "lucide-react/icons/eye" ;
78import Sparkles from "lucide-react/icons/sparkles" ;
89import Users from "lucide-react/icons/users" ;
@@ -14,7 +15,11 @@ import { Textarea } from "@/components/ui/textarea";
1415
1516import { WorkflowEdgeInspector } from "./workflow-edge-inspector" ;
1617import { WorkflowNodeInspector } from "./workflow-node-inspector" ;
17- import type { WorkflowEdgeType , WorkflowNodeType } from "./workflow-types" ;
18+ import type {
19+ WorkflowEdgeType ,
20+ WorkflowExecutionStatus ,
21+ WorkflowNodeType ,
22+ } from "./workflow-types" ;
1823
1924export interface WorkflowSidebarProps {
2025 nodes : ReactFlowNode < WorkflowNodeType > [ ] ;
@@ -27,6 +32,8 @@ export interface WorkflowSidebarProps {
2732 workflowName ?: string ;
2833 workflowDescription ?: string ;
2934 onWorkflowUpdate ?: ( name : string , description ?: string ) => void ;
35+ workflowStatus ?: WorkflowExecutionStatus ;
36+ workflowErrorMessage ?: string ;
3037}
3138
3239export function WorkflowSidebar ( {
@@ -40,6 +47,8 @@ export function WorkflowSidebar({
4047 workflowName = "" ,
4148 workflowDescription = "" ,
4249 onWorkflowUpdate,
50+ workflowStatus,
51+ workflowErrorMessage,
4352} : WorkflowSidebarProps ) {
4453 // Determine what to show based on selection
4554 const totalSelected = selectedNodes . length + selectedEdges . length ;
@@ -53,6 +62,10 @@ export function WorkflowSidebar({
5362 const [ localDescription , setLocalDescription ] = useState ( workflowDescription ) ;
5463 const updateTimeoutRef = useRef < NodeJS . Timeout | null > ( null ) ;
5564
65+ // Collapsible section state
66+ const [ propertiesExpanded , setPropertiesExpanded ] = useState ( true ) ;
67+ const [ errorExpanded , setErrorExpanded ] = useState ( true ) ;
68+
5669 // Update local state when props change
5770 useEffect ( ( ) => {
5871 setLocalName ( workflowName ) ;
@@ -137,42 +150,84 @@ export function WorkflowSidebar({
137150 ) : (
138151 < div className = "h-full flex flex-col" >
139152 < div className = "border-b border-border" >
140- < div className = "px-4 py-3" >
141- < h2 className = "text-base font-semibold text-foreground mb-1" >
153+ < button
154+ onClick = { ( ) => setPropertiesExpanded ( ! propertiesExpanded ) }
155+ className = "group w-full px-4 py-3 flex items-center justify-between"
156+ >
157+ < h2 className = "text-base font-semibold text-foreground" >
142158 Workflow Properties
143159 </ h2 >
144- < p className = "text-sm text-muted-foreground" >
145- Configure the name and description for this workflow.
146- </ p >
147- </ div >
148- < div className = "px-4 pb-4 space-y-3" >
149- < div >
150- < Label htmlFor = "workflow-name" > Workflow Name</ Label >
151- < Input
152- id = "workflow-name"
153- value = { localName }
154- onChange = { handleNameChange }
155- placeholder = "Enter workflow name"
156- className = "mt-2"
157- disabled = { disabled }
158- />
159- </ div >
160- < div >
161- < Label htmlFor = "workflow-description" >
162- Description (Optional)
163- </ Label >
164- < Textarea
165- id = "workflow-description"
166- value = { localDescription }
167- onChange = { handleDescriptionChange }
168- placeholder = "Describe what you are building"
169- className = "mt-2"
170- maxLength = { 256 }
171- rows = { 3 }
172- disabled = { disabled }
173- />
160+ < ChevronDownIcon
161+ className = { `h-4 w-4 ${
162+ propertiesExpanded ? "rotate-0" : "-rotate-90"
163+ } text-neutral-400 group-hover:text-neutral-700 dark:text-neutral-500 dark:group-hover:text-neutral-300`}
164+ />
165+ </ button >
166+ { propertiesExpanded && (
167+ < >
168+ < div className = "px-4 pb-2" >
169+ < p className = "text-sm text-muted-foreground" >
170+ Configure the name and description for this workflow.
171+ </ p >
172+ </ div >
173+ < div className = "px-4 pb-4 space-y-3" >
174+ < div >
175+ < Label htmlFor = "workflow-name" > Workflow Name</ Label >
176+ < Input
177+ id = "workflow-name"
178+ value = { localName }
179+ onChange = { handleNameChange }
180+ placeholder = "Enter workflow name"
181+ className = "mt-2"
182+ disabled = { disabled }
183+ />
184+ </ div >
185+ < div >
186+ < Label htmlFor = "workflow-description" >
187+ Description (Optional)
188+ </ Label >
189+ < Textarea
190+ id = "workflow-description"
191+ value = { localDescription }
192+ onChange = { handleDescriptionChange }
193+ placeholder = "Describe what you are building"
194+ className = "mt-2"
195+ maxLength = { 256 }
196+ rows = { 3 }
197+ disabled = { disabled }
198+ />
199+ </ div >
200+ </ div >
201+ </ >
202+ ) }
203+ </ div >
204+
205+ { /* Workflow Error Section */ }
206+ < div className = "border-b border-border" >
207+ < button
208+ onClick = { ( ) => setErrorExpanded ( ! errorExpanded ) }
209+ className = "group w-full px-4 py-3 flex items-center justify-between"
210+ >
211+ < h2 className = "text-base font-semibold text-foreground" >
212+ Error
213+ </ h2 >
214+ < ChevronDownIcon
215+ className = { `h-4 w-4 ${
216+ errorExpanded ? "rotate-0" : "-rotate-90"
217+ } text-neutral-400 group-hover:text-neutral-700 dark:text-neutral-500 dark:group-hover:text-neutral-300`}
218+ />
219+ </ button >
220+ { errorExpanded && (
221+ < div className = "px-4 pb-4" >
222+ { workflowStatus === "error" && workflowErrorMessage ? (
223+ < p className = "text-sm text-red-600 dark:text-red-400 break-words" >
224+ { workflowErrorMessage }
225+ </ p >
226+ ) : (
227+ < p className = "text-sm text-muted-foreground" > No errors</ p >
228+ ) }
174229 </ div >
175- </ div >
230+ ) }
176231 </ div >
177232
178233 < div className = "flex-1 flex flex-col items-center justify-center text-center px-4" >
0 commit comments