Calendar: current-time dot is cut off at the day column edge (all widths) #1002

Open
opened 2026-10-03 09:21:37 +00:00 by kayg · 7 comments
Owner

Owner report (2026-10-03, screenshot)

"The dot is slightly cut off in the Calendar for the current time? Checked at all widths."
The current-time dot (.now-line::before, 10 px, packages/ui/src/components/calendar/GridColumn.svelte ~line 1507) sits at left: 0 of a line that starts at left: -1px inside the day column, and the column clips its overflow (overflow: clip, ~line 832). So part of the dot is cut at the column edge at every width.

Fix

  • The dot is fully visible at every width, zoom level and theme: centre it on the column's leading edge (the published calendar convention) and render it in a layer that the column does not clip (for example an overlay at the TimeGrid level positioned from the same now value, or overflow: clip with overflow-clip-margin). Do not drop the column's clipping for events.
  • Keep the line 2 px, the faint line in other columns, the snapped glow (#536) and the reduced-motion rules. Tokens only (no new numeric literals; the guard check fails on them).
  • Day, Week (first column and middle columns) and the phone 3-day view.

Verification

Production-build screenshots at 390/820/1440, light and dark, with 3x crops of the dot in Day and Week (first and middle column); an e2e assertion that the dot's bounding box is not clipped (its visible rect equals its full rect). Focused tests + bun run check.

## Owner report (2026-10-03, screenshot) "The dot is slightly cut off in the Calendar for the current time? Checked at all widths." The current-time dot (`.now-line::before`, 10 px, `packages/ui/src/components/calendar/GridColumn.svelte` ~line 1507) sits at `left: 0` of a line that starts at `left: -1px` inside the day column, and the column clips its overflow (`overflow: clip`, ~line 832). So part of the dot is cut at the column edge at every width. ## Fix - The dot is fully visible at every width, zoom level and theme: centre it on the column's leading edge (the published calendar convention) and render it in a layer that the column does not clip (for example an overlay at the TimeGrid level positioned from the same `now` value, or `overflow: clip` with `overflow-clip-margin`). Do not drop the column's clipping for events. - Keep the line 2 px, the faint line in other columns, the snapped glow (#536) and the reduced-motion rules. Tokens only (no new numeric literals; the guard check fails on them). - Day, Week (first column and middle columns) and the phone 3-day view. ## Verification Production-build screenshots at 390/820/1440, light and dark, with 3x crops of the dot in Day and Week (first and middle column); an e2e assertion that the dot's bounding box is not clipped (its visible rect equals its full rect). Focused tests + bun run check.
Author
Owner

Correction: the overflow: clip at ~line 832 belongs to the event block, not the column. First find the actual clipping ancestor of .now-line::before (DevTools / getBoundingClientRect vs. the clipped visible rect: content-visibility, contain: paint, overflow on .col or the scroller), then fix there.

Correction: the overflow: clip at ~line 832 belongs to the event block, not the column. First find the actual clipping ancestor of .now-line::before (DevTools / getBoundingClientRect vs. the clipped visible rect: content-visibility, contain: paint, overflow on .col or the scroller), then fix there.
Author
Owner

Started job/nowdot-1002 from base f06679b11cde29cc0b7120fdab5f721389caf695. I read the issue body and correction comment. I am tracing the rendered clipping ancestor before changing the Calendar dot.

Started `job/nowdot-1002` from base `f06679b11cde29cc0b7120fdab5f721389caf695`. I read the issue body and correction comment. I am tracing the rendered clipping ancestor before changing the Calendar dot.
Author
Owner

One scope gap from the repo trace: the Calendar route supports Day (one visible day) and Week (seven visible days), and the existing Calendar E2E explicitly records that there is no separate 3-day route (apps/web/e2e/calendar.mjs). I will cover the phone Week grid at 390 px; I will not add a new Calendar view as part of this dot fix.

One scope gap from the repo trace: the Calendar route supports Day (one visible day) and Week (seven visible days), and the existing Calendar E2E explicitly records that there is no separate 3-day route (`apps/web/e2e/calendar.mjs`). I will cover the phone Week grid at 390 px; I will not add a new Calendar view as part of this dot fix.
Author
Owner

Finding: the current-time dot is clipped by .col { content-visibility: auto; } in GridColumn.svelte. The overflow: clip rule is on the Event block in GridColumn.svelte, so it is a separate clip and remains unchanged. The new focused E2E measures both ancestor clipping and the simulated column clip.

Finding: the current-time dot is clipped by `.col { content-visibility: auto; }` in `GridColumn.svelte`. The `overflow: clip` rule is on the Event block in `GridColumn.svelte`, so it is a separate clip and remains unchanged. The new focused E2E measures both ancestor clipping and the simulated column clip.
Author
Owner

Focused E2E found a second geometry issue before screenshot capture: on Day at 390 px in light theme, the full 10 px dot was visible but its centre was 57.61 px below the current-time line centre (dot y 308.80–318.80; line y 255.19–257.19). The percentage was measured against the padded grid area, while the line is measured against the 24-hour column. I am aligning the dot with the shared hour-height token and will rerun the matrix.

Focused E2E found a second geometry issue before screenshot capture: on Day at 390 px in light theme, the full 10 px dot was visible but its centre was 57.61 px below the current-time line centre (dot y 308.80–318.80; line y 255.19–257.19). The percentage was measured against the padded grid area, while the line is measured against the 24-hour column. I am aligning the dot with the shared hour-height token and will rerun the matrix.
Author
Owner

The second E2E rerun passed all 390 px and 820 px cases, then found a scale-specific mismatch at Day/1440/light: the dot centre was 42.22 px above the line. --hour is intentionally non-inherited for zoom performance, so the dot read its 48 px registered initial value while the column used the scaled hour height. I am updating only the dot node in the existing zoom frame.

The second E2E rerun passed all 390 px and 820 px cases, then found a scale-specific mismatch at Day/1440/light: the dot centre was 42.22 px above the line. `--hour` is intentionally non-inherited for zoom performance, so the dot read its 48 px registered initial value while the column used the scaled hour height. I am updating only the dot node in the existing zoom frame.
Author
Owner

Forgejo #1002 final report

Branch: job/nowdot-1002
Head: da11f8d6c88d8d10ff6253da873c3a5d6db01c75
Commits: d18d6d652 (paint-clip fix), da11f8d6c (scaled-hour alignment); merged origin/dev at d4e718881 before final verification.

Built

TimeGrid now draws the 10px current-time dot as a sibling outside GridColumn's content-visibility:auto paint containment. It centers the dot on the current-time line and day-column leading edge. Zoom updates the dot's single --dot-hour value in the existing animation frame; it does not make the shared, non-inherited --hour token invalidate Event nodes. GridColumn's 2px line, faint lines, snap glow and reduced-motion rules remain in place. Event clipping remains unchanged.

Files

  • packages/ui/src/components/calendar/TimeGrid.svelte — dot placement and hour alignment.
  • packages/ui/src/components/calendar/GridColumn.svelte — remove the clipped pseudo-element dot and document the paint-containment boundary.
  • packages/ui/src/tokens.css — shared 10px dot size token.
  • apps/web/e2e/calendar-now-dot-1002.mjs — focused production E2E and screenshot matrix.
  • apps/web/package.json — focused E2E script.
  • docs/DESIGN.md — merged upstream §62 update from origin/dev.

UX gaps closed

  • The full dot remains visible at the day edge while GridColumn and Event clipping stay intact.
  • The dot is decorative (aria-hidden, pointer-events:none), so it adds no misleading focus stop or interaction.
  • The geometry assertion covers Day and Week first/middle columns at 390, 820 and 1440px, light and dark, with macOS platform hints.

UX gaps left

  • There is no separate 3-day Calendar route in the app. Phone evidence uses the existing Week route at 390px; this job did not add a new view.

Decisions

  • Place the dot in TimeGrid, outside the paint-contained GridColumn, and use the existing date/hour track geometry.
  • Set the dot's drawn hour height on this one node because --hour is intentionally non-inherited for zoom performance.
  • Use existing Day and Week routes for coverage; no separate 3-day route is defined in the current Calendar UI.

Gates

bun run check output:

$ node scripts/check-user-storage.mjs && node scripts/check-type-tokens.mjs && node scripts/check-motion-tokens.mjs && svelte-kit sync && svelte-check --tsconfig ./tsconfig.json
User browser caches use userStorage; only documented device/public-link exceptions remain.
Text sizes and UI shape values use shared role tokens.
UI transitions and animation options use shared motion tokens or documented exceptions.
Loading svelte-check in workspace: /home/kayg/Developer/calternal-wt/nowdot-1002/apps/web
Getting Svelte diagnostics...

svelte-check found 0 errors and 0 warnings

Focused production E2E command: bun run test:e2e:calendar-now-dot-1002

$ bun e2e/calendar-now-dot-1002.mjs
PASS day 390px light: 10px dot fully visible; column paint clip would leave 4px; active clips: tg-body svelte-bhx0az
PASS week-first 390px light: 10px dot fully visible; column paint clip would leave 4px; active clips: tg-body svelte-bhx0az
PASS week-middle 390px light: 10px dot fully visible; column paint clip would leave 4px; active clips: tg-body svelte-bhx0az
PASS day 390px dark: 10px dot fully visible; column paint clip would leave 4px; active clips: tg-body svelte-bhx0az
PASS week-first 390px dark: 10px dot fully visible; column paint clip would leave 4px; active clips: tg-body svelte-bhx0az
PASS week-middle 390px dark: 10px dot fully visible; column paint clip would leave 4px; active clips: tg-body svelte-bhx0az
PASS day 820px light: 10px dot fully visible; column paint clip would leave 4px; active clips: tg-body svelte-bhx0az
PASS week-first 820px light: 10px dot fully visible; column paint clip would leave 4px; active clips: tg-body svelte-bhx0az
PASS week-middle 820px light: 10px dot fully visible; column paint clip would leave 4px; active clips: tg-body svelte-bhx0az
PASS day 820px dark: 10px dot fully visible; column paint clip would leave 4px; active clips: tg-body svelte-bhx0az
PASS week-first 820px dark: 10px dot fully visible; column paint clip would leave 4px; active clips: tg-body svelte-bhx0az
PASS week-middle 820px dark: 10px dot fully visible; column paint clip would leave 4px; active clips: tg-body svelte-bhx0az
PASS day 1440px light: 10px dot fully visible; column paint clip would leave 3.984375px; active clips: tg-body svelte-bhx0az
PASS week-first 1440px light: 10px dot fully visible; column paint clip would leave 4px; active clips: tg-body svelte-bhx0az
PASS week-middle 1440px light: 10px dot fully visible; column paint clip would leave 4px; active clips: tg-body svelte-bhx0az
PASS day 1440px dark: 10px dot fully visible; column paint clip would leave 3.984375px; active clips: tg-body svelte-bhx0az
PASS week-first 1440px dark: 10px dot fully visible; column paint clip would leave 4px; active clips: tg-body svelte-bhx0az
PASS week-middle 1440px dark: 10px dot fully visible; column paint clip would leave 4px; active clips: tg-body svelte-bhx0az
calendar current-time dot e2e: 18 production screenshots and 18 3× crops saved to /home/kayg/Developer/calternal-wt/nowdot-1002/artifacts/calendar-now-dot-1002

Production build: bun run build passed; Vite wrote the static site to apps/web/build. It emitted existing vendor use client directive warnings.

Server build for the local E2E:

Finished `dev` profile [unoptimized + debuginfo] target(s) in 27m 29s

node --check apps/web/e2e/calendar-now-dot-1002.mjs and git diff --check passed with no output. No Rust files changed, so cargo fmt, cargo clippy and cargo test were not run. cargo clean completed: Removed 7237 files, 4.6GiB total.

Screenshots attached

The 18 production screenshots and all 18 3× crops are attached below. Full screenshots and crops use the macOS platform hints.

View Width Appearance Full screenshot Crop
Day 1440px Dark PNG 3× crop
Day 1440px Light PNG 3× crop
Day 390px Dark PNG 3× crop
Day 390px Light PNG 3× crop
Day 820px Dark PNG 3× crop
Day 820px Light PNG 3× crop
Week · first day 1440px Dark PNG 3× crop
Week · first day 1440px Light PNG 3× crop
Week · first day 390px Dark PNG 3× crop
Week · first day 390px Light PNG 3× crop
Week · first day 820px Dark PNG 3× crop
Week · first day 820px Light PNG 3× crop
Week · middle day 1440px Dark PNG 3× crop
Week · middle day 1440px Light PNG 3× crop
Week · middle day 390px Dark PNG 3× crop
Week · middle day 390px Light PNG 3× crop
Week · middle day 820px Dark PNG 3× crop
Week · middle day 820px Light PNG 3× crop

Full bun run test and the full E2E/adversarial matrices remain for the merge round under the repo verification policy.

# Forgejo #1002 final report Branch: `job/nowdot-1002` Head: `da11f8d6c88d8d10ff6253da873c3a5d6db01c75` Commits: `d18d6d652` (paint-clip fix), `da11f8d6c` (scaled-hour alignment); merged `origin/dev` at `d4e718881` before final verification. ## Built TimeGrid now draws the 10px current-time dot as a sibling outside GridColumn's `content-visibility:auto` paint containment. It centers the dot on the current-time line and day-column leading edge. Zoom updates the dot's single `--dot-hour` value in the existing animation frame; it does not make the shared, non-inherited `--hour` token invalidate Event nodes. GridColumn's 2px line, faint lines, snap glow and reduced-motion rules remain in place. Event clipping remains unchanged. ## Files - `packages/ui/src/components/calendar/TimeGrid.svelte` — dot placement and hour alignment. - `packages/ui/src/components/calendar/GridColumn.svelte` — remove the clipped pseudo-element dot and document the paint-containment boundary. - `packages/ui/src/tokens.css` — shared 10px dot size token. - `apps/web/e2e/calendar-now-dot-1002.mjs` — focused production E2E and screenshot matrix. - `apps/web/package.json` — focused E2E script. - `docs/DESIGN.md` — merged upstream §62 update from `origin/dev`. ## UX gaps closed - The full dot remains visible at the day edge while `GridColumn` and Event clipping stay intact. - The dot is decorative (`aria-hidden`, `pointer-events:none`), so it adds no misleading focus stop or interaction. - The geometry assertion covers Day and Week first/middle columns at 390, 820 and 1440px, light and dark, with macOS platform hints. ## UX gaps left - There is no separate 3-day Calendar route in the app. Phone evidence uses the existing Week route at 390px; this job did not add a new view. ## Decisions - Place the dot in TimeGrid, outside the paint-contained GridColumn, and use the existing date/hour track geometry. - Set the dot's drawn hour height on this one node because `--hour` is intentionally non-inherited for zoom performance. - Use existing Day and Week routes for coverage; no separate 3-day route is defined in the current Calendar UI. ## Gates `bun run check` output: ```text $ node scripts/check-user-storage.mjs && node scripts/check-type-tokens.mjs && node scripts/check-motion-tokens.mjs && svelte-kit sync && svelte-check --tsconfig ./tsconfig.json User browser caches use userStorage; only documented device/public-link exceptions remain. Text sizes and UI shape values use shared role tokens. UI transitions and animation options use shared motion tokens or documented exceptions. Loading svelte-check in workspace: /home/kayg/Developer/calternal-wt/nowdot-1002/apps/web Getting Svelte diagnostics... svelte-check found 0 errors and 0 warnings ``` Focused production E2E command: `bun run test:e2e:calendar-now-dot-1002` ```text $ bun e2e/calendar-now-dot-1002.mjs PASS day 390px light: 10px dot fully visible; column paint clip would leave 4px; active clips: tg-body svelte-bhx0az PASS week-first 390px light: 10px dot fully visible; column paint clip would leave 4px; active clips: tg-body svelte-bhx0az PASS week-middle 390px light: 10px dot fully visible; column paint clip would leave 4px; active clips: tg-body svelte-bhx0az PASS day 390px dark: 10px dot fully visible; column paint clip would leave 4px; active clips: tg-body svelte-bhx0az PASS week-first 390px dark: 10px dot fully visible; column paint clip would leave 4px; active clips: tg-body svelte-bhx0az PASS week-middle 390px dark: 10px dot fully visible; column paint clip would leave 4px; active clips: tg-body svelte-bhx0az PASS day 820px light: 10px dot fully visible; column paint clip would leave 4px; active clips: tg-body svelte-bhx0az PASS week-first 820px light: 10px dot fully visible; column paint clip would leave 4px; active clips: tg-body svelte-bhx0az PASS week-middle 820px light: 10px dot fully visible; column paint clip would leave 4px; active clips: tg-body svelte-bhx0az PASS day 820px dark: 10px dot fully visible; column paint clip would leave 4px; active clips: tg-body svelte-bhx0az PASS week-first 820px dark: 10px dot fully visible; column paint clip would leave 4px; active clips: tg-body svelte-bhx0az PASS week-middle 820px dark: 10px dot fully visible; column paint clip would leave 4px; active clips: tg-body svelte-bhx0az PASS day 1440px light: 10px dot fully visible; column paint clip would leave 3.984375px; active clips: tg-body svelte-bhx0az PASS week-first 1440px light: 10px dot fully visible; column paint clip would leave 4px; active clips: tg-body svelte-bhx0az PASS week-middle 1440px light: 10px dot fully visible; column paint clip would leave 4px; active clips: tg-body svelte-bhx0az PASS day 1440px dark: 10px dot fully visible; column paint clip would leave 3.984375px; active clips: tg-body svelte-bhx0az PASS week-first 1440px dark: 10px dot fully visible; column paint clip would leave 4px; active clips: tg-body svelte-bhx0az PASS week-middle 1440px dark: 10px dot fully visible; column paint clip would leave 4px; active clips: tg-body svelte-bhx0az calendar current-time dot e2e: 18 production screenshots and 18 3× crops saved to /home/kayg/Developer/calternal-wt/nowdot-1002/artifacts/calendar-now-dot-1002 ``` Production build: `bun run build` passed; Vite wrote the static site to `apps/web/build`. It emitted existing vendor `use client` directive warnings. Server build for the local E2E: ```text Finished `dev` profile [unoptimized + debuginfo] target(s) in 27m 29s ``` `node --check apps/web/e2e/calendar-now-dot-1002.mjs` and `git diff --check` passed with no output. No Rust files changed, so `cargo fmt`, `cargo clippy` and `cargo test` were not run. `cargo clean` completed: `Removed 7237 files, 4.6GiB total`. ## Screenshots attached The 18 production screenshots and all 18 3× crops are attached below. Full screenshots and crops use the macOS platform hints. | View | Width | Appearance | Full screenshot | Crop | |---|---:|---|---|---| | Day | 1440px | Dark | [PNG](https://git.kayg.org/attachments/8fcc934d-a849-4436-b8aa-98af2b9c0afe) | [3× crop](https://git.kayg.org/attachments/61b4eaee-37bf-4ae2-b2f2-f81e6898306f) | | Day | 1440px | Light | [PNG](https://git.kayg.org/attachments/52944a76-5ea1-4c9c-9230-3be3bb9527ba) | [3× crop](https://git.kayg.org/attachments/29f32faa-54d1-42a2-ba87-4afad1202cc5) | | Day | 390px | Dark | [PNG](https://git.kayg.org/attachments/a45147b1-e104-4fca-977b-df122198d087) | [3× crop](https://git.kayg.org/attachments/cbf2b49f-c7c5-4fca-ae24-02581a24fa10) | | Day | 390px | Light | [PNG](https://git.kayg.org/attachments/2522b9b9-64c4-449e-80bc-6f29e2638ef8) | [3× crop](https://git.kayg.org/attachments/4294c4dc-87c0-417d-b5cb-0067c0cd2b6e) | | Day | 820px | Dark | [PNG](https://git.kayg.org/attachments/1f6e0510-990b-44e1-8025-f62be788bbef) | [3× crop](https://git.kayg.org/attachments/71030c5d-6768-4e5a-a94d-3a6aea4c6825) | | Day | 820px | Light | [PNG](https://git.kayg.org/attachments/ee91a980-e8b8-4089-8753-53669b38da44) | [3× crop](https://git.kayg.org/attachments/ea06cf9d-7f39-4034-aa2f-43ee13fdd41e) | | Week · first day | 1440px | Dark | [PNG](https://git.kayg.org/attachments/08cb9685-a389-4fa7-85f4-4ea6393bfcd6) | [3× crop](https://git.kayg.org/attachments/184194fb-085f-4bea-9a6a-5f365213fc50) | | Week · first day | 1440px | Light | [PNG](https://git.kayg.org/attachments/8adfb776-cf9c-4061-8bab-e22d154790e4) | [3× crop](https://git.kayg.org/attachments/7af25297-7399-4ce1-abdf-2d030ce8e199) | | Week · first day | 390px | Dark | [PNG](https://git.kayg.org/attachments/9ed97a52-f153-4c3f-a50e-064ec5f6fd9e) | [3× crop](https://git.kayg.org/attachments/f3441291-442f-42e6-aaef-9d7275459153) | | Week · first day | 390px | Light | [PNG](https://git.kayg.org/attachments/13f7f0ba-de3d-4ce6-af35-7a657dc1734c) | [3× crop](https://git.kayg.org/attachments/60832666-1563-454a-985f-eb6c568058bf) | | Week · first day | 820px | Dark | [PNG](https://git.kayg.org/attachments/a0609b99-a128-46c3-b4c8-c28440ac2b5f) | [3× crop](https://git.kayg.org/attachments/c1cdf755-d475-4311-9e9a-eef0d7db4019) | | Week · first day | 820px | Light | [PNG](https://git.kayg.org/attachments/447a7a5b-0bea-4ac7-91d8-4dc39717fdae) | [3× crop](https://git.kayg.org/attachments/fcb5e40a-092b-4528-ae34-fd123a0ce66a) | | Week · middle day | 1440px | Dark | [PNG](https://git.kayg.org/attachments/11388ad1-1ac2-4735-b8e4-74ef85ab8ea6) | [3× crop](https://git.kayg.org/attachments/1910b9f9-e1a9-43c6-abc6-d07ba19f1522) | | Week · middle day | 1440px | Light | [PNG](https://git.kayg.org/attachments/677a6a62-508d-4a17-8f74-7ec9a5ac0360) | [3× crop](https://git.kayg.org/attachments/2718a352-6ec3-49e3-9974-91232cf7ed5e) | | Week · middle day | 390px | Dark | [PNG](https://git.kayg.org/attachments/bcce43ed-1dc2-4778-8adf-72d905e802a3) | [3× crop](https://git.kayg.org/attachments/15bf2041-c72a-4e4b-9b6b-2dfff696612d) | | Week · middle day | 390px | Light | [PNG](https://git.kayg.org/attachments/572d35a4-a21e-4d7c-acf1-56fb854ece18) | [3× crop](https://git.kayg.org/attachments/00a8344d-1fc6-47af-8d12-7f430fa90bcd) | | Week · middle day | 820px | Dark | [PNG](https://git.kayg.org/attachments/5e91e504-398b-4bd1-9980-9ed454a6b0b8) | [3× crop](https://git.kayg.org/attachments/c9460339-f75c-4396-b933-67e61d9a2ca3) | | Week · middle day | 820px | Light | [PNG](https://git.kayg.org/attachments/0c5f59a7-bbb3-410a-9018-f4c2f154061c) | [3× crop](https://git.kayg.org/attachments/ddc28197-3f31-410f-bfeb-3e77d311e6a7) | Full `bun run test` and the full E2E/adversarial matrices remain for the merge round under the repo verification policy.
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#1002
No description provided.