From 03c23d51eb460c1f5ed4abb32f2ce956ec5dbc38 Mon Sep 17 00:00:00 2001 From: Bill Leoutsakos Date: Thu, 24 Sep 2026 11:25:26 -0700 Subject: [PATCH 1/2] Add shared Code.Viewer appearances for product surfaces --- .../components/trace-view/trace-view.tsx | 3 +- .../components/log-details/log-details.tsx | 3 +- .../workflow-mcp-servers.tsx | 2 +- .../deploy-modal/components/api/api.tsx | 6 +- .../components/output-panel/output-panel.tsx | 3 +- .../preview-editor/preview-editor.tsx | 6 +- .../emcn/src/components/code/code.test.tsx | 57 ++++++++++++++++++- packages/emcn/src/components/code/code.tsx | 25 +++++++- packages/emcn/src/index.ts | 1 + .../src/lib/code-hover-card.tsx | 3 +- 10 files changed, 96 insertions(+), 13 deletions(-) diff --git a/apps/sim/app/workspace/[workspaceId]/logs/components/log-details/components/trace-view/trace-view.tsx b/apps/sim/app/workspace/[workspaceId]/logs/components/log-details/components/trace-view/trace-view.tsx index b1e2313af8b..b9ae284b385 100644 --- a/apps/sim/app/workspace/[workspaceId]/logs/components/log-details/components/trace-view/trace-view.tsx +++ b/apps/sim/app/workspace/[workspaceId]/logs/components/log-details/components/trace-view/trace-view.tsx @@ -495,7 +495,8 @@ function DetailCodeSection({ {activeConfigTab === 'cursor' && ( @@ -533,7 +533,7 @@ console.log(limits);` code={getStreamCommand()} language={LANGUAGE_SYNTAX[language]} wrapText - className='min-h-0! rounded-sm border border-[var(--border-1)]' + className='min-h-0!' /> @@ -579,7 +579,7 @@ console.log(limits);` code={getAsyncCommand()} language={LANGUAGE_SYNTAX[language]} wrapText - className='min-h-0! rounded-sm border border-[var(--border-1)]' + className='min-h-0!' /> )} diff --git a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/terminal/components/output-panel/output-panel.tsx b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/terminal/components/output-panel/output-panel.tsx index 7eb787be542..daa24590d8e 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/terminal/components/output-panel/output-panel.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/[workflowId]/components/terminal/components/output-panel/output-panel.tsx @@ -66,7 +66,8 @@ const OutputCodeContent = React.memo(function OutputCodeContent({ code={code} showGutter language={language} - className='m-0 min-h-full rounded-none border-0 bg-[var(--bg)] dark:bg-[var(--bg)]' + appearance='flat' + className='m-0 min-h-full' paddingLeft={8} gutterStyle={{ backgroundColor: 'transparent' }} wrapText={wrapText} diff --git a/apps/sim/app/workspace/[workspaceId]/w/components/preview/components/preview-editor/preview-editor.tsx b/apps/sim/app/workspace/[workspaceId]/w/components/preview/components/preview-editor/preview-editor.tsx index 8b027c4c74a..715532c9643 100644 --- a/apps/sim/app/workspace/[workspaceId]/w/components/preview/components/preview-editor/preview-editor.tsx +++ b/apps/sim/app/workspace/[workspaceId]/w/components/preview/components/preview-editor/preview-editor.tsx @@ -1226,7 +1226,8 @@ function PreviewEditorContent({ { ;(globalThis as { IS_REACT_ACT_ENVIRONMENT?: boolean }).IS_REACT_ACT_ENVIRONMENT = true + vi.stubGlobal( + 'ResizeObserver', + class { + observe() {} + unobserve() {} + disconnect() {} + } + ) host = document.createElement('div') document.body.appendChild(host) root = createRoot(host) @@ -20,6 +28,7 @@ beforeEach(() => { afterEach(() => { if (root) act(() => root?.unmount()) host?.remove() + vi.unstubAllGlobals() root = null host = null }) @@ -60,3 +69,49 @@ describe('Code.Viewer workflow references', () => { expect(host?.querySelector('[data-search-match]')?.textContent).toBe('result') }) }) + +describe('Code.Viewer appearances', () => { + for (const virtualized of [false, true]) { + it(`applies the inspection surface to ${virtualized ? 'virtualized' : 'standard'} output`, async () => { + await act(async () => { + root?.render( + + ) + await sleep(1) + }) + + const viewer = host?.firstElementChild + expect(viewer?.classList.contains('rounded-md')).toBe(true) + expect(viewer?.classList.contains('border-0')).toBe(true) + expect(viewer?.classList.contains('bg-[var(--surface-4)]!')).toBe(true) + expect(viewer?.classList.contains('dark:bg-[var(--surface-3)]!')).toBe(true) + expect(viewer?.classList.contains('max-h-[300px]')).toBe(true) + }) + } + + it('keeps the flat viewer separate from the default code container', async () => { + await act(async () => { + root?.render( + <> + + + + ) + await sleep(1) + }) + + const [defaultViewer, flatViewer] = Array.from(host?.children ?? []) + expect(defaultViewer.classList.contains('rounded-sm')).toBe(true) + expect(flatViewer.classList.contains('rounded-none')).toBe(true) + expect(flatViewer.classList.contains('bg-[var(--bg)]')).toBe(true) + expect(flatViewer.classList.contains('dark:bg-[var(--bg)]')).toBe(true) + expect(flatViewer.textContent).toContain('flat') + }) +}) diff --git a/packages/emcn/src/components/code/code.tsx b/packages/emcn/src/components/code/code.tsx index 2e540301caa..2f0a42a5781 100644 --- a/packages/emcn/src/components/code/code.tsx +++ b/packages/emcn/src/components/code/code.tsx @@ -13,6 +13,7 @@ import { import { escapeRegExp } from '@sim/utils/string' import { findWorkflowReferenceTokens } from '@sim/utils/workflow-references' import { useVirtualizer } from '@tanstack/react-virtual' +import { cva, type VariantProps } from 'class-variance-authority' import { ChevronRight } from '../../icons' import { cn } from '../../lib/cn' import './code.css' @@ -856,6 +857,18 @@ function applySearchHighlightingToLine( */ type CodeViewerDensity = 'default' | 'compact' +/** Container appearances shared by the standard and virtualized viewers. */ +export const codeViewerAppearanceVariants = cva('', { + variants: { + appearance: { + default: '', + inspection: 'rounded-md border-0 bg-[var(--surface-4)]! dark:bg-[var(--surface-3)]!', + flat: 'rounded-none border-0 bg-[var(--bg)] dark:bg-[var(--bg)]', + }, + }, + defaultVariants: { appearance: 'default' }, +}) + interface CodeViewerProps { /** Code content to display */ code: string @@ -865,6 +878,8 @@ interface CodeViewerProps { language?: 'javascript' | 'json' | 'python' | 'bash' | 'toml' /** Additional CSS classes for the container */ className?: string + /** Container appearance for code inspected in logs/previews or on flat surfaces. */ + appearance?: NonNullable['appearance']> /** Visual density for read-only code. */ density?: CodeViewerDensity /** Highlight Sim `{{ENV}}` and `` references with the platform accent. */ @@ -948,6 +963,7 @@ type ViewerInnerProps = { language: 'javascript' | 'json' | 'python' | 'bash' | 'toml' /** Additional CSS classes for the container */ className?: string + appearance: NonNullable /** Visual density for read-only code. */ density: CodeViewerDensity highlightWorkflowReferences: boolean @@ -978,6 +994,7 @@ const VirtualizedViewerInner = memo(function VirtualizedViewerInner({ showGutter, language, className, + appearance, density, highlightWorkflowReferences, paddingLeft, @@ -1147,6 +1164,7 @@ const VirtualizedViewerInner = memo(function VirtualizedViewerInner({ wrapText ? 'overflow-x-hidden' : 'overflow-x-auto', 'overflow-y-auto', 'dark:bg-[var(--code-bg)]', + codeViewerAppearanceVariants({ appearance }), className )} style={{ height: containerHeight }} @@ -1196,6 +1214,7 @@ const ViewerInner = memo(function ViewerInner({ showGutter, language, className, + appearance, density, highlightWorkflowReferences, paddingLeft, @@ -1309,7 +1328,7 @@ const ViewerInner = memo(function ViewerInner({ // Grid-based rendering for gutter alignment (works with wrap) if (showGutter) { return ( - +
+
       
     

From dffc482e22dd139205efa800cd7b8bfe1fff8c14 Mon Sep 17 00:00:00 2001
From: Bill Leoutsakos 
Date: Thu, 24 Sep 2026 11:43:01 -0700
Subject: [PATCH 2/2] Test flat virtualized Code.Viewer terminal chrome

---
 .../emcn/src/components/code/code.test.tsx    | 32 ++++++++++++++++++-
 1 file changed, 31 insertions(+), 1 deletion(-)

diff --git a/packages/emcn/src/components/code/code.test.tsx b/packages/emcn/src/components/code/code.test.tsx
index 353fd592820..f9b249ab21c 100644
--- a/packages/emcn/src/components/code/code.test.tsx
+++ b/packages/emcn/src/components/code/code.test.tsx
@@ -1,7 +1,7 @@
 /**
  * @vitest-environment jsdom
  */
-import { act } from 'react'
+import { act, createRef } from 'react'
 import { sleep } from '@sim/utils/helpers'
 import { createRoot, type Root } from 'react-dom/client'
 import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
@@ -114,4 +114,34 @@ describe('Code.Viewer appearances', () => {
     expect(flatViewer.classList.contains('dark:bg-[var(--bg)]')).toBe(true)
     expect(flatViewer.textContent).toContain('flat')
   })
+
+  it('applies flat chrome on the virtualized gutter path used by the terminal', async () => {
+    const contentRef = createRef()
+    await act(async () => {
+      root?.render(
+        
+      )
+      await sleep(1)
+    })
+
+    const viewer = host?.firstElementChild
+    expect(contentRef.current).toBe(viewer)
+    expect(viewer?.classList.contains('rounded-none')).toBe(true)
+    expect(viewer?.classList.contains('border-0')).toBe(true)
+    expect(viewer?.classList.contains('bg-[var(--bg)]')).toBe(true)
+    expect(viewer?.classList.contains('dark:bg-[var(--bg)]')).toBe(true)
+    expect(viewer?.classList.contains('overflow-x-hidden')).toBe(true)
+    expect(viewer?.classList.contains('min-h-full')).toBe(true)
+    expect(viewer?.classList.contains('rounded-sm')).toBe(false)
+  })
 })