77 ChevronDown ,
88 cn ,
99 disclosureChevronClass ,
10- handleKeyboardActivation ,
1110 Popover ,
1211 PopoverContent ,
1312 PopoverItem ,
@@ -27,6 +26,7 @@ import {
2726 LogRowContextMenu ,
2827 OutputPanel ,
2928 StatusDisplay ,
29+ TerminalRowButton ,
3030 ToggleButton ,
3131} from '@/app/workspace/[workspaceId]/w/[workflowId]/components/terminal/components'
3232import {
@@ -110,33 +110,25 @@ const BlockRow = memo(function BlockRow({
110110 const isCanceled = Boolean ( entry . isCanceled )
111111
112112 return (
113- < div
113+ < TerminalRowButton
114114 data-entry-id = { entry . id }
115- role = 'button'
116- tabIndex = { 0 }
117- className = { isSelected ? ROW_STYLES . rowSelected : ROW_STYLES . row }
118- onClick = { ( e ) => {
119- e . stopPropagation ( )
120- onSelect ( entry )
121- } }
122- onKeyDown = { ( event ) =>
123- handleKeyboardActivation ( event , ( ) => onSelect ( entry ) , { stopPropagation : true } )
124- }
115+ selected = { isSelected }
116+ onClick = { ( ) => onSelect ( entry ) }
125117 >
126- < div className = { ROW_STYLES . content } >
118+ < span className = { ROW_STYLES . content } >
127119 < EntryBlockTile blockType = { entry . blockType } />
128120 < span className = { hasError ? ROW_STYLES . labelError : ROW_STYLES . label } >
129121 { entry . blockName }
130122 </ span >
131- </ div >
123+ </ span >
132124 < span className = { cn ( ROW_STYLES . status , ! isRunning && ROW_STYLES . statusIdle ) } >
133125 < StatusDisplay
134126 isRunning = { isRunning }
135127 isCanceled = { isCanceled }
136128 formattedDuration = { formatDuration ( entry . durationMs , { precision : 2 } ) ?? '-' }
137129 />
138130 </ span >
139- </ div >
131+ </ TerminalRowButton >
140132 )
141133} )
142134
@@ -175,32 +167,23 @@ const IterationNodeRow = memo(function IterationNodeRow({
175167 return (
176168 < div className = 'flex min-w-0 flex-col' >
177169 { /* Iteration Header */ }
178- < div
179- role = 'button'
180- tabIndex = { 0 }
181- className = { ROW_STYLES . row }
182- onClick = { ( e ) => {
183- e . stopPropagation ( )
184- onToggle ( )
185- } }
186- onKeyDown = { ( event ) => handleKeyboardActivation ( event , onToggle , { stopPropagation : true } ) }
187- >
188- < div className = { ROW_STYLES . content } >
170+ < TerminalRowButton aria-expanded = { hasChildren ? isExpanded : undefined } onClick = { onToggle } >
171+ < span className = { ROW_STYLES . content } >
189172 < span className = { hasError ? ROW_STYLES . labelError : ROW_STYLES . label } >
190173 { iterationLabel }
191174 </ span >
192175 { hasChildren && (
193176 < ChevronDown className = { cn ( disclosureChevronClass , ! isExpanded && '-rotate-90' ) } />
194177 ) }
195- </ div >
178+ </ span >
196179 < span className = { cn ( ROW_STYLES . status , ! hasRunningChild && ROW_STYLES . statusIdle ) } >
197180 < StatusDisplay
198181 isRunning = { hasRunningChild }
199182 isCanceled = { hasCanceledChild }
200183 formattedDuration = { formatDuration ( entry . durationMs , { precision : 2 } ) ?? '-' }
201184 />
202185 </ span >
203- </ div >
186+ </ TerminalRowButton >
204187
205188 { /* Nested Blocks */ }
206189 { renderChildren && isExpanded && hasChildren && (
@@ -258,33 +241,25 @@ const SubflowNodeRow = memo(function SubflowNodeRow({
258241 return (
259242 < div className = 'flex min-w-0 flex-col' >
260243 { /* Subflow Header */ }
261- < div
262- role = 'button'
263- tabIndex = { 0 }
264- className = { ROW_STYLES . row }
265- onClick = { ( e ) => {
266- e . stopPropagation ( )
267- onToggleNode ( nodeId )
268- } }
269- onKeyDown = { ( event ) =>
270- handleKeyboardActivation ( event , ( ) => onToggleNode ( nodeId ) , { stopPropagation : true } )
271- }
244+ < TerminalRowButton
245+ aria-expanded = { hasChildren ? isExpanded : undefined }
246+ onClick = { ( ) => onToggleNode ( nodeId ) }
272247 >
273- < div className = { ROW_STYLES . content } >
248+ < span className = { ROW_STYLES . content } >
274249 < EntryBlockTile blockType = { entry . blockType } />
275250 < span className = { hasError ? ROW_STYLES . labelError : ROW_STYLES . label } > { displayName } </ span >
276251 { hasChildren && (
277252 < ChevronDown className = { cn ( disclosureChevronClass , ! isExpanded && '-rotate-90' ) } />
278253 ) }
279- </ div >
254+ </ span >
280255 < span className = { cn ( ROW_STYLES . status , ! hasRunningDescendant && ROW_STYLES . statusIdle ) } >
281256 < StatusDisplay
282257 isRunning = { hasRunningDescendant }
283258 isCanceled = { hasCanceledDescendant }
284259 formattedDuration = { formatDuration ( entry . durationMs , { precision : 2 } ) ?? '-' }
285260 />
286261 </ span >
287- </ div >
262+ </ TerminalRowButton >
288263
289264 { /* Nested Iterations */ }
290265 { renderChildren && isExpanded && hasChildren && (
@@ -347,43 +322,31 @@ const WorkflowNodeRow = memo(function WorkflowNodeRow({
347322 return (
348323 < div className = 'flex min-w-0 flex-col' >
349324 { /* Workflow Block Header */ }
350- < div
351- role = 'button'
352- tabIndex = { 0 }
353- className = { isSelected ? ROW_STYLES . rowSelected : ROW_STYLES . row }
354- onClick = { ( e ) => {
355- e . stopPropagation ( )
325+ < TerminalRowButton
326+ aria-expanded = { hasChildren ? isExpanded : undefined }
327+ selected = { isSelected }
328+ onClick = { ( ) => {
356329 if ( ! isSelected ) onSelectEntry ( entry )
357330 if ( hasChildren ) onToggleNode ( nodeId )
358331 } }
359- onKeyDown = { ( event ) =>
360- handleKeyboardActivation (
361- event ,
362- ( ) => {
363- if ( ! isSelected ) onSelectEntry ( entry )
364- if ( hasChildren ) onToggleNode ( nodeId )
365- } ,
366- { stopPropagation : true }
367- )
368- }
369332 >
370- < div className = { ROW_STYLES . content } >
333+ < span className = { ROW_STYLES . content } >
371334 < EntryBlockTile blockType = { entry . blockType } />
372335 < span className = { hasError ? ROW_STYLES . labelError : ROW_STYLES . label } >
373336 { entry . blockName }
374337 </ span >
375338 { hasChildren && (
376339 < ChevronDown className = { cn ( disclosureChevronClass , ! isExpanded && '-rotate-90' ) } />
377340 ) }
378- </ div >
341+ </ span >
379342 < span className = { cn ( ROW_STYLES . status , ! hasRunningDescendant && ROW_STYLES . statusIdle ) } >
380343 < StatusDisplay
381344 isRunning = { hasRunningDescendant }
382345 isCanceled = { hasCanceledDescendant }
383346 formattedDuration = { formatDuration ( entry . durationMs , { precision : 2 } ) ?? '-' }
384347 />
385348 </ span >
386- </ div >
349+ </ TerminalRowButton >
387350
388351 { /* Nested Child Blocks — rendered through EntryNodeRow for full loop/parallel support */ }
389352 { renderChildren && isExpanded && hasChildren && (
0 commit comments