port: covers (approved mockup) #852

Closed
kayg wants to merge 11 commits from port/style-3 into port/style-2
Owner

port: covers (approved mockup) — slice 3 of 3 (stacked on port/style-2)

  • A cover is three plain lines: cover-image: [Title](<../Photos/…>), cover-position: 50% 30%, cover-height: short|tall (standard = no line). Link written like every picture (relative, angle brackets); unit-tested round trip.
  • Cover is a CodeMirror block widget before the title (scrolls with the text); the real first # line is pulled up over a blur band, black or white by the band's measured tone (measured once per picture+focal point, cached locally). Phone: runs to the card's edges.
  • Pill: Change · Reposition (drag / arrows / Done) · Remove (with Undo). Style sheet Page tab: Cover row, Short/Standard/Tall (desktop), "Use this picture as the cover" suggestion. Note ⋯: Add/Change cover.
  • Upload goes through lib/cover-upload.ts, the ONE module that talks to POST /api/v1/attachments; swap to port-attachments' attachments/upload.ts when it lands.
  • Loaded lazily from idle-screens the first time a note has a cover.

Gates: svelte-check, vitest, cover.spec.ts (desktop, phone, touch) on chromium+webkit.
Bundle (brotli): first JS 240.0, all JS 321.7 (dev 311.9; budget 315 needs kayg's OK).
Not ported: in-page "Add cover" button, drop/paste onto the top (overlaps port-attachments' drop/paste), the library picker and list-row cover thumbnails, server-stored tone. Mockup cover page could not be run for side-by-side shots (its covers.html fails to load in dev); product shots are in shots/port-style/product-pr3.

🤖 Generated with Claude Code

## port: covers (approved mockup) — slice 3 of 3 (stacked on port/style-2) - A cover is three plain lines: `cover-image: [Title](<../Photos/…>)`, `cover-position: 50% 30%`, `cover-height: short|tall` (standard = no line). Link written like every picture (relative, angle brackets); unit-tested round trip. - Cover is a CodeMirror block widget before the title (scrolls with the text); the real first `# ` line is pulled up over a blur band, black or white by the band's measured tone (measured once per picture+focal point, cached locally). Phone: runs to the card's edges. - Pill: Change · Reposition (drag / arrows / Done) · Remove (with Undo). Style sheet Page tab: Cover row, Short/Standard/Tall (desktop), "Use this picture as the cover" suggestion. Note ⋯: Add/Change cover. - Upload goes through `lib/cover-upload.ts`, the ONE module that talks to `POST /api/v1/attachments`; swap to port-attachments' `attachments/upload.ts` when it lands. - Loaded lazily from `idle-screens` the first time a note has a cover. **Gates**: svelte-check, vitest, `cover.spec.ts` (desktop, phone, touch) on chromium+webkit. **Bundle (brotli)**: first JS 240.0, all JS 321.7 (dev 311.9; budget 315 needs kayg's OK). **Not ported**: in-page "Add cover" button, drop/paste onto the top (overlaps port-attachments' drop/paste), the library picker and list-row cover thumbnails, server-stored tone. Mockup cover page could not be run for side-by-side shots (its covers.html fails to load in dev); product shots are in `shots/port-style/product-pr3`. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
kayg added 11 commits 2026-11-02 10:27:26 +00:00
Author
Owner

Gate results (head 80e733b8): union of cover/style/bars/backdrop/lazy/editor/toast/phone specs: chromium-1440 95/95, chromium-390 513 pass (note-bars:100 and bar-taps:55 failed under load / spec fixed, pass 15/15 repeated), webkit-1440 89 pass + 3 load flakes that pass in isolation, webkit-390 511 pass + bar-taps:55 (fixed in spec, passes). Cover shots: shots/port-style/product-pr3 (cover, pill, Style row at 1440 and 390).

Gate results (head 80e733b8): union of cover/style/bars/backdrop/lazy/editor/toast/phone specs: chromium-1440 95/95, chromium-390 513 pass (note-bars:100 and bar-taps:55 failed under load / spec fixed, pass 15/15 repeated), webkit-1440 89 pass + 3 load flakes that pass in isolation, webkit-390 511 pass + bar-taps:55 (fixed in spec, passes). Cover shots: `shots/port-style/product-pr3` (cover, pill, Style row at 1440 and 390).
Author
Owner

Cover now full-bleed like the mockup (spans the frame the panes leave visible, from its top edge, title lower-left at the text column; phone: from the top of the screen, no card for a covered note). Upload uses lib/attachments/upload.ts byte-identical to #846's. Bundle (brotli, idle-screens / index / all js): dev 39.2/239.5/311.9, #850 43.1/239.5/315.5, #851 45.3/239.6/317.9, #852 49.1/240.0/322.1.

Cover now full-bleed like the mockup (spans the frame the panes leave visible, from its top edge, title lower-left at the text column; phone: from the top of the screen, no card for a covered note). Upload uses lib/attachments/upload.ts byte-identical to #846's. Bundle (brotli, idle-screens / index / all js): dev 39.2/239.5/311.9, #850 43.1/239.5/315.5, #851 45.3/239.6/317.9, #852 49.1/240.0/322.1.
Author
Owner

BM10 follow-up (new head 08b6d9ad, on top of #851 80934507). Nothing in this PR caused a listed failure on its own; it merges #851/#850 and adds the cover. Cover specs are stable at the merge on all four projects (cover.spec: pointer position fixed for the full-bleed cover). The merge needs 25 lazy-UI rewrites (search 1 + stack 24), as the train had.

BM10 follow-up (new head 08b6d9ad, on top of #851 80934507). Nothing in this PR caused a listed failure on its own; it merges #851/#850 and adds the cover. Cover specs are stable at the merge on all four projects (`cover.spec`: pointer position fixed for the full-bleed cover). The merge needs 25 lazy-UI rewrites (search 1 + stack 24), as the train had.
Author
Owner

BM14c Style stack: causes and fixes (pushed to #852 port/style-3, head 07b6770a)

Cause 1 (most of the red). #851 gave PageTab a noteId prop and #852's merge of #851/#850 took the <PageTab /> call from the #851 side of StyleSheet.svelte:142 (no noteId), while #850's side had <PageTab {noteId} />. So the Cover row got no note, and cover / Width / Opacity / style-sheet / note-bars specs lost their rows and timed out. svelte-check showed it as Property 'noteId' is missing (the only train-only error). Fix: f757dc1e passes noteId.

Cause 2 (note-bars.spec.ts:237, phone, WebKit 13/20 after cause 1 was fixed). The Page tab builds itself in steps (looks, then rows + Cover, then colour; 40 ms timers). StyleSheet dropped its held room (min-height) as soon as the tab was mounted, so the capsule shrank to the looks (307 px) and grew back; the spec's still() saw the shrunken moment and compared "Text page shorter than Page" against 307 (Text is 394). Fixes: fed76ea1 keeps the held room until PageTab says its last step is in (onready), and 07b6770a updates the held-room guesses for the taller Page tab with the Cover row (measured on the stack: page 464 phone / 553 wide, sheet 516 / 605; they were 362/451 and 414/503 from before the Cover row). No assertion, threshold or timeout changed.

Results on the merged train tree + these 3 commits (train b59e4a5e plus cherry-picks, dev-01, CI=1 --workers=1 --retries=0 --repeat-each=20)

Cases: cover.spec.ts:124, :143; style-sheet.spec.ts:26, :49; note-bars.spec.ts:319 (desktop), :237 (phone); opacity.spec.ts:122; width.spec.ts:177, :48 and :86 (1440 only). Cases that do not apply to a width are skipped by their own test.skip.

project failed passed skipped (by the spec)
chromium-1440 0 180 20
chromium-390 0 140 60
webkit-1440 0 180 20
webkit-390 0 140 60

Notes on the runs: the very first parallel runs shared one test-results dir and a port, giving ENOENT/port errors (my harness, not the app); every number above is from runs with their own --output. One webkit-1440 run beside three other 20x runs had 1 failure in 180 (note-bars.spec.ts:319, tablist not up in 5 s under heavy load); the same project alone, repeated: 180/180. svelte-check on the stack: only the 2 errors in e2e/review4-signout.spec.ts:225-226 that origin/dev has too; StyleSheet.svelte:142 is gone.

Style sheet open time (kept)

note-bars-motion.spec.ts "rest to Style sheet", throttled-390 (6x CPU), --no-deps --repeat-each=20: 20/20 pass; longest main-thread task of the open: min 80, median 92, p90 128, max 172 ms (limit 250; goal median ≤ 120). Held room did not add any task.

Not done

vim.spec.ts:387 (:w says Saved): not touched. It fails on dev too and I did not find a quick deterministic fix; left as is for #895.

## BM14c Style stack: causes and fixes (pushed to #852 `port/style-3`, head `07b6770a`) **Cause 1 (most of the red).** #851 gave `PageTab` a `noteId` prop and #852's merge of #851/#850 took the `<PageTab />` call from the #851 side of `StyleSheet.svelte:142` (no `noteId`), while #850's side had `<PageTab {noteId} />`. So the Cover row got no note, and cover / Width / Opacity / style-sheet / note-bars specs lost their rows and timed out. `svelte-check` showed it as `Property 'noteId' is missing` (the only train-only error). Fix: `f757dc1e` passes `noteId`. **Cause 2 (`note-bars.spec.ts:237`, phone, WebKit 13/20 after cause 1 was fixed).** The Page tab builds itself in steps (looks, then rows + Cover, then colour; 40 ms timers). `StyleSheet` dropped its held room (`min-height`) as soon as the tab was *mounted*, so the capsule shrank to the looks (307 px) and grew back; the spec's `still()` saw the shrunken moment and compared "Text page shorter than Page" against 307 (Text is 394). Fixes: `fed76ea1` keeps the held room until PageTab says its last step is in (`onready`), and `07b6770a` updates the held-room guesses for the taller Page tab with the Cover row (measured on the stack: page 464 phone / 553 wide, sheet 516 / 605; they were 362/451 and 414/503 from before the Cover row). No assertion, threshold or timeout changed. ## Results on the merged train tree + these 3 commits (train `b59e4a5e` plus cherry-picks, dev-01, `CI=1 --workers=1 --retries=0 --repeat-each=20`) Cases: cover.spec.ts:124, :143; style-sheet.spec.ts:26, :49; note-bars.spec.ts:319 (desktop), :237 (phone); opacity.spec.ts:122; width.spec.ts:177, :48 and :86 (1440 only). Cases that do not apply to a width are skipped by their own `test.skip`. | project | failed | passed | skipped (by the spec) | |---|---|---|---| | chromium-1440 | 0 | 180 | 20 | | chromium-390 | 0 | 140 | 60 | | webkit-1440 | 0 | 180 | 20 | | webkit-390 | 0 | 140 | 60 | Notes on the runs: the very first parallel runs shared one `test-results` dir and a port, giving ENOENT/port errors (my harness, not the app); every number above is from runs with their own `--output`. One webkit-1440 run beside three other 20x runs had 1 failure in 180 (`note-bars.spec.ts:319`, tablist not up in 5 s under heavy load); the same project alone, repeated: 180/180. `svelte-check` on the stack: only the 2 errors in `e2e/review4-signout.spec.ts:225-226` that origin/dev has too; `StyleSheet.svelte:142` is gone. ## Style sheet open time (kept) `note-bars-motion.spec.ts` "rest to Style sheet", throttled-390 (6x CPU), `--no-deps --repeat-each=20`: 20/20 pass; longest main-thread task of the open: min 80, **median 92**, p90 128, max 172 ms (limit 250; goal median ≤ 120). Held room did not add any task. ## Not done `vim.spec.ts:387` (`:w` says Saved): not touched. It fails on dev too and I did not find a quick deterministic fix; left as is for #895.
Author
Owner

Correction to cause 1: #850 passes <PageTab {noteId} />; #851's StyleSheet.svelte rewrote that call as <PageTab /> (its PageTab takes no prop); #852 made PageTab require noteId for the Cover row and kept #851's call. So the missing prop is a #851/#852 interaction, fixed on #852 by f757dc1e.

Correction to cause 1: #850 passes `<PageTab {noteId} />`; #851's `StyleSheet.svelte` rewrote that call as `<PageTab />` (its PageTab takes no prop); #852 made `PageTab` require `noteId` for the Cover row and kept #851's call. So the missing prop is a #851/#852 interaction, fixed on #852 by `f757dc1e`.
Author
Owner

Content landed in dev via 12103f1c97 — closing.

Content landed in dev via 12103f1c973f1e810dd4a9a3bff5a705514d70b0 — closing.
kayg closed this pull request 2026-11-07 18:11:58 +00:00
Some checks failed
Markdown extraction contract / markdown-native-contract (pull_request) Has been cancelled
CI / server (pull_request) Has been cancelled
CI / rust (pull_request) Has been cancelled
CI / web (pull_request) Has been cancelled
Markdown extraction contract / markdown-editor-contract (pull_request) Has been cancelled

Pull request closed

Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
kayg/calternal!852
No description provided.