Files list: select-all circle not aligned with rows; icons and names jump right when selection starts #576

Open
opened 2026-10-01 05:29:10 +00:00 by kayg · 6 comments
Owner

Owner report (2026-10-01, screenshots on calternal.cloud cc25c441b): "still not properly aligned!"

Files list, default state (no selection): the header's select-all circle sits at x≈52, but the rows start with the folder icon at x≈75. The circle sits over a column that the rows do not have. In the selected state, the row circles line up under the header circle, but every folder icon and name jumps right (icon 75 → 120, name 122 → 168): a horizontal layout shift when selection mode starts. (The checkbox animation itself is OK.)
Fix (shared FileCollection header + row; Finder/Photos conventions):

  • The header's select-all control aligns with the rows' leading column in both states. In the default state, either (a) put the header control over the icon column, with the same centre x as the folder icons, or (b) reserve the mark column in the rows as an empty slot, so the icon never moves. Pick the one that keeps zero horizontal shift when selection mode turns on (the owner hates jumps). (b) with a narrow slot is likely best; justify it with screenshots of both.
  • Names never move when selection starts or ends. The mark fades/scales in place (the shared spring; none for keyboard, #527).
  • Check this against job/align-538 (#538, merged in round 4: the vertical centre line). This is the horizontal axis; keep both.
    Test: a layout assertion: the icon and name x positions are identical before and after Select All (±0.5 px); the header control's centre x equals the row mark/icon column's centre x. Screenshots at 390/820/1440, both themes, zoomed 3×. Web gates.
## Owner report (2026-10-01, screenshots on calternal.cloud cc25c441b): "still not properly aligned!" Files list, default state (no selection): the header's select-all circle sits at x≈52, but the rows start with the folder icon at x≈75. The circle sits over a column that the rows do not have. In the selected state, the row circles line up under the header circle, but every folder icon and name **jumps right** (icon 75 → 120, name 122 → 168): a horizontal layout shift when selection mode starts. (The checkbox animation itself is OK.) **Fix (shared FileCollection header + row; Finder/Photos conventions):** - The header's select-all control aligns with the rows' leading column **in both states**. In the default state, either (a) put the header control over the icon column, with the same centre x as the folder icons, or (b) reserve the mark column in the rows as an empty slot, so the icon never moves. Pick the one that keeps **zero horizontal shift** when selection mode turns on (the owner hates jumps). (b) with a narrow slot is likely best; justify it with screenshots of both. - Names never move when selection starts or ends. The mark fades/scales in place (the shared spring; none for keyboard, #527). - Check this against job/align-538 (#538, merged in round 4: the vertical centre line). This is the horizontal axis; keep both. **Test:** a layout assertion: the icon and name x positions are identical before and after Select All (±0.5 px); the header control's centre x equals the row mark/icon column's centre x. Screenshots at 390/820/1440, both themes, zoomed 3×. Web gates.
Author
Owner

Owner correction (2026-10-01): the right shift of icons and names when selection starts is intended (the checkboxes get their own column). The defect is only the default state: the header select-all circle (x≈52) does not sit over the rows' leading icon column (x≈75). Align the header control with the icon column in the default state, and with the row circles in selection mode.

**Owner correction (2026-10-01):** the right shift of icons and names when selection starts is **intended** (the checkboxes get their own column). The defect is only the default state: the header select-all circle (x≈52) does not sit over the rows' leading icon column (x≈75). Align the header control with the icon column in the default state, and with the row circles in selection mode.
Author
Owner

Starting work on job/selalign-576. Branch HEAD/base SHA: 1af8ead262; origin/dev at start: 687ff70313.

Starting work on job/selalign-576. Branch HEAD/base SHA: 1af8ead262daf0a4ad22a60564dc75bab0005cf4; origin/dev at start: 687ff703136e71e89f8dfba139e93cd0788b25c1.
Author
Owner

Finding from the component and production e2e code: .fc-head keeps the select-all checkbox as its first grid item while the selection track is 0 px, so the default control is placed over the collapsed mark track. The row icon remains in the next track. The current production e2e alignment check only compares header and row marks after selection; it does not check the default icon centre or the Name heading in either state. I am adding those geometry checks to the existing real-server screenshot flow.

Finding from the component and production e2e code: `.fc-head` keeps the select-all checkbox as its first grid item while the selection track is 0 px, so the default control is placed over the collapsed mark track. The row icon remains in the next track. The current production e2e alignment check only compares header and row marks after selection; it does not check the default icon centre or the Name heading in either state. I am adding those geometry checks to the existing real-server screenshot flow.
Author
Owner

The production E2E regression assertion failed on the existing layout as expected: desktop/light default state measured the header circle centre at 346.390625 CSS px and the row icon centre at 351.4375 CSS px (5.046875 px apart). The Name heading and row name both began at 368.484375 px. This isolates the default checkbox placement; the new CSS keeps it centred in the shared first track and shifts it to the icon centre while that track is collapsed.

The production E2E regression assertion failed on the existing layout as expected: desktop/light default state measured the header circle centre at 346.390625 CSS px and the row icon centre at 351.4375 CSS px (5.046875 px apart). The Name heading and row name both began at 368.484375 px. This isolates the default checkbox placement; the new CSS keeps it centred in the shared first track and shifts it to the icon centre while that track is collapsed.
Author
Owner

Finding: the shared motion tokens set every duration to 0 ms and force transition: none when data-input="keyboard". motion.ts also snapped Svelte transitions and springs, and the Settings shortcut had a separate instant-open flag. This still existed in origin/dev and conflicted with the 2026-10-01 owner override.

Evidence: four focused tests failed before the change (keyboard capsule transition, interactive spring, and two pill-feedback cases). After the shared policy change, the focused tests pass. The full web suite passes (148 files, 1,011 tests), and the real-production browser motion probe passes.

The shared tokens now apply equally to keyboard and pointer input; reduced-motion preferences still disable motion. The probe and production screenshots for Files, Today, Search, and Settings at 390/820/1440 px in light and dark are attached to this issue.

Finding: the shared motion tokens set every duration to 0 ms and force `transition: none` when `data-input="keyboard"`. `motion.ts` also snapped Svelte transitions and springs, and the Settings shortcut had a separate instant-open flag. This still existed in `origin/dev` and conflicted with the 2026-10-01 owner override. Evidence: four focused tests failed before the change (keyboard capsule transition, interactive spring, and two pill-feedback cases). After the shared policy change, the focused tests pass. The full web suite passes (148 files, 1,011 tests), and the real-production browser motion probe passes. The shared tokens now apply equally to keyboard and pointer input; reduced-motion preferences still disable motion. The probe and production screenshots for Files, Today, Search, and Settings at 390/820/1440 px in light and dark are attached to this issue.
Author
Owner

Final report — #576

Implemented and committed on job/selalign-576. The header select-all circle now aligns with the row icon centre while the selection track is collapsed, then aligns with the row mark centre when the 24px selection track appears. The intended icon/name shift on selection remains. The Name heading stays aligned with the row name in both states.

Geometry assertions passed within ±0.5 CSS px in default and selection states at 390, 820 and 1440 px in light and dark themes. The final production run also passed the reduced-motion check. Screenshot crops use browser rasterization at 3×; 18 crops (none/some/all marks × three widths × two themes) are in the ignored artifacts/selalign-576 directory.

Alignment evidence attached to this issue:

The shared motion change follows the 2026-10-01 owner override: keyboard and pointer actions now use the same motion tokens, and reduced-motion preferences still remove motion. Responsive production captures for Files, Today, Search and Settings at all three widths in both themes are also attached:

Performance profile

Added workloads.keyboard_motion to docs/perf/baseline.json. This is an initial local production-SPA profile with 1,000 real Files API entries. The shared host was busy (load average 8.89 / 11.29 / 15.62), so treat these as recorded local measurements, not a quiet-host comparison:

  • Average, 20 ArrowDown/ArrowUp moves: p50 11.65 ms, p95 25.59 ms; browser CPU 0.57 s (202.9% aggregate); RSS 619,630,592 → 624,361,472 B.
  • Burst, 100 moves: p50 9.34 ms, p95 20.78 ms; browser CPU 2.35 s (192.4% aggregate); peak browser RSS 664,879,104 B.

Commits

  • 4eae2296e — make keyboard actions use shared motion.
  • a9d839e17 — align the Files header select-all control.
  • 139f419ee — record the keyboard motion profile.
  • 174b554e1 — wait for an asynchronously loaded row in the reduced-motion E2E check.

Head SHA: 174b554e1a.

Gates

Web check output: svelte-check found 0 errors and 0 warnings
Web test output:

Test Files 148 passed (148)
Tests 1011 passed (1011)
Duration 69.52s (transform 51%, environment 18%, import 15%, tests 11%, setup 4%)

Production Files E2E output:

SELECTION_SCREENSHOTS /home/kayg/Developer/calternal-wt/selalign-576/apps/web/../../artifacts/selalign-576
FILES SELECTION E2E PASSED
CSP REPORTS files: 0 across 7 pages

Keyboard motion probe output: PASS keyboard and pointer selection, Tab and overlay transitions animate; reduced motion remains supported
Build output: ✓ built in 1m 6s
cargo clean output: Removed 7237 files, 4.6GiB total

No Rust crate or API route changed, so per-crate Rust gates and the API adversarial round did not apply. Known gap: the profile ran locally under high shared-host load and has no quiet perf-host comparator. The web test run showed existing jsdom CSS parse/scrollTo notices; the suite passed. The build emitted existing Vite “use client” module directive notices.

Decisions where DESIGN was silent

The collapsed-header offset uses the shared icon and toolbar-gap tokens, then animates translate with the existing morph spring. When the mark track opens, the offset becomes zero so the control and row marks share the same grid centre. The selection-mode row shift remains because the owner confirmed it is intended.

## Final report — #576 Implemented and committed on job/selalign-576. The header select-all circle now aligns with the row icon centre while the selection track is collapsed, then aligns with the row mark centre when the 24px selection track appears. The intended icon/name shift on selection remains. The Name heading stays aligned with the row name in both states. Geometry assertions passed within ±0.5 CSS px in default and selection states at 390, 820 and 1440 px in light and dark themes. The final production run also passed the reduced-motion check. Screenshot crops use browser rasterization at 3×; 18 crops (none/some/all marks × three widths × two themes) are in the ignored artifacts/selalign-576 directory. Alignment evidence attached to this issue: - No marks: [phone light](https://git.kayg.org/attachments/20e6e799-bd42-4156-850c-1852c8e577a0) · [phone dark](https://git.kayg.org/attachments/8a61509b-e94a-4622-bd68-cb5f89b81876) · [tablet light](https://git.kayg.org/attachments/acc0762b-4033-4a4a-a0ac-bb6116ca1b28) · [tablet dark](https://git.kayg.org/attachments/fe654239-f613-4d34-ae3b-11def8232eab) · [desktop light](https://git.kayg.org/attachments/3420c3f9-8ab8-4d0a-be30-0b75ac8d2038) · [desktop dark](https://git.kayg.org/attachments/3adc5461-bd2b-41a0-99d4-46e753f902d9) - All marked: [phone light](https://git.kayg.org/attachments/b539519b-b687-412c-9628-ae68d8a58dc5) · [phone dark](https://git.kayg.org/attachments/8a595ee6-2422-4a53-8c01-18b0738aba72) · [tablet light](https://git.kayg.org/attachments/001c88b4-0d46-4d4a-bc70-ad5794d58f1c) · [tablet dark](https://git.kayg.org/attachments/e01bf2dd-b0ab-470b-9c90-62ca5599b326) · [desktop light](https://git.kayg.org/attachments/5141b7b3-cef3-420b-a82b-3fd539063a76) · [desktop dark](https://git.kayg.org/attachments/3bc93b28-1a65-4a55-b555-9fb40c3e5aad) The shared motion change follows the 2026-10-01 owner override: keyboard and pointer actions now use the same motion tokens, and reduced-motion preferences still remove motion. Responsive production captures for Files, Today, Search and Settings at all three widths in both themes are also attached: - Files: [phone light](https://git.kayg.org/attachments/a3f1bdf0-3687-4d59-85a1-4ff811e573d2) · [phone dark](https://git.kayg.org/attachments/cc0e0945-e8e2-4ca5-a4b9-33cdc22b2a4b) · [tablet light](https://git.kayg.org/attachments/8f2dd5dc-8a7a-4f55-a938-cedf7f386150) · [tablet dark](https://git.kayg.org/attachments/ef71cfb2-fba4-4d56-a4bc-d851efa584b7) · [desktop light](https://git.kayg.org/attachments/94dc5111-1682-40a2-b9b0-016a5fedc828) · [desktop dark](https://git.kayg.org/attachments/e2df5918-d994-4bb3-a93a-c46d065a67e8) - Today: [phone light](https://git.kayg.org/attachments/ecdf7aba-3abe-42c8-a0b4-6a53d332ad90) · [phone dark](https://git.kayg.org/attachments/d57ff73e-04d4-4c64-847b-9becc458aa1b) · [tablet light](https://git.kayg.org/attachments/4988534e-16d1-4cf7-9996-a050d57aa824) · [tablet dark](https://git.kayg.org/attachments/9dde5fb6-72c4-44e1-8aa7-7f7bb289654e) · [desktop light](https://git.kayg.org/attachments/03c2f8f5-59fb-42f7-934e-62416f5d8f42) · [desktop dark](https://git.kayg.org/attachments/7c6fe328-235e-482f-a33d-a7646ccc6e4b) - Search: [phone light](https://git.kayg.org/attachments/cce6a4f3-41bb-47a3-96b4-2bef11578916) · [phone dark](https://git.kayg.org/attachments/dc57e2da-c5e0-4841-ac8b-655063420359) · [tablet light](https://git.kayg.org/attachments/485a93cb-b5d4-4ef7-9e2b-ffcfb9e9f589) · [tablet dark](https://git.kayg.org/attachments/624e8db4-e4e8-4b73-9980-4f97de69cd1d) · [desktop light](https://git.kayg.org/attachments/e6348d08-fd2f-466e-96c1-3555ce65ba10) · [desktop dark](https://git.kayg.org/attachments/2185907c-d9a1-4154-97fc-01c71d2ff7c5) - Settings: [phone light](https://git.kayg.org/attachments/e5e859bf-f2df-458a-9e05-e49ee53793f5) · [phone dark](https://git.kayg.org/attachments/3a15e3ee-f84c-4b83-b860-b4a1bc60a750) · [tablet light](https://git.kayg.org/attachments/f7030fc2-d9dd-4268-b221-e76db9633add) · [tablet dark](https://git.kayg.org/attachments/daf72dec-4a0b-43a3-bb95-0f20904802d5) · [desktop light](https://git.kayg.org/attachments/e5a66d6e-a45c-4830-8056-bfae9ef18887) · [desktop dark](https://git.kayg.org/attachments/8d1c1836-1078-44a2-b90f-ac2fe6799b9b) ### Performance profile Added workloads.keyboard_motion to docs/perf/baseline.json. This is an initial local production-SPA profile with 1,000 real Files API entries. The shared host was busy (load average 8.89 / 11.29 / 15.62), so treat these as recorded local measurements, not a quiet-host comparison: - Average, 20 ArrowDown/ArrowUp moves: p50 11.65 ms, p95 25.59 ms; browser CPU 0.57 s (202.9% aggregate); RSS 619,630,592 → 624,361,472 B. - Burst, 100 moves: p50 9.34 ms, p95 20.78 ms; browser CPU 2.35 s (192.4% aggregate); peak browser RSS 664,879,104 B. ### Commits - 4eae2296e — make keyboard actions use shared motion. - a9d839e17 — align the Files header select-all control. - 139f419ee — record the keyboard motion profile. - 174b554e1 — wait for an asynchronously loaded row in the reduced-motion E2E check. Head SHA: 174b554e1a66f53b0c9d92ede41b47eac145f419. ### Gates Web check output: svelte-check found 0 errors and 0 warnings Web test output: > Test Files 148 passed (148) > Tests 1011 passed (1011) > Duration 69.52s (transform 51%, environment 18%, import 15%, tests 11%, setup 4%) Production Files E2E output: > SELECTION_SCREENSHOTS /home/kayg/Developer/calternal-wt/selalign-576/apps/web/../../artifacts/selalign-576 > FILES SELECTION E2E PASSED > CSP REPORTS files: 0 across 7 pages Keyboard motion probe output: PASS keyboard and pointer selection, Tab and overlay transitions animate; reduced motion remains supported Build output: ✓ built in 1m 6s cargo clean output: Removed 7237 files, 4.6GiB total No Rust crate or API route changed, so per-crate Rust gates and the API adversarial round did not apply. Known gap: the profile ran locally under high shared-host load and has no quiet perf-host comparator. The web test run showed existing jsdom CSS parse/scrollTo notices; the suite passed. The build emitted existing Vite “use client” module directive notices. ### Decisions where DESIGN was silent The collapsed-header offset uses the shared icon and toolbar-gap tokens, then animates translate with the existing morph spring. When the mark track opens, the offset becomes zero so the control and row marks share the same grid centre. The selection-mode row shift remains because the owner confirmed it is intended.
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#576
No description provided.