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,79 @@ 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') + }) + + 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) + }) +}) 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 ( - +
+