perf(web): port mockup frame fixes (instant motion, toast, store memo) #1044
Closed
kayg
wants to merge 4 commits from
perf/web-mockup-frame-fixes into dev
pull from: perf/web-mockup-frame-fixes
merge into: kayg:dev
kayg:main
kayg:feat/style-sheet-fixes
kayg:storage/wal-checkpoint-off-save-1051
kayg:t3/paged-search-reconcile-final
kayg:feat/pass8
kayg:review/calendar-2
kayg:fix/shared-row-swipes
kayg:feat/contrast
kayg:dev
kayg:feat/collections-db
kayg:fix/instant-keys-1056
kayg:feat/money-round
kayg:perf/stalls-1054
kayg:wip/tiering-v3-cold4
kayg:wip/tiering-v3-cold5
kayg:port/rows-actions
kayg:port/rows-drop
kayg:port/hidden-blocks
kayg:port/rows
kayg:port/port-tables
kayg:port/port-tables-2
kayg:t3/mail-1011-liveness
kayg:port/devices
kayg:port/port-attachments
kayg:port/port-attachments-2
kayg:port/port-attachments-3
kayg:docs/design-consistency
kayg:docs/engineering-standards
kayg:fix/rusqlite-0.41-rustsec-2026-0459
kayg:feat/iphone-fixes
kayg:shared/restore-and-stale-918-919
kayg:fix/phone-top-band-contrast
kayg:feat/notes-approve
kayg:perf/soak-max-gate
kayg:feat/files-s1-identity
kayg:fix/lifecycle-event-id
kayg:feat/quickfix
kayg:wip/tiering-v3-cold
kayg:port/contacts-merge
kayg:port/contacts-edit
kayg:test/shared-room-no-deleted-text
kayg:perf/first-paint-credits
kayg:fix/shared-history-after-grant
kayg:fix/phone-swipe-regressions
kayg:feat/contrast-r1
kayg:review/sharing-pr3-review
kayg:feat/tiering-v3-s2-tags
kayg:feat/folder-drop
kayg:fix/deskpills-lazy-share
kayg:feat/sharing-s1-pr3
kayg:tmp/money-round-before
kayg:fix/phone-pane-backdrop-roots
kayg:fix/palette-preload-chips
kayg:fix/invite-defaults
kayg:port/tasks-matrix
kayg:fix/restore-green-gates
kayg:fix/sharing-fast-path-hardening
kayg:t3/photos-s1
kayg:feat/tiering-v3-s1-namespace
kayg:notes-archive-hide
kayg:feat/tasks-actions
kayg:t3/photos-plan-slice-one
kayg:feat/whiteboard-s1
kayg:t3/paged-search-reconcile
kayg:t3/smooth-pane-transitions
kayg:t3/index-position-startup-scan
kayg:fix/private-staging-759b-r2
kayg:feat/dav-transport
kayg:feat/imap-notes-fetch
kayg:feat/imap-notes-projection
kayg:feat/imap-notes-readonly
kayg:feat/imap-notes-auth
kayg:feat/imap-notes-server-foundation
kayg:docs/undo-block-ids-plan
kayg:fix/undo-768
kayg:proto/block-identity-v7d
kayg:issue/carddav-read-perf-fix-r2
kayg:issue/carddav-read-r2
kayg:docs/imap-766-plan-v2
kayg:docs/imap-notes-plan
kayg:docs/quota-plan-2
kayg:fix/parallel-test-flakes
kayg:feat/contacts-companion-pure
kayg:docs/calendar-backend-v2-plan
kayg:feat/calendar-ical-converter
kayg:docs/tasks-writes-v2-plan
kayg:docs/carddav-writes-v2-plan
kayg:docs/contacts-import-v2-plan
kayg:issue/610-pm-midnight
kayg:feat/calendar-v2-s1-containment
kayg:docs/dav-recorder-v2-plan
kayg:plan/previews-865
kayg:plan/save-log-durable-entry
kayg:fix/e2e-data-on-ram
kayg:feat/appwindow3
kayg:feat/appwindow2
kayg:feat/appwindow
kayg:feat/money-p1
kayg:feat/keys-sheet
kayg:review/calendar-2-themes
kayg:feat/smooth-cursor
kayg:fix/float-style
kayg:review/calendar-2-float
kayg:release/2026-11-06-hotfix
kayg:archive/port/rows-drop-code
kayg:archive/port/rows-actions
kayg:archive/port/rows
kayg:scratch/tasks-894-ui-gates
kayg:review/calendar-2-night-wip
kayg:release/2026-11-05
kayg:archive/feat/tiering-v3-s1-namespace
kayg:archive/flaky/rows-drop-fixed
kayg:archive/flaky/rows-actions
kayg:archive/feat/tiering-v3-reader
kayg:archive/feat/tiering-v3-roots
kayg:archive/flaky/rows
kayg:sim/bm15-final
kayg:sim/bm15-fix
kayg:sim/bm15-bis-932
kayg:sim/bm15-bis-909
kayg:sim/bm15
kayg:sim/bm15-bis-887
kayg:perf/tiering-option-b
kayg:port/style-3
kayg:port/style-2
kayg:port/style
kayg:fix/sw-lazy-precache
kayg:fix/vim-w-waits-for-save
kayg:fix/signout-test-races
kayg:fp-scratch/all
kayg:sim/bm15-first-paint
kayg:archive/bm15/rows-drop
kayg:archive/bm15/rows-actions
kayg:fix/palette-snippet-contrast
kayg:archive/bm15/rows
kayg:archive/bm15/hidden
kayg:archive/plan/save-log-durable-entry
kayg:mock/money-fix2
kayg:archive/fix/e2e-data-on-ram
kayg:mock/appearance-all
kayg:mock/pill-press
kayg:archive/docs/design-consistency
kayg:mock/auto-swipes
kayg:mock/mail-actions
kayg:archive/feat/mail-p1
kayg:mock/money-static
kayg:archive/review/standards-917
kayg:archive/docs/engineering-standards
kayg:perf/tiering-761-fix
kayg:mock/type-audit
kayg:mock/third-pane
kayg:feat/contacts-import-v2-s1
kayg:perf/executor-hot-path
kayg:archive/port/hidden-blocks
kayg:archive/port/devices
kayg:scratch/executor-on-894
kayg:scratch/executor-spans2
kayg:scratch/executor-spans
kayg:train/2026-11-03-bm14c
kayg:archive/port/rows-drop
kayg:feat/tiering-761-d-scale
kayg:feat/tiering-761-c-index
kayg:feat/tiering-761-b-reader
kayg:archive/review/sharing-pr3-review-9fec3d1f
kayg:train/2026-11-03-bm14b
kayg:perf/ports-lazy-budgets
kayg:feat/tiering-761-a-migration
kayg:train/2026-11-03-bm14
kayg:train/2026-11-03-bm12
kayg:archive/review/sharing-pr3-review
kayg:archive/feat/sharing-s1-pr3
kayg:train/2026-11-03-bm11
kayg:archive/feat/imap-notes-fetch
kayg:train/2026-11-03-bm10
kayg:archive/review/sharing-pr3-review-code
kayg:archive/plan/previews-865
kayg:train/2026-11-02-bm9
kayg:archive/port/port-attachments-3
kayg:archive/port/contacts-merge
kayg:fix/motion-audit-859
kayg:train/2026-11-02-bm8
kayg:archive/scratch/bm8-prep
kayg:archive/port/port-pickers
kayg:archive/port/port-tables-2
kayg:archive/port/port-tables
kayg:archive/feat/sharing-s1-pr3-code
kayg:archive/scratch/bm7-fixed
kayg:train/2026-11-02-bm7
kayg:archive/fix/parallel-test-flakes-code-minipc01
kayg:train/2026-11-02-bm6
kayg:docs/imap-766-readonly-slice
kayg:feat/dav-recorder-v3
kayg:research/788-diagnosis
kayg:archive/fix/parallel-test-flakes
kayg:archive/perf/pr792-cold-index-edit
kayg:docs/sharing-slice-1
kayg:archive/docs/imap-766-plan-v2
kayg:feat/dav-recorder-v2
kayg:archive/docs/dav-recorder-v2-plan
kayg:spike/imap-766-s0-cases
kayg:archive/fix/undo-768
kayg:feat/dav-recorder
kayg:archive/docs/contacts-import-v2-plan
kayg:archive/feat/calendar-ical-converter
kayg:feat/contacts-import
kayg:perf/cold-growth-on-764
kayg:perf/cold-growth-on-tiering
kayg:archive/docs/tasks-writes-v2-plan
kayg:archive/docs/calendar-backend-v2-plan
kayg:archive/feat/contacts-companion-pure
kayg:feat/tasks-set-status
kayg:feat/tasks-move-reorder
kayg:archive/docs/carddav-writes-v2-plan
kayg:archive/feat/calendar-v2-s1-containment
kayg:feat/tasks-delete-promote-duplicate
kayg:archive/feat/dav-transport
kayg:archive/fix/carddav-rebuild-r1
kayg:archive/fix/carddav-retention-r1
kayg:feat/carddav-writes
kayg:perf/quota-on-tiering
kayg:perf/quota-simple
kayg:perf/cold-growth-on-quota-stack
kayg:feat/calendar-identity
kayg:feat/calendar-event-parser
kayg:feat/calendar-props-maps
kayg:port/glass-when-ring
kayg:feat/tiering-761-s1
kayg:wip/10by32-01-impl-759b-scratch-20261030
kayg:wip/6by32-01-bm3-webkit-pause-20261030
kayg:wip/10by32-01-bm3-chromium-pause-20261030
kayg:wip/6by32-01-tier-761-s1-pause-20261030
kayg:spike/imap-766-s0
kayg:wip/6by32-02-calternal-pause-20261030
kayg:wip/8by64-01-review-688-pause-20261030
kayg:wip/6by32-01-verify-744-pause-20261030
kayg:wip/6by32-01-verify-742-pause-20261030
kayg:fix/private-staging-759b
kayg:wip/6by32-01-review-748-pause-20261030
kayg:wip/6by32-01-review-733c-pause-20261030
kayg:wip/6by32-01-review-733b-pause-20261030
kayg:wip/6by32-01-perf-idle-8-pause-20261030
kayg:wip/6by32-01-perf767-base-pause-20261030
kayg:wip/6by32-01-perf767b-767-pause-20261030
kayg:wip/6by32-01-perf767b-764-pause-20261030
kayg:wip/6by32-01-perf767-767-pause-20261030
kayg:wip/6by32-01-perf767-764-pause-20261030
kayg:wip/6by32-01-lists-b-pause-20261030
kayg:wip/6by32-01-ids-verify5-pause-20261030
kayg:wip/6by32-01-ids-verify4-pause-20261030
kayg:review/calendar-month
kayg:wip/10by32-02-undo-768-20261030
kayg:test/ids-verify3
kayg:wip/10by32-02-bm3-chromium-20261030
kayg:wip/10by32-01-review-753-20261030
kayg:wip/10by32-01-perf-idle-2-20261030
kayg:wip/10by32-01-bm2-webkit2-20261030
kayg:plan/759b-staging
kayg:train/2026-10-30-bm2
kayg:review/758b-tests
kayg:review/758-tests
kayg:review/764d-tests
kayg:review/767b-tests
kayg:review/preview-2026-10-29
kayg:review/767-tests
kayg:docs/tiering-731-plan
kayg:wip/c6b02-when2
kayg:wip/c6b02-tasks-create-fix5
kayg:wip/c6b02-settings-frost-mock
kayg:wip/c6b02-settings-frost-base
kayg:wip/c6b02-settings-frost
kayg:wip/c6b02-ring
kayg:wip/c6b02-review-733d
kayg:wip/c6b02-bm1-full-a
kayg:wip/compute02-when-field
kayg:wip/compute02-webkit-lists-repro
kayg:wip/compute02-train-bl2-dev
kayg:wip/compute02-dev-green-pw164
kayg:docs/deploy-plan
kayg:review/764c-tests
kayg:review/764b-tests
kayg:review/748g-tests
kayg:review/764-tests
kayg:review/759b-tests
kayg:fix/storage-owner-liveness-642
kayg:fix/storage-fix-7
kayg:wip/compute02-storage-fix-7
kayg:review/759-tests
kayg:feat/tiering-731
kayg:wip/tiering-731-first-attempt
kayg:wip/compute02-storage-fix-1
kayg:review/754g-tests
kayg:perf/idle-honest-2
kayg:review/754f-tests
kayg:review/754e-tests
kayg:review/755-tests
kayg:review/754d-tests
kayg:review/754c-tests
kayg:review/754b-tests
kayg:review/754-tests
kayg:fix/storage-private-tmp-642-dev
kayg:wip/compute02-verify-750
kayg:test/ids-verify5
kayg:test/ids-verify4
kayg:fix/storage-exact-file-quarantine-642
kayg:wip/compute02-verify-740
kayg:perf/one-flush-save
kayg:review/calendar-static
kayg:wip/compute02-verify-737
kayg:review/indexing-ring
kayg:review/when-field-2
kayg:wip/compute02-review-733
kayg:proto/block-identity-2-review
kayg:proto/block-identity-review
kayg:wip/c6b02-tc-design
kayg:review/when-field
kayg:issue/tasks-create-ids
kayg:issue/tasks-create
kayg:review/combined
kayg:wip/compute02-review-combined
kayg:review/task-polish
kayg:review/top-buttons
kayg:review/q1-q5
kayg:train/2026-10-26-bl2
kayg:archive/wt-398h
kayg:archive/train-bm-proptest-seed
kayg:archive/integ325-293
kayg:archive/integ325-ci
kayg:archive/client-auth-review-baseline
kayg:archive/wt-sim-4853
kayg:archive/wt-sim-4811
kayg:archive/wt-448m
kayg:archive/wt-398a-allocator
kayg:issue/calendar-adr
kayg:archive/old/train/2026-10-23bk2
kayg:archive/old/train/2026-10-23bk
kayg:issue/469-mockup-9a
kayg:issue/smart-tasks-mockup
kayg:issue/469-menus
kayg:issue/652-signout-flake
kayg:issue/652-history-fix7
kayg:issue/652-history-fix6
kayg:archive/old/issue/spring-check-perf
kayg:issue/spring-check-perf
kayg:issue/659-rename-fast
kayg:archive/old/train/2026-10-21ar
kayg:issue/search-hardening-3
kayg:issue/652-history-fix5
kayg:issue/660-port-sheets-glass
kayg:issue/652-history-fix4
kayg:issue/652-history-fix3
kayg:issue/652-history-fix2
kayg:issue/652-history-flake
kayg:train/2026-10-21an
kayg:issue/settings-admin-port
kayg:issue/search-port
kayg:train/2026-10-20am
kayg:issue/storage-split-fix2
kayg:issue/storage-split
kayg:archive/old/issue/folder-ids-fix
kayg:train/2026-10-20al
kayg:archive/old/issue/folder-ids
kayg:train/2026-10-20ak
kayg:issue/tables-mockup
kayg:train/2026-10-19aj
kayg:train/2026-10-19ai
kayg:issue/469-merge-fixes
kayg:issue/sidebar-band
kayg:archive/old/issue/608-settings-spec
kayg:train/2026-10-19ah
kayg:issue/swipe-offscreen
kayg:train/2026-10-19ag
kayg:archive/old/issue/590-nlp-adr
kayg:archive/old/issue/587-event-after-write-2
kayg:train/2026-10-19af
kayg:archive/old/issue/587-event-after-write
kayg:issue/469-pill-room-c
kayg:issue/469-pill-room
kayg:train/2026-10-19ae
kayg:issue/469-narrow-handle
kayg:issue/397-ios-swipe-2
kayg:archive/old/issue/adrs-photos-files-tasks
kayg:issue/469-desk-fixes
kayg:archive/old/issue/auto-update-adr
kayg:issue/469-filter-gap
kayg:issue/469-port-1b
kayg:issue/442-opacity-flake
kayg:archive/397-ios-swipe-2
kayg:issue/327-web-fast-3
kayg:archive/old/issue/469-port-1
kayg:issue/469-port-1
kayg:issue/327-web-fast-2
kayg:archive/old/issue/327-web-fast
kayg:archive/old/issue/425-stt-bench-vq1
kayg:archive/old/issue/445-no-bleed
kayg:archive/old/issue/400-swipe-mockup-2
kayg:issue/426-client-review
kayg:issue/426-client-2
kayg:issue/426-client
kayg:archive/old/issue/476-safe-area-lab
kayg:archive/445-top-light-2
kayg:archive/old/issue/445-top-light
kayg:issue/471-blocks-mockup
kayg:archive/old/issue/448-links-app-2
kayg:archive/old/issue/448-links-app
kayg:archive/old/issue/398-cold-links
kayg:issue/434-442-small-2
kayg:issue/434-442-small
kayg:archive/old/issue/398-unload
kayg:archive/old/issue/445-bottom-band
kayg:issue/445-bottom-band
kayg:issue/351-rem-3
kayg:archive/312-views-mockup
kayg:issue/351-rem-2
kayg:issue/351-rem
kayg:archive/old/issue/327-first-note
kayg:issue/395-width-phone
kayg:archive/old/issue/327-typing
kayg:issue/396-ios-edges
kayg:issue/397-ios-swipe
kayg:archive/398-allocator
kayg:archive/old/issue/327-notes-index
kayg:issue/345-347-contrast-empty-2
kayg:archive/old/issue/44-arenas
kayg:issue/44-arenas
kayg:archive/integ325
kayg:archive/old/issue/327-perf-harness
kayg:archive/old/issue/44-thp
kayg:issue/44-thp
kayg:archive/old/issue/285-sticky-pills
kayg:archive/old/issue/44-trim-3
kayg:issue/44-trim-3
kayg:archive/old/issue/165-cards
kayg:archive/old/issue/165-picker-2
kayg:archive/old/issue/212-multi-select
No reviewers
Labels
Milestone
Clear milestone
No items
No milestone
Projects
Clear projects
No items
No project
Assignees
Clear assignees
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!1044
Loading…
Reference in a new issue
No description provided.
Delete branch "perf/web-mockup-frame-fixes"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Ports the four frame fixes found in the mockup on 11-09 (#1031 comment 88902, #1030) into the real app (
apps/web+packages/ui). One commit per item (item 2 dropped after measuring); basedev0878cb550.1. Keyboard motion switch per element (
data-instant)packages/ui/src/styles/base.css: the rule:root[data-last-input="keyboard"] * { transition-duration: 0s }is gone. It restyled every element on each flip of the root attribute (a key after a click, a click after a key), in the frame of the next press. Its replacement answers one element at a time:[data-instant], [data-instant]::before, [data-instant]::after.inputSource.svelte.ts: newinstant()(true after a key, elseundefined, so Svelte drops the attribute).input.laststill drives script animations, and the root attributes stay for rules that name their own elements and for focus rings.data-instant={instant()}: Morph (capsule, halo, glass, clip), Pill, ContextMenu menus, Selector, SquishSwitch, and ToastCapsule (slot, inner).apps/web/src/components/Shell.svelte: Shell already had its own scoped.instantswitch (rules that name its panes, frame, bar and editor column), but only Focus set it. The places toggle (Ctrl+\) now sets it too, and it covers the resizers. These were the only twokeys-no-motionfailures once the global rule went (in both Chromium and WebKit).e2e/keys-no-motion.spec.ts: every "a key moves nothing" test stays as it was. Two guards are added:data-last-input/data-input(*,*::before,> *);data-instant) and an explicit list of rules that name their own elements ([data-contact], [data-side], .list .press, .shade).2. Frosted backdrop layer: dropped
Ported, measured in real Safari with frost on, and dropped: no win in
apps/web(see the evidence comment). The mockup keeps its GlobalLayer fix.3. ToastCapsule: transform-only spring, size from the ResizeObserver entry
The glass sits at its final size and only scales (
scale(sx, sy)from the same springs; the transform is removed at rest). Its size comes fromentry.borderBoxSize, neveroffsetWidth/offsetHeight. A resize redraws the old size as a scale inside the observer callback (after layout, before paint), so no frame shows it already settled. That frame is why the old$effectre-measured. The dot is the capsule scaled to 12 px tall (uniform scale keeps the corners round), as in the mockup.apps/web/src/components/bar/Toast.sveltesets no glass size and needed nothing.4. Store: one note change wakes only the lists it is in
NotesIndexkeeps a member set per list (journal,pinned, each tag and each parent tag;eachKey(note, fn)walks them without allocating) and records the lists each change touched. An edit that keeps kind, pin and tags only records; nothing moves between sets.notes.svelte.tskeeps one$stateversion per list and remembers each list's array until its own version moves:store.notesis the same array until a note changes;listNotes('tag:x'),pinnedand the Journal read their member sets (O(m log m)), not a filter over every note;#tagreader does not re-run when a note outside it is edited.tagCounts) are the sets' sizes (O(tags)), no longer a walk over every note.eachKeywalk per note, no allocation.src/lib/notes-index.test.ts: one edit touches the same 4 lists in a Home of 200 and of 20,000 notes. Retag, pin, day-note and delete touch exactly what they should. After churn, the sets give the same Journal, Pinned, tag lists and counts as the old full scans.Note: dev's
store.noteswas already cached per change tick (unlike the mockup's[...map.values()]). The real cost was the single global tick plus the per-list full filters, and that is what this item removes.Decisions (made, not asked)
Evidence (real Safari ABAB, specs, unit tests, bundle gate) follows as comments.
🤖 Generated with Claude Code
perf(web): port mockup frame fixes (instant motion, backdrop layer, toast, store memo)to perf(web): port mockup frame fixes (instant motion, toast, store memo)Evidence (head
b4fca844a; measured arms below)Item 2 (backdrop compositor layer) is DROPPED from this PR. In the real app it is not a win. With the account's frost on (checked in every run:
.backdropfilter: blur(24px); thefrostedclass and transform appear only on the arm that has the commit), real Safari, 10 rounds each:a66799a04)adb4b989c)Both comparisons point the wrong way. The VM was noisy, so this does not prove a regression, but the no-regression rule rules the change out. My guess at the cause: in
apps/webthe frosted.backdropalready hascontain: strictand its own stacking, unlike the mockup's GlobalLayer; promoting it only adds a full-screen layer. The mockup fix stays in the mockup.Real Safari 26.5.2, Mac VM (macos-01), ABAB, fresh page load each run. A = dev
0878cb550, B = PR (a57596b5e: the three items here plus item 2, with frost off, i.e. item 2 inactive)Servers on dev-01 (same binary for every arm, built from dev's crates), reached over a loopback forwarder. Each Home has 2,000 notes in 20 tags. 1440×948 (S3 at 390×844). The idle baseline (same session, 900 ms) is max 19 ms in every arm.
notes.append)"Blocked" is a MessageChannel ping probe: it sums gaps over 2 ms. Edits reached the page: All showed the edited note on top 32/40 (dev) and 33/40 (PR). The rest is my check's prefix match, not missed edits.
Mac condition: free pages were low at times (8–57 k pages of 16 KB, no swap). That's under the 2 GB rule, and it explains the shared outlier rounds. Every arm ran interleaved in the same session.
Mac gotcha found: a long-running Safari on the VM could not open IndexedDB ("UnknownError: Unable to open database file on disk"), so the app stayed on the setup screen (
claimDevicethrows insidecheckAuth().catch(()=>{})). Quitting Safari before each run fixes it.Specs, dev-01,
--workers=1, against dev0878cb550(same binary)preload, lazy-ui, lazy-offline, glass, glass-roots, shortcuts, keys-no-motion, list-catch-up, list-chrome, list-fit, list-search, sidebar-edge, note-bars, note-bars-motion, note-pills, toast-bar, tags, sheet-pinned, journal-trash:
a57596b5e)0 failures on either side. After the shell fix, keys-no-motion passes in both engines. Before it,
Ctrl+\andCtrl+.moved Shell's grid, panes and resizers. The specs ran ona57596b5e; the head only drops the item-2 Backdrop CSS. backdrop-page (look-* projects) was not run.Unit tests and checks (dev-01)
vitest run, web: the newnotes-index.test.tspasses 5/5. The rest of the suite: 207 passed at the first run.vitest run, ui: 96/96.svelte-check --threshold error: 0 errors, same 17 warnings as dev.Bundle gate (
perf/web.sh --bundle-only --gate): first paint ≤ dev NOT met0878cb550a57596b5eDev itself is already over its
chunk.indexbudget line (223.2). Dropping item 2 removes about 21 B raw. Per module (from source maps):I already compacted the store (one keyed member map, no per-note allocation, the Journal and tag counts from the sets). What remains is the fixes' own code. The only levers left are lazy-loading other features' first-paint code:
trash.svelte.ts,RowActions,backdrop-art: each changes some first-screen behaviour;soft-picture: baked synchronously on a phone's first screen;Toasts: eager on purpose.I did not do that in this PR. #1022 frees 1.6 KB of first paint precisely "so the ports have room". With it merged, this PR is under dev's current first paint.
Rebased on dev
7c50123c3(after #1022): head79f755ecdTrims inside this PR's own code
instant()is now a one-liner:input.last === "keyboard" || undefined.list-search.ts: themembersOfcache was already unused on dev and is removed. The search corpus is keyed onlistNotes(scope), which is now one memoized array per list, so a #tag search no longer rebuilds its corpus when a note outside the tag changes. That code lives in the lazyListSearchchunk: −0.022 KB.data-instantper component (Morph 4 → 1, ToastCapsule 2 → 1). This would move bytes from JS into scoped CSS rules naming the same parts, for roughly zero net.instant =assignments. They stay: a pointer toggle has to reset the switch.Bundle gate (
perf/web.sh --bundle-only, dev-01, same session):7c50123c379f755ecdThe raw growth is the same as before (+1.0 KB). What fell from +0.58 to +0.10 is how it compresses next to #1022's new layout. For scale, chunks this PR does not touch (
vim,code-rust,WhenField) move by ±0.04 KB between the two builds.Budget lines, regenerated: every measured line is within its
perf/budgets.jsonline for both builds;chunk.indexis 222.607 against 222.71. The chunk lines still sum to the 525.01 total. Following the "index follows the measured size" convention changes no line, sobudgets.jsonis untouched.Cross-cutting specs on all four projects at this head: results follow (queued behind today's train on dev-01).
Cross-cutting specs at head
79f755ecd(dev-01, server built from dev7c50123c3's crates,--workers=1)preload, lazy-ui, lazy-offline, glass, keys-no-motion:
No Mac turn: since the last real-Safari run, the code changes are
instant()returning the same values in one line and the lazy ListSearch corpus key. Neither changes what runs in a frame.kayg OK'd the +0.1 KB first paint (11-10). Merged into dev; closing.
Pull request closed