@@ -38,6 +38,7 @@ import { useCodeViewerFeatures } from '@/hooks/use-code-viewer'
3838const DEFAULT_BLOCK_COLOR = '#6b7280'
3939const TREE_PANE_WIDTH = 300
4040const INDENT_PX = 12
41+ const ROW_BASE_PADDING_LEFT = 12
4142const MIN_BAR_PCT = 0.5
4243
4344interface TraceViewProps {
@@ -344,7 +345,7 @@ const TraceTreeRow = memo(function TraceTreeRow({
344345 >
345346 < div
346347 className = 'flex min-w-0 items-center gap-1.5 pt-1 pr-2'
347- style = { { paddingLeft : 8 + depth * INDENT_PX } }
348+ style = { { paddingLeft : ROW_BASE_PADDING_LEFT + depth * INDENT_PX } }
348349 >
349350 { canExpand ? (
350351 < button
@@ -733,7 +734,6 @@ const TraceDetailPane = memo(function TraceDetailPane({ span }: { span: TraceSpa
733734
734735 return (
735736 < div className = 'flex min-h-0 flex-1 flex-col gap-3 overflow-y-auto px-3.5 pt-3 pb-4' >
736- { /* Header */ }
737737 < div className = 'flex items-start gap-2' >
738738 { ! isIterationType ( span . type ) && (
739739 < div
@@ -777,7 +777,6 @@ const TraceDetailPane = memo(function TraceDetailPane({ span }: { span: TraceSpa
777777 </ div >
778778 </ div >
779779
780- { /* Metadata block */ }
781780 { metaEntries . length > 0 && (
782781 < div className = 'flex flex-col gap-1.5 rounded-md border border-[var(--border)] bg-[var(--surface-2)] px-2.5 py-2 dark:bg-transparent' >
783782 { metaEntries . map ( ( m ) => (
@@ -786,26 +785,34 @@ const TraceDetailPane = memo(function TraceDetailPane({ span }: { span: TraceSpa
786785 </ div >
787786 ) }
788787
789- { /* Content sections */ }
788+ { /* Keys by label: without them, React reused a single DetailCodeSection
789+ across span changes and carried isOpen between sections with different
790+ labels — a collapsed Output on one span appeared as a collapsed Input
791+ on the next. */ }
790792 { span . input !== undefined && span . input !== null && (
791- < DetailCodeSection label = 'Input' data = { span . input } />
793+ < DetailCodeSection key = 'input' label = 'Input' data = { span . input } />
792794 ) }
793795 { span . output !== undefined && span . output !== null && (
794796 < DetailCodeSection
797+ key = { isDirectError ? 'error' : 'output' }
795798 label = { isDirectError ? 'Error' : 'Output' }
796799 data = { span . output }
797800 isError = { isDirectError }
798801 />
799802 ) }
800- { span . thinking && < DetailCodeSection label = 'Thinking' data = { span . thinking } /> }
803+ { span . thinking && < DetailCodeSection key = 'thinking' label = 'Thinking' data = { span . thinking } /> }
801804 { span . modelToolCalls && span . modelToolCalls . length > 0 && (
802- < DetailCodeSection label = 'Tool calls' data = { span . modelToolCalls } />
805+ < DetailCodeSection key = 'tool-calls' label = 'Tool calls' data = { span . modelToolCalls } />
803806 ) }
804807 { span . errorMessage && (
805- < DetailCodeSection label = 'Error message' data = { span . errorMessage } isError />
808+ < DetailCodeSection
809+ key = 'error-message'
810+ label = 'Error message'
811+ data = { span . errorMessage }
812+ isError
813+ />
806814 ) }
807815
808- { /* Raw timing footer */ }
809816 { Number . isFinite ( startedAt ) && Number . isFinite ( endedAt ) && startedAt > 0 && endedAt > 0 && (
810817 < div className = 'flex items-center justify-between font-medium text-[var(--text-tertiary)] text-caption' >
811818 < span > Started { new Date ( startedAt ) . toISOString ( ) } </ span >
@@ -823,7 +830,6 @@ const TraceDetailPane = memo(function TraceDetailPane({ span }: { span: TraceSpa
823830 * follow block-by-block and segment-by-segment what happened and why.
824831 */
825832export const TraceView = memo ( function TraceView ( { traceSpans } : TraceViewProps ) {
826- const containerRef = useRef < HTMLDivElement > ( null )
827833 const [ searchQuery , setSearchQuery ] = useState ( '' )
828834
829835 const { normalizedSpans, allIds, totalDuration, runStartMs, firstRootId, blockCount } =
@@ -898,10 +904,13 @@ export const TraceView = memo(function TraceView({ traceSpans }: TraceViewProps)
898904 const handleCollapseAll = useCallback ( ( ) => setExpandedNodes ( new Set ( ) ) , [ ] )
899905
900906 useEffect ( ( ) => {
901- const container = containerRef . current
902- if ( ! container ) return
903907 const handler = ( e : KeyboardEvent ) => {
904- if ( ! container . contains ( document . activeElement ) ) return
908+ // Ignore while typing in inputs / contentEditable (filter box, etc.).
909+ const target = e . target as HTMLElement | null
910+ if ( target ) {
911+ const tag = target . tagName
912+ if ( tag === 'INPUT' || tag === 'TEXTAREA' || target . isContentEditable ) return
913+ }
905914 if ( ! selectedId ) return
906915 const currentIndex = flatList . findIndex ( ( entry ) => getSpanId ( entry . span ) === selectedId )
907916 if ( currentIndex === - 1 ) return
@@ -950,7 +959,7 @@ export const TraceView = memo(function TraceView({ traceSpans }: TraceViewProps)
950959 }
951960
952961 return (
953- < div ref = { containerRef } className = '-mx-3.5 flex h-full min-h-0 flex-col' >
962+ < div className = '-mx-3.5 flex h-full min-h-0 flex-col' >
954963 { /* Header strip */ }
955964 < div className = 'flex items-center gap-2 border-[var(--border)] border-b px-3.5 pb-2' >
956965 < span
0 commit comments