Repository navigation
feat: give rendered Markdown a readable visual hierarchy - #660
Conversation
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
|
@richardfogaca is attempting to deploy a commit to the Compozy Team on Vercel. A member of the Team first needs to authorize it. |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Advanced Run ID: ⛔ Files ignored due to path filters (5)
📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
Included review availability: Your plan provides up to 8 included reviews per hour; 6 remain after this review. WalkthroughMarkdown 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. ChangesMarkdown prose styling
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
Merge Risk: ⚪ Minimal · up to 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)
✅ Passed checks (4 passed)
✨ Finishing Touches 💡 1🛠️ Fix failing CI checks 💡
🧪 Generate unit tests (beta)
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. Comment |
|
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.
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.
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:strongfg-strong, underline at 5.5% whiteaccent-strong, solid 1px same-color underline, 3px offset--text-inline-code(0.9em), already in the ladder but unusedH2 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:
--text-prose-h1..h3ladder 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.nowrapheaders. Cells useoverflow-wrap: normal, so identifiers never break mid-word and wide tables scroll inside their own frame instead of crushing columns.compactsurfaces (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 fromdata-compacton 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.One design decision to review: links use
accent-strong, which is a second accent use in a viewport. I recorded it inDESIGN.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 isfg-strongwith amutedunderline, a one-line change inMarkdownAnchor.How you verified it
Same representative sample before and after, from the real component (
MessageMarkdown→LongAnswerstory).Before (
main@ 7b64ab1)After (this branch)
After, 352px column (
NarrowColumnstory) — the table is 453px wide inside a 350px frame and scrolls there; the Markdown column does not cross the viewport.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_bodiesmid-word; that is fixed in the implementation (td codeisnowrap), as the Storybook capture above shows.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,
strong600, linkrgb(246, 135, 79)with a solid 1px underline at 3px offset, table frame 1pxline-strongwith 7px radius,thonsurface-glaze,td13.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.Compactstory: 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— regeneratedDESIGN.mdtoken tables andfont-size-classes.generated.ts(sotailwind-mergetreats the new sizes as font sizes, not colours).make gate— passes on the final commit:js-packages-uiandjs-weblanes PASS. One earlier run failed onsheet.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.tsreads the realtokens.cssbytes through a token reader now shared with the focus-ring audit, and takes its tiers from the samePROSE_TYPE/PROSE_TYPE_COMPACT/PROSE_LINKconstants 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.tsxcovers the three densities, andMessageMarkdown/ThinkingBlocktests cover thecompactpassthrough on both render paths. New stories:Markdown(Reading,Compact,CompactRelaxed) inpackages/ui, andLongAnswer,NarrowColumn,CompactforMessageMarkdown.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. Nopackages/sitedocs update needed.docs/_memory/change-impact.mdhas 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, andTA-web-task-result-disclosure. Storybook verification coveredStreamMarkdown/MessageMarkdownand the reasoning panel only; theDescriptionCardand task surfaces were not inspected, and no live-runtime walk was done. Each entry says so, and I left everyqa_statusas 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 inmarkdown.tsxnever match in plain<Markdown>because Streamdown emitscode[data-block];compactstaysboolean | "relaxed"rather than becoming adensityprop, 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 gatepasses locally; this PR is delivered only after its required CI checks are greenSummary by CodeRabbit
New Features
Bug Fixes