Repository navigation
A playground that works on a phone, and exporters that arrive when wanted - #6
Merged
Merged
Conversation
It was not. The inspector holds a fixed 290px beside a card up to 640 wide, which on a 375px screen pushed the card off the left edge and left the whole page scrolling sideways — so the landing page's own invitation to open the playground led somewhere broken. Below 60rem the columns become rows, the card is scaled to the room it actually has, and the inspector becomes a sheet the View menu opens rather than a column that is always there. 60rem because the widest card a stack ships with is 640 and the inspector wants 290 beside it, so anything under about 960 cannot hold both — a landscape phone very much included. The rules live in a web-only stylesheet layered over the theme rather than in the theme itself, which belongs to the desktop, where the window is never 375 pixels wide. The zoom comes from measuring the stage, not the window: the menu bar, the status bar and any open sheet have taken their share first, and a landscape phone has plenty of width and almost no height. Part.tsx now divides a drag by the scale it measures off the part, so a part still lands where the finger left it. At 1:1 that divisor is one and the desktop is unchanged; the drag also rounds to whole pixels now, which it should always have done. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01R7eaxUAqy2gKQSBNnYZoFr
An SVG renderer, a font database and a text shaper come with the PDF and Decker exporters, and together they were most of what HyperLab compiled to: 1.6 MB over the wire, paid for by everyone who only wanted to click through Cluedo. They are now a WebAssembly module of their own, fetched the first time an export is asked for. The runtime that opens a stack is 326 KB. The seam is the stack's own single-file JSON, which persistence already reads and writes. A new stack_text command hands the text over — distinct from save_stack_json, which marks the document clean because a download *is* the save, and exporting a PDF is not saving. The export module parses it and works from that, so the two modules share no state. Driving the page confirms the split holds: opening Cluedo fetches the runtime and neither the exporters nor the typeface; exporting fetches both, once, and the PDF still comes out with its artwork labels. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01R7eaxUAqy2gKQSBNnYZoFr
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.
Two problems the landing page's own invitation created: it sends people to
a playground that did not work on a phone, and it made everybody download
an SVG renderer to get there.
The playground on a phone
The inspector holds a fixed 290px beside a card up to 640 wide, so on a
375px screen the card was pushed off the left edge and the whole page
scrolled sideways.
Below 60rem the columns become rows, the card scales to the room it has, and
the inspector becomes a sheet the View menu opens rather than a column
that is always there. 60rem, because 640 + 290 cannot fit under about 960 —
landscape phones very much included.
The rules live in
apps/web/src/mobile.css, layered over the theme ratherthan folded into it: the theme belongs to the desktop, where the window is
never 375 pixels wide. The zoom comes from measuring the stage with a
ResizeObserver, not the window, because the menu bar, the status bar andany open sheet have taken their share first — and a landscape phone has
plenty of width and almost no height.
Three attempts got this wrong before measurement caught them: a 48rem
breakpoint that let landscape phones fall through to the desktop layout; a
ResizeObserverthat never attached, becauseAppreturns early with aloading notice and the ref was still null when the effect ran; and a
sideways-scrolling menu bar, where
overflow-xmade a clipping context andcut off the menu dropping out of its own button. The bar wraps now.
One shared file
Part.tsxdivides a drag by the scale it measures off the part, so a partlands where the finger left it on a scaled card. At 1:1 the divisor is one
and the desktop is unchanged — checked by driving both (
zoom 0.95 → 42 card px, expected 42;zoom 1.00 → 40, expected 40). It also rounds towhole pixels now, which it should always have done.
The exporters are fetched when somebody exports
An SVG renderer, a font database and a text shaper come with PDF and Decker
export, and together they were most of what HyperLab compiled to.
They are now
crates/web-export, a module of its own. The seam is thestack's own single-file JSON, so the two modules share no state. That needed
a
stack_textcommand distinct fromsave_stack_json— the latter marks thedocument clean, because a download is the save, and exporting a PDF is not
saving.
Verified
CI green on
3306348. Beyond that, the built site was driven in Chromium:with no sideways scroll; the desktop keeps its inspector, its unscaled
card and no View menu.
typeface. Exporting fetches both, once. The PDF still carries its artwork
labels.
🤖 Generated with Claude Code
https://claude.ai/code/session_01R7eaxUAqy2gKQSBNnYZoFr
Generated by Claude Code