Conversation
The feed column is capped at 860px, so on a wide window most of the
screen is empty and diffs scroll sideways. Add a per-workspace width
setting, persisted and broadcast like the theme:
- GET/PUT /api/width ({"id":"normal"|"wide"}), stored via
Store.setSetting("width") (no schema change), width-changed SSE so
other tabs follow, public-read GET like /api/theme.
- A toggle beside Stream/Timeline (hidden on phones) puts a `wide`
class on the engine root; #stream and .standalone-main grow to
1600px. Mobile rules and normal mode are untouched.
- Markdown keeps a readable ~80ch measure via right padding on its
iframe, so no server render change, cache key or frame reload.
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Padding the markdown iframe capped the whole document at 740px, so fenced code blocks and tables still scrolled sideways inside a half-empty wide card. Cap prose elements in MD_CSS at just above their normal-column width instead: normal mode is unchanged, wide frames keep a readable measure, and pre/table use the full width. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VZX7jtqqerDjNe5Q813hbK
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VZX7jtqqerDjNe5Q813hbK
Even a 1600px column can't fit a 4000px line, so text surfaces still scrolled sideways. In wide mode the viewer now asks the server-rendered text kinds (markdown, code, terminal, diff; `softWrap` in the surface metadata) for `?wrap=1`: pre-wrap for markdown fences, code and terminal, with code lines hanging under the code rather than the line number, and @pierre/diffs' native `overflow: "wrap"` for diffs. The flag is part of the render cache key and ignored for other kinds. Normal mode output is byte-identical. The frame URL is now built in one place (surfaceSrc). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01VZX7jtqqerDjNe5Q813hbK
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Refs #223. This covers the "display the text over a wider area" part. It doesn't include the collapsible sidebar or the text-density config.
Problem
The feed column is capped at
max-width: 860px(#streamand.standalone-main). On a ~1930px window about 60% of the screen stays empty, and diff and code cards scroll sideways to show lines that would fit.What this adds
GET/PUT /api/widthtakes{"id":"normal"|"wide"}. It's stored withStore.setSetting("width")like the theme, so there's no schema change and it works on SqlStore, JsonFileStore and the Durable Object. Awidth-changedSSE event makes other open tabs follow live. Like/api/theme, the GET is readable in public-read mode and the PUT still needs auth.↔pill sits beside Stream/Timeline and is hidden on phones. It puts awideclass on the engine root, and#stream/.standalone-maingrow to 1600px. Onlymax-widthchanges, so the phone@mediarules are untouched.MD_CSScaps prose elements (p, headings, lists,dl,blockquote) at 780px, just above their width in the normal column. Fenced code blocks and tables aren't capped, so they use the full width in wide mode. The CSS is static, so there's no render-cache key change and nothing reloads on toggle.?wrap=1for the server-rendered text kinds. The wrappable kinds are markdown, code, terminal and diff, marked bysoftWrapinSURFACE_KIND_METADATA. Markdown fences, code and terminal output usepre-wrap, and wrapped code lines hang under the code rather than the line number. Diffs use @pierre/diffs' nativeoverflow: "wrap". The flag is part of the render cache key and ignored for other kinds. With wrap off, output is byte-identical: a unit test deep-compares it, and an e2e test checks that all four kinds scroll in normal mode and don't in wide mode.surfaceSrcnow builds every frame URL, including the version picker's.Normal stays the default, and the self-hosted normal layout is unchanged.
Side effects worth knowing
/s/:id, now caps prose at 780px in normal mode too. It used to span the whole dialog or page..wideclass through the engine as-is. There's no embed-specific e2e.Verification
npm test: 502/502 node, 8/8 viewernpm run test:worker: 1/1npm run test:e2e: 190 passed (chromium + webkit), including the newe2e/width.spec.ts. That spec checks that the toggle widens the column and persists across a reload, that another tab follows live, that the phone layout is unchanged, that a long-line diff has no horizontal overflow in wide mode, that markdown prose is the same width as its code block in normal mode, and that in wide mode prose stays ≤780px while the code block goes past 1200px.typecheck,lint,format:check: passbench:check --gate deterministic: no regressionsChangeset: minor.
🤖 Generated with Claude Code
https://claude.ai/code/session_01VZX7jtqqerDjNe5Q813hbK