Skip to content

feat(web): redesign SyntheticMessageBlock — markdown, subtle card, collapsible#1559

Merged
lsm merged 2 commits intodevfrom
space/style-synthetic-messages-in-space-thread-render-markdown
Apr 21, 2026
Merged

feat(web): redesign SyntheticMessageBlock — markdown, subtle card, collapsible#1559
lsm merged 2 commits intodevfrom
space/style-synthetic-messages-in-space-thread-render-markdown

Conversation

@lsm
Copy link
Copy Markdown
Owner

@lsm lsm commented Apr 21, 2026

Redesigns the synthetic message card in Space task threads.

Changes:

  • Subtle dark card (bg-gray-900 border border-gray-700) replaces purple background. Purple is accent-only: small dot + "Synthetic" label in header.
  • Text blocks render through MarkdownRenderer (headings, bold, lists, inline/fenced code) instead of raw monospace text.
  • Collapsible by default when content exceeds ~8 lines — "Show more / Show less" toggle mirrors ThinkingBlock. Line count shown in collapsed header.
  • Copy button stays in the action row only (no duplicate inside the card).
  • Right-aligned placement preserved.

Tests updated:

  • Mock MarkdownRenderer for unit isolation; new collapse/expand tests using scrollHeight mock.
  • overflow-protection.test.tsx: updated assertions to check .prose class (provided by MarkdownRenderer) instead of removed Tailwind utility classes.

Pre-existing failure: SpaceIsland flaky test fails intermittently in full-suite runs due to test ordering / Suspense timing — confirmed pre-existing, unrelated to this PR.

@lsm
Copy link
Copy Markdown
Owner Author

lsm commented Apr 21, 2026

Review: feat(web): redesign SyntheticMessageBlock — markdown, subtle card, collapsible

Verdict: Approve with minor nit

This is a clean, well-executed redesign. The implementation follows the design spec precisely and reuses the existing MarkdownRenderer and ThinkingBlock patterns effectively. Test coverage is thorough (81 tests, all passing). No regressions.

What's done well

  • Markdown rendering: Correctly uses the existing MarkdownRenderer for text blocks, keeping a single rendering path.
  • Collapse/Expand: Solid dual-measurement approach — useLayoutEffect for initial sync measurement + ResizeObserver to handle async MarkdownRenderer content loading. The child ref (contentRef) is inside the maxHeight parent but since it has no overflow clipping itself, scrollHeight correctly returns the true content height.
  • Styling: Matches the design spec (gray-900 bg, gray-700 border, purple dot + label only). Right-aligned placement preserved.
  • Test coverage: Comprehensive — new Collapse/Expand Behavior and Markdown Rendering describe blocks. Good use of scrollHeight mocking for the collapse tests.
  • No regressions: All 7135 web tests pass (the 1 failure in SpaceIsland.test.tsx is pre-existing and unrelated).

Minor nit

  • Misleading comment (line 183): The comment {/* Inner ref measured for height — outside the maxHeight container */} says "outside the maxHeight container" but contentRef is actually inside the wrapper that applies maxHeight. The measurement still works correctly because the child div has no overflow clipping — but the comment should be fixed to avoid confusion for future readers.

Not a blocker

  • The overflow-protection.test.tsx file doesn't mock MarkdownRenderer but its assertions on .prose work because the real MarkdownRenderer always renders a <div class="prose ..."> container (the class is in JSX, not set by the async innerHTML). This is fine, but consider adding the mock there too for explicitness.

@lsm
Copy link
Copy Markdown
Owner Author

lsm commented Apr 21, 2026

Thanks for the thorough review!

Nit fixed (commit 0ba6a0ca6):

  • Updated the comment on the contentRef div to accurately describe why scrollHeight works from inside the maxHeight wrapper: "contentRef is inside the maxHeight wrapper but has no overflow clipping of its own, so scrollHeight returns the true unclipped content height."
  • Also added explicit MarkdownRenderer mock to overflow-protection.test.tsx for consistency with SyntheticMessageBlock.test.tsx.

lsm added 2 commits April 20, 2026 23:11
…e card, collapsible

Replace the purple-background synthetic message card with a cleaner, more readable design:

- **Subtle dark card**: `bg-gray-900 border border-gray-700` instead of purple background.
  Purple is now accent-only (small dot + header label).
- **Markdown rendering**: text blocks now render through `MarkdownRenderer` (headings,
  bold, lists, inline code, fenced code blocks) instead of raw monospace text.
- **Collapsible content**: defaults to ~8 lines collapsed with "Show more / Show less"
  toggle (mirrors ThinkingBlock). Uses `useLayoutEffect` for initial measurement and
  `ResizeObserver` to re-check after MarkdownRenderer's async HTML update. Header shows
  line count when collapsed.
- **No copy inside card**: copy button stays in the action row below (where it already
  was); not duplicated inside the card.

Update tests: mock `MarkdownRenderer` for unit isolation, add collapse/expand tests
(using `scrollHeight` mock), update overflow-protection tests to check `.prose` class
instead of removed `whitespace-pre-wrap`/`break-words` utility classes.
…ownRenderer in overflow tests

- Fix comment on contentRef div: was incorrectly described as "outside the
  maxHeight container" — it is inside, but scrollHeight works because the div
  has no overflow clipping of its own.
- Add explicit MarkdownRenderer mock to overflow-protection.test.tsx for
  clarity, matching the approach used in SyntheticMessageBlock.test.tsx.
@lsm lsm force-pushed the space/style-synthetic-messages-in-space-thread-render-markdown branch from 0ba6a0c to 3f400b7 Compare April 21, 2026 03:11
@lsm lsm enabled auto-merge (squash) April 21, 2026 03:14
@lsm lsm merged commit dafbeca into dev Apr 21, 2026
44 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant