feat(ui): jump to first unread - floating pill returns to the unread divider (LC-294) #325

Merged
longjacksonle merged 1 commit from feat/lc-294-jump-to-first-unread into main 2026-06-14 21:27:37 +02:00

Summary

A floating "jump to first unread" pill that returns the reader to the unread divider after they have scrolled away. Mirror of the LC-242 jump-to-latest pill, pointing up.

Background

The room already renders a [data-unread-divider] ("Unread messages") and auto_scroll.html auto-anchors to it on load. There was no way to get back to it once you scrolled past it. This adds that affordance (standard Slack/Discord behavior).

Changes

  • server/templates/partials/jump_to_unread.html (new): hidden #lc-jump-unread button, up-chevron, anchored top-center so it never collides with the bottom-right latest pill.
  • server/templates/room/page.html: include the new partial inside the relative wrapper around #messages.
  • server/templates/partials/auto_scroll.html: query the unread divider independently of the permalink anchor; isDividerVisible() (bounding-rect intersection), renderUnreadPill() (visible iff a divider exists and is off-screen), click handler that scrolls the divider into view (block:'start', smooth unless prefers-reduced-motion). Driven from the initial anchor, scroll, ResizeObserver, and live OOB append; torn down with the existing listeners.
  • server/locales/{en,es}/room.ftl: room-jump-unread-label + room-jump-unread-aria.

Entirely client-side over already-rendered markup: no server, route, DB, or model change.

Testing

  • just check, just fmt, just test, just test-saas all pass.
  • No new Rust test (mirrors LC-242, which added none for the jump-to-latest pill; there is no server handler to unit-test). Existing room-render tests still pass and the new keys resolve.

Not operator-visible (no env/config/contract change).

## Summary A floating "jump to first unread" pill that returns the reader to the unread divider after they have scrolled away. Mirror of the LC-242 jump-to-latest pill, pointing up. ## Background The room already renders a `[data-unread-divider]` ("Unread messages") and `auto_scroll.html` auto-anchors to it on load. There was no way to get back to it once you scrolled past it. This adds that affordance (standard Slack/Discord behavior). ## Changes - `server/templates/partials/jump_to_unread.html` (new): hidden `#lc-jump-unread` button, up-chevron, anchored top-center so it never collides with the bottom-right latest pill. - `server/templates/room/page.html`: include the new partial inside the relative wrapper around `#messages`. - `server/templates/partials/auto_scroll.html`: query the unread divider independently of the permalink anchor; `isDividerVisible()` (bounding-rect intersection), `renderUnreadPill()` (visible iff a divider exists and is off-screen), click handler that scrolls the divider into view (block:'start', smooth unless prefers-reduced-motion). Driven from the initial anchor, scroll, ResizeObserver, and live OOB append; torn down with the existing listeners. - `server/locales/{en,es}/room.ftl`: `room-jump-unread-label` + `room-jump-unread-aria`. Entirely client-side over already-rendered markup: no server, route, DB, or model change. ## Testing - `just check`, `just fmt`, `just test`, `just test-saas` all pass. - No new Rust test (mirrors LC-242, which added none for the jump-to-latest pill; there is no server handler to unit-test). Existing room-render tests still pass and the new keys resolve. Not operator-visible (no env/config/contract change).
feat(ui): jump to first unread - floating pill returns to the unread divider (LC-294)
All checks were successful
check-secrets / TruffleHog (push) Successful in 4s
check-secrets / Nosey parker (push) Successful in 4s
check-secrets / Kingfisher (push) Successful in 6s
check-secrets / Kingfisher (pull_request) Successful in 5s
check-secrets / Nosey parker (pull_request) Successful in 6s
Check / clippy + fmt + tests (pull_request) Successful in 2m20s
check-secrets / TruffleHog (pull_request) Successful in 6s
Create release / Create release from merged PR (pull_request) Has been skipped
4466325200
Add a "jump to first unread" pill that mirrors the LC-242 jump-to-latest pill but points up. The room already renders an unread divider and auto-anchors to it on load; this adds the affordance to return there after the reader scrolls away.

The pill appears whenever the `[data-unread-divider]` element exists but is scrolled out of the `#messages` viewport, and on click smooth-scrolls back to it (instant under prefers-reduced-motion). It is anchored top-center so it never collides with the bottom-right latest pill, and the divider is queried independently of the permalink anchor so it still works when a `#msg-<id>` deep link took the initial scroll. Visibility is driven from the same hooks as the latest pill (initial anchor, scroll, ResizeObserver, live OOB append) and torn down alongside them.

Entirely client-side over already-rendered markup: no server, route, DB, or model change. en/es parity for the new keys.

#LC-294
#LC-295

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
longjacksonle deleted branch feat/lc-294-jump-to-first-unread 2026-06-14 21:27:38 +02:00
Sign in to join this conversation.
No reviewers
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
psa-systems/lets-chat!325
No description provided.