Commit a7a6f02
fix: mermaid diagram rendering — sizing, virtualizer overlap, error loops, and text contrast
Five interconnected issues fixed across the mermaid rendering pipeline:
1. **Natural SVG sizing** — Mermaid sets width="100%" + max-width style on SVGs,
which combined with CSS [&_svg]:w-full forced every diagram to stretch to
container width. Small diagrams (ER) ballooned; wide diagrams (timeline) got
cramped. Fix: post-process SVGs to use pixel width from max-width, remove
forced-width CSS classes, let overflow-x-auto handle horizontal scroll.
2. **Virtualizer overlap/collapse** — Messages overlapped after mermaid rendered
or during scrolling. Two root causes:
- Missing getItemKey on virtualizer — sizes were cached by positional index,
so when rows shifted (new messages, tool grouping), cached sizes mapped to
wrong items.
- CHAT_CONTENT_RESIZED_EVENT handler called virtualizer.measure() which nukes
the entire itemSizeCache, forcing all items back to bad estimates. The
ResizeObserver on each measureElement ref already handles individual size
changes — measure() was destructively redundant.
3. **Mermaid error spam loop** — Failed diagrams triggered an infinite
unmount/remount cycle: error state changed row height → virtualizer remounted
fresh component → retried render → failed again → loop (dozens of errors/sec).
Fix: added mermaidErrorCache (module-level Map) so failed renders are cached
and never retried on remount.
4. **Container detach crashes** — mermaid.render(id, code, container) passes the
component's container for DOM measurements (getBBox, getBoundingClientRect).
Virtualizer can unmount the component mid-render, detaching the container and
crashing mermaid with null reference errors. Fix: omit the container argument
— mermaid creates its own temp element in document.body.
5. **Text contrast on custom fills** — Mermaid's inline style directives
(e.g. `style DEV fill:#e1f5ff`) set light pastel fills but don't adjust text
color. In dark mode, light theme text on light fills is invisible. Fix:
post-process SVG nodes with custom inline fills, compute luminance, and set
text to #1a1a1a (light bg) or #f5f5f5 (dark bg). Runs before caching.
Also removed the mermaid-specific bubble width override (max-w-[50%]) from
MessageBubble — all assistant messages now use consistent max-w-[85%], with
diagram sizing handled entirely by MermaidDiagram's own container.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>1 parent e243248 commit a7a6f02
3 files changed
Lines changed: 118 additions & 22 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
492 | 492 | | |
493 | 493 | | |
494 | 494 | | |
| 495 | + | |
495 | 496 | | |
496 | 497 | | |
497 | 498 | | |
| |||
582 | 583 | | |
583 | 584 | | |
584 | 585 | | |
| 586 | + | |
| 587 | + | |
| 588 | + | |
| 589 | + | |
585 | 590 | | |
586 | 591 | | |
587 | | - | |
588 | 592 | | |
589 | | - | |
| 593 | + | |
| 594 | + | |
| 595 | + | |
590 | 596 | | |
591 | 597 | | |
592 | 598 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
6 | 6 | | |
7 | 7 | | |
8 | 8 | | |
9 | | - | |
| 9 | + | |
10 | 10 | | |
11 | 11 | | |
| 12 | + | |
| 13 | + | |
12 | 14 | | |
13 | 15 | | |
14 | 16 | | |
| |||
210 | 212 | | |
211 | 213 | | |
212 | 214 | | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
| 229 | + | |
| 230 | + | |
| 231 | + | |
| 232 | + | |
| 233 | + | |
| 234 | + | |
| 235 | + | |
| 236 | + | |
| 237 | + | |
| 238 | + | |
| 239 | + | |
| 240 | + | |
| 241 | + | |
| 242 | + | |
| 243 | + | |
| 244 | + | |
| 245 | + | |
| 246 | + | |
| 247 | + | |
| 248 | + | |
| 249 | + | |
| 250 | + | |
| 251 | + | |
| 252 | + | |
| 253 | + | |
| 254 | + | |
| 255 | + | |
| 256 | + | |
| 257 | + | |
| 258 | + | |
| 259 | + | |
| 260 | + | |
| 261 | + | |
| 262 | + | |
| 263 | + | |
| 264 | + | |
| 265 | + | |
| 266 | + | |
| 267 | + | |
| 268 | + | |
| 269 | + | |
| 270 | + | |
| 271 | + | |
213 | 272 | | |
214 | 273 | | |
215 | 274 | | |
| |||
263 | 322 | | |
264 | 323 | | |
265 | 324 | | |
| 325 | + | |
| 326 | + | |
| 327 | + | |
266 | 328 | | |
267 | 329 | | |
268 | 330 | | |
269 | 331 | | |
| 332 | + | |
| 333 | + | |
| 334 | + | |
| 335 | + | |
| 336 | + | |
| 337 | + | |
| 338 | + | |
| 339 | + | |
| 340 | + | |
| 341 | + | |
270 | 342 | | |
271 | 343 | | |
272 | 344 | | |
| |||
277 | 349 | | |
278 | 350 | | |
279 | 351 | | |
280 | | - | |
| 352 | + | |
| 353 | + | |
| 354 | + | |
| 355 | + | |
| 356 | + | |
| 357 | + | |
281 | 358 | | |
282 | 359 | | |
283 | 360 | | |
284 | | - | |
285 | | - | |
286 | 361 | | |
| 362 | + | |
| 363 | + | |
| 364 | + | |
| 365 | + | |
| 366 | + | |
| 367 | + | |
| 368 | + | |
| 369 | + | |
| 370 | + | |
| 371 | + | |
| 372 | + | |
| 373 | + | |
| 374 | + | |
| 375 | + | |
| 376 | + | |
| 377 | + | |
| 378 | + | |
| 379 | + | |
| 380 | + | |
| 381 | + | |
| 382 | + | |
| 383 | + | |
| 384 | + | |
| 385 | + | |
| 386 | + | |
| 387 | + | |
287 | 388 | | |
288 | 389 | | |
289 | 390 | | |
290 | 391 | | |
291 | | - | |
| 392 | + | |
| 393 | + | |
| 394 | + | |
292 | 395 | | |
293 | 396 | | |
294 | 397 | | |
| |||
301 | 404 | | |
302 | 405 | | |
303 | 406 | | |
304 | | - | |
305 | | - | |
306 | | - | |
307 | | - | |
308 | | - | |
309 | | - | |
310 | | - | |
311 | | - | |
312 | | - | |
313 | | - | |
314 | | - | |
315 | 407 | | |
316 | 408 | | |
317 | 409 | | |
| |||
339 | 431 | | |
340 | 432 | | |
341 | 433 | | |
342 | | - | |
| 434 | + | |
343 | 435 | | |
344 | 436 | | |
345 | 437 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
325 | 325 | | |
326 | 326 | | |
327 | 327 | | |
328 | | - | |
329 | | - | |
330 | 328 | | |
331 | 329 | | |
332 | 330 | | |
| |||
336 | 334 | | |
337 | 335 | | |
338 | 336 | | |
339 | | - | |
| 337 | + | |
340 | 338 | | |
341 | 339 | | |
342 | 340 | | |
| |||
0 commit comments