MOTION: squish switch and spring checkbox (sveltebits) in the shared toggle and checkbox #406

Closed
opened 2026-09-29 05:30:42 +00:00 by kayg · 26 comments
Owner

Request (owner, 2026-09-29)

"for toggles, can we use this effect? https://sveltebits.xyz/micro/squish-switch i really love the motion here. for checkboxes: https://sveltebits.xyz/micro/spring-check our app should be fun to use! love the motion around the UI!"

Build (CLAUDE.md: cherry-pick sveltebits.xyz components, restyle to calternal tokens)

  • Switch: port the squish-switch motion into the one shared toggle/switch component (search for it; every toggle in the app must already use it — migrate any that don't). Keep role tokens (accent for on), the #291 spring constants where they fit, 44 px touch target, role="switch" with aria-checked, keyboard (Space), reduced motion = instant state change.
  • Checkbox: port spring-check into the one shared checkbox (the Files row and header checkboxes, task checkboxes, settings, selection) — every checkbox in the app uses it. Tri-state (indeterminate dash) animates too. Job select-align (#398) is fixing checkbox alignment in Files right now: change only the checkbox's internal drawing and motion, not its box or layout, and merge dev before finishing.
  • Licence: confirm the sveltebits snippets' licence is AGPL-compatible and credit it in NOTICE if required.
  • Evidence: frame strips of on/off and check/uncheck/indeterminate at 1x and 2x, light and dark (theme asserted), reduced-motion capture; a list of every call site migrated.
## Request (owner, 2026-09-29) "for toggles, can we use this effect? https://sveltebits.xyz/micro/squish-switch i really love the motion here. for checkboxes: https://sveltebits.xyz/micro/spring-check our app should be fun to use! love the motion around the UI!" ## Build (CLAUDE.md: cherry-pick sveltebits.xyz components, restyle to calternal tokens) - **Switch:** port the squish-switch motion into the one shared toggle/switch component (search for it; every toggle in the app must already use it — migrate any that don't). Keep role tokens (accent for on), the #291 spring constants where they fit, 44 px touch target, `role="switch"` with `aria-checked`, keyboard (Space), reduced motion = instant state change. - **Checkbox:** port spring-check into the one shared checkbox (the Files row and header checkboxes, task checkboxes, settings, selection) — every checkbox in the app uses it. Tri-state (indeterminate dash) animates too. Job select-align (#398) is fixing checkbox **alignment** in Files right now: change only the checkbox's internal drawing and motion, not its box or layout, and merge dev before finishing. - Licence: confirm the sveltebits snippets' licence is AGPL-compatible and credit it in NOTICE if required. - Evidence: frame strips of on/off and check/uncheck/indeterminate at 1x and 2x, light and dark (theme asserted), reduced-motion capture; a list of every call site migrated.
Author
Owner

Starting work on branch job/micro-motion from dev at d0d83a32b41e67b64f6586690ba4946e41878160.

Starting work on branch `job/micro-motion` from `dev` at `d0d83a32b41e67b64f6586690ba4946e41878160`.
Author
Owner

Finding: the upstream SvelteBits repository's LICENSE.md is MIT + Commons Clause and says the components may not be redistributed as a ported version. The repo's existing packages/ui/src/components/tooltip/warmth.ts records that the same terms are incompatible with AGPL-3.0-only. I will implement the observed squish and spring-check behavior independently with calternal tokens and the #291 shared spring driver; I will not copy the snippets, so no NOTICE attribution for copied code is needed.

Finding: the upstream SvelteBits repository's `LICENSE.md` is MIT + Commons Clause and says the components may not be redistributed as a ported version. The repo's existing `packages/ui/src/components/tooltip/warmth.ts` records that the same terms are incompatible with AGPL-3.0-only. I will implement the observed squish and spring-check behavior independently with calternal tokens and the #291 shared spring driver; I will not copy the snippets, so no NOTICE attribution for copied code is needed.
Author
Owner

Finding: the shared-control scan found six native checkbox inputs across the composer, Notes conversion, Note selection, search saving, mail settings and recovery-key acknowledgement. Photos has a separate role="checkbox" day selector, menus draw checked checkbox items themselves, and the Tiptap task list is styled as a native input in NoteEditorSurface.svelte. These call sites currently use different markup and drawing. I am moving them to one Checkbox in packages/ui, with native inputs retained where form behavior requires them and button semantics retained for tri-state selection.

Finding: the shared-control scan found six native checkbox inputs across the composer, Notes conversion, Note selection, search saving, mail settings and recovery-key acknowledgement. Photos has a separate `role="checkbox"` day selector, menus draw checked checkbox items themselves, and the Tiptap task list is styled as a native input in `NoteEditorSurface.svelte`. These call sites currently use different markup and drawing. I am moving them to one `Checkbox` in `packages/ui`, with native inputs retained where form behavior requires them and button semantics retained for tri-state selection.
Author
Owner

Finding: the standalone packages/editor test config does not define the app's $lib alias. Importing Checkbox through the full @calternal/ui barrel causes Vite to transform Menu.svelte and fail on $lib/menuNav. I will expose the shared checkbox at the direct @calternal/ui/Checkbox.svelte package subpath and use that from the task node view. This is a small public export that keeps the editor dependency narrow.

Finding: the standalone `packages/editor` test config does not define the app's `$lib` alias. Importing `Checkbox` through the full `@calternal/ui` barrel causes Vite to transform `Menu.svelte` and fail on `$lib/menuNav`. I will expose the shared checkbox at the direct `@calternal/ui/Checkbox.svelte` package subpath and use that from the task node view. This is a small public export that keeps the editor dependency narrow.
Author
Owner

During review, I found that the Files tile selection mark had lost its glass-media surface during the shared-component migration. The new Checkbox mark now restores that surface while keeping the 22 px mark and existing tile position. The focused UI regression set passes (5 files, 13 tests). Fix is in 0943e13a.

During review, I found that the Files tile selection mark had lost its `glass-media` surface during the shared-component migration. The new Checkbox mark now restores that surface while keeping the 22 px mark and existing tile position. The focused UI regression set passes (5 files, 13 tests). Fix is in 0943e13a.
Author
Owner

The first production build exposed an unused .day-check selector in PhotoTimeline after the control moved into Checkbox.svelte. The reduced-motion rule now targets the shared component's global class. Fix is in 5d388e53; I will rebuild before capture.

The first production build exposed an unused `.day-check` selector in PhotoTimeline after the control moved into Checkbox.svelte. The reduced-motion rule now targets the shared component's global class. Fix is in 5d388e53; I will rebuild before capture.
Author
Owner

Production screenshot harness finding: the Photos selection helper cannot reach the “More actions” item at 820 px because the mode header folds that item at this width. The run captured the empty state and timeline/viewer states, then timed out on that selector. The app exposes touch long-press selection; I will use that path for checkbox evidence at the narrow widths. This is a screenshot-helper mismatch, not an observed Photos selection failure.

Production screenshot harness finding: the Photos selection helper cannot reach the “More actions” item at 820 px because the mode header folds that item at this width. The run captured the empty state and timeline/viewer states, then timed out on that selector. The app exposes touch long-press selection; I will use that path for checkbox evidence at the narrow widths. This is a screenshot-helper mismatch, not an observed Photos selection failure.
Author
Owner

Production screenshot navigation after merging dev emitted an uncaught browser error:

TypeError: Cannot read properties of null (reading 'origin')

The stack points to apps/web/src/lib/components/app-sidebar.svelte:200. The afterNavigate handler checks from and to, then reads from.url.origin and to.url.origin without checking either url. Photos screenshots still completed, but this is a client error during route changes. I left the unrelated sidebar navigation behavior unchanged in #406.

Production screenshot navigation after merging `dev` emitted an uncaught browser error: ```text TypeError: Cannot read properties of null (reading 'origin') ``` The stack points to `apps/web/src/lib/components/app-sidebar.svelte:200`. The `afterNavigate` handler checks `from` and `to`, then reads `from.url.origin` and `to.url.origin` without checking either `url`. Photos screenshots still completed, but this is a client error during route changes. I left the unrelated sidebar navigation behavior unchanged in #406.
Author
Owner

The Files production screenshot probe found a phone touch-target regression in the new shared checkbox: the fc-select-all-control header measured below the existing 44 px target-floor assertion. Checkbox.svelte only applied the Files hit-area rule to .fc-check-control, while this caller keeps the .fc-select-all-control class. I added that existing class to the shared hit-area selector and rebuilt the production SPA. I kept the assertion unchanged.

The Files production screenshot probe found a phone touch-target regression in the new shared checkbox: the `fc-select-all-control` header measured below the existing 44 px target-floor assertion. `Checkbox.svelte` only applied the Files hit-area rule to `.fc-check-control`, while this caller keeps the `.fc-select-all-control` class. I added that existing class to the shared hit-area selector and rebuilt the production SPA. I kept the assertion unchanged.
Author
Owner

The production Composer repro for the End time checkbox exposed a broken correction path. In Log mode, entering 9-10 correction probe, long-pressing the parsed time, and choosing “Edit time…” closes the menu but leaves Composer open without its Edit time FieldPopover. The new E2E regression check times out waiting for the End time checkbox. onCorrectionAction clears correction before reading correctionList, which is derived from that same state; the selected action is then lost. I am retaining the action before closing the menu and will rerun the focused production flow.

The production Composer repro for the End time checkbox exposed a broken correction path. In Log mode, entering `9-10 correction probe`, long-pressing the parsed time, and choosing “Edit time…” closes the menu but leaves Composer open without its Edit time FieldPopover. The new E2E regression check times out waiting for the End time checkbox. `onCorrectionAction` clears `correction` before reading `correctionList`, which is derived from that same state; the selected action is then lost. I am retaining the action before closing the menu and will rerun the focused production flow.
Author
Owner

Production screenshot capture exposed a real Composer correction bug while opening the shared End time checkbox. Selecting “Edit time…” cleared the correction state before reading the selected row from the derived correctionList, so the popover never opened. I resolved the row first, then cleared the menu state, and added a production E2E regression that asserts the End time checkbox appears. The new flow passes. The broader Composer run later stops at the existing page-error assertion because the merged sidebar throws Cannot read properties of null (reading 'origin'); I left that expectation unchanged and recorded the sidebar finding separately.

Production screenshot capture exposed a real Composer correction bug while opening the shared End time checkbox. Selecting “Edit time…” cleared the `correction` state before reading the selected row from the derived `correctionList`, so the popover never opened. I resolved the row first, then cleared the menu state, and added a production E2E regression that asserts the End time checkbox appears. The new flow passes. The broader Composer run later stops at the existing page-error assertion because the merged sidebar throws `Cannot read properties of null (reading 'origin')`; I left that expectation unchanged and recorded the sidebar finding separately.
Author
Owner

Final report — #406

Branch job/micro-motion is pushed. Head: 740664bff4abe69da38f2bdac9698985335b44d0. The branch includes the single required merge from dev; there is no merge into dev.

Built

  • Added the shared animated Checkbox with none / some / all states, indeterminate accessibility semantics, and reduced-motion behavior. Migrated Files, Photos, menus, Editor tasks, Composer, recovery acknowledgement, Notes, saved-search pinning, conversion, and Mail controls. Removed the duplicate Files checkbox.
  • Added the squish spring to the shared Toggle. Its ::after thumb keeps the existing contrast-token contract and switch geometry.
  • Fixed the Composer correction action. It now resolves the selected time row before clearing its derived list. The added production E2E reaches and asserts the End time checkbox.
  • While capturing Files evidence, fixed the shared checkbox selector so Files keeps its existing 44 px touch target.

Changed files

apps/web/e2e/{composer,files,photos}.mjs; apps/web/src/lib/auth/components/RecoveryKeyWords.svelte; apps/web/src/lib/components/{FieldPopover.svelte.test.ts,NoteList.svelte,Toggle.svelte.test.ts,search-dialog.svelte}; apps/web/src/lib/composer/Composer.svelte; apps/web/src/lib/files/FileCollection.svelte.test.ts; apps/web/src/lib/notes/NoteEditorSurface.svelte; apps/web/src/lib/photos/PhotoTimeline.svelte; apps/web/src/routes/notes/convert/+page.svelte; apps/web/src/routes/settings/mail/MailSection.svelte; packages/editor/src/{Editor.svelte.test.ts,components/TaskItemView.svelte,extensions.ts}; packages/ui/package.json; packages/ui/src/components/{Checkbox.svelte,Toggle.svelte,composer/FieldPopover.svelte,files/FileCollection.svelte,files/FileSelectionCheckbox.svelte,menu/MenuItem.svelte}; packages/ui/src/index.ts.

Gates and evidence

bun run check output:

Loading svelte-check in workspace: /home/kayg/Developer/calternal-wt/micro-motion/apps/web
Getting Svelte diagnostics...

svelte-check found 0 errors and 0 warnings

bun run test output:

 Test Files  126 passed (126)
      Tests  802 passed (802)
   Start at  12:04:32
   Duration  81.44s (transform 55%, environment 17%, import 15%, tests 9%, setup 3%)

cargo fmt --check: exit 0, no output. Clippy was stopped at the owner’s approximately four-hour job limit (exit 130, no lint diagnostic before interruption). cargo test and the one adversarial round remain unrun. cargo clean completed: Removed 12428 files, 6.3GiB total.

Production evidence: Files matrix passed (FILES SCREENSHOTS PASSED; CSP REPORTS files: 0 across 3 pages). Photos matrix passed (PHOTOS SCREENSHOTS PASSED; CSP REPORTS photos: 0 across 2 pages). The cross-surface production capture completed at 390 / 820 / 1440 px in light and dark. Composer’s new correction assertion passed, then that broader run failed its existing no-page-errors assertion because of the sidebar error below.

Attached screenshot sheets

Shared control call sites: Files menu, Notes list, none, Notes list, selected, Editor task, Notes conversion, Mail, Appearance switch, Composer End time, Search pin, Recovery acknowledgement crop.

Files selection: Files, Recent, Trash.

Photos: timelines and scrubber, viewer, tags, stack, upload, selection.

Motion: spring frames, reduced motion.

Known gap and decisions

  • Merged dev sidebar navigation throws TypeError: Cannot read properties of null (reading 'origin') in app-sidebar.svelte:200 when from.url or to.url is null. Photos screenshot-only logs it; Composer E2E later fails its existing page-errors assertion. This was reported separately and left unchanged.
  • SvelteBits upstream is MIT plus Commons Clause, which does not meet this repo’s AGPL-compatible dependency/source rule. No upstream source was copied; the motion was implemented independently, so no NOTICE credit was added.
  • The shared checkbox uses explicit tri-state values and preserves the existing checkbox box/layout for #398. The switch draws the animated thumb on ::after to preserve its established token contrast test and geometry.

The cargo completion and adversarial round are the remaining gates for a later time-boxed pass. Issue remains open.

## Final report — #406 Branch `job/micro-motion` is pushed. Head: `740664bff4abe69da38f2bdac9698985335b44d0`. The branch includes the single required merge from `dev`; there is no merge into `dev`. ### Built - Added the shared animated `Checkbox` with `none` / `some` / `all` states, indeterminate accessibility semantics, and reduced-motion behavior. Migrated Files, Photos, menus, Editor tasks, Composer, recovery acknowledgement, Notes, saved-search pinning, conversion, and Mail controls. Removed the duplicate Files checkbox. - Added the squish spring to the shared `Toggle`. Its `::after` thumb keeps the existing contrast-token contract and switch geometry. - Fixed the Composer correction action. It now resolves the selected time row before clearing its derived list. The added production E2E reaches and asserts the End time checkbox. - While capturing Files evidence, fixed the shared checkbox selector so Files keeps its existing 44 px touch target. ### Changed files `apps/web/e2e/{composer,files,photos}.mjs`; `apps/web/src/lib/auth/components/RecoveryKeyWords.svelte`; `apps/web/src/lib/components/{FieldPopover.svelte.test.ts,NoteList.svelte,Toggle.svelte.test.ts,search-dialog.svelte}`; `apps/web/src/lib/composer/Composer.svelte`; `apps/web/src/lib/files/FileCollection.svelte.test.ts`; `apps/web/src/lib/notes/NoteEditorSurface.svelte`; `apps/web/src/lib/photos/PhotoTimeline.svelte`; `apps/web/src/routes/notes/convert/+page.svelte`; `apps/web/src/routes/settings/mail/MailSection.svelte`; `packages/editor/src/{Editor.svelte.test.ts,components/TaskItemView.svelte,extensions.ts}`; `packages/ui/package.json`; `packages/ui/src/components/{Checkbox.svelte,Toggle.svelte,composer/FieldPopover.svelte,files/FileCollection.svelte,files/FileSelectionCheckbox.svelte,menu/MenuItem.svelte}`; `packages/ui/src/index.ts`. ### Gates and evidence `bun run check` output: ```text Loading svelte-check in workspace: /home/kayg/Developer/calternal-wt/micro-motion/apps/web Getting Svelte diagnostics... svelte-check found 0 errors and 0 warnings ``` `bun run test` output: ```text Test Files 126 passed (126) Tests 802 passed (802) Start at 12:04:32 Duration 81.44s (transform 55%, environment 17%, import 15%, tests 9%, setup 3%) ``` `cargo fmt --check`: exit 0, no output. Clippy was stopped at the owner’s approximately four-hour job limit (exit 130, no lint diagnostic before interruption). `cargo test` and the one adversarial round remain unrun. `cargo clean` completed: `Removed 12428 files, 6.3GiB total`. Production evidence: Files matrix passed (`FILES SCREENSHOTS PASSED`; `CSP REPORTS files: 0 across 3 pages`). Photos matrix passed (`PHOTOS SCREENSHOTS PASSED`; `CSP REPORTS photos: 0 across 2 pages`). The cross-surface production capture completed at 390 / 820 / 1440 px in light and dark. Composer’s new correction assertion passed, then that broader run failed its existing no-page-errors assertion because of the sidebar error below. ### Attached screenshot sheets Shared control call sites: [Files menu](https://git.kayg.org/attachments/b2bbbdfa-8bd1-40a7-af83-e6f2ddb4944f), [Notes list, none](https://git.kayg.org/attachments/e1d990a6-cac0-43e7-9d50-f70a11320d1f), [Notes list, selected](https://git.kayg.org/attachments/19bdbbbb-7467-4a65-8368-020cfafd831a), [Editor task](https://git.kayg.org/attachments/4693afe9-6c84-4f22-8333-8551d32cfccc), [Notes conversion](https://git.kayg.org/attachments/265e0c52-ed50-4b7a-a800-90280376bdaa), [Mail](https://git.kayg.org/attachments/5fe3c0de-b796-45f9-89cb-ad16d99ef63e), [Appearance switch](https://git.kayg.org/attachments/7d0f4a66-a6df-4b8a-a196-8ba127aa2189), [Composer End time](https://git.kayg.org/attachments/e0a3323d-bffd-4e75-939e-3207bef0b774), [Search pin](https://git.kayg.org/attachments/e6049909-c8a0-444f-9a02-40c2b8b85ede), [Recovery acknowledgement crop](https://git.kayg.org/attachments/aaa6b06b-bf0d-47db-8a86-57d7a071e30a). Files selection: [Files](https://git.kayg.org/attachments/2f81e902-51c2-475e-9956-122aa3e790a6), [Recent](https://git.kayg.org/attachments/e33042bc-5b4a-4a7a-a86a-be6ca88044a4), [Trash](https://git.kayg.org/attachments/231d8329-48c5-45ed-815f-31beff070e2b). Photos: [timelines and scrubber](https://git.kayg.org/attachments/a0703d13-7872-449d-9524-7dce764d7e05), [viewer, tags, stack, upload](https://git.kayg.org/attachments/8f577ef7-d427-4cc5-a84f-2b3db16a4f74), [selection](https://git.kayg.org/attachments/f1922e72-accc-4d25-9c5f-2f747aa49376). Motion: [spring frames](https://git.kayg.org/attachments/f1069b85-b4c4-4059-bbe3-fb0c71b25a7d), [reduced motion](https://git.kayg.org/attachments/67f49d37-ba66-452f-8929-ad983fcd5062). ### Known gap and decisions - Merged `dev` sidebar navigation throws `TypeError: Cannot read properties of null (reading 'origin')` in `app-sidebar.svelte:200` when `from.url` or `to.url` is null. Photos screenshot-only logs it; Composer E2E later fails its existing page-errors assertion. This was reported separately and left unchanged. - SvelteBits upstream is MIT plus Commons Clause, which does not meet this repo’s AGPL-compatible dependency/source rule. No upstream source was copied; the motion was implemented independently, so no NOTICE credit was added. - The shared checkbox uses explicit tri-state values and preserves the existing checkbox box/layout for #398. The switch draws the animated thumb on `::after` to preserve its established token contrast test and geometry. The cargo completion and adversarial round are the remaining gates for a later time-boxed pass. Issue remains open.
Author
Owner

Resuming #406 on job/micro-motion at 740664bff4abe69da38f2bdac9698985335b44d0. Base at start: c86f2ab30d119f09a33ca96dc5a7f6ff0bb96b4d. I read CLAUDE.md, CONTEXT.md and DESIGN.md sections 3, 15, 28, 35 and 38. I will merge dev once, preserve #398's shared Files tracks and always-rendered marks, add the spring checkbox within that structure, rerun the alignment sweep, capture the requested motion evidence and run the web gates.

Resuming #406 on `job/micro-motion` at `740664bff4abe69da38f2bdac9698985335b44d0`. Base at start: `c86f2ab30d119f09a33ca96dc5a7f6ff0bb96b4d`. I read CLAUDE.md, CONTEXT.md and DESIGN.md sections 3, 15, 28, 35 and 38. I will merge `dev` once, preserve #398's shared Files tracks and always-rendered marks, add the spring checkbox within that structure, rerun the alignment sweep, capture the requested motion evidence and run the web gates.
Author
Owner

Merge update: dev is merged once at 32e94e8ad30bf860b2f29364b6ee82a05c760070. I kept #398's --fc-leading-columns, always-rendered row/tile marks and header track. FileSelectionCheckbox now delegates to the shared #406 Checkbox, so its classes preserve placement while the shared component draws and animates the mark. Validation so far: bun run check reported svelte-check found 0 errors and 0 warnings; focused component tests passed (3 files, 5 tests).

Merge update: `dev` is merged once at `32e94e8ad30bf860b2f29364b6ee82a05c760070`. I kept #398's `--fc-leading-columns`, always-rendered row/tile marks and header track. `FileSelectionCheckbox` now delegates to the shared #406 Checkbox, so its classes preserve placement while the shared component draws and animates the mark. Validation so far: `bun run check` reported `svelte-check found 0 errors and 0 warnings`; focused component tests passed (3 files, 5 tests).
Author
Owner

Correction to the merge update: the full merge commit SHA is 32e94e8acd4829fb0aa01bb2fccafd0e4de4fcf0 (not the mistyped SHA in my previous comment).

Correction to the merge update: the full merge commit SHA is `32e94e8acd4829fb0aa01bb2fccafd0e4de4fcf0` (not the mistyped SHA in my previous comment).
Author
Owner

The Files alignment sweep found that the interactive header mark no longer has the .fc-check class. bun e2e/layout-sweep.mjs --only select-list reports missing: true for all 12 width/theme/scale combinations; the follow-up paint check then fails because its selector returns no Element. The row mark still uses .fc-check, while the interactive control puts .fc-check-control on its button. I will add the existing mark class to the shared Checkbox indicator used by the Files header, preserving the 22 px mark and #398 grid tracks, then rerun the sweep.

The Files alignment sweep found that the interactive header mark no longer has the `.fc-check` class. `bun e2e/layout-sweep.mjs --only select-list` reports `missing: true` for all 12 width/theme/scale combinations; the follow-up paint check then fails because its selector returns no Element. The row mark still uses `.fc-check`, while the interactive control puts `.fc-check-control` on its button. I will add the existing mark class to the shared Checkbox indicator used by the Files header, preserving the 22 px mark and #398 grid tracks, then rerun the sweep.
Author
Owner

The fix is committed as 76a83ce3 (fix(files): preserve checkbox mark hook). The Files alignment sweep now passes at 390, 820 and 1440 px, in Paper and Tokyo Night, at 100% and 200% text size. Every measured checkbox/name x-offset is 0 px; the largest cap-height y-offset is 0.15625 px. Output ends with LAYOUT SWEEP PASSED.

The fix is committed as `76a83ce3` (`fix(files): preserve checkbox mark hook`). The Files alignment sweep now passes at 390, 820 and 1440 px, in Paper and Tokyo Night, at 100% and 200% text size. Every measured checkbox/name x-offset is 0 px; the largest cap-height y-offset is 0.15625 px. Output ends with `LAYOUT SWEEP PASSED`.
Author
Owner

The 820 px production capture found that the shared desktop dialog is not horizontally centered: left: 50% places its 580 px surface at x=410, so its right edge is x=990 outside the 820 px viewport. The Expires control is then unreachable in the dialog. The 1440 px measurement shows the same rightward offset. I will correct the shared dialog's independent translate so it centers on both axes, then rerun the production captures and e2e flows.

The 820 px production capture found that the shared desktop dialog is not horizontally centered: `left: 50%` places its 580 px surface at x=410, so its right edge is x=990 outside the 820 px viewport. The Expires control is then unreachable in the dialog. The 1440 px measurement shows the same rightward offset. I will correct the shared dialog's independent `translate` so it centers on both axes, then rerun the production captures and e2e flows.
Author
Owner

bun run test:e2e:composer reported zero page errors, then exited during its first screenshot. The harness expected computed colorScheme system for stored mode: system, but Chromium reported light ('light' !== 'system') while the palette remained mono; the preceding PASS time correction opens the End time checkbox had passed. I left the shared theme assertion unchanged because this job does not change system-theme behavior.

`bun run test:e2e:composer` reported zero page errors, then exited during its first screenshot. The harness expected computed `colorScheme` `system` for stored `mode: system`, but Chromium reported `light` (`'light' !== 'system'`) while the palette remained `mono`; the preceding `PASS time correction opens the End time checkbox` had passed. I left the shared theme assertion unchanged because this job does not change system-theme behavior.
Author
Owner

bun run test:e2e:files reported CSP REPORTS files: 0 across 1 pages, then failed at apps/web/e2e/files.mjs:373: its assertion requires the Pinned sidebar section to precede Smart folders. The run exited with AssertionError: false == true; I did not change the existing sidebar expectation.

`bun run test:e2e:files` reported `CSP REPORTS files: 0 across 1 pages`, then failed at `apps/web/e2e/files.mjs:373`: its assertion requires the `Pinned` sidebar section to precede `Smart folders`. The run exited with `AssertionError: false == true`; I did not change the existing sidebar expectation.
Author
Owner

bun run test:e2e:photos passed its empty-state, timeline, zoom, scrubber, viewer, and /p/<id> checks, then reported CSP REPORTS photos: 0 across 2 pages. It timed out at apps/web/e2e/photos.mjs:626 after Escape closed the viewer because the test could not find the May 2024 heading within 30 seconds. I left that existing expectation unchanged. The helper wrote /tmp/photos-e2e-failure-1790693724250.png; I am removing that temporary file after recording the failure.

`bun run test:e2e:photos` passed its empty-state, timeline, zoom, scrubber, viewer, and `/p/<id>` checks, then reported `CSP REPORTS photos: 0 across 2 pages`. It timed out at `apps/web/e2e/photos.mjs:626` after Escape closed the viewer because the test could not find the `May 2024` heading within 30 seconds. I left that existing expectation unchanged. The helper wrote `/tmp/photos-e2e-failure-1790693724250.png`; I am removing that temporary file after recording the failure.
Author
Owner

#406 final status

Branch: job/micro-motion
HEAD: d9802aab11c68ff8f013a582ec88d91488634428
The branch includes the required dev merge (32e94e8acd4829fb0aa01bb2fccafd0e4de4fcf0). The worktree is clean. No push, deploy, or promotion was made.

Built

  • Added thumb-only spring squish to the shared Toggle and a spring check draw-in to the shared Checkbox. The Checkbox supports checked, unchecked, and indeterminate states; wrappers keep their existing geometry and reduced motion disables the transition.
  • Integrated the shared Checkbox into Files while preserving #398's shared grid tracks, persistent marks, and .fc-check hook. The production Files alignment sweep passed at 390, 820, and 1440 px, paper and Tokyo Night, 100% and 200%: horizontal offsets stayed at 0 px.
  • Corrected shared dialog centering after the production sweep found clipped/off-center desktop Share surfaces.
  • Added production-build CDP frame capture and regression coverage.

Code files: packages/ui/src/components/{Toggle.svelte,Checkbox.svelte,OverlaySurface.svelte}, packages/ui/src/components/files/{FileCollection.svelte,FileSelectionCheckbox.svelte}, apps/web/src/lib/files/FileCollection.svelte.test.ts, apps/web/e2e/micro-motion-evidence.mjs.

Visual evidence remains local and uncommitted in artifacts/micro-motion/: the manifest contains 54 captures and the directory has 89 PNGs. It covers switch on/off; checkbox check/uncheck/some-to-all; reduced-motion and 3x rest crops; widths 390, 820, 1440; paper and Tokyo Night. The 500 ms strips contain the captured compositor frames.

Completed gates

bun run check:

Text sizes use shared role tokens.
Loading svelte-check in workspace: /home/kayg/Developer/calternal-wt/micro-motion/apps/web
Getting Svelte diagnostics...

svelte-check found 0 errors and 0 warnings

bun run test:

 Test Files  126 passed (126)
      Tests  803 passed (803)
   Start at  16:58:47
   Duration  125.31s (transform 52%, environment 21%, import 14%, tests 10%, setup 4%)

Rust gates completed after the dev merge:

cargo fmt --check: exit 0, no output
cargo clippy -p calternal-auth --all-targets -- -D warnings
Finished dev profile [unoptimized + debuginfo] target(s) in 29m 28s
cargo test -p calternal-auth
 test result: ok. 63 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 30.15s
Doc-tests calternal_auth
running 0 tests
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s
cargo clippy -p calternal-cli --all-targets -- -D warnings
Finished dev profile [unoptimized + debuginfo] target(s) in 19m 51s
cargo test -p calternal-cli
 test result: ok. 23 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.77s
 test result: ok. 15 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 1.17s
cargo clippy -p calternal-collab --all-targets -- -D warnings
Finished `dev` profile [unoptimized + debuginfo] target(s) in 23m 49s
cargo test -p calternal-collab
 test result: ok. 24 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.75s
 test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 80.15s
 test result: ok. 11 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 10.46s
 test result: ok. 5 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 30.27s
 test result: ok. 15 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.08s
 test result: ok. 5 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 21.99s
Doc-tests calternal_collab
running 0 tests
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s

The captured production E2E runs for composer, Files, and Photos reported no browser page errors. They did not all pass their existing functional assertions:

  • Composer stopped at the shared theme assertion (light computed vs stored system) after the time-correction checkbox check passed.
  • Files stopped at the existing ordering assertion for Pinned vs Smart folders (AssertionError: false == true).
  • Photos passed its earlier timeline and viewer checks, then timed out waiting for May 2024 after Escape closed the viewer.
    These expectations were left unchanged.

Remaining gates and known gaps

This job exceeded the owner’s approximately four-hour work limit (first feature commit: 07:43 CEST; stop: about 20:00 CEST). I stopped the active calternal-server clippy process and did not run cargo test -p calternal-server or the one-time adversarial server round. At interruption the log had reached Checking oauth2 v5.0.0; the process ended with:

EXIT_CODE=130

The server clippy gate and server tests remain outstanding, as does the adversarial round for the server/API changes in the merged dev history.

cargo clean removed 10.0 GiB, and apps/web/build was removed. No screenshot or video was committed.

Decisions not specified by DESIGN

  • The motion uses CSS spring transitions and animates only the switch thumb and checkbox mark. It keeps control bounds fixed and disables motion for reduced-motion users.
  • I used an independent CSS/SVG implementation because SvelteBits is MIT plus Commons Clause; no SvelteBits source was copied.
  • The evidence helper records real production UI actions with Chromium CDP compositor frames, including an explicit settled frame and 3x rest crops.
  • The desktop dialog centering correction was required by real-build evidence; DESIGN did not specify the observed Share-surface offset.
# #406 final status Branch: `job/micro-motion` HEAD: `d9802aab11c68ff8f013a582ec88d91488634428` The branch includes the required `dev` merge (`32e94e8acd4829fb0aa01bb2fccafd0e4de4fcf0`). The worktree is clean. No push, deploy, or promotion was made. ## Built - Added thumb-only spring squish to the shared Toggle and a spring check draw-in to the shared Checkbox. The Checkbox supports checked, unchecked, and indeterminate states; wrappers keep their existing geometry and reduced motion disables the transition. - Integrated the shared Checkbox into Files while preserving #398's shared grid tracks, persistent marks, and `.fc-check` hook. The production Files alignment sweep passed at 390, 820, and 1440 px, paper and Tokyo Night, 100% and 200%: horizontal offsets stayed at `0 px`. - Corrected shared dialog centering after the production sweep found clipped/off-center desktop Share surfaces. - Added production-build CDP frame capture and regression coverage. Code files: `packages/ui/src/components/{Toggle.svelte,Checkbox.svelte,OverlaySurface.svelte}`, `packages/ui/src/components/files/{FileCollection.svelte,FileSelectionCheckbox.svelte}`, `apps/web/src/lib/files/FileCollection.svelte.test.ts`, `apps/web/e2e/micro-motion-evidence.mjs`. Visual evidence remains local and uncommitted in `artifacts/micro-motion/`: the manifest contains 54 captures and the directory has 89 PNGs. It covers switch on/off; checkbox check/uncheck/some-to-all; reduced-motion and 3x rest crops; widths 390, 820, 1440; paper and Tokyo Night. The 500 ms strips contain the captured compositor frames. ## Completed gates `bun run check`: ```text Text sizes use shared role tokens. Loading svelte-check in workspace: /home/kayg/Developer/calternal-wt/micro-motion/apps/web Getting Svelte diagnostics... svelte-check found 0 errors and 0 warnings ``` `bun run test`: ```text Test Files 126 passed (126) Tests 803 passed (803) Start at 16:58:47 Duration 125.31s (transform 52%, environment 21%, import 14%, tests 10%, setup 4%) ``` Rust gates completed after the `dev` merge: ```text cargo fmt --check: exit 0, no output cargo clippy -p calternal-auth --all-targets -- -D warnings Finished dev profile [unoptimized + debuginfo] target(s) in 29m 28s cargo test -p calternal-auth test result: ok. 63 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 30.15s Doc-tests calternal_auth running 0 tests test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s cargo clippy -p calternal-cli --all-targets -- -D warnings Finished dev profile [unoptimized + debuginfo] target(s) in 19m 51s cargo test -p calternal-cli test result: ok. 23 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.77s test result: ok. 15 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 1.17s cargo clippy -p calternal-collab --all-targets -- -D warnings Finished `dev` profile [unoptimized + debuginfo] target(s) in 23m 49s cargo test -p calternal-collab test result: ok. 24 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.75s test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 80.15s test result: ok. 11 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 10.46s test result: ok. 5 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 30.27s test result: ok. 15 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.08s test result: ok. 5 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 21.99s Doc-tests calternal_collab running 0 tests test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.00s ``` The captured production E2E runs for composer, Files, and Photos reported no browser page errors. They did not all pass their existing functional assertions: - Composer stopped at the shared theme assertion (`light` computed vs stored `system`) after the time-correction checkbox check passed. - Files stopped at the existing ordering assertion for `Pinned` vs `Smart folders` (`AssertionError: false == true`). - Photos passed its earlier timeline and viewer checks, then timed out waiting for `May 2024` after Escape closed the viewer. These expectations were left unchanged. ## Remaining gates and known gaps This job exceeded the owner’s approximately four-hour work limit (first feature commit: 07:43 CEST; stop: about 20:00 CEST). I stopped the active `calternal-server` clippy process and did not run `cargo test -p calternal-server` or the one-time adversarial server round. At interruption the log had reached `Checking oauth2 v5.0.0`; the process ended with: ```text EXIT_CODE=130 ``` The server clippy gate and server tests remain outstanding, as does the adversarial round for the server/API changes in the merged `dev` history. `cargo clean` removed 10.0 GiB, and `apps/web/build` was removed. No screenshot or video was committed. ## Decisions not specified by DESIGN - The motion uses CSS spring transitions and animates only the switch thumb and checkbox mark. It keeps control bounds fixed and disables motion for reduced-motion users. - I used an independent CSS/SVG implementation because SvelteBits is MIT plus Commons Clause; no SvelteBits source was copied. - The evidence helper records real production UI actions with Chromium CDP compositor frames, including an explicit settled frame and 3x rest crops. - The desktop dialog centering correction was required by real-build evidence; DESIGN did not specify the observed Share-surface offset.
Author
Owner

Starting merge-only round 3 on branch job/micro-motion, current head/base SHA d9802aab11c68ff8f013a582ec88d91488634428. I will fetch origin/dev, merge it, resolve the two named conflicts while preserving dev's shared Settings rows and #398 selection tests plus the accepted Toggle and Checkbox motion, then run bun run check and the full bun run test.

Starting merge-only round 3 on branch `job/micro-motion`, current head/base SHA `d9802aab11c68ff8f013a582ec88d91488634428`. I will fetch `origin/dev`, merge it, resolve the two named conflicts while preserving dev's shared Settings rows and #398 selection tests plus the accepted Toggle and Checkbox motion, then run `bun run check` and the full `bun run test`.
Author
Owner

Merge finding: origin/dev converted Mail account groups to SettingsCard and SettingsRow, and used a native checkbox for the SMTP login preference. I kept the shared settings components and used the #406 Checkbox there for spring motion. FileCollection.svelte.test.ts now keeps #398's select-all assertions, #406's mixed-state drawing assertion, and dev's FileName coverage.

Merge finding: `origin/dev` converted Mail account groups to `SettingsCard` and `SettingsRow`, and used a native checkbox for the SMTP login preference. I kept the shared settings components and used the #406 `Checkbox` there for spring motion. `FileCollection.svelte.test.ts` now keeps #398's select-all assertions, #406's mixed-state drawing assertion, and dev's `FileName` coverage.
Author
Owner

Check finding: after the Mail preference moved to the shared Checkbox, svelte-check reported the old .same-login input selector as unused (0 errors, 1 warning in MailSection.svelte). I removed that stale native-input rule; the shared component owns the drawing and its 18 px size.

Check finding: after the Mail preference moved to the shared `Checkbox`, `svelte-check` reported the old `.same-login input` selector as unused (0 errors, 1 warning in `MailSection.svelte`). I removed that stale native-input rule; the shared component owns the drawing and its 18 px size.
Author
Owner

Finished merge-only round 3.

  • Merged origin/dev (918b4764aded5aa385ef784acb8887cf4361bf36) into job/micro-motion.
  • Resolved MailSection.svelte with dev's shared SettingsCard/SettingsRow behavior and the shared #406 Checkbox for the SMTP login preference. Resolved FileCollection.svelte.test.ts with dev's FileName coverage while preserving #398 selection assertions and #406 mixed-state checkbox coverage.
  • Merge commit: 7fe0c54dedfd5d3c36c5d4e387f9e79254325b5f (parents d9802aab11c68ff8f013a582ec88d91488634428 and 918b4764aded5aa385ef784acb8887cf4361bf36). Working tree is clean.

Gates run from apps/web:

bun run check

$ node scripts/check-type-tokens.mjs && svelte-kit sync && svelte-check --tsconfig ./tsconfig.json
Text sizes use shared role tokens.
Loading svelte-check in workspace: /home/kayg/Developer/calternal-wt/micro-motion/apps/web
Getting Svelte diagnostics...

svelte-check found 0 errors and 0 warnings

bun run test

$ vitest run

 RUN  v5.0.1 /home/kayg/Developer/calternal-wt/micro-motion/apps/web

 Test Files  129 passed (129)
      Tests  825 passed (825)
   Start at  20:14:40
   Duration  101.96s (transform 49%, environment 20%, import 15%, tests 11%, setup 5%)

Environment  |component| jsdom was created 41 times · 114.78s total, 28% of tracked time
             create it once per worker with pool: 'vmThreads' (keeps per-file isolation) or isolate: false (shares it across files)
             learn more at https://vitest.dev/guide/improving-performance#test-environments

No Rust changes or new screenshots. No additional design decisions were needed; the conflict choices followed the round 3 instructions.

Finished merge-only round 3. - Merged `origin/dev` (`918b4764aded5aa385ef784acb8887cf4361bf36`) into `job/micro-motion`. - Resolved `MailSection.svelte` with dev's shared `SettingsCard`/`SettingsRow` behavior and the shared #406 `Checkbox` for the SMTP login preference. Resolved `FileCollection.svelte.test.ts` with dev's `FileName` coverage while preserving #398 selection assertions and #406 mixed-state checkbox coverage. - Merge commit: `7fe0c54dedfd5d3c36c5d4e387f9e79254325b5f` (parents `d9802aab11c68ff8f013a582ec88d91488634428` and `918b4764aded5aa385ef784acb8887cf4361bf36`). Working tree is clean. Gates run from `apps/web`: `bun run check` ```text $ node scripts/check-type-tokens.mjs && svelte-kit sync && svelte-check --tsconfig ./tsconfig.json Text sizes use shared role tokens. Loading svelte-check in workspace: /home/kayg/Developer/calternal-wt/micro-motion/apps/web Getting Svelte diagnostics... svelte-check found 0 errors and 0 warnings ``` `bun run test` ```text $ vitest run RUN v5.0.1 /home/kayg/Developer/calternal-wt/micro-motion/apps/web Test Files 129 passed (129) Tests 825 passed (825) Start at 20:14:40 Duration 101.96s (transform 49%, environment 20%, import 15%, tests 11%, setup 5%) Environment |component| jsdom was created 41 times · 114.78s total, 28% of tracked time create it once per worker with pool: 'vmThreads' (keeps per-file isolation) or isolate: false (shares it across files) learn more at https://vitest.dev/guide/improving-performance#test-environments ``` No Rust changes or new screenshots. No additional design decisions were needed; the conflict choices followed the round 3 instructions.
kayg closed this issue 2026-09-29 18:20:40 +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#406
No description provided.