Skip to content

Commit d98b134

Browse files
committed
fix(chat): preview inline images with shared lightbox
1 parent bb5b414 commit d98b134

2 files changed

Lines changed: 44 additions & 7 deletions

File tree

apps/sim/app/workspace/[workspaceId]/home/components/message-content/components/chat-content/chat-content-images.test.tsx

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,28 @@ describe('standard Markdown private chat images', () => {
116116
'https://example.com/chart.png'
117117
)
118118
})
119+
it('opens the same authenticated image in the shared attachment preview with zoom and dismissal', async () => {
120+
await render('![Button diagram](/tmp/manual.png)')
121+
const preview = container.querySelector<HTMLButtonElement>(
122+
'button[aria-label="Preview Button diagram"]'
123+
)
124+
const src = container.querySelector('img')?.getAttribute('src')
125+
expect(preview).not.toBeNull()
126+
expect(document.querySelector('[role="dialog"]')).toBeNull()
127+
await act(async () => preview?.click())
128+
const enlarged = document.querySelector<HTMLImageElement>('[role="dialog"] img')
129+
expect(enlarged?.getAttribute('src')).toBe(src)
130+
expect(enlarged?.getAttribute('alt')).toBe('Button diagram')
131+
await act(async () =>
132+
document.querySelector<HTMLButtonElement>('button[aria-label="Zoom in"]')?.click()
133+
)
134+
expect(enlarged?.style.zoom).toBe('1.25')
135+
await act(async () =>
136+
document.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape', bubbles: true }))
137+
)
138+
expect(document.querySelector('[role="dialog"]')).toBeNull()
139+
expect(container.querySelector('img')?.getAttribute('src')).toBe(src)
140+
})
119141
it('never displays image syntax inside fenced or inline code', async () => {
120142
await render('`![Code](/tmp/x.png)`\n\n```markdown\n![Example](files/x.png)\n```')
121143
expect(container.querySelector('img')).toBeNull()

apps/sim/app/workspace/[workspaceId]/home/components/message-content/components/chat-content/chat-content.tsx

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,14 @@ import 'prismjs/components/prism-bash'
2121
import 'prismjs/components/prism-css'
2222
import 'prismjs/components/prism-markup'
2323
import '@sim/emcn/components/code/code.css'
24-
import { Checkbox, CopyCodeButton, cn, languages, highlight as prismHighlight } from '@sim/emcn'
24+
import {
25+
Checkbox,
26+
CopyCodeButton,
27+
cn,
28+
Lightbox,
29+
languages,
30+
highlight as prismHighlight,
31+
} from '@sim/emcn'
2532
import { extractTextContent } from '@/lib/core/utils/react-node-text'
2633
import {
2734
inlineChatImageUrl,
@@ -448,12 +455,20 @@ const MARKDOWN_COMPONENTS = {
448455
img({ src, alt }: ComponentPropsWithoutRef<'img'>) {
449456
if (typeof src !== 'string' || !src) return null
450457
return (
451-
<img
452-
src={src}
453-
alt={alt ?? ''}
454-
loading='lazy'
455-
className='my-4 h-auto max-w-full rounded-lg border border-[var(--border)]'
456-
/>
458+
<Lightbox src={src} alt={alt ?? ''}>
459+
<button
460+
type='button'
461+
aria-label={alt ? `Preview ${alt}` : 'Preview image'}
462+
className='my-4 block max-w-full cursor-zoom-in rounded-lg'
463+
>
464+
<img
465+
src={src}
466+
alt={alt ?? ''}
467+
loading='lazy'
468+
className='m-0 block h-auto max-h-[360px] w-auto max-w-full rounded-lg border border-[var(--border)] object-contain'
469+
/>
470+
</button>
471+
</Lightbox>
457472
)
458473
},
459474
}

0 commit comments

Comments
 (0)