Repository navigation
feat(cloud): show the app as a rounded card from 1024 px with a 56 px rail on every tablet and desktop width - #1261
Merged
Merged
Conversation
…6 px rail The approved shell v2 and the dense tablet concept show the app as one rounded card on the canvas from laptop and iPad landscape widths, not only from 1536 px. The card's spacing and radius grow from 4 to 8 px and from 10 to 14 px up to 1440 px, so the wide card stays as it is. From 768 to 1023 px the app stays flush. The rail is 56 px wide at every width from 768 px with 44 px targets, as touch needs them. In the installed app the card stays below the status bar and keeps its content above the home indicator.
…led-app insets The shell tests now cover the iPad sizes of the dense tablet mockup and the 1023/1024 px boundary. The card's spacing and radius are whole pixels, so hydration and the controller cannot move a column by a fraction of a pixel and the home-indicator inset stays exact. The docs describe the card from 1024 px.
Tooltip triggers set their own font size, which beats a utility on the control, so search, help and the app grid kept 15 px icons. The icon carries its 20 px size, and the rail test checks every control's icon.
The flush range ended at max-width 1023px and the card started at min-width 1024px, so a fractional width between them, such as a zoomed window, matched neither and fell back to the base rail and canvas rules. The phone range had the same gap at 767/768 px. Each shell query now states only min-width and negates it for the range below, so neighbouring modes are exact opposites. A test pins the queries so a max-width query cannot bring the gap back.
The flush and card modes left fractional widths in neither mode. The lesson names the error class and its guard, so other style sheets that pair max-width with min-width queries can be checked against it.
ValentinKolb
enabled auto-merge
October 16, 2026 16:00
github-merge-queue
Bot
removed this pull request from the merge queue due to a conflict with the base branch
Oct 16, 2026
# Conflicts: # docs-site/docs/en/contributing/lessons-learned.md
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.
Outcome
Signed-in pages show the app as one rounded card on the app canvas from 1024 px, not only from 1536 px. The card holds the app's navigation, main area and detail, and the rail sits beside it on the canvas. The card's spacing grows from 4 px at 1024 px to 8 px at 1440 px and its radius from 10 px to 14 px, in whole pixels (iPad landscape 1194 px: 6 px and 12 px, as in the dense tablet mockup). From 1440 px it is the card of today. From 768 to 1023 px the app stays flush, and phones are unchanged.
The rail is 56 px wide at every width from 768 px, with 44 px controls and 20 px icons. The avatar is 32 px in a 44 px target.
In the installed iPad app, the card and the rail stay below the status bar. The card keeps its spacing at the bottom, and the workspace surfaces, or the page's scroll end, stay above the home indicator. The flush range still fills the insets (#1067).
Part of #1255 (parity rows R1, R2, C1, C2, C3; C4 is covered by tests with emulated insets). The checklist issue stays open for the other slices.
Parity rows (light, mockup next to build)
Screenshots (v3): https://artifacts.qdt-dev-1.k2b.dev/cloud/shell-v2-card/v/3/ (01 mockup, 02 Mail build, 03 Mail main before, 04 page without a workspace (Profile) build, 05 the same page before; widths 1024, 1194x834, 834x1194, 694x834, 390x844, 1440x900, 1920x1080)
.rail56,.rb44Open questions for the maintainer (also in #1255):
The build images are the development stack (main) with this branch's full compiled stylesheet served in place of
global.css, compiled from the rootstyles.csslike the real build, so every app utility is present. The two markup details (20 px rail icons, 32 px avatar) are applied to the page in the picture. The browser tests use the real markup.Changed happy paths
h-dvh, the shell's islands (perf(cloud): render the app shell with at most four islands #1033).Root cause
Mostly not a defect: the shell switched the card on at 1536 px (
packages/cloud/src/styles/global.css, flush block 768-1535 px), and the rail was sized for a mouse.Bug fixed along the way (review finding): the shell modes were written as
max-width: 1023px/min-width: 1024px(and 767/768 for phones), so a fractional width matched neither and the shell fell back to its base rules (rail 8 px to the right, base spacing). Each shell query now states onlymin-widthand its negationnot all and (min-width: …). Error class "Breakpoint gap", recorded in Lessons learned.How we prevent regressions
packages/cloud/src/ssr/compact-shell.browser.test.ts(Chromium and WebKit) pins the card at 1024, 1194x834, 1440 and 1920 (spacing and radius per width), flush at 834x1194 and 1023, the phone at 390 and 694, a page without a workspace, the 56 px rail with 44 px controls and 20 px icons, notices, and identical unrounded boxes served, after the controller attaches and after a reload, with no horizontal overflow. 34 of its and app-canvas's assertions fail on main's stylesheet.packages/cloud/src/styles/app-canvas.browser.test.tsemulates the installed app's safe areas for the card (1194x834, 1440x900) and the flush range (834x1194).packages/cloud/src/styles/shell-modes.test.tspins the shell media queries tomin-widthand its negation, so amax-widthquery cannot bring the breakpoint gap back. Playwright snaps viewports and iframes to whole pixels in Chromium and WebKit (checked), so no browser test can reach the gap.Docs
frontend/layout-and-navigation.md: the shell table, the app bar's 44 px targets, the notice strip range, and the installed app from 1024 px.frontend/application-shells.md,build/define-app.md, UI contextlayout/workspace.md, and theflatJSDoc inAppWorkspace.tsx: the card from 1024 px.contributing/lessons-learned.md: new error class "Breakpoint gap" and its lesson.Verification
bun run test --filter packages/cloud(all 3 suites pass, integration skipped: no server code changed); Chromiumcompact-shell,app-canvas,app-badges,page-trail,layout-viewport109/109; WebKit (Playwright 1.63 server) the same five files 109/109 before the rebase, andcompact-shell,app-canvas, uidetail-float, uiworkspace-levels133 pass / 0 fail after it.account-pages,me/app,OutgoingMail, notebooksbook-links(Chromium), coreaccount-pages(WebKit).bun run --cwd packages/cloud typecheck,packages/uitypecheck, docs check (141 pages),git diff --check; Codex (gpt-6.1-sol) review against main: no actionable findings.round()(Chrome < 125) would lose the card spacing and radius.Operations
No configuration change. Operators of signed-in laptops and iPads in landscape see the card layout after the update.