Skip to content

Commit 9d64913

Browse files
authored
improvement(diff): refine embedded diff presentation (#8862)
* improvement(diff): refine embedded diff presentation * fix(diff): keep comparison headings aligned while scrolling * fix(diff): keep the comparison divider outside scroll fades * fix(diff): pair complete change blocks in document comparisons * fix(diff): preserve heading-level changes in comparisons
1 parent 903c16d commit 9d64913

3 files changed

Lines changed: 508 additions & 258 deletions

File tree

‎apps/sim/app/workspace/[workspaceId]/files/components/file-viewer/rich-markdown-editor/code-block.tsx‎

Lines changed: 27 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,15 @@ import type { ReactNodeViewProps } from '@tiptap/react'
1313
import { NodeViewContent, NodeViewWrapper, ReactNodeViewRenderer } from '@tiptap/react'
1414
import { DASHBOARD_EMBED_LANGUAGE } from '@/lib/dashboards/embed-language'
1515
import { DIFF_EMBED_LANGUAGE } from '@/lib/diff/embed-language'
16+
import {
17+
looksLikeMermaid,
18+
MermaidDiagram,
19+
} from '@/app/workspace/[workspaceId]/files/components/file-viewer/mermaid-diagram'
20+
import { MarkdownCodeBlock } from '@/app/workspace/[workspaceId]/files/components/file-viewer/rich-markdown-editor/code-block-schema'
21+
import { detectLanguage } from '@/app/workspace/[workspaceId]/files/components/file-viewer/rich-markdown-editor/detect-language'
1622
import { MarkdownStreamingContext } from '@/app/workspace/[workspaceId]/files/components/file-viewer/rich-markdown-editor/markdown-streaming-context'
17-
import { looksLikeMermaid, MermaidDiagram } from '../mermaid-diagram'
18-
import { MarkdownCodeBlock } from './code-block-schema'
19-
import { detectLanguage } from './detect-language'
20-
import { useEditorEditable } from './use-editor-editable'
23+
import { ToolbarButton } from '@/app/workspace/[workspaceId]/files/components/file-viewer/rich-markdown-editor/menus/toolbar-button'
24+
import { useEditorEditable } from '@/app/workspace/[workspaceId]/files/components/file-viewer/rich-markdown-editor/use-editor-editable'
2125

2226
/** Kept out of every rich-markdown surface's graph until a document actually holds a dashboard. */
2327
const DashboardEmbed = lazy(() =>
@@ -53,9 +57,6 @@ const LANGUAGE_OPTIONS = [
5357
{ value: 'yaml', label: 'YAML' },
5458
] as const
5559

56-
const CONTROL_CLASS =
57-
'flex size-[24px] items-center justify-center rounded-lg text-[var(--text-icon)] outline-hidden transition-colors hover-hover:bg-[var(--surface-hover)] hover-hover:text-[var(--text-body)] focus-visible:bg-[var(--surface-hover)] [&_svg]:size-[14px]'
58-
5960
/**
6061
* Code block view with hover controls (language picker, line-wrap, copy). When the block holds
6162
* Mermaid — tagged ```mermaid or {@link looksLikeMermaid auto-detected} — it renders as a diagram
@@ -66,7 +67,7 @@ const CONTROL_CLASS =
6667
* dashboard panels the same way.
6768
*/
6869
function CodeBlockView({ node, updateAttributes, editor, getPos }: ReactNodeViewProps) {
69-
const [wrap, setWrap] = useState(false)
70+
const [wrap, setWrap] = useState(() => node.attrs.language === DIFF_EMBED_LANGUAGE)
7071
const [menuOpen, setMenuOpen] = useState(false)
7172
const [editingInline, setEditingInline] = useState(false)
7273
const [peekSource, setPeekSource] = useState(false)
@@ -144,15 +145,17 @@ function CodeBlockView({ node, updateAttributes, editor, getPos }: ReactNodeView
144145
<NodeViewWrapper className='group relative'>
145146
<div
146147
className={cn(
147-
'absolute top-1.5 right-2 z-10 flex items-center gap-0.5 opacity-0 transition-opacity group-focus-within:opacity-100 group-hover:opacity-100',
148+
'absolute top-1.5 right-2 z-10 flex items-center gap-0.5 opacity-0 transition-opacity group-focus-within:opacity-100 group-hover:opacity-100 [@media(any-pointer:coarse)]:opacity-100 [@media(hover:none)]:opacity-100',
149+
isDiff && showRendered && 'top-3 right-3 opacity-100',
150+
isRendered && showSource && 'static mb-1 justify-end opacity-100',
148151
menuOpen && 'opacity-100'
149152
)}
150153
contentEditable={false}
151154
>
152155
{isRendered && (
153-
<button
154-
type='button'
155-
aria-label={
156+
<ToolbarButton
157+
icon={showSource ? Eye : Code}
158+
label={
156159
showSource
157160
? isDashboard
158161
? 'Show dashboard'
@@ -161,12 +164,8 @@ function CodeBlockView({ node, updateAttributes, editor, getPos }: ReactNodeView
161164
: 'Show diagram'
162165
: 'Show source'
163166
}
164-
onMouseDown={(event) => event.preventDefault()}
165167
onClick={toggleSource}
166-
className={CONTROL_CLASS}
167-
>
168-
{showSource ? <Eye /> : <Code />}
169-
</button>
168+
/>
170169
)}
171170
{!isRendered &&
172171
(editable ? (
@@ -204,30 +203,19 @@ function CodeBlockView({ node, updateAttributes, editor, getPos }: ReactNodeView
204203
{label}
205204
</span>
206205
))}
207-
{!isRendered && editable && (
208-
<button
209-
type='button'
210-
aria-label='Toggle line wrap'
211-
aria-pressed={wrap}
212-
onMouseDown={(event) => event.preventDefault()}
206+
{(isDiff || (!isRendered && editable)) && (
207+
<ToolbarButton
208+
icon={Wrap}
209+
label='Toggle line wrap'
210+
isActive={wrap}
213211
onClick={() => setWrap((value) => !value)}
214-
className={cn(
215-
CONTROL_CLASS,
216-
wrap && 'bg-[var(--surface-active)] text-[var(--text-body)]'
217-
)}
218-
>
219-
<Wrap />
220-
</button>
212+
/>
221213
)}
222-
<button
223-
type='button'
224-
aria-label='Copy code'
225-
onMouseDown={(event) => event.preventDefault()}
214+
<ToolbarButton
215+
icon={copied ? Check : Duplicate}
216+
label={copied ? 'Copied' : isDiff ? 'Copy diff' : 'Copy code'}
226217
onClick={() => copy(text)}
227-
className={CONTROL_CLASS}
228-
>
229-
{copied ? <Check /> : <Duplicate />}
230-
</button>
218+
/>
231219
</div>
232220
<pre className={cn('code-editor-theme pr-20', showRendered && 'hidden')} data-wrap={wrap}>
233221
<NodeViewContent<'code'> as='code' />
@@ -252,7 +240,7 @@ function CodeBlockView({ node, updateAttributes, editor, getPos }: ReactNodeView
252240
</Suspense>
253241
) : isDiff ? (
254242
<Suspense fallback={null}>
255-
<DiffEmbed source={text} isStreaming={isStreaming} />
243+
<DiffEmbed source={text} isStreaming={isStreaming} wrapLines={wrap} />
256244
</Suspense>
257245
) : (
258246
<MermaidDiagram definition={text} className='mermaid-diagram-frame' />

0 commit comments

Comments
 (0)