Menus: leading icon on every item (macOS Tahoe style), trailing check for toggles, no empty gutter #176

Closed
opened 2026-09-26 14:09:32 +00:00 by kayg · 28 comments
Owner

Owner 2026-09-26 (screenshot: Files ⋯ menu has an empty leading gutter reserved for the 'Show hidden files' check, so every item looks indented for no reason). Rule for ALL dropdowns, context menus and submenus, implemented once in the shared menu component (after #157 lands, merge dev first; do not fork the component):

  • every item has a leading icon (Lucide, same size/stroke as the rest of the app, optically centred on the text baseline), all icons in one aligned column;
  • toggle items show state with a trailing check (or a paired on/off icon), never an empty reserved leading gutter;
  • submenu items keep the trailing chevron; an item never has both a check and a chevron;
  • if a menu has no icons at all, no gutter is reserved;
  • keyboard shortcuts stay right-aligned in their own column (after #159's registry).
    Go through every menu in the app and give each item a fitting icon (View as, Sort by, Show hidden files, Copy link, Rename, Move, Share, Pin, Delete (destructive colour), etc.). Screenshots of every menu light+dark, 1440+390, for Claude's review. Add the rule to DESIGN §34 in ASD-STE100.
Owner 2026-09-26 (screenshot: Files ⋯ menu has an empty leading gutter reserved for the 'Show hidden files' check, so every item looks indented for no reason). Rule for ALL dropdowns, context menus and submenus, implemented once in the shared menu component (after #157 lands, merge dev first; do not fork the component): - every item has a leading icon (Lucide, same size/stroke as the rest of the app, optically centred on the text baseline), all icons in one aligned column; - toggle items show state with a trailing check (or a paired on/off icon), never an empty reserved leading gutter; - submenu items keep the trailing chevron; an item never has both a check and a chevron; - if a menu has no icons at all, no gutter is reserved; - keyboard shortcuts stay right-aligned in their own column (after #159's registry). Go through every menu in the app and give each item a fitting icon (View as, Sort by, Show hidden files, Copy link, Rename, Move, Share, Pin, Delete (destructive colour), etc.). Screenshots of every menu light+dark, 1440+390, for Claude's review. Add the rule to DESIGN §34 in ASD-STE100.
Author
Owner

Starting #176 in job/menu-icons, on top of the merged #157 shared overlay glass commit. Base HEAD: 19676b443485821c2df96e03f8f0e357cf32ee74.

Starting #176 in `job/menu-icons`, on top of the merged #157 shared overlay glass commit. Base HEAD: `19676b443485821c2df96e03f8f0e357cf32ee74`.
Author
Owner

Finding for #176: packages/ui/src/components/menu/MenuItem.svelte currently draws checked radio/checkbox state in the leading glyph slot, and FilesBrowser.svelte builds the Files actions, sort, and hidden-files menu without Lucide icons. The shared Menu already resolves shortcut through the #159 registry. I will retain that source and move toggle state to a trailing check, then add fitting icons to the remaining menu nodes.

Finding for #176: `packages/ui/src/components/menu/MenuItem.svelte` currently draws checked radio/checkbox state in the leading glyph slot, and `FilesBrowser.svelte` builds the Files actions, sort, and hidden-files menu without Lucide icons. The shared `Menu` already resolves `shortcut` through the #159 registry. I will retain that source and move toggle state to a trailing check, then add fitting icons to the remaining menu nodes.
Author
Owner

Implementation progress: commits 474ddb1e (shared leading icon and trailing state slots) and 2797b580 (Lucide icons across app menus, §34 rule, and menu-slot tests). Web check passed with 0 errors and 0 warnings; all 434 existing tests passed, plus 4 focused menu-slot tests; production web build passed. Next: merge current dev, run final gates, and attach production screenshots for light/dark at 1440 and 390.

Implementation progress: commits `474ddb1e` (shared leading icon and trailing state slots) and `2797b580` (Lucide icons across app menus, §34 rule, and menu-slot tests). Web check passed with 0 errors and 0 warnings; all 434 existing tests passed, plus 4 focused menu-slot tests; production web build passed. Next: merge current `dev`, run final gates, and attach production screenshots for light/dark at 1440 and 390.
Author
Owner

Post-merge finding and fix: the new Analytics period menu and its “Copy link to this view” overflow action had no icons. The period rows now use matching Lucide calendar icons and the link action uses Link in commit 8fe43730. The first web check also showed that 51 merged-lockfile packages were absent from this worktree’s node_modules; bun install --frozen-lockfile synchronized them without changing lockfiles. Follow-up gates: svelte-check found 0 errors and 0 warnings; Test Files 69 passed (69), Tests 538 passed (538).

Post-merge finding and fix: the new Analytics period menu and its “Copy link to this view” overflow action had no icons. The period rows now use matching Lucide calendar icons and the link action uses Link in commit 8fe43730. The first web check also showed that 51 merged-lockfile packages were absent from this worktree’s node_modules; `bun install --frozen-lockfile` synchronized them without changing lockfiles. Follow-up gates: `svelte-check found 0 errors and 0 warnings`; `Test Files 69 passed (69)`, `Tests 538 passed (538)`.
Author
Owner

Starting continuation on branch job/menu-icons at base dev SHA f6418fc72d750d941f23554ad16381f6dd400fd6. The checkpoint is HEAD 8fe437300a7b26825f0ab949657eb677db9022cf; the working tree is clean.

Starting continuation on branch `job/menu-icons` at base `dev` SHA `f6418fc72d750d941f23554ad16381f6dd400fd6`. The checkpoint is HEAD `8fe437300a7b26825f0ab949657eb677db9022cf`; the working tree is clean.
Author
Owner

Finding during production screenshot setup: cargo build -p calternal-server stopped in icu_locale_core with can't find crate for tinystr. cargo tree -p calternal-server -i tinystr confirms the dependency path, and the selected target/debug/deps/libtinystr-2c8b64f7bf425860.rmeta is 0 bytes while another fingerprint has a valid artifact. The target directory is local to this worktree. I will clear the tinystr build output and retry; this points to an incomplete target artifact, not a source error.

Finding during production screenshot setup: `cargo build -p calternal-server` stopped in `icu_locale_core` with `can't find crate for tinystr`. `cargo tree -p calternal-server -i tinystr` confirms the dependency path, and the selected `target/debug/deps/libtinystr-2c8b64f7bf425860.rmeta` is 0 bytes while another fingerprint has a valid artifact. The target directory is local to this worktree. I will clear the `tinystr` build output and retry; this points to an incomplete target artifact, not a source error.
Author
Owner

Follow-up finding: the retry rebuilt tinystr and passed the ICU stage, then stopped at hashlink with can't find crate for hashbrown. The selected target/debug/deps/libhashbrown-dc6a8e10e8495dfa.rmeta is also 0 bytes; a different fingerprint has a valid artifact. This confirms the local target cache has more than one incomplete dependency output. I will clear the local target cache and rebuild with the required low-debug settings.

Follow-up finding: the retry rebuilt `tinystr` and passed the ICU stage, then stopped at `hashlink` with `can't find crate for hashbrown`. The selected `target/debug/deps/libhashbrown-dc6a8e10e8495dfa.rmeta` is also 0 bytes; a different fingerprint has a valid artifact. This confirms the local target cache has more than one incomplete dependency output. I will clear the local target cache and rebuild with the required low-debug settings.
Author
Owner

Screenshot sweep finding: Notes context menus live in the navigation sidebar, which is hidden in collapsed and phone layouts. The tag tree is rendered on Calendar routes, not /notes. The first capture pass therefore omitted those sidebar menus on touch layouts. I changed the review route to /today and made the capture pass open the sidebar before those context menus (commit a5b41247).

Screenshot sweep finding: Notes context menus live in the navigation sidebar, which is hidden in collapsed and phone layouts. The tag tree is rendered on Calendar routes, not `/notes`. The first capture pass therefore omitted those sidebar menus on touch layouts. I changed the review route to `/today` and made the capture pass open the sidebar before those context menus (commit `a5b41247`).
Author
Owner

Phone capture finding (verified with the production build): the app keeps a zero-sized desktop sidebar mounted while the navigation sheet is open. The Notes capture used .first(), so Playwright selected the hidden desktop row even though the same seeded row was visible in the sheet at y=173..217. I scoped both Notes and tag context-menu locators to the active sidebar container. The corrected Notes capture passed all 8 requested width/state/theme screens (LAYOUT SWEEP PASSED). Commit: 91207f68.

Phone capture finding (verified with the production build): the app keeps a zero-sized desktop sidebar mounted while the navigation sheet is open. The Notes capture used `.first()`, so Playwright selected the hidden desktop row even though the same seeded row was visible in the sheet at y=173..217. I scoped both Notes and tag context-menu locators to the active sidebar container. The corrected Notes capture passed all 8 requested width/state/theme screens (`LAYOUT SWEEP PASSED`). Commit: `91207f68`.
Author
Owner

Touch Photos capture finding: openContext sets actionSheet for coarse pointers, so the real production surface is an accessible “Photo actions” dialog, while desktop uses the shared role=menu. The layout sweep had waited only for role=menu on phone. It now waits for the surface rendered for each pointer type; the production capture passed all 8 phone width/state/theme screens. Commit: 1a0d4434.

The corrected tag-menu capture also exposed calendar layout shift: CLS 0.193 while loading on /today at 1440 collapsed. I’m moving that capture route to the Calendar week view and will verify it there.

Touch Photos capture finding: `openContext` sets `actionSheet` for coarse pointers, so the real production surface is an accessible “Photo actions” dialog, while desktop uses the shared `role=menu`. The layout sweep had waited only for `role=menu` on phone. It now waits for the surface rendered for each pointer type; the production capture passed all 8 phone width/state/theme screens. Commit: `1a0d4434`. The corrected tag-menu capture also exposed `calendar layout shift: CLS 0.193 while loading` on `/today` at 1440 collapsed. I’m moving that capture route to the Calendar week view and will verify it there.
Author
Owner

Capture adjustment committed as part of 895aaddd: /today is the correct mode for the sidebar tag tree but its page-load CLS hit 0.193 in one 1440 collapsed sample while the calendar data loaded. I moved the tag menu screenshot route to /calendar/week/<today>, which uses the same Calendar sidebar and has a stable layout in the existing menu sweep. Syntax and whitespace checks pass; the production capture is pending because another worktree's Playwright run is using the shared browser slot.

Capture adjustment committed as part of `895aaddd`: `/today` is the correct mode for the sidebar tag tree but its page-load CLS hit 0.193 in one 1440 collapsed sample while the calendar data loaded. I moved the tag menu screenshot route to `/calendar/week/<today>`, which uses the same Calendar sidebar and has a stable layout in the existing menu sweep. Syntax and whitespace checks pass; the production capture is pending because another worktree's Playwright run is using the shared browser slot.
Author
Owner

The /calendar/week/<today> tag-menu recapture passed all 8 width/state/theme screens against the merged production web build:

checked 8 screens
LAYOUT SWEEP PASSED

This avoids the /today page-load CLS sample while keeping the Calendar tag sidebar. Screenshot set: /home/kayg/.local/state/codex-jobs/calternal/menu-icons/screens/menus.

The `/calendar/week/<today>` tag-menu recapture passed all 8 width/state/theme screens against the merged production web build: ``` checked 8 screens LAYOUT SWEEP PASSED ``` This avoids the `/today` page-load CLS sample while keeping the Calendar tag sidebar. Screenshot set: `/home/kayg/.local/state/codex-jobs/calternal/menu-icons/screens/menus`.
Author
Owner

Adversarial finding on the merged real server: the one-page PDF TUS final PATCH returned NO RESPONSE (b'timed out') at the probe's 30 s request timeout. The server process remained alive and /readyz returned 200 in under 0.3 s. At the same time, host load average was 18.76, with multiple concurrent adversarial servers and a Chromium session on other worktrees. The same round reported only SLOW timings for the tiny video fixture: 11.1 s to create and 18.5 s to PATCH. I will make one bounded isolated repeat of the PDF PATCH after the concurrent runners finish; if it reproduces without that load, I will investigate it as an API failure.

Adversarial finding on the merged real server: the one-page PDF TUS final PATCH returned `NO RESPONSE (b'timed out')` at the probe's 30 s request timeout. The server process remained alive and `/readyz` returned 200 in under 0.3 s. At the same time, host load average was 18.76, with multiple concurrent adversarial servers and a Chromium session on other worktrees. The same round reported only `SLOW` timings for the tiny video fixture: 11.1 s to create and 18.5 s to PATCH. I will make one bounded isolated repeat of the PDF PATCH after the concurrent runners finish; if it reproduces without that load, I will investigate it as an API failure.
Author
Owner

The round 2 share-options section also reported SLOW thumbnail was not generated within 30 s; the dependent public thumbnail reads then returned 404 for both sizes, so the probe skipped checks that need thumbnail bytes. Two adversarial servers were running the same upload checks concurrently and both server processes were CPU-bound. I’m treating this as a load-dependent result and will check the derivative state once this round settles.

The round 2 `share-options` section also reported `SLOW thumbnail was not generated within 30 s`; the dependent public thumbnail reads then returned 404 for both sizes, so the probe skipped checks that need thumbnail bytes. Two adversarial servers were running the same upload checks concurrently and both server processes were CPU-bound. I’m treating this as a load-dependent result and will check the derivative state once this round settles.
Author
Owner

Post-merge adversarial round started on cdc09b1d126a64b93c2dd27b8f7c8f91c44fc77c (latest dev tip was its second parent). Authorization matrix: 916/916 passed. Hostile bytes: 0 findings. The live editor probe found persisted duplicate block IDs after a 500-step undo/redo storm; filed as #225 and linked from #186. The editor restart finding was a runner handshake timeout, not an established product failure (#226). The recovery-key 403 was a stale-session probe expectation (#227). Slowloris sockets targeted the Node test proxy rather than Rust backend (#228). Other successful requests marked SLOW match the shared host load. Round 2 is still running; thumbnail generation timed out and its dependent header check was skipped.

Post-merge adversarial round started on `cdc09b1d126a64b93c2dd27b8f7c8f91c44fc77c` (latest `dev` tip was its second parent). Authorization matrix: 916/916 passed. Hostile bytes: 0 findings. The live editor probe found persisted duplicate block IDs after a 500-step undo/redo storm; filed as #225 and linked from #186. The editor restart finding was a runner handshake timeout, not an established product failure (#226). The recovery-key 403 was a stale-session probe expectation (#227). Slowloris sockets targeted the Node test proxy rather than Rust backend (#228). Other successful requests marked `SLOW` match the shared host load. Round 2 is still running; thumbnail generation timed out and its dependent header check was skipped.
Author
Owner

Gate progress for #176 (head 7f353785): cargo fmt, Clippy, the full Cargo test suite, bun run check, bun run test, and the production build all exited successfully.

The refreshed menu screenshots are still pending. A Photos performance run in another worktree has held its Playwright browser for more than 18 minutes (photos-perf.mjs --items 20000 --files 50000 --notes 10000 --analytics-entries 10000 --large-note). I stopped this job’s first capture attempt to keep one browser active on the shared host. I will rerun the menu capture after that browser exits, then post the final report and screenshot results.

Gate progress for #176 (head 7f353785): cargo fmt, Clippy, the full Cargo test suite, bun run check, bun run test, and the production build all exited successfully. The refreshed menu screenshots are still pending. A Photos performance run in another worktree has held its Playwright browser for more than 18 minutes (`photos-perf.mjs --items 20000 --files 50000 --notes 10000 --analytics-entries 10000 --large-note`). I stopped this job’s first capture attempt to keep one browser active on the shared host. I will rerun the menu capture after that browser exits, then post the final report and screenshot results.
Author
Owner

The Photos performance run exited. A separate UI audit worktree then started layout-sweep.mjs --consistency just after this job began the screenshot refresh. I stopped this job’s sweep after about one minute; its server and browser have exited. The UI audit browser remains active at five minutes. I will resume the current-build menu capture after it releases the browser. The source gates still pass and the worktree is clean.

The Photos performance run exited. A separate UI audit worktree then started `layout-sweep.mjs --consistency` just after this job began the screenshot refresh. I stopped this job’s sweep after about one minute; its server and browser have exited. The UI audit browser remains active at five minutes. I will resume the current-build menu capture after it releases the browser. The source gates still pass and the worktree is clean.
Author
Owner

The UI audit browser ended, but a csp worktree started bun e2e/a11y.mjs before this job could start its menu capture. That browser has remained active for over 18 minutes. This job’s browser is stopped. The merged production build and all source gates pass on head a312002e; the refreshed screenshots are still pending.

The UI audit browser ended, but a `csp` worktree started `bun e2e/a11y.mjs` before this job could start its menu capture. That browser has remained active for over 18 minutes. This job’s browser is stopped. The merged production build and all source gates pass on head a312002e; the refreshed screenshots are still pending.
Author
Owner

Continuation progress: merged current dev tip 895d3479 into job/menu-icons without conflicts. New HEAD: 26f5895ef5. This merge includes the latest shared menu component and backend/API work, so I will rerun final gates and one bounded real-server adversarial pass on this HEAD. The shared Chromium slot is still occupied; screenshot refresh and browser probes will wait until it is free.

Continuation progress: merged current dev tip 895d3479 into job/menu-icons without conflicts. New HEAD: 26f5895ef5955780334ab9723a1b1ae7ad65792c. This merge includes the latest shared menu component and backend/API work, so I will rerun final gates and one bounded real-server adversarial pass on this HEAD. The shared Chromium slot is still occupied; screenshot refresh and browser probes will wait until it is free.
Author
Owner

Continuation update: dev advanced to 5af2ff78 during verification. I merged it cleanly into ; HEAD is now 7b4477904a and the worktree is clean. The merge adds filesystem/server/API updates, so I am rerunning the final gates and will run one real-server adversarial pass on this HEAD. Screenshot capture will follow when the shared Chromium slot is free.

Continuation update: dev advanced to 5af2ff78 during verification. I merged it cleanly into ; HEAD is now 7b4477904aa4ad7c33f92f16d55d99a44cacbe99 and the worktree is clean. The merge adds filesystem/server/API updates, so I am rerunning the final gates and will run one real-server adversarial pass on this HEAD. Screenshot capture will follow when the shared Chromium slot is free.
Author
Owner

Continuation update: dev advanced to 5af2ff78 during verification. I merged it cleanly into job/menu-icons; HEAD is now 7b4477904a and the worktree is clean. The merge adds filesystem/server/API updates, so I am rerunning the final gates and will run one real-server adversarial pass on this HEAD. Screenshot capture will follow when the shared Chromium slot is free.

Continuation update: dev advanced to 5af2ff78 during verification. I merged it cleanly into `job/menu-icons`; HEAD is now 7b4477904aa4ad7c33f92f16d55d99a44cacbe99 and the worktree is clean. The merge adds filesystem/server/API updates, so I am rerunning the final gates and will run one real-server adversarial pass on this HEAD. Screenshot capture will follow when the shared Chromium slot is free.
Author
Owner

Final gate progress on HEAD 7b4477904a (merged dev 5af2ff78):

  • cargo fmt --check: exit 0, no output.
  • cargo clippy --all-targets -- -D warnings: Finished dev profile [unoptimized + debuginfo] target(s) in 1m 09s.
  • cargo test: exit 0; the changed filesystem, server and workspace suites passed.
  • bun run check: svelte-check found 0 errors and 0 warnings.
  • bun run test: Test Files 81 passed (81); Tests 589 passed (589).
  • bun run build: ✓ built in 1m 44s; Wrote site to "build"; ✔ done. It keeps the existing vendored use client directive warnings.

The shared host has multiple active Chromium sweeps, so I have not started the real-server adversarial runner or refreshed the menu screenshots yet. I will start those when the shared browser slot is clear. dev has since advanced to 0558cc4e; those newer commits touch only deployment files and are outside this verification.

Final gate progress on HEAD 7b4477904aa4ad7c33f92f16d55d99a44cacbe99 (merged dev 5af2ff78): - `cargo fmt --check`: exit 0, no output. - `cargo clippy --all-targets -- -D warnings`: `Finished `dev` profile [unoptimized + debuginfo] target(s) in 1m 09s`. - `cargo test`: exit 0; the changed filesystem, server and workspace suites passed. - `bun run check`: `svelte-check found 0 errors and 0 warnings`. - `bun run test`: `Test Files 81 passed (81)`; `Tests 589 passed (589)`. - `bun run build`: `✓ built in 1m 44s`; `Wrote site to "build"`; `✔ done`. It keeps the existing vendored `use client` directive warnings. The shared host has multiple active Chromium sweeps, so I have not started the real-server adversarial runner or refreshed the menu screenshots yet. I will start those when the shared browser slot is clear. `dev` has since advanced to 0558cc4e; those newer commits touch only deployment files and are outside this verification.
Author
Owner

Blocked on shared browser capacity after the final source gates on 7b447790. At 2026-09-27, other worktrees have had active Chromium E2E sweeps for more than 35 minutes, with additional sweeps starting behind them. The adversarial runner and menu screenshot sweep both launch Chromium, so I have not started either while those sessions are active. This job remains open; the 176 screenshots currently in the standard directory are from the earlier build and are not current evidence. I will continue when the browser queue clears.

Blocked on shared browser capacity after the final source gates on 7b447790. At 2026-09-27, other worktrees have had active Chromium E2E sweeps for more than 35 minutes, with additional sweeps starting behind them. The adversarial runner and menu screenshot sweep both launch Chromium, so I have not started either while those sessions are active. This job remains open; the 176 screenshots currently in the standard directory are from the earlier build and are not current evidence. I will continue when the browser queue clears.
Author
Owner

Final pass on HEAD 7b4477904a. The one required dev merge (5af2ff78) is already in HEAD. I am running the final gate set, current production menu captures, and one bounded adversarial round now.

Final pass on HEAD 7b4477904aa4ad7c33f92f16d55d99a44cacbe99. The one required dev merge (5af2ff78) is already in HEAD. I am running the final gate set, current production menu captures, and one bounded adversarial round now.
Author
Owner

Merged current dev 200d171ea3 into job/menu-icons once; new HEAD is 27542ce832. The merge completed without conflicts and preserved the menu icon changes and focused slot tests. Running the final checks against this head now.

Merged current dev 200d171ea35e1de53ad56e6c1d7fcef95881f0a3 into job/menu-icons once; new HEAD is 27542ce83285ffd70c446824c30c7113cb03eb6e. The merge completed without conflicts and preserved the menu icon changes and focused slot tests. Running the final checks against this head now.
Author
Owner

Completed — menu icons (#176)

Built

Implemented the shared aligned leading-icon column, trailing toggle check, submenu chevron, conditional no-icon gutter, and right-aligned shortcut column. Added fitting Lucide icons throughout app menus, documented the rule in DESIGN §34, and added menu component tests and screenshot coverage.

Files changed:

  • packages/ui/src/components/menu/Menu.svelte, MenuItem.svelte, types.ts; ChromeActions.svelte; ModeHeader.svelte
  • apps/web/src/lib/components/app-sidebar.svelte; composer, files, notes, notifications, photos, and search components; analytics, ask, calendar, notes, tag, and tags routes
  • apps/web/src/lib/menu/MenuItem.svelte.test.ts; apps/web/src/lib/modeHeader.svelte.test.ts; apps/web/e2e/layout-sweep.mjs
  • docs/DESIGN.md

Branch

Branch: job/menu-icons
HEAD: 27542ce83285ffd70c446824c30c7113cb03eb6e
Merged dev once at 200d171ea35e1de53ad56e6c1d7fcef95881f0a3. The branch was pushed; origin/job/menu-icons points to HEAD. No additional source changes were needed after the merge.

Gates

All commands exited 0. Output excerpts:

cargo fmt --check
(no output)

cargo clippy --all-targets -- -D warnings
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 1m 42s

cargo test
72 test-result harnesses: 1,278 passed, 0 failed, 12 ignored.
test result: ok. 480 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.49s

bun run check
Loading svelte-check in workspace: /home/kayg/Developer/calternal-wt/menu-icons/apps/web
Getting Svelte diagnostics...

svelte-check found 0 errors and 0 warnings

bun run test
 Test Files  82 passed (82)
      Tests  593 passed (593)
   Start at  18:54:04
   Duration  115.23s (transform 70%, import 12%, environment 10%, tests 6%, setup 2%)

bun run build
✓ built in 1m 26s
Run npm run preview to preview your production build locally.

> Using @sveltejs/adapter-static
  Wrote site to "build"
  ✔ done

Adversarial round

Ran one 15-minute timeboxed round. The event tag probe passed Unicode/bidi, a 65,536-byte category, 7 malformed values, and 24 parallel reads. Authorization matrix passed 916/916 requests across 229 OpenAPI operations and four identities. Hostile-bytes probe reported 0 findings. The runner reported 60 findings, all marked SLOW with expected HTTP statuses; no non-SLOW finding appeared. The media worker did not produce a thumbnail in 10 seconds, so its dependent header check was skipped. The run reached the time cap while attack2.py was starting; that subprobe is incomplete.

Screenshots

Captured 176 screenshots from the production build (desktop and phone, open and collapsed sidebar, both themes). ZIP attached here: menus-27542ce8.zip. The PNGs are not committed.

The menu-filtered sweep reported 12 layout failures:

  • Analytics controls were 12 px from the card edge where the sweep expects 18 px, at 1440 and 390 widths with the Paper theme, sidebar open and collapsed.
  • Recent-file context/overflow screenshots at 390 width, Paper theme, sidebar open and collapsed reported the BURST_023.JPG label center 8.5 px above its icon.

These need visual review and follow-up. Claude's screenshot review is pending.

Decisions

DESIGN §34 did not prescribe an icon for every action. I chose existing Lucide icons by action meaning and kept the app's established icon size and stroke. No additional interaction rule was introduced.

Remaining work

Review the attached screenshots; resolve or file the 12 sweep failures; rerun the unfinished attack2.py subprobe in a later scheduled round. cargo clean and removal of generated web build output follow this report.

## Completed — menu icons (#176) ### Built Implemented the shared aligned leading-icon column, trailing toggle check, submenu chevron, conditional no-icon gutter, and right-aligned shortcut column. Added fitting Lucide icons throughout app menus, documented the rule in DESIGN §34, and added menu component tests and screenshot coverage. Files changed: - `packages/ui/src/components/menu/Menu.svelte`, `MenuItem.svelte`, `types.ts`; `ChromeActions.svelte`; `ModeHeader.svelte` - `apps/web/src/lib/components/app-sidebar.svelte`; composer, files, notes, notifications, photos, and search components; analytics, ask, calendar, notes, tag, and tags routes - `apps/web/src/lib/menu/MenuItem.svelte.test.ts`; `apps/web/src/lib/modeHeader.svelte.test.ts`; `apps/web/e2e/layout-sweep.mjs` - `docs/DESIGN.md` ### Branch Branch: `job/menu-icons` HEAD: `27542ce83285ffd70c446824c30c7113cb03eb6e` Merged `dev` once at `200d171ea35e1de53ad56e6c1d7fcef95881f0a3`. The branch was pushed; `origin/job/menu-icons` points to HEAD. No additional source changes were needed after the merge. ### Gates All commands exited 0. Output excerpts: ```text cargo fmt --check (no output) cargo clippy --all-targets -- -D warnings Finished `dev` profile [unoptimized + debuginfo] target(s) in 1m 42s cargo test 72 test-result harnesses: 1,278 passed, 0 failed, 12 ignored. test result: ok. 480 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.49s bun run check Loading svelte-check in workspace: /home/kayg/Developer/calternal-wt/menu-icons/apps/web Getting Svelte diagnostics... svelte-check found 0 errors and 0 warnings bun run test Test Files 82 passed (82) Tests 593 passed (593) Start at 18:54:04 Duration 115.23s (transform 70%, import 12%, environment 10%, tests 6%, setup 2%) bun run build ✓ built in 1m 26s Run npm run preview to preview your production build locally. > Using @sveltejs/adapter-static Wrote site to "build" ✔ done ``` ### Adversarial round Ran one 15-minute timeboxed round. The event tag probe passed Unicode/bidi, a 65,536-byte category, 7 malformed values, and 24 parallel reads. Authorization matrix passed 916/916 requests across 229 OpenAPI operations and four identities. Hostile-bytes probe reported 0 findings. The runner reported 60 findings, all marked `SLOW` with expected HTTP statuses; no non-SLOW finding appeared. The media worker did not produce a thumbnail in 10 seconds, so its dependent header check was skipped. The run reached the time cap while `attack2.py` was starting; that subprobe is incomplete. ### Screenshots Captured 176 screenshots from the production build (desktop and phone, open and collapsed sidebar, both themes). ZIP attached here: [menus-27542ce8.zip](https://git.kayg.org/attachments/ee90f9b4-4d42-4890-aa45-11a7ca36acea). The PNGs are not committed. The menu-filtered sweep reported 12 layout failures: - Analytics controls were 12 px from the card edge where the sweep expects 18 px, at 1440 and 390 widths with the Paper theme, sidebar open and collapsed. - Recent-file context/overflow screenshots at 390 width, Paper theme, sidebar open and collapsed reported the `BURST_023.JPG` label center 8.5 px above its icon. These need visual review and follow-up. Claude's screenshot review is pending. ### Decisions DESIGN §34 did not prescribe an icon for every action. I chose existing Lucide icons by action meaning and kept the app's established icon size and stroke. No additional interaction rule was introduced. ### Remaining work Review the attached screenshots; resolve or file the 12 sweep failures; rerun the unfinished `attack2.py` subprobe in a later scheduled round. `cargo clean` and removal of generated web build output follow this report.
Author
Owner

Post-report cleanup complete: cargo clean removed 43,185 files (23.9 GiB), and apps/web/build plus apps/web/.svelte-kit were removed. The worktree is clean. Pushed branch job/menu-icons remains at 27542ce832.

Post-report cleanup complete: cargo clean removed 43,185 files (23.9 GiB), and apps/web/build plus apps/web/.svelte-kit were removed. The worktree is clean. Pushed branch job/menu-icons remains at 27542ce83285ffd70c446824c30c7113cb03eb6e.
Author
Owner

Merged in 21d985bf (conflicts resolved in favour of the shared MENU_ICONS map; svelte-check 0/0, web tests 593/593). Menus still lack blur until #246. Layout-sweep findings (Analytics 12 px padding, recent-file label offset) → follow-up.

Merged in 21d985bf (conflicts resolved in favour of the shared MENU_ICONS map; svelte-check 0/0, web tests 593/593). Menus still lack blur until #246. Layout-sweep findings (Analytics 12 px padding, recent-file label offset) → follow-up.
kayg closed this issue 2026-09-27 17:43:16 +00:00
kayg referenced this issue from a commit 2026-09-27 17:43:17 +00:00
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#176
No description provided.