Render dashboard preview panes inside medium-matching chrome (browser for web, email for emails)#5888
Conversation
The preview pane previously showed a bare iframe with the page URL as a caption underneath and an open-in-new-tab arrow up in the sidebar header. This wraps every preview state in a browser-style chrome bar: the page title and URL centered like a browser tab and address bar, with the open-in-new-tab arrow on the right of the bar itself. The sidebar-header preview link and the separate URL caption are gone — the chrome carries the page's identity in one place, matching the follow-up called out on the first-class Pages PR. Co-authored-by: Sahil Lavingia <sahil@gumroad.com>
Greptile SummaryThis PR gives dashboard previews shared chrome that matches the previewed medium. The main changes are:
Confidence Score: 5/5This looks safe to merge. No blocking issues found in the changed code.
What T-Rex did
Important Files Changed
Reviews (11): Last reviewed commit: "Fix preview framing and refresh screensh..." | Re-trigger Greptile |
|
Ensure works both light and dark mode |
The chrome container was hardcoded bg-white, which clashed with the dashboard in dark mode. bg-background follows the theme; the bar and placeholder already used theme tokens, and the framed page documents handle their own prefers-color-scheme. Co-authored-by: Sahil Lavingia <sahil@gumroad.com>
|
Done — the chrome container was hardcoded Will grab light + dark screenshots from the preview app for the Before/After table. |
|
Screenshots |
Light and dark captures of the three editor preview states (rich text page, Home storefront frame, new-page placeholder) from the preview app. Co-authored-by: Sahil Lavingia <sahil@gumroad.com>
|
Added — light + dark captures of all three preview states (rich text page, Home storefront frame, new-page placeholder) are in the Before/After section now, taken from the preview app at the current head. The chrome bar, borders, and placeholder follow the dashboard theme in dark mode; the framed rich text page flips dark via its own |
|
That button padding way too much. |
The default icon button size (48px) dwarfed the slim chrome bar and read as oversized padding. Use a compact 32px button with a smaller arrow icon, and tighten the bar padding to match. Co-authored-by: Sahil Lavingia <sahil@gumroad.com>
|
Fixed — the arrow was using the stock icon-button size (48px), which is why it looked so padded inside the slim chrome bar. It's now a compact 32px button with a smaller arrow, and the bar's side padding is tightened to match (fefd462). Refreshed screenshots coming once the preview app picks up the new commit. |
|
Screenshots refreshed from the preview app at the new head — the compact button is in all six captures (light + dark for rich text, Home, and new page), same filenames so the Before/After tables in the description show the current state. |
|
We can remove the "Preview" header as it's implied by the chrome and vertically aligns both sides. |
The browser-style chrome already identifies the pane as a preview, so the sidebar heading duplicated it and pushed the chrome below the top of the edit form. PreviewSidebar gains a hideHeader option (keeping an aria-label for the region); other PreviewSidebar users are unchanged. Co-authored-by: Sahil Lavingia <sahil@gumroad.com>
|
Done — removed the "Preview" heading from the sidebar, so the chrome bar now sits at the top of the pane, aligned with the edit form. |
Extract the Pages editor's browser-style preview chrome into a shared PreviewChrome component and render every PreviewSidebar consumer inside it: product edit, bundle edit, the three checkout dashboard previews, workflow emails, and profile settings. The redundant "Preview" heading (and the separate open-in-new-tab arrow next to it) is gone everywhere; the chrome bar carries each surface's title, public URL, and open link instead. Surfaces without a meaningful public URL (the receipt preview, workflow emails) render the chrome with a title only.
The chrome's overflow-hidden (needed for the rounded-corner clipping) zeroes its automatic minimum flex size, so inside the sidebar's fixed-height flex column it compressed to the viewport and clipped tall previews — the workflow email list's 'View content' button became invisible (CI: workflows_spec 'allows creating a new email'). shrink-0 restores the sidebar as the scroll container.
Per Sahil, the preview chrome should match the medium being previewed:
web pages keep the browser-style title + URL bar, but emails land in
inboxes, so the two email surfaces now render an email-client header
instead. PreviewChrome gains a discriminated variant prop:
variant="email" takes a From line and an optional Subject and drops
the URL bar and open-in-new-tab arrow (an email has no URL to open),
while the default web variant is unchanged.
Both surfaces show honest values sourced from the real mailer config:
- Workflow emails: From is the exact sender PostEmailApi/PostResendApi
build (creator name <username@creators domain>), passed through a new
email_from field in the workflow form context. No Subject line — the
pane stacks every email in the workflow, each with its own subject as
its heading, so a single chrome-level Subject would be ambiguous.
- Product edit Receipt tab: From mirrors CustomerMailer#receipt
(creator name <noreply@customers domain>) via a new receipt_email_from
edit prop, and Subject mirrors ReceiptPresenter::MailSubject for the
single-purchase preview the receipt endpoint renders (You bought /
You got / You've subscribed to {product}!).
…ctation The full-hash equality spec for a brand-new product's edit_props was not updated when the Receipt preview gained its email-style chrome, which added receipt_email_from to the presenter output.
…ct source - Mobile: restore a full-size labeled 'Open in new tab' button above the frame (compact 32px icon arrow stays desktop-only inside the chrome bar). - Checkout: drop the open-in-new-tab arrow entirely — the pane shows a synthetic sample cart while /checkout would render the seller's persisted cart, so the destination could never match the preview. - Receipt: subject and body now come from the same Rails preview response (ReceiptPresenter#mail_subject rides along with the rendered HTML as JSON), so unsaved client state can no longer disagree with the rendered receipt. PurchasePreview gains explicit link_name/price_cents so MailSubject sees real values instead of method_missing nils.
…utton, checkout sans arrow, server-sourced receipt subject)
|
@gianfrancopiana All four addressed (code in 95d548d, media refreshed after it):
|
|
@gumclaw See below.
The tooltip gets cut off on hover. We should fix this. The chrome still reads as a generic header rather than browser chrome. Please make these changes:
Please refresh the light and dark screenshots after these changes. And make sure everything you add is consistent with Gumroad's design. Avoid new patterns. |
…ddress field, fixed tooltip, bigger arrow hit area - Chrome bar gets a subtle bg-body surface fill so it separates from the preview frame (both variants) - URL moves into a quiet inset address field (bg-active-bg pill) with middle truncation so the page's own path segment stays visible; full URL kept in the accessibility tree - Open-in-new-tab tooltip positioned bottom-end so it no longer clips against the sidebar edge - Arrow stays visually compact (32px) but an invisible ::after pad extends its hit area to 44x44px - Only the arrow reacts on hover (unchanged Button hover); no fake browser controls added Co-authored-by: Gianfranco <gianfranco@gumroad.com>
|
@gianfrancopiana Got it — all of this is on me and I'll take it in one pass:
I'll build this from existing Gumroad design primitives (no new patterns), verify it live, and refresh the light and dark screenshots after the changes. ETA: updated code + screenshots within ~12 hours (by ~13:00 UTC today). |
|
Status update on the round-2 items: all six code changes are on the branch in c106154 (surface fill, inset address field with middle truncation, fixed tooltip clipping, centered title + right arrow, 44×44px arrow hit area with hover on the arrow only, no fake controls) and CI is fully green. The one thing still outstanding is the light/dark screenshot refresh against the new chrome — I missed my ~13:00 UTC estimate on that. Refreshed screenshots will be up by ~20:00 UTC today, and I'll ping here when the body is updated so it's ready for another look. |
…s, light+dark)
|
@gianfrancopiana handle locally, feedback loop is too slow for the remaining changes |
|
Standing down — it's all yours locally, @gianfrancopiana. I won't push to this branch anymore. Where the branch is at head
The PR body's table maps every surface to its chrome variant if you need a reference while iterating. |
|
Updated the preview chrome and checkout layout, refreshed all light/dark screenshots, and enabled auto-merge so this will merge once CI is green. |
|
Seems like light mode is rendering in dark mode within the preview pr-5888-after-bundle-edit-dark.png |
|
Get CI green too |
|
CI is green now. Test Slow 22 failed on a single spec ( |
|
And the light mode within dark mode fix? Fix the tool bar too should be dark bg too or just slightly lighter than the text field bg |
|
Checked the pixels in The editor preview pins So the screenshot is faithful: dark dashboard, dark chrome, seller-colored page in the frame — the same contrast a real browser window shows when a dark-mode user opens a white website. If we'd rather have the preview adopt the dashboard's scheme when the seller hasn't customized their colors, the override to change is the |
|
Fix is up: #5992. Two changes, both from this comment:
The PR is draft until I get dark/light screenshots from its hosted preview — will un-draft and ping once they're in the body. |
## What The rich text editor toolbar now follows dark mode. The toolbar uses an inverted `bg-primary` bar, which is black in light mode but flips to near-white in dark mode — a bright strip across an otherwise dark editor. In dark mode it now uses the page background (`bg-body`, `#242423`), which sits slightly lighter than the black text field beneath it, with regular foreground text. Light mode is unchanged. The `--color-muted` override for toolbar icons now derives from `currentColor` so muted icons stay legible on both bars. Re-opened from #5992 after review: the preview-palette portion of that PR was dropped (`#ffffff` is the seller's actual storefront background, so making the preview inherit dark mode would stop it matching what buyers see; scheme-aware default pages need a proper theme model first). This PR is the surviving toolbar-only fix on a clean branch. ## Why Sahil flagged the toolbar on #5888 after merge: the description toolbar stayed light in dark mode ("Fix the tool bar too — should be dark bg too or just slightly lighter than the text field bg"). ## Before / After **Before (dark mode):** light toolbar strip across the dark editor — visible in the top area of  **After:** capturing from the preview app once the deploy is up; PR stays draft until attached. ## QA steps 1. Set the OS/browser to dark mode. 2. Open a product or bundle editor — the description toolbar should render dark, slightly lighter than the text field beneath it, with legible icons. 3. Switch to light mode — the toolbar is unchanged from before (inverted black bar). ## Test plan - TSX-only change to `RichTextEditor.tsx`; no Ruby touched. - Prettier + ESLint clean on the changed file. - CI on this PR builds fresh assets and runs the full suite. --- ## AI disclosure Authored by Claude Fable 5 (Hermes agent) from Sahil's review comment on #5888. Carried over from #5992 with the preview-palette change removed per gianfrancopiana's review. Co-authored-by: Claude Fable 5 <noreply@anthropic.com>

What
Wraps dashboard preview panes in shared chrome that matches the medium being previewed:
The shared frame is used by Pages, product and bundle editors, the Receipt tab, Checkout, workflow emails, and profile settings. Preview frames no longer repeat a separate Preview heading or URL caption.
Checkout is intentionally different: it is labeled Checkout preview and has no URL or arrow because it renders a synthetic cart that does not exist at
/checkout. Its layout now responds to the preview container, so the narrow embedded preview uses the real checkout's stacked layout while the full checkout still switches to two columns when there is enough room.Receipt From, Subject, and body values come from the same Rails preview response, so unsaved client state cannot make the chrome disagree with the email body.
Per-surface chrome
Why
This follows the first-class Pages work in #5812 and Sahil's direction to apply the same preview language to product pages and all other preview panes, while matching email previews to email rather than browser chrome.
The result keeps identity and actions in one place, aligns the preview with the edit form, and avoids false affordances. Only the arrow reacts on hover; the preview frame itself stays unchanged. No fake browser controls were added.
Screenshots
All after screenshots were recaptured locally at the current branch head in a consistent 1600×1000 viewport.
Rich text page
Home
New page
Product edit
Bundle edit
Receipt tab
Checkout form
Workflow emails
Profile settings
Test plan
bin/test-confidence: 99% green; the tool classified and skipped 21 existing branch failures.spec/requests/checkout/form_spec.rb: 8 examples, 0 failures.npm run typecheckcurrently stops before checking project source because this branch cannot resolve the configuredvite/clienttype definition (TS2688).Combined scope note: this PR carries the full stack from #5894, which was merged into this branch and closed.