Page title jumps when the sidebar toggles; Files Size/Kind column gap #1158

Open
opened 2026-10-05 15:33:27 +00:00 by kayg · 3 comments
Owner

Follow-up to #1138 (orchestrator review, 2026-10-05)

#1138 keeps the content column fixed when the sidebar opens/closes at wide widths (verified at 1920: the file list does not move). One jump remains: the page title ("Files") moves ~45 px because the sidebar toggle button is placed before the title only while the sidebar is collapsed.

Expected: when the window has room (the toggle fits in the left margin outside the content column), the collapsed-state toggle sits in the margin to the left of the content column, vertically centred on the title, so the title's x never changes between open and collapsed. At widths where it does not fit, keep today's inline placement. Same on every Tab. Also: Files list Size and Kind columns have no gap between them ("718 KB" butts against "HEIC image"; headers "Size" "Kind" touch): one column-gap token between all columns, Size header right-aligned with its values.

Evidence: e2e measures the page title's left edge open vs collapsed at 1920/1440/1024 (equal where the toggle fits); 4x crops; screenshots light + dark.

## Follow-up to #1138 (orchestrator review, 2026-10-05) #1138 keeps the content column fixed when the sidebar opens/closes at wide widths (verified at 1920: the file list does not move). One jump remains: the page title ("Files") moves ~45 px because the sidebar toggle button is placed before the title only while the sidebar is collapsed. Expected: when the window has room (the toggle fits in the left margin outside the content column), the collapsed-state toggle sits in the margin to the left of the content column, vertically centred on the title, so the title's x never changes between open and collapsed. At widths where it does not fit, keep today's inline placement. Same on every Tab. Also: Files list Size and Kind columns have no gap between them ("718 KB" butts against "HEIC image"; headers "Size" "Kind" touch): one column-gap token between all columns, Size header right-aligned with its values. Evidence: e2e measures the page title's left edge open vs collapsed at 1920/1440/1024 (equal where the toggle fits); 4x crops; screenshots light + dark.
Author
Owner

Starting #1158 on branch job/toggle-1158, based at c0d17b64a11593b6bb63b10f9e8ef4ca841fe9fe (the current origin/dev merge base). I will keep the shared Top row title fixed when the collapsed sidebar toggle can fit in the margin, and add the Files list column gap and right-align Size. I will verify at the requested widths and themes using the real production build.

Starting #1158 on branch `job/toggle-1158`, based at `c0d17b64a11593b6bb63b10f9e8ef4ca841fe9fe` (the current `origin/dev` merge base). I will keep the shared Top row title fixed when the collapsed sidebar toggle can fit in the margin, and add the Files list column gap and right-align Size. I will verify at the requested widths and themes using the real production build.
Author
Owner

Source review found the Files list already sets column-gap: var(--toolbar-gap) on both .fc-head and .fc-item-inner, and the Size heading and values already use end alignment (packages/ui/src/components/files/FileCollection.svelte). The existing Files e2e checks measured Size/Kind gap and alignment at 1440 (apps/web/e2e/files.mjs). I will run that against the production build and keep the smallest additional change that makes the reported visual state verifiable.

Source review found the Files list already sets `column-gap: var(--toolbar-gap)` on both `.fc-head` and `.fc-item-inner`, and the Size heading and values already use end alignment (`packages/ui/src/components/files/FileCollection.svelte`). The existing Files e2e checks measured Size/Kind gap and alignment at 1440 (`apps/web/e2e/files.mjs`). I will run that against the production build and keep the smallest additional change that makes the reported visual state verifiable.
Author
Owner

Completed

The collapsed sidebar toggle now leaves the title's flex flow when the actual row gutter can hold it. It stays vertically centred on the title, and remains inline when the gutter is too narrow. This uses the shared ModeHeader, so all Tabs use the same behavior.

The Files Size/Kind spacing and Size alignment were already present in the merged FileCollection styles. The production e2e now checks the computed token gap between all columns, the Size header/value right edge, and alignment against a real API-uploaded file row.

Evidence

The focused production e2e passed for 8 Tabs at 1920, 1440 and 1024px (24 geometry checks), and captured both sidebar states at 1920, 1440, 1024, 820 and 390px in light and dark.

UX gaps closed

  • Removed the collapsed-toggle title jump where an outside gutter fits the control.
  • Kept the toggle inline where it does not fit.
  • Added live Files metadata spacing and alignment assertions.

UX gaps left

No additional interaction behavior changed. A separate manual screen-reader audit was not part of this layout-focused run.

Files

  • packages/ui/src/components/ModeHeader.svelte
  • apps/web/e2e/sidebar-content-shift-1138.mjs
  • apps/web/e2e/harness.mjs
  • apps/web/e2e/files.mjs

Decisions

DESIGN does not set the exact gutter cutoff. The detached placement requires a 64px outside gutter for the touch target, shared gap and scale room. On a wide fine-pointer Photos row, the toggle may use the viewport edge when its full capsule and a 4px inset fit; narrower full-width rows keep the inline control.

Verification

Production e2e result:

PASS sidebar content shift, resize and Mac production screenshot matrix

Focused Vitest result:

 Test Files  1 passed (1)
      Tests  18 passed (18)

Svelte check result:

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

Production build result:

Compressed 885 static variants; saved 20918441 bytes.

bun run check stopped at the existing perf-lint exception ratchet. The same failure was present before and after the UI change:

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

No Rust files changed, so Rust format, clippy and test gates were not applicable. The server build used for the API-backed production e2e passed. Full web tests and full adversarial matrices remain for the merge round under the shared verification policy.

Head: f6fe6009993fc701b7075948c869008d22507cfd
Commits: 785a3d75d, f6fe60099

## Completed The collapsed sidebar toggle now leaves the title's flex flow when the actual row gutter can hold it. It stays vertically centred on the title, and remains inline when the gutter is too narrow. This uses the shared ModeHeader, so all Tabs use the same behavior. The Files Size/Kind spacing and Size alignment were already present in the merged FileCollection styles. The production e2e now checks the computed token gap between all columns, the Size header/value right edge, and alignment against a real API-uploaded file row. ## Evidence - [Full production screenshot set (20 viewport screenshots and 22 4× crops, light/dark, macOS emulation)](https://git.kayg.org/attachments/ab81c404-4886-4cc5-8aed-edfb61961a6e) - Title crop, 1920px, light: ![1920 light title and sidebar toggle](https://git.kayg.org/attachments/c7ab1148-57ea-4213-9d91-0a5e3c76d0ce) - Title crop, 1920px, dark: ![1920 dark title and sidebar toggle](https://git.kayg.org/attachments/f5d92a3d-c2c0-49db-a7ee-a31dd97463b6) - Files Size/Kind crop, 1920px, light: ![1920 light Files Size and Kind columns](https://git.kayg.org/attachments/393c0ad6-405f-423a-b3e2-a48bd2dc3119) - Files Size/Kind crop, 1920px, dark: ![1920 dark Files Size and Kind columns](https://git.kayg.org/attachments/ea811109-ab94-47dc-8752-7fe31ccb406c) The focused production e2e passed for 8 Tabs at 1920, 1440 and 1024px (24 geometry checks), and captured both sidebar states at 1920, 1440, 1024, 820 and 390px in light and dark. ## UX gaps closed - Removed the collapsed-toggle title jump where an outside gutter fits the control. - Kept the toggle inline where it does not fit. - Added live Files metadata spacing and alignment assertions. ## UX gaps left No additional interaction behavior changed. A separate manual screen-reader audit was not part of this layout-focused run. ## Files - `packages/ui/src/components/ModeHeader.svelte` - `apps/web/e2e/sidebar-content-shift-1138.mjs` - `apps/web/e2e/harness.mjs` - `apps/web/e2e/files.mjs` ## Decisions DESIGN does not set the exact gutter cutoff. The detached placement requires a 64px outside gutter for the touch target, shared gap and scale room. On a wide fine-pointer Photos row, the toggle may use the viewport edge when its full capsule and a 4px inset fit; narrower full-width rows keep the inline control. ## Verification Production e2e result: ``` PASS sidebar content shift, resize and Mac production screenshot matrix ``` Focused Vitest result: ``` Test Files 1 passed (1) Tests 18 passed (18) ``` Svelte check result: ``` svelte-check found 0 errors and 4 warnings in 3 files ``` Production build result: ``` Compressed 885 static variants; saved 20918441 bytes. ``` `bun run check` stopped at the existing perf-lint exception ratchet. The same failure was present before and after the UI change: ``` perf-lint: INVALID: exception ratchet: contract.blaze: 290 exceptions exceed the ratchet ceiling 289; fix the new violation instead; contract.blocked-network: 356 exceptions exceed the ratchet ceiling 355; fix the new violation instead; contract.dom-bound: 290 exceptions exceed the ratchet ceiling 289; fix the new violation instead; contract.model-bound: 290 exceptions exceed the ratchet ceiling 289; fix the new violation instead; contract.row-identity: 290 exceptions exceed the ratchet ceiling 289; fix the new violation instead; contract.snapshot: 356 exceptions exceed the ratchet ceiling 355; fix the new violation instead; coverage.profile: 356 exceptions exceed the ratchet ceiling 355; fix the new violation instead; coverage.readiness: 356 exceptions exceed the ratchet ceiling 355; fix the new violation instead; io.unresolved-call: 16191 exceptions exceed the ratchet ceiling 16190; fix the new violation instead; render.blaze-adapter: 290 exceptions exceed the ratchet ceiling 289; fix the new violation instead; render.bound: 290 exceptions exceed the ratchet ceiling 289; fix the new violation instead; render.model_byte_cap: 290 exceptions exceed the ratchet ceiling 289; fix the new violation instead; render.model_row_cap: 290 exceptions exceed the ratchet ceiling 289; fix the new violation instead; total: ledger has 21977 exceptions; ratchet total is 21964 ``` No Rust files changed, so Rust format, clippy and test gates were not applicable. The server build used for the API-backed production e2e passed. Full web tests and full adversarial matrices remain for the merge round under the shared verification policy. Head: `f6fe6009993fc701b7075948c869008d22507cfd` Commits: `785a3d75d`, `f6fe60099`
Commenting is not possible because the repository is archived.
No labels
No milestone
No project
No assignees
1 participant
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-v0#1158
No description provided.