Notes TOC rail: ticks stick to the sidebar edge, no inline heading fragments #1113

Open
opened 2026-10-05 07:39:27 +00:00 by kayg · 10 comments
Owner

Owner report (2026-10-05, production)

"What are these? If these are the steppers we talked about for the table of contents, I thought we talked about them sticking to the sidebar instead of whatever abomination this is."

Today (production): the TOC rail for Notes renders inside the note text area, and each tick shows a clipped fragment of its heading text next to it ("— 5…", "— t…", "— W…"), cut by the card edge.

Owner decision (supersedes the placement in #636): the ticks attach to the sidebar edge: a quiet column of ticks sits in the gutter along the sidebar's right edge (or the window's left edge when the sidebar is collapsed), sticky while the note scrolls. Ticks only: no text beside them. The heading title appears only in the glass hover pill (with Copy link to heading). Everything else from #636 stays: tick length by level, active section longer and brighter, click scrolls with the shared spring, keyboard navigation landmark with arrow keys, hidden under 3 headings, phones use "Contents" in the ⋯ menu.

## Owner report (2026-10-05, production) "What are these? If these are the steppers we talked about for the table of contents, I thought we talked about them sticking to the sidebar instead of whatever abomination this is." Today (production): the TOC rail for Notes renders inside the note text area, and each tick shows a clipped fragment of its heading text next to it ("— 5…", "— t…", "— W…"), cut by the card edge. **Owner decision (supersedes the placement in #636):** the ticks attach to the **sidebar edge**: a quiet column of ticks sits in the gutter along the sidebar's right edge (or the window's left edge when the sidebar is collapsed), **sticky** while the note scrolls. Ticks only: no text beside them. The heading title appears only in the glass hover pill (with Copy link to heading). Everything else from #636 stays: tick length by level, active section longer and brighter, click scrolls with the shared spring, keyboard navigation landmark with arrow keys, hidden under 3 headings, phones use "Contents" in the ⋯ menu.
Author
Owner

Starting #1113 on branch job/editorrail-1113, based on 27644444a91dad244073113b0ec8ec7a61f2a212 (dev). I’m tracing the current Notes rail and editor card geometry before moving the rail to the sidebar edge. I’ll keep #1113 and #1114 fixes in separate commits.

Starting #1113 on branch `job/editorrail-1113`, based on `27644444a91dad244073113b0ec8ec7a61f2a212` (`dev`). I’m tracing the current Notes rail and editor card geometry before moving the rail to the sidebar edge. I’ll keep #1113 and #1114 fixes in separate commits.
Author
Owner

Continuing #1113 and #1114 in job/editorrail-1113 at d9d283a341a85b74febdfe3bc857eaf9f13b7874. The branch includes the earlier fixes and the merge from origin/dev at 4a8e22609e51f53b037d1296dc757e8f0e2b833a; current origin/dev is 98584d6f78510a4c72b2d2b9193c46581db04742. I am checking the web/editor gates and production screenshots before reporting readiness.

Continuing #1113 and #1114 in `job/editorrail-1113` at `d9d283a341a85b74febdfe3bc857eaf9f13b7874`. The branch includes the earlier fixes and the merge from `origin/dev` at `4a8e22609e51f53b037d1296dc757e8f0e2b833a`; current `origin/dev` is `98584d6f78510a4c72b2d2b9193c46581db04742`. I am checking the web/editor gates and production screenshots before reporting readiness.
Author
Owner

Follow-up verification finding: after refreshing the exact source fingerprints in contracts/perf/exceptions.json, bun run check reports perf-lint: INVALID: adoption checkpoint differs from its exact live ledger entry. The #1058 checkpoint stores the same accepted entries and hashes. I will update only matching checkpoint hashes for the unchanged rules and limits, then rerun the gate.

Follow-up verification finding: after refreshing the exact source fingerprints in `contracts/perf/exceptions.json`, `bun run check` reports `perf-lint: INVALID: adoption checkpoint differs from its exact live ledger entry`. The #1058 checkpoint stores the same accepted entries and hashes. I will update only matching checkpoint hashes for the unchanged rules and limits, then rerun the gate.
Author
Owner

The web fingerprint audit found 180 more exact hash-only mismatches in four Svelte files already identical to origin/dev: apps/web/src/routes/calendar/[view]/[date]/+page.svelte, apps/web/src/routes/settings/[...path]/+page.svelte, packages/ui/src/components/OverlaySurface.svelte and packages/ui/src/components/calendar/ItemPreview.svelte. Every current finding still has its recorded limit; the web-only audit found no unmatched scopes. I am refreshing these live hashes and their matching #1058 checkpoint entries so the requested bun run check can run on the merged tree.

The web fingerprint audit found 180 more exact hash-only mismatches in four Svelte files already identical to `origin/dev`: `apps/web/src/routes/calendar/[view]/[date]/+page.svelte`, `apps/web/src/routes/settings/[...path]/+page.svelte`, `packages/ui/src/components/OverlaySurface.svelte` and `packages/ui/src/components/calendar/ItemPreview.svelte`. Every current finding still has its recorded limit; the web-only audit found no unmatched scopes. I am refreshing these live hashes and their matching #1058 checkpoint entries so the requested `bun run check` can run on the merged tree.
Author
Owner

The next bun run check failure is io.unresolved-call in crates/plugins/notes/src/tasks_api.rs at by_day:by_day:040ccd4176238084. The Rust source is unchanged between the merge base and current origin/dev; the stored scope fingerprint is stale in the merged ledger. I am auditing exact Rust findings before deciding whether the same hash-only repair applies.

The next `bun run check` failure is `io.unresolved-call` in `crates/plugins/notes/src/tasks_api.rs` at `by_day:by_day:040ccd4176238084`. The Rust source is unchanged between the merge base and current `origin/dev`; the stored scope fingerprint is stale in the merged ledger. I am auditing exact Rust findings before deciding whether the same hash-only repair applies.
Author
Owner

Completed #1113 and #1114 on job/editorrail-1113.

Head: 77299c5c99cea0a2f795776816ca7fb6f3833cd1b.

Built

  • The Note contents rail stays fixed to the sidebar edge while #route-content scrolls. Clicking a heading reveals it through the shell scroller.
  • The hover title and Copy link Pill stays inside the Note card. Its pointer bridge begins after the tick target. The shared warm tooltip token now uses a 94% surface fill, with a solid surface under reduced transparency.
  • The block action capsule now has a focused production E2E capture and geometry assertion at all required widths.

Files

apps/web/src/lib/notes/NoteContents.svelte, apps/web/src/lib/notes/anchors.ts, packages/ui/src/tokens.css, apps/web/e2e/tocrail-636.mjs, apps/web/e2e/notes.mjs, contracts/perf/exceptions.json.

UX gaps closed

  • Heading ticks have no inline fragments and stay at the sidebar edge at the top, middle and bottom of the Note.
  • The heading preview clears its own tick trigger, shows the selected title and Copy link, and stays in the Note card.
  • The same rail placement is captured with the sidebar collapsed. The phone Note and contents sheet are also included.
  • The block action capsule is checked at 390, 820 and 1440 px in both review palettes.

UX gaps left

  • The broader NOTES_E2E_SERIES_ONLY run stopped before the block action flow at the existing #632 section Card gap assertion: -9px. The dedicated #1114 production capture passed.
  • bun run check stops in perf-lint on an unrelated stale NotesExplorer.svelte exception fingerprint. Standalone svelte-check passed with four CSS warnings in other files.

Decisions

  • Anchor reveal uses #route-content when the shell provides it and keeps the Window fallback for other hosts.
  • The Note card offset is computed with CSS tokens and viewport/card width constraints. No runtime layout measurement was added.
  • The shared tooltip fill uses a 94% --surface mix because the existing tooltip token had no root declaration and the review needs Note text behind the Pill to stay legible.

Gates and evidence

bun run check:

$ ../../scripts/perf-lint --check && node scripts/check-user-storage.mjs && node scripts/check-glass-tokens.mjs && node scripts/check-type-tokens.mjs && node scripts/check-focus-tokens.mjs && node scripts/check-motion-tokens.mjs && svelte-kit sync && svelte-check --tsconfig ./tsconfig.json
perf-lint: parse Rust product sources
perf-lint: parse browser product sources
perf-lint: validate coverage and architecture
perf-lint: INVALID: ('render.bound', 'apps/web/src/lib/notes/NotesExplorer.svelte', 'apps/web/src/lib/notes/NotesExplorer.svelte#each:3c7baf2164751d7e:1'): unused or changed exception

Standalone Svelte check:

svelte-check found 0 errors and 4 warnings in 3 files

Focused anchors Vitest:

 Test Files  1 passed (1)
      Tests  6 passed (6)
   Start at  12:18:53
   Duration  51.18s (transform 75%, environment 10%, import 10%, tests 4%, setup 2%)

Editor tests:

 Test Files  21 passed (21)
      Tests  434 passed (434)
   Start at  11:09:35
   Duration  46.37s (transform 6.70s, setup 801ms, import 18.98s, tests 21.41s, environment 41.25s)

Glass token check:

Glass alpha, blur and backdrop-filter roles use packages/ui/src/tokens.css.

TOC production E2E:

tocrail-636/1113 e2e: six headings, sidebar-edge ticks, active section, hover Copy link, arrow keys, phone sheet and two-heading threshold passed

Block action production E2E:

notes #1114 block-action edge e2e: 1440, 820 and 390 px in Mono/Noir passed
CSP REPORTS notes: 0 across 1 pages

Rust gates were not run because this change touches no Rust crate. cargo clean removed 8627 files (7.2 GiB); apps/web/build and apps/web/.svelte-kit were removed.

READY FOR MERGE: no. The package check and the broader section Card E2E still need the issues above resolved or reviewed.

Production screenshots (macOS platform rendering)

Note at rest (1440, 820 and phone; Mono and Noir)

tocrail-note-1440-mono.png

tocrail-note-1440-noir.png

tocrail-note-390-mono.png

tocrail-note-390-noir.png

tocrail-note-820-mono.png

tocrail-note-820-noir.png

Rail pinned at middle and bottom scroll positions

tocrail-scroll-bottom-1440-mono.png

tocrail-scroll-bottom-1440-noir.png

tocrail-scroll-bottom-820-mono.png

tocrail-scroll-bottom-820-noir.png

tocrail-scroll-middle-1440-mono.png

tocrail-scroll-middle-1440-noir.png

tocrail-scroll-middle-820-mono.png

tocrail-scroll-middle-820-noir.png

tocrail-hover-1440-mono.png

tocrail-hover-1440-noir.png

tocrail-hover-820-mono.png

tocrail-hover-820-noir.png

Collapsed sidebar

tocrail-collapsed-1440-mono.png

tocrail-collapsed-1440-noir.png

4× sidebar-edge crops

tocrail-edge-1440-mono-4x.png

tocrail-edge-1440-noir-4x.png

tocrail-edge-820-mono-4x.png

tocrail-edge-820-noir-4x.png

Phone contents sheet

tocrail-contents-sheet-390-mono.png

tocrail-contents-sheet-390-noir.png

Completed #1113 and #1114 on `job/editorrail-1113`. Head: `77299c5c99cea0a2f795776816ca7fb6f3833cd1b`. ### Built - The Note contents rail stays fixed to the sidebar edge while `#route-content` scrolls. Clicking a heading reveals it through the shell scroller. - The hover title and Copy link Pill stays inside the Note card. Its pointer bridge begins after the tick target. The shared warm tooltip token now uses a 94% surface fill, with a solid surface under reduced transparency. - The block action capsule now has a focused production E2E capture and geometry assertion at all required widths. ### Files `apps/web/src/lib/notes/NoteContents.svelte`, `apps/web/src/lib/notes/anchors.ts`, `packages/ui/src/tokens.css`, `apps/web/e2e/tocrail-636.mjs`, `apps/web/e2e/notes.mjs`, `contracts/perf/exceptions.json`. ### UX gaps closed - Heading ticks have no inline fragments and stay at the sidebar edge at the top, middle and bottom of the Note. - The heading preview clears its own tick trigger, shows the selected title and Copy link, and stays in the Note card. - The same rail placement is captured with the sidebar collapsed. The phone Note and contents sheet are also included. - The block action capsule is checked at 390, 820 and 1440 px in both review palettes. ### UX gaps left - The broader `NOTES_E2E_SERIES_ONLY` run stopped before the block action flow at the existing #632 section Card gap assertion: `-9px`. The dedicated #1114 production capture passed. - `bun run check` stops in perf-lint on an unrelated stale `NotesExplorer.svelte` exception fingerprint. Standalone `svelte-check` passed with four CSS warnings in other files. ### Decisions - Anchor reveal uses `#route-content` when the shell provides it and keeps the Window fallback for other hosts. - The Note card offset is computed with CSS tokens and viewport/card width constraints. No runtime layout measurement was added. - The shared tooltip fill uses a 94% `--surface` mix because the existing tooltip token had no root declaration and the review needs Note text behind the Pill to stay legible. ### Gates and evidence `bun run check`: ```text $ ../../scripts/perf-lint --check && node scripts/check-user-storage.mjs && node scripts/check-glass-tokens.mjs && node scripts/check-type-tokens.mjs && node scripts/check-focus-tokens.mjs && node scripts/check-motion-tokens.mjs && svelte-kit sync && svelte-check --tsconfig ./tsconfig.json perf-lint: parse Rust product sources perf-lint: parse browser product sources perf-lint: validate coverage and architecture perf-lint: INVALID: ('render.bound', 'apps/web/src/lib/notes/NotesExplorer.svelte', 'apps/web/src/lib/notes/NotesExplorer.svelte#each:3c7baf2164751d7e:1'): unused or changed exception ``` Standalone Svelte check: ```text svelte-check found 0 errors and 4 warnings in 3 files ``` Focused anchors Vitest: ```text Test Files 1 passed (1) Tests 6 passed (6) Start at 12:18:53 Duration 51.18s (transform 75%, environment 10%, import 10%, tests 4%, setup 2%) ``` Editor tests: ```text Test Files 21 passed (21) Tests 434 passed (434) Start at 11:09:35 Duration 46.37s (transform 6.70s, setup 801ms, import 18.98s, tests 21.41s, environment 41.25s) ``` Glass token check: ```text Glass alpha, blur and backdrop-filter roles use packages/ui/src/tokens.css. ``` TOC production E2E: ```text tocrail-636/1113 e2e: six headings, sidebar-edge ticks, active section, hover Copy link, arrow keys, phone sheet and two-heading threshold passed ``` Block action production E2E: ```text notes #1114 block-action edge e2e: 1440, 820 and 390 px in Mono/Noir passed CSP REPORTS notes: 0 across 1 pages ``` Rust gates were not run because this change touches no Rust crate. `cargo clean` removed 8627 files (7.2 GiB); `apps/web/build` and `apps/web/.svelte-kit` were removed. READY FOR MERGE: no. The package check and the broader section Card E2E still need the issues above resolved or reviewed. ## Production screenshots (macOS platform rendering) ### Note at rest (1440, 820 and phone; Mono and Noir) ![tocrail-note-1440-mono.png](https://git.kayg.org/attachments/0f128c71-389b-4be7-850a-8ad7422d2e28) ![tocrail-note-1440-noir.png](https://git.kayg.org/attachments/de877845-c338-43da-a0ca-40c2fca7da67) ![tocrail-note-390-mono.png](https://git.kayg.org/attachments/9a493aa4-de54-481e-a9c1-465b876516c7) ![tocrail-note-390-noir.png](https://git.kayg.org/attachments/ebf01c69-c017-4568-979e-b4831d63254c) ![tocrail-note-820-mono.png](https://git.kayg.org/attachments/9cccafd6-2683-40a9-81e7-4489e157ae86) ![tocrail-note-820-noir.png](https://git.kayg.org/attachments/f84c03fe-b25c-40d4-9c59-f5098f48d5f9) ### Rail pinned at middle and bottom scroll positions ![tocrail-scroll-bottom-1440-mono.png](https://git.kayg.org/attachments/469f22d8-4bbb-4896-b293-7a7c0ce371f1) ![tocrail-scroll-bottom-1440-noir.png](https://git.kayg.org/attachments/0146749d-a505-4d77-8d50-22c3db00c408) ![tocrail-scroll-bottom-820-mono.png](https://git.kayg.org/attachments/fce43c2c-5057-4a30-b560-5fb748bb2f9c) ![tocrail-scroll-bottom-820-noir.png](https://git.kayg.org/attachments/ef0af20e-fab9-42cd-90b6-1566b99001cf) ![tocrail-scroll-middle-1440-mono.png](https://git.kayg.org/attachments/463a4cb9-071a-4664-8560-c3912a035fba) ![tocrail-scroll-middle-1440-noir.png](https://git.kayg.org/attachments/6bdf01a5-8238-4520-8c49-d13bbc3f1cf5) ![tocrail-scroll-middle-820-mono.png](https://git.kayg.org/attachments/c9c07d9e-7a39-4194-93a0-f731de899068) ![tocrail-scroll-middle-820-noir.png](https://git.kayg.org/attachments/135609d2-357e-4611-b889-864ee94925b6) ### Heading title and Copy link hover Pill ![tocrail-hover-1440-mono.png](https://git.kayg.org/attachments/fcbf80f1-b6f5-4224-bca6-1418488bab3b) ![tocrail-hover-1440-noir.png](https://git.kayg.org/attachments/9370c6c8-e181-4ffc-a00b-a83a63f8ce48) ![tocrail-hover-820-mono.png](https://git.kayg.org/attachments/beeb5c6b-9879-4af6-847b-001ece4317dc) ![tocrail-hover-820-noir.png](https://git.kayg.org/attachments/2e4946fa-eb0e-47bb-9138-cd3e95d94e0a) ### Collapsed sidebar ![tocrail-collapsed-1440-mono.png](https://git.kayg.org/attachments/1a35802b-44a7-455e-b8f1-ac7f147aadcf) ![tocrail-collapsed-1440-noir.png](https://git.kayg.org/attachments/39e01dbe-692e-45f9-99df-e6d56f01901d) ### 4× sidebar-edge crops ![tocrail-edge-1440-mono-4x.png](https://git.kayg.org/attachments/03500352-627e-488c-a063-dd0211bc09c9) ![tocrail-edge-1440-noir-4x.png](https://git.kayg.org/attachments/5fbfbc72-42f5-47ca-83a2-9404666d5b93) ![tocrail-edge-820-mono-4x.png](https://git.kayg.org/attachments/fca7a3c2-af21-4d6a-9df5-ada597cc0025) ![tocrail-edge-820-noir-4x.png](https://git.kayg.org/attachments/f04ce926-158d-49aa-b960-81254d0a6573) ### Phone contents sheet ![tocrail-contents-sheet-390-mono.png](https://git.kayg.org/attachments/b4558906-14a0-46af-bc9e-62effa16bc47) ![tocrail-contents-sheet-390-noir.png](https://git.kayg.org/attachments/b3c8a812-6994-442b-92e1-edc87dd7f737)
Author
Owner

Orchestrator visual review of your screenshots (head 77299c5c9): NOT shippable. Two defects, both cover the User's text:

  1. apps/web/artifacts/tocrail-1113/tocrail-hover-1440-noir.png: the heading hover Pill ("Goals for the teams launching the new r… 🔗") appears INSIDE the Note card over the first paragraph (x≈515-810), hiding "...review." It must open next to the hovered tick in the gutter beside the sidebar edge (anchored to the tick, to its right, vertically centred on it), never over the Note card text. If there is not room, it may extend over the empty gutter only.
  2. apps/web/artifacts/editorrail-1114/block-actions-card-edge-1440-noir.png: the block action capsule (→ ⏱ ⋯) covers the first word(s) of the paragraph ("The pilot" hidden). It must never overlap text glyphs. Place it in the Note card's leading padding/gutter (outside the text column, vertically aligned with the block's first line), shrinking to the drag handle + ⋯ if needed, or outside the card edge at wide widths. On 390 px use the existing touch behaviour (no hover capsule).

Add an e2e assertion for both: the Pill's and capsule's bounding rects do not intersect any text rect of the Note body (use Range.getClientRects over the block's text). Also fix the perf-lint INVALID for NotesExplorer.svelte so bun run check passes, and the #632 section gap assertion (-9px) if it is yours.

New screenshots at 1440/820/390, Noir + Paper White, plus 4x crops of both. Commit, comment on #1113 with head SHA. Do not push.

Orchestrator visual review of your screenshots (head 77299c5c9): NOT shippable. Two defects, both cover the User's text: 1. apps/web/artifacts/tocrail-1113/tocrail-hover-1440-noir.png: the heading hover Pill ("Goals for the teams launching the new r… 🔗") appears INSIDE the Note card over the first paragraph (x≈515-810), hiding "...review." It must open next to the hovered tick in the gutter beside the sidebar edge (anchored to the tick, to its right, vertically centred on it), never over the Note card text. If there is not room, it may extend over the empty gutter only. 2. apps/web/artifacts/editorrail-1114/block-actions-card-edge-1440-noir.png: the block action capsule (→ ⏱ ⋯) covers the first word(s) of the paragraph ("The pilot" hidden). It must never overlap text glyphs. Place it in the Note card's leading padding/gutter (outside the text column, vertically aligned with the block's first line), shrinking to the drag handle + ⋯ if needed, or outside the card edge at wide widths. On 390 px use the existing touch behaviour (no hover capsule). Add an e2e assertion for both: the Pill's and capsule's bounding rects do not intersect any text rect of the Note body (use Range.getClientRects over the block's text). Also fix the perf-lint INVALID for NotesExplorer.svelte so `bun run check` passes, and the #632 section gap assertion (-9px) if it is yours. New screenshots at 1440/820/390, Noir + Paper White, plus 4x crops of both. Commit, comment on #1113 with head SHA. Do not push.
Author
Owner

Starting #1113/#1114 placement follow-up on branch job/editorrail-1113. Base: merge-base with origin/dev 98584d6f78. Starting head: 77299c5c99. I am tracing the existing TOC rail and block-action placement, then I will add text-rect overlap assertions, fix the perf-lint and card-gap findings, capture the requested review set, and run the focused web checks.

Starting #1113/#1114 placement follow-up on branch job/editorrail-1113. Base: merge-base with origin/dev 98584d6f78510a4c72b2d2b9193c46581db04742. Starting head: 77299c5c99cea0a2f795776816ca7fb6f3833cd1. I am tracing the existing TOC rail and block-action placement, then I will add text-rect overlap assertions, fix the perf-lint and card-gap findings, capture the requested review set, and run the focused web checks.
Author
Owner

Finding after the required git fetch origin && git merge origin/dev (merge parent 04afb0043c559c59084e4ec12609bb9fe679cbf6): bun run check stops in perf-lint before source parsing because merged contracts/perf/exceptions.json has 21,977 entries while contracts/perf/ratchet.json allows 21,964. The 13-entry mismatch is already present in origin/dev; this job did not change either contract file. I am preserving the ledger and ratchet as merged rather than raising the ceiling without an owner-approved baseline change.

Finding after the required `git fetch origin && git merge origin/dev` (merge parent `04afb0043c559c59084e4ec12609bb9fe679cbf6`): `bun run check` stops in perf-lint before source parsing because merged `contracts/perf/exceptions.json` has 21,977 entries while `contracts/perf/ratchet.json` allows 21,964. The 13-entry mismatch is already present in `origin/dev`; this job did not change either contract file. I am preserving the ledger and ratchet as merged rather than raising the ceiling without an owner-approved baseline change.
Author
Owner

Finished: #1113 and #1114

Branch: job/editorrail-1113
Integrated origin/dev at merge commit ce5b746fe7c7526fd6edb7c058e0a4bd0b8a814a.
Head: 1f42a7eff61e074c6cdace6f5d33ea9d3e4976f5

Commits:

  • cf2b59f4c — Keep Note block actions clear of text (#1114).
  • 1f42a7eff — Move Note contents Pill beside its tick (#1113).

Built

  • The Note contents hover Pill opens right of its tick, stays vertically centred, and stops before Note body glyphs. The CSS width uses existing Note inset tokens. It does not measure text or layout at runtime.
  • The full block action capsule sits outside the Note Card when the sidebar gutter fits it. At tighter widths it keeps one More control in the leading gutter and exposes Make a note and Remind me in the shared menu. The 390 px touch view keeps the existing touch toolbar and does not show the hover capsule.
  • Added Range.getClientRects() assertions for Note body text and the Pill/capsule bounds. The focused #1114 run also checks the #632 18 px section Card inset.
  • Screenshots use macOS platform emulation, Paper White and Noir, at 1440, 820 and 390 px. All 26 selected screenshots and detail crops are attached below.

Files

  • apps/web/src/lib/notes/NoteContents.svelte
  • apps/web/e2e/tocrail-636.mjs
  • apps/web/src/lib/editor/format/BlockHoverActions.svelte
  • apps/web/src/lib/editor/format/BlockHoverActions.svelte.test.ts
  • apps/web/src/lib/editor/blockMenu.ts
  • apps/web/src/lib/editor/blockMenu.test.ts
  • apps/web/src/lib/notes/NoteEditorSurface.svelte
  • apps/web/src/lib/notes/NoteView.svelte
  • apps/web/src/lib/notes/icons.ts
  • apps/web/e2e/notes.mjs

Decisions

  • Use a token-bounded hover Pill beside the tick. If the available gutter is too narrow, the title truncates and the Copy link control remains available; the full heading stays in the accessible names.
  • Use the full block capsule outside the Card at wide widths; use one More control in the empty leading gutter when it cannot fit. Hide the capsule when no safe slot exists. Keep the current touch toolbar on phones.

UX gaps closed

  • The Pill and block capsule no longer cover Note glyphs at the reviewed widths.
  • The compact More menu actions work. Remind me opens its dialog; Make a note creates and opens the linked Note.
  • Phone touch uses the existing toolbar with no hover capsule.
  • The #632 split Note Card stack and bottom inset pass at 18 px.

UX gaps left

  • The broader NOTES_E2E_SERIES_ONLY=1 attempt still times out in the earlier #606 offline-editor flow while waiting for .note-card .editor-surface .ProseMirror[contenteditable="true"]. The requested #632 assertion ran separately in the focused edge flow and passed.

Verification

bunx vitest run src/lib/editor/blockMenu.test.ts src/lib/editor/format/BlockHoverActions.svelte.test.ts --maxWorkers=2:

 RUN  v5.0.1 /home/kayg/Developer/calternal-wt/editorrail-1113/apps/web

 Test Files  2 passed (2)
      Tests  9 passed (9)
   Start at  16:19:37
   Duration  15.50s (transform 79%, environment 8%, import 6%, tests 4%, setup 3%)

  Transform  |component| transforming modules took 12.13s · 79% of tracked time, re-done on every run
             persist transforms across runs with fsModuleCache: true
             learn more: https://vitest.dev/guide/improving-performance#caching-between-reruns

Focused block-action and #632 e2e (NOTES_E2E_BLOCK_ACTIONS_ONLY=1):

notes #632 split-Card stack gap and insets passed
block selection: Note card edge 820 paper-white
block selection: Note card edge 1440 paper-white
block selection: Note card edge 820 noir
block selection: Note card edge 1440 noir
block selection: 390 px paper-white touch selection
block selection: 390 px noir touch selection
block selection: compact Make a note action
notes #1114 block-action edge e2e: 1440, 820, 390 px and compact actions in Paper White/Noir passed
CSP REPORTS notes: 0 across 3 pages

TOC production e2e:

tocrail-636/1113 e2e: six headings, sidebar-edge ticks, active section, hover Copy link, arrow keys, phone sheet and two-heading threshold passed

Standalone Svelte check:

svelte-check found 0 errors and 4 warnings in 3 files

bun run check is blocked before Svelte checks by a mismatch already present in origin/dev (f2a34dd6e9372cdd2c77c7b41c32e2c9a7a096b2): exceptions.json has 21,977 entries and ratchet.json allows 21,964. The current NotesExplorer findings (12) match its 12 recorded pins at hash c37355ddecc20b88a69ba6dc0e4b2e2b750d51b4413318786293d6ac483ed257; the runner fails at the global ratchet check before validating those pins. I did not raise ceilings or remove active findings to mask the inherited mismatch.

Exact bun run check output:

perf-lint: INVALID: exception ratchet: contract.blaze: 290 exceptions exceed the ratchet ceiling 289; fix the new violation instead; contract.blocked-network: 356 exceptions exceed the ratchet ceiling 355; fix the new violation instead; contract.dom-bound: 290 exceptions exceed the ratchet ceiling 289; fix the new violation instead; contract.model-bound: 290 exceptions exceed the ratchet ceiling 289; fix the new violation instead; contract.row-identity: 290 exceptions exceed the ratchet ceiling 289; fix the new violation instead; contract.snapshot: 356 exceptions exceed the ratchet ceiling 355; fix the new violation instead; coverage.profile: 356 exceptions exceed the ratchet ceiling 355; fix the new violation instead; coverage.readiness: 356 exceptions exceed the ratchet ceiling 355; fix the new violation instead; io.unresolved-call: 16191 exceptions exceed the ratchet ceiling 16190; fix the new violation instead; render.blaze-adapter: 290 exceptions exceed the ratchet ceiling 289; fix the new violation instead; render.bound: 290 exceptions exceed the ratchet ceiling 289; fix the new violation instead; render.model_byte_cap: 290 exceptions exceed the ratchet ceiling 289; fix the new violation instead; render.model_row_cap: 290 exceptions exceed the ratchet ceiling 289; fix the new violation instead; total: ledger has 21977 exceptions; ratchet total is 21964

No Rust files changed, so Rust gates were not run. cargo clean completed (Removed 8626 files, 7.2GiB total); apps/web/build was removed. No screenshots were committed or pushed.

For the merge round

  • cd apps/web && bun run check — first reconcile the inherited perf exception/ratchet mismatch; then it must pass perf-lint, token checks and Svelte diagnostics.
  • cd apps/web && bun run test — run the full web unit suite.
  • cd apps/web && bun e2e/notes.mjs --screenshots artifacts/editorrail-1114 — run the full Notes integration flow, including block actions and card layout.

Attached screenshots

TOC rail (#1113):

Block actions (#1114):

## Finished: #1113 and #1114 Branch: `job/editorrail-1113` Integrated `origin/dev` at merge commit `ce5b746fe7c7526fd6edb7c058e0a4bd0b8a814a`. Head: `1f42a7eff61e074c6cdace6f5d33ea9d3e4976f5` Commits: - `cf2b59f4c` — Keep Note block actions clear of text (#1114). - `1f42a7eff` — Move Note contents Pill beside its tick (#1113). ### Built - The Note contents hover Pill opens right of its tick, stays vertically centred, and stops before Note body glyphs. The CSS width uses existing Note inset tokens. It does not measure text or layout at runtime. - The full block action capsule sits outside the Note Card when the sidebar gutter fits it. At tighter widths it keeps one More control in the leading gutter and exposes Make a note and Remind me in the shared menu. The 390 px touch view keeps the existing touch toolbar and does not show the hover capsule. - Added `Range.getClientRects()` assertions for Note body text and the Pill/capsule bounds. The focused #1114 run also checks the #632 18 px section Card inset. - Screenshots use macOS platform emulation, Paper White and Noir, at 1440, 820 and 390 px. All 26 selected screenshots and detail crops are attached below. ### Files - `apps/web/src/lib/notes/NoteContents.svelte` - `apps/web/e2e/tocrail-636.mjs` - `apps/web/src/lib/editor/format/BlockHoverActions.svelte` - `apps/web/src/lib/editor/format/BlockHoverActions.svelte.test.ts` - `apps/web/src/lib/editor/blockMenu.ts` - `apps/web/src/lib/editor/blockMenu.test.ts` - `apps/web/src/lib/notes/NoteEditorSurface.svelte` - `apps/web/src/lib/notes/NoteView.svelte` - `apps/web/src/lib/notes/icons.ts` - `apps/web/e2e/notes.mjs` ### Decisions - Use a token-bounded hover Pill beside the tick. If the available gutter is too narrow, the title truncates and the Copy link control remains available; the full heading stays in the accessible names. - Use the full block capsule outside the Card at wide widths; use one More control in the empty leading gutter when it cannot fit. Hide the capsule when no safe slot exists. Keep the current touch toolbar on phones. ### UX gaps closed - The Pill and block capsule no longer cover Note glyphs at the reviewed widths. - The compact More menu actions work. Remind me opens its dialog; Make a note creates and opens the linked Note. - Phone touch uses the existing toolbar with no hover capsule. - The #632 split Note Card stack and bottom inset pass at 18 px. ### UX gaps left - The broader `NOTES_E2E_SERIES_ONLY=1` attempt still times out in the earlier #606 offline-editor flow while waiting for `.note-card .editor-surface .ProseMirror[contenteditable="true"]`. The requested #632 assertion ran separately in the focused edge flow and passed. ### Verification `bunx vitest run src/lib/editor/blockMenu.test.ts src/lib/editor/format/BlockHoverActions.svelte.test.ts --maxWorkers=2`: ```text RUN v5.0.1 /home/kayg/Developer/calternal-wt/editorrail-1113/apps/web Test Files 2 passed (2) Tests 9 passed (9) Start at 16:19:37 Duration 15.50s (transform 79%, environment 8%, import 6%, tests 4%, setup 3%) Transform |component| transforming modules took 12.13s · 79% of tracked time, re-done on every run persist transforms across runs with fsModuleCache: true learn more: https://vitest.dev/guide/improving-performance#caching-between-reruns ``` Focused block-action and #632 e2e (`NOTES_E2E_BLOCK_ACTIONS_ONLY=1`): ```text notes #632 split-Card stack gap and insets passed block selection: Note card edge 820 paper-white block selection: Note card edge 1440 paper-white block selection: Note card edge 820 noir block selection: Note card edge 1440 noir block selection: 390 px paper-white touch selection block selection: 390 px noir touch selection block selection: compact Make a note action notes #1114 block-action edge e2e: 1440, 820, 390 px and compact actions in Paper White/Noir passed CSP REPORTS notes: 0 across 3 pages ``` TOC production e2e: ```text tocrail-636/1113 e2e: six headings, sidebar-edge ticks, active section, hover Copy link, arrow keys, phone sheet and two-heading threshold passed ``` Standalone Svelte check: ```text svelte-check found 0 errors and 4 warnings in 3 files ``` `bun run check` is blocked before Svelte checks by a mismatch already present in `origin/dev` (`f2a34dd6e9372cdd2c77c7b41c32e2c9a7a096b2`): `exceptions.json` has 21,977 entries and `ratchet.json` allows 21,964. The current NotesExplorer findings (12) match its 12 recorded pins at hash `c37355ddecc20b88a69ba6dc0e4b2e2b750d51b4413318786293d6ac483ed257`; the runner fails at the global ratchet check before validating those pins. I did not raise ceilings or remove active findings to mask the inherited mismatch. Exact `bun run check` output: ```text perf-lint: INVALID: exception ratchet: contract.blaze: 290 exceptions exceed the ratchet ceiling 289; fix the new violation instead; contract.blocked-network: 356 exceptions exceed the ratchet ceiling 355; fix the new violation instead; contract.dom-bound: 290 exceptions exceed the ratchet ceiling 289; fix the new violation instead; contract.model-bound: 290 exceptions exceed the ratchet ceiling 289; fix the new violation instead; contract.row-identity: 290 exceptions exceed the ratchet ceiling 289; fix the new violation instead; contract.snapshot: 356 exceptions exceed the ratchet ceiling 355; fix the new violation instead; coverage.profile: 356 exceptions exceed the ratchet ceiling 355; fix the new violation instead; coverage.readiness: 356 exceptions exceed the ratchet ceiling 355; fix the new violation instead; io.unresolved-call: 16191 exceptions exceed the ratchet ceiling 16190; fix the new violation instead; render.blaze-adapter: 290 exceptions exceed the ratchet ceiling 289; fix the new violation instead; render.bound: 290 exceptions exceed the ratchet ceiling 289; fix the new violation instead; render.model_byte_cap: 290 exceptions exceed the ratchet ceiling 289; fix the new violation instead; render.model_row_cap: 290 exceptions exceed the ratchet ceiling 289; fix the new violation instead; total: ledger has 21977 exceptions; ratchet total is 21964 ``` No Rust files changed, so Rust gates were not run. `cargo clean` completed (`Removed 8626 files, 7.2GiB total`); `apps/web/build` was removed. No screenshots were committed or pushed. ### For the merge round - `cd apps/web && bun run check` — first reconcile the inherited perf exception/ratchet mismatch; then it must pass perf-lint, token checks and Svelte diagnostics. - `cd apps/web && bun run test` — run the full web unit suite. - `cd apps/web && bun e2e/notes.mjs --screenshots artifacts/editorrail-1114` — run the full Notes integration flow, including block actions and card layout. ### Attached screenshots **TOC rail (#1113):** - [tocrail-note-1440-paper-white.png](https://git.kayg.org/attachments/c0c2cdb7-2aca-4fc3-99d2-5bb7d84494a7) - [tocrail-note-1440-noir.png](https://git.kayg.org/attachments/ef5308b2-0182-4af1-b70b-74579a964342) - [tocrail-note-820-paper-white.png](https://git.kayg.org/attachments/0e8f6b69-ab2e-4929-b465-43eb35eb2941) - [tocrail-note-820-noir.png](https://git.kayg.org/attachments/ee8ba912-8cb6-4319-beeb-390075cd3f8a) - [tocrail-note-390-paper-white.png](https://git.kayg.org/attachments/6c79bc69-ce47-4c7a-8e3e-fc15693829ef) - [tocrail-note-390-noir.png](https://git.kayg.org/attachments/a8f43f83-c65d-428c-865b-cc6caf9bee79) - [tocrail-hover-1440-paper-white.png](https://git.kayg.org/attachments/6022287f-5f4d-4af8-8c60-5239c52c61b9) - [tocrail-hover-1440-paper-white-4x.png](https://git.kayg.org/attachments/deecb818-a2f6-449e-9ef0-55a327f5e9c6) - [tocrail-hover-1440-noir.png](https://git.kayg.org/attachments/0226c68a-d120-435c-9854-10e48cb48f9f) - [tocrail-hover-1440-noir-4x.png](https://git.kayg.org/attachments/810802e1-3728-4394-a937-5934f4180bac) - [tocrail-hover-820-paper-white.png](https://git.kayg.org/attachments/1c6cc0a2-c075-495f-90c7-4a3c1cdc895b) - [tocrail-hover-820-paper-white-4x.png](https://git.kayg.org/attachments/bcace3f9-4f77-4527-b492-d947280bb3f7) - [tocrail-hover-820-noir.png](https://git.kayg.org/attachments/7aba1605-0787-414f-9dd8-30b439a00111) - [tocrail-hover-820-noir-4x.png](https://git.kayg.org/attachments/be1520df-075c-4ca5-8382-d20b2abe28f3) - [tocrail-contents-sheet-390-paper-white.png](https://git.kayg.org/attachments/15d907d7-4f8c-41a1-828c-d5ad47715768) - [tocrail-contents-sheet-390-noir.png](https://git.kayg.org/attachments/993cd5e4-e9fd-400f-9d2a-60b635b730e6) **Block actions (#1114):** - [block-actions-card-edge-1440-paper-white.png](https://git.kayg.org/attachments/b7253764-6168-4fa9-9d27-df0bb52595bd) - [block-actions-card-edge-1440-paper-white-4x.png](https://git.kayg.org/attachments/d48e65ef-1605-433a-ac2b-93635d469747) - [block-actions-card-edge-1440-noir.png](https://git.kayg.org/attachments/da064abd-80f4-4074-ab2e-ab7ca542395f) - [block-actions-card-edge-1440-noir-4x.png](https://git.kayg.org/attachments/cd292dd4-f668-407b-9ad6-e86b5a9f376d) - [block-actions-card-edge-820-paper-white.png](https://git.kayg.org/attachments/27bf1230-8321-4a8e-91d4-91db2422361b) - [block-actions-card-edge-820-paper-white-4x.png](https://git.kayg.org/attachments/149bb3fe-e12e-4dc0-86d6-9e66ae17d69f) - [block-actions-card-edge-820-noir.png](https://git.kayg.org/attachments/2e83617b-7691-4ef3-886f-bfaac4d4234a) - [block-actions-card-edge-820-noir-4x.png](https://git.kayg.org/attachments/b49f4617-7acd-49c0-a0ce-7dd3aa34c795) - [block-actions-card-edge-390-paper-white.png](https://git.kayg.org/attachments/c27553be-b177-4845-a03e-fee2adda9979) - [block-actions-card-edge-390-noir.png](https://git.kayg.org/attachments/d51dbb99-cae7-4ad0-9a9e-515e2ab74bf6)
Sign in to join this conversation.
No labels
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#1113
No description provided.