Skip to content

feat: give rendered Markdown a readable visual hierarchy - #660

Merged
pedronauck merged 3 commits into
compozy:mainfrom
richardfogaca:feat/session-reading-preview
Sep 18, 2026
Merged

pedronauck merged 3 commits into
compozy:mainfrom
richardfogaca:feat/session-reading-preview

Conversation

@richardfogaca

@richardfogaca richardfogaca commented Sep 17, 2026 •

Copy link
Copy Markdown
Contributor

What & why

Fixes #653.

Long assistant answers read as one uniform block because the prose type scale had almost no range. Measured on main, against a 15px body:

Element Before After
H1 / H2 / H3 16 / 15 / 13.5px 22 / 18 / 16px
H4 13.5px, weight 510 15px, weight 600
H5 · H6 13.5px, weight 510, muted 13.5px, weight 600, muted
strong weight 510 weight 600
Links fg-strong, underline at 5.5% white accent-strong, solid 1px same-color underline, 3px offset
Paragraph gap 8px (less than the 10.5px line gap) 14px
Table cells 12.5px, 6×8px padding, no header fill 13.5px, 8×12px padding, tinted header, framed
Inline code fixed 12.5px --text-inline-code (0.9em), already in the ladder but unused

H2 was exactly body size and H3–H6 were smaller than the paragraphs they introduce, so size could not signal level. This PR changes values only; the per-element component map and the Markdown safe-mode contract are untouched.

What changes for a reader:

  • Headings ride a new --text-prose-h1..h3 ladder with matching --tracking-prose-*. Flowing text sits 12 / 10 / 6 / 4px under H1–H4, framed blocks keep their own 20px, and stacked headings collapse their gap.
  • Links are recognisable at rest. The underline is solid and shares the text colour, so it clears the 3:1 non-text floor and colour is never the only cue.
  • Tables get one frame (same radius as the compact code block), a tinted header, row rules with no doubled bottom edge, and nowrap headers. Cells use overflow-wrap: normal, so identifiers never break mid-word and wide tables scroll inside their own frame instead of crushing columns.
  • Lists indent 24px with muted markers, tabular ordered numerals, more air between items, and a list sits closer to the paragraph that introduces it.
  • compact surfaces (tool panels, palette previews) keep today's heading sizes, weights, cell padding, and indents on purpose; the ladder is for reading columns. Each prose part picks its density from data-compact on the root rather than the root overriding the parts. compact="relaxed" is new: the reasoning panel uses it to keep small headings with its previous 8px paragraph breaks inside the 240px scroller.
  • Message edges: a message ends flush whether its last block is a paragraph, a list, or a blockquote.

One design decision to review: links use accent-strong, which is a second accent use in a viewport. I recorded it in DESIGN.md §9 as the sanctioned accent in running text rather than leave the "one accent" contract silently contradicted. If you would rather keep prose neutral, the fallback is fg-strong with a muted underline, a one-line change in MarkdownAnchor.

How you verified it

Same representative sample before and after, from the real component (MessageMarkdown → LongAnswer story).

Before (main @ 7b64ab1)

Before

After (this branch)

After

After, 352px column (NarrowColumn story) — the table is 453px wide inside a 350px frame and scrolls there; the Markdown column does not cross the viewport.

After, narrow

Design prototype used to agree the direction

Built from the real tokens before touching the component. In the side-by-side shot the proposed table still breaks message_bodies mid-word; that is fixed in the implementation (td code is nowrap), as the Storybook capture above shows.

Prototype, side by side

Prototype, proposed with accent links

Computed styles read from the rendered stories on this branch: H1 22px/600, H2 18px/600, H3 16px/600, H4 15px/600, H5 13.5px/600, strong 600, link rgb(246, 135, 79) with a solid 1px underline at 3px offset, table frame 1px line-strong with 7px radius, th on surface-glaze, td 13.5px. Gaps: 8px from a lead-in paragraph to its list, 12 / 10 / 6 / 4px under H1–H4, 20px between a heading and a table, code block, or blockquote, 0px trailing after any last block. Compact story: 16 / 15 / 13.5 / 13.5 / 13.5px with main's weights and padding. Reasoning panel: data-compact="true", data-rhythm="relaxed", 8px paragraphs.

Commands:

  • make codegen — regenerated DESIGN.md token tables and font-size-classes.generated.ts (so tailwind-merge treats the new sizes as font sizes, not colours).
  • make gate — passes on the final commit: js-packages-ui and js-web lanes PASS. One earlier run failed on sheet.test.tsx (toHaveFocus), which is unrelated to this diff and intermittent: 2 of 6 isolated runs failed locally under load, and it passed once the machine was quiet.

Tests: prose-ladder-contract.test.ts reads the real tokens.css bytes through a token reader now shared with the focus-ring audit, and takes its tiers from the same PROSE_TYPE / PROSE_TYPE_COMPACT / PROSE_LINK constants the components render with. It fails if H1–H3 stop outranking the prose body (the regression this PR fixes), if the compact tier grows with depth or exceeds the reading tier, if link text drops below 4.5:1, or if the underline drops below 3:1 on any prose surface. stream-markdown.test.tsx covers the three densities, and MessageMarkdown / ThinkingBlock tests cover the compact passthrough on both render paths. New stories: Markdown (Reading, Compact, CompactRelaxed) in packages/ui, and LongAnswer, NarrowColumn, Compact for MessageMarkdown.

Impact

Web surface only: every <Markdown> / <StreamMarkdown> consumer (session messages, thinking blocks, task inline results, description cards, palette detail). No CLI command, HTTP/UDS route, config key, stored data, or public shape changes. No packages/site docs update needed. docs/_memory/change-impact.md has the full entry.

QA: dated impact entries in seven scenarios: ET-web-session-transcript-calm-grammar, RT-055, TA-107, ET-web-agent-detail-tab-parity, ET-palette-domain-views, TA-web-task-detail-redesign, and TA-web-task-result-disclosure. Storybook verification covered StreamMarkdown / MessageMarkdown and the reasoning panel only; the DescriptionCard and task surfaces were not inspected, and no live-runtime walk was done. Each entry says so, and I left every qa_status as recorded rather than claim or reset a result I did not earn. Reset them if that is your convention.

Known and deliberately left alone, all identical on main: compact H3/H4 render at 13.5px under a 15px body on the reasoning panel and palette detail; the table scroll frame is not keyboard-focusable (a region that is focusable only when it overflows, with a localisable label, is its own change); the [&_pre] rules in markdown.tsx never match in plain <Markdown> because Streamdown emits code[data-block]; compact stays boolean | "relaxed" rather than becoming a density prop, since renaming a primitive's API is your call.

Other possible follow-ups: GitHub-style callouts (> [!NOTE]), table copy-as-CSV, collapsing very long messages.


  • make gate passes locally; this PR is delivered only after its required CI checks are green
  • New or changed behavior is covered by tests, or I explained above why not
  • If an agent wrote or co-wrote this, I named it above and verified the result myself

Summary by CodeRabbit

  • New Features

    • Added a consistent typography scale for prose headings.
    • Added compact and relaxed markdown display modes for dense content.
    • Updated markdown rendering with improved heading, paragraph, list, blockquote, table, and code-block spacing.
    • Added refreshed styling for links, inline code, emphasis, and table cells.
    • Applied relaxed compact formatting to reasoning content.
    • Extended compact formatting to streamed and message markdown.
  • Bug Fixes

    • Improved readability and contrast for inline code and markdown content.

Headings spanned 13.5-16px around a 15px body, so H2 matched body size
and H3-H6 rendered smaller than the paragraphs they introduce. Add a
prose heading ladder (22/18/16) with matching tracking, semibold
emphasis, accent-strong underlined links, a block rhythm wider than the
line gap, and framed tables with a tinted header that scroll inside
their own frame. Compact surfaces keep the small heading tier.

A token contract test keeps every heading tier above the prose body and
the link color at AA contrast on each prose surface.

Fixes compozy#653
@vercel

vercel Bot commented Sep 17, 2026

Copy link
Copy Markdown

@richardfogaca is attempting to deploy a commit to the Compozy Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai

coderabbitai Bot commented Sep 17, 2026 •

Copy link
Copy Markdown
Contributor

Review Change StackReview Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Advanced

Run ID: c045022d-a45b-45da-b50a-4da95d4d08d0

📥 Commits

Reviewing files that changed from the base of the PR and between 0219e98 and 75f008e.

⛔ Files ignored due to path filters (5)
  • DESIGN.md is excluded by !**/*.md
  • docs/_memory/change-impact.md is excluded by !**/*.md
  • docs/qa/scenarios/TA-107.md is excluded by !**/*.md
  • docs/qa/scenarios/TA-web-task-detail-redesign.md is excluded by !**/*.md
  • docs/qa/scenarios/TA-web-task-result-disclosure.md is excluded by !**/*.md
📒 Files selected for processing (1)
  • packages/ui/src/components/custom/markdown-prose-parts.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/ui/src/components/custom/markdown-prose-parts.tsx

Included review availability: Your plan provides up to 8 included reviews per hour; 6 remain after this review.


Walkthrough

Markdown rendering now uses shared typography tokens, revised element styling, normal and compact density recipes, updated spacing, stronger table presentation, and adjusted streamed code-block margins. Session markdown forwards density settings, and tests validate typography, contrast, and rendering markers.

Changes

Markdown prose styling

Layer / File(s) Summary
Prose tokens and contracts
packages/ui/src/tokens.css, packages/ui/src/components/custom/markdown-prose-constants.ts, packages/ui/src/__tests__/*
Adds prose heading and tracking tokens, shared typography and link constants, a shared token reader, and contracts for heading order, compact sizing, and link contrast.
Markdown element styling
packages/ui/src/components/custom/markdown-prose-parts.tsx
Updates inline code, links, emphasis, blockquotes, rules, headings, lists, and tables with shared classes and compact overrides.
Prose density and spacing
packages/ui/src/components/custom/markdown.tsx, packages/ui/src/components/custom/stream-markdown.tsx, packages/ui/src/components/custom/__tests__/stream-markdown.test.tsx
Adds relaxed compact rendering, density markers, revised spacing rules, and my-5 streamed code-block margins.
Session density propagation
web/src/systems/session/components/message-markdown.tsx, web/src/systems/session/components/thinking-block.tsx, web/src/systems/session/components/__tests__/*
Forwards compact settings through direct and revealed message rendering. Thinking content uses relaxed compact rendering. Tests cover both paths.

Priority: ➖ Normal

Estimated code review effort: 4 (Complex) | ~45 minutes

Change: Feature · Severity of issue fixed: Medium

Sequence Diagram(s)

sequenceDiagram
  participant ThinkingBlock
  participant MessageMarkdown
  participant StreamMarkdown
  participant Markdown
  ThinkingBlock->>MessageMarkdown: pass compact="relaxed"
  MessageMarkdown->>StreamMarkdown: forward compact mode
  StreamMarkdown->>Markdown: forward compact mode
  Markdown->>Markdown: select relaxed prose recipe
Loading

Merge Risk: ⚪ Minimal · up to 75f00

The reviewed Markdown table and density behavior preserve the intended responsive and compact-reading presentation, with no confirmed merge-blocking issue.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 10.34% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 29 functions across 12 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The pull request meets the coding requirements in #653. It adds separate heading tiers, accent links with hover-capable underline styling, stronger table borders and spacing, list indentation, paragra…
Out of Scope Changes check ✅ Passed The changes stay within #653. Token updates, component mapping, density variants, contrast tests, and rendering tests directly support Markdown readability. Compact and relaxed behavior supports the s…
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the primary change: improving the visual hierarchy of rendered Markdown. It is concise, specific, and related to the changeset.
  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
🛠️ Fix failing CI checks 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Create a new PR

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@richardfogaca
richardfogaca marked this pull request as ready for review September 17, 2026 21:23
Copilot AI lite review requested due to automatic review settings September 17, 2026 21:23

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@greptile-apps

greptile-apps Bot commented Sep 17, 2026 •

Copy link
Copy Markdown

RetriggerConfidence Score: 5/5

The PR appears safe to merge, with no new actionable code defect identified.

Summary

The PR improves rendered Markdown hierarchy and readability across shared UI and session surfaces.

  • Adds dedicated prose heading and tracking tokens.
  • Updates headings, links, emphasis, lists, tables, inline code, and block spacing.
  • Adds compact and compact-relaxed rendering modes and applies the latter to reasoning panels.
  • Adds contract tests, component tests, representative Storybook stories, impact documentation, and affected QA scenario entries.

Reviews (3) · Last reviewed commit: "docs: correct Markdown QA notes and marg..."

Comment thread docs/_memory/change-impact.md
coderabbitai[bot]
coderabbitai Bot previously approved these changes Sep 17, 2026
Each prose part now picks its density from data-compact on the root, so
compact surfaces keep their previous sizes, weights, and padding while
still gaining the link, emphasis, and table fixes. Add compact="relaxed"
for the reasoning panel, which keeps small headings with prose breaks.

Spacing: a paragraph hugs the list it introduces, flowing text yields to
the heading above it (12/10/6/4px), framed blocks keep their own margin,
and a message ends flush whatever its last block is. Links use a solid
same-color underline to clear the non-text contrast floor. Tables drop
the double bottom rule and the redundant cell min-width and nowrap.

The contract test reads the constants the components render with, a
shared token reader replaces the duplicated helper, and the new density
prop ships with stories and tests. QA scenarios that own Markdown
surfaces carry dated impact entries.
coderabbitai[bot]
coderabbitai Bot previously approved these changes Sep 17, 2026
The TA-107 note implied DescriptionCard sits inside the 72ch cap and was
covered by the inspected stories; only StreamMarkdown has the cap and the
card was not inspected. DESIGN.md and the prose parts comment claimed
parts own density outright, but the root recipes still own block margins.

Add impact notes for the two task surfaces that render reading-tier
Markdown and had none, stating plainly that neither was inspected.
@pedronauck
pedronauck merged commit 6a3b6cd into compozy:main Sep 18, 2026
47 of 48 checks passed
@pedronauck pedronauck mentioned this pull request Sep 18, 2026
This was referenced Sep 27, 2026
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.

Improve visual hierarchy and readability of rendered Markdown

3 participants