App: phone/desktop list chrome from the approved mockup (slice 1) #522

Closed
kayg wants to merge 0 commits from issue/469-port-1b into dev
Owner

Refs #469, closes #511. Replaces #516, rebased onto train v (dev + #518 web speed + #519, with #513 links and #520). Slice 1 of bringing the approved chrome mockup (issue/469-chrome-mockup-3) into the app. Not merged; waits for kayg.

Ported

  • Lists (Journal, All notes, tags, Pinned, Trash; phone and desktop): group headings are H2s in the title's face, sentence case; no "Today" pill in the list rows or the note header; list/gallery as a springy morph (morphLayout), glass gallery cards (the shared dense step, no blur per card). The gallery keeps windowing: a band of two cards is one windowed row.
  • Phone: large title placed lower with the count as a subtitle; headings share the title's left edge, rows are indented 16 pt.
  • Phone top chrome (apps/web/src/chrome/): floating glass pills (back; header pill that fades in when the title scrolls away; ⋯ and, when a page registers one, Share in one grouped pill with no divider), icon sizes from the mockup (glyph.ts), a short progressive blur (packages/ui/src/chrome/ProgressiveBlur.svelte) that is display: none until content is under it. What ⋯ holds comes from a page-actions registry (pages.ts, plugins/), what the header says from a header-source registry (header/).
  • Glass and look: float tint 0.30 / 0.36, blur 20, sat 180 (already the shared values); dense step 0.48 (the mockup is finalising it); look v2 ink, paper, shadows and radii as tokens; line height 1.6 and body 17 px kept (not v2's dense scale).
  • Text: #506's font change is already in dev, so this branch carries none of it.
  • "+" raises the keyboard inside the tap (hidden-field hand-over), then the editor puts the caret in the title. Verified on the iPhone simulator.

Decisions to look at

  • Share is not drawn yet: sharing is out of scope, and no fake buttons. The pill is the round ⋯ alone until a page calls registerPageShare; the grouped styling is in place.
  • Pills are on the list screens and the Trash only. A note keeps its band and back button; the note's header pill needs the heading tracker for the editor's own DOM, which is a later slice. Places has no pills yet.
  • Light panels keep their old tint: v2's lighter-ink, more see-through panel failed the contrast spec (4.5:1 on dawn/day) so only v2's inks, paper, shadows and radii are taken in light. Dark panels take v2's.
  • Dark dim 30% -> 42%: on v2's nearly black paper a 30% dim was not a different colour (phone-edges needs ΔE > 2).
  • The header pill fades through its glass layer and words, not an opacity on the pill (an opacity around glass failed glass.spec's backdrop-root check).

Rebase notes

Kept all of dev's behaviour: the links plugin (noteLinks with follow and relink), the stale-list guard, the notes index (byDay, newestFirst) and windowing. list-window.ts gained an optional per (notes per row, default 1) so a gallery band of two cards is one windowed row; Row has ns beside n. "No Today pill" removes only the pill's UI (row and note heading); isToday stays exported. Nothing from #521 (phone document scrolling) is taken.

Tests (all with --no-deps --workers=1 through build-slot.sh, on this branch with a server built from it)

  • list-chrome (new), links, missing-links, phone-bars, phone-edges, touch-select, switching: chromium-390 + chromium-1440 454 passed, webkit-390 + webkit-1440 454 passed, 0 failed. contrast: 4 passed.
  • bun run check: 0 errors, the same 12 warnings.
  • Web harness at 100k (Chromium, 4x CPU, train v vs this branch, 2 interleaved rounds, busy host): cold TBT p50 2292 / 1842 ms vs 1287 / 2067 ms, cold time to first note 3078 / 3470 vs 3369 / 4013 ms, All notes scroll frame p50 217 / 167 vs 158 / 150 ms. #518's gains hold; the numbers are on #511.

Screenshots and the perf table are on #511.

🤖 Generated with Claude Code

https://claude.ai/code/session_019QGa6qjALuHyi8H1naGp6b

Refs #469, closes #511. Replaces #516, rebased onto train v (dev + #518 web speed + #519, with #513 links and #520). Slice 1 of bringing the approved chrome mockup (`issue/469-chrome-mockup-3`) into the app. Not merged; waits for kayg. ## Ported - **Lists** (Journal, All notes, tags, Pinned, Trash; phone and desktop): group headings are H2s in the title's face, sentence case; no "Today" pill in the list rows or the note header; list/gallery as a springy morph (`morphLayout`), glass gallery cards (the shared dense step, no blur per card). The gallery keeps windowing: a band of two cards is one windowed row. - **Phone**: large title placed lower with the count as a subtitle; headings share the title's left edge, rows are indented 16 pt. - **Phone top chrome** (`apps/web/src/chrome/`): floating glass pills (back; header pill that fades in when the title scrolls away; ⋯ and, when a page registers one, Share in one grouped pill with no divider), icon sizes from the mockup (`glyph.ts`), a short progressive blur (`packages/ui/src/chrome/ProgressiveBlur.svelte`) that is `display: none` until content is under it. What ⋯ holds comes from a page-actions registry (`pages.ts`, `plugins/`), what the header says from a header-source registry (`header/`). - **Glass and look**: float tint 0.30 / 0.36, blur 20, sat 180 (already the shared values); dense step 0.48 (the mockup is finalising it); look v2 ink, paper, shadows and radii as tokens; line height 1.6 and body 17 px kept (not v2's dense scale). - **Text**: #506's font change is already in dev, so this branch carries none of it. - **"+"** raises the keyboard inside the tap (hidden-field hand-over), then the editor puts the caret in the title. Verified on the iPhone simulator. ## Decisions to look at - **Share is not drawn yet**: sharing is out of scope, and no fake buttons. The pill is the round ⋯ alone until a page calls `registerPageShare`; the grouped styling is in place. - **Pills are on the list screens and the Trash only.** A note keeps its band and back button; the note's header pill needs the heading tracker for the editor's own DOM, which is a later slice. Places has no pills yet. - **Light panels keep their old tint**: v2's lighter-ink, more see-through panel failed the contrast spec (4.5:1 on dawn/day) so only v2's inks, paper, shadows and radii are taken in light. Dark panels take v2's. - **Dark dim 30% -> 42%**: on v2's nearly black paper a 30% dim was not a different colour (phone-edges needs ΔE > 2). - The header pill fades through its glass layer and words, not an opacity on the pill (an opacity around glass failed glass.spec's backdrop-root check). ## Rebase notes Kept all of dev's behaviour: the links plugin (`noteLinks` with `follow` and `relink`), the stale-list guard, the notes index (`byDay`, `newestFirst`) and windowing. `list-window.ts` gained an optional `per` (notes per row, default 1) so a gallery band of two cards is one windowed row; `Row` has `ns` beside `n`. "No Today pill" removes only the pill's UI (row and note heading); `isToday` stays exported. Nothing from #521 (phone document scrolling) is taken. ## Tests (all with --no-deps --workers=1 through build-slot.sh, on this branch with a server built from it) - `list-chrome` (new), `links`, `missing-links`, `phone-bars`, `phone-edges`, `touch-select`, `switching`: chromium-390 + chromium-1440 454 passed, webkit-390 + webkit-1440 454 passed, 0 failed. `contrast`: 4 passed. - `bun run check`: 0 errors, the same 12 warnings. - Web harness at 100k (Chromium, 4x CPU, train v vs this branch, 2 interleaved rounds, busy host): cold TBT p50 2292 / 1842 ms vs 1287 / 2067 ms, cold time to first note 3078 / 3470 vs 3369 / 4013 ms, All notes scroll frame p50 217 / 167 vs 158 / 150 ms. #518's gains hold; the numbers are on #511. Screenshots and the perf table are on #511. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_019QGa6qjALuHyi8H1naGp6b
kayg added 23 commits 2026-10-17 06:17:35 +00:00
perf/web.sh measures the built app as production serves it on 10k and 100k
fixture Homes, Chromium (CPU 4x) and WebKit: bundle sizes, boot (TBT as
web.dev defines it, every long task, first paint, time to interactive),
keystroke to paint, the blaze test (#271), scrolling, memory, layout shift
and main-thread CPU. web.* budgets in perf/budgets.json; CI gates the
bundle sizes. docs/perf/web.md.

Replaces #360.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Yyy8fQGxPLkLa8v8NXz7T
- frontmatterEnd walks lines without copying and remembers per document.
- The note metadata keeps `base` under its own key, written only when it
  changed (older records still read).
- A preview whose text matches the live document swaps its binding in
  place (a compartment) instead of building and parsing a new state.
- Clouds worked out in slices (lib/slices.ts), date labels morph only once
  tapped, the offline merge code loads only when a merge runs.

Replaces #402 and part of #454.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Yyy8fQGxPLkLa8v8NXz7T
- lib/notes-index.ts: notes newest first by binary search, tag counts,
  file to id, the Journal's order; views are told once per batch.
- groups() slices ordered lists by binary search; NoteList works out its
  visible rows from group sizes (lib/list-window.ts). Nothing walks every
  note on the main thread.
- The background fill (#422, pages of 2000) is fetched and parsed in a
  worker (lib/notes-fill.worker.ts) and handed over 250 notes at a time;
  without a worker, pages of 500 the plain way.
- The first note's text comes over plain HTTP (notes.peek) when nothing is
  remembered, instead of waiting for its room; peeks come 12 at a time.
- Typing: properties re-read only when an edit reaches them, the bar's
  block list replaced only when it held something.
- Theme colour once per frame; the Settings bar builds at the next idle.

Replaces #394, #407 and the rest of #454.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Yyy8fQGxPLkLa8v8NXz7T
Fill pages are fetched by a worker now, whose requests the page doesn't
always see: the app marks html[data-listed] when the whole list is in, and
the harness waits for it (builds without the fill worker: request silence).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Yyy8fQGxPLkLa8v8NXz7T
Test stale note lists deterministically
Some checks failed
CI / server (pull_request) Successful in 26s
CI / rust (pull_request) Failing after 2m4s
CI / web (pull_request) Failing after 47s
3c2c2bc040
Fix web speed train regressions
Some checks failed
CI / server (pull_request) Successful in 26s
CI / rust (pull_request) Failing after 1m53s
CI / web (pull_request) Failing after 34s
f20c348e29
fix notes delete link state visibility
Some checks failed
CI / server (pull_request) Successful in 36s
CI / rust (pull_request) Successful in 2m50s
CI / web (pull_request) Failing after 53m48s
7db5ab0533
Merge remote-tracking branch 'origin/issue/448-missing-flake' into train/2026-10-17v
Some checks failed
CI / server (pull_request) Successful in 30s
CI / rust (pull_request) Successful in 2m24s
CI / web (pull_request) Failing after 23s
a920947d38
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019QGa6qjALuHyi8H1naGp6b
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019QGa6qjALuHyi8H1naGp6b
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019QGa6qjALuHyi8H1naGp6b
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019QGa6qjALuHyi8H1naGp6b
Test: the contrast measurement sees the glass under the + button, not the button (#469, #511)
Some checks failed
CI / server (pull_request) Successful in 31s
CI / rust (pull_request) Successful in 2m29s
CI / web (pull_request) Failing after 23s
77aaaa0f34
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019QGa6qjALuHyi8H1naGp6b
Author
Owner

Landed in train w2, #532.

Landed in train w2, #532.
kayg closed this pull request 2026-10-17 12:57:44 +00:00
Some checks failed
CI / server (pull_request) Successful in 31s
CI / rust (pull_request) Successful in 2m29s
CI / web (pull_request) Failing after 23s

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!522
No description provided.