Skip to content

Add floating day indicator (WhatsApp-style) + fix orphaned date dividers on per-channel clear#78

Open
maxlamagna wants to merge 1 commit into
bcurts:mainfrom
maxlamagna:day-float-indicator
Open

Add floating day indicator (WhatsApp-style) + fix orphaned date dividers on per-channel clear#78
maxlamagna wants to merge 1 commit into
bcurts:mainfrom
maxlamagna:day-float-indicator

Conversation

@maxlamagna

@maxlamagna maxlamagna commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Closes #77

What this does

While scrolling, a small floating capsule appears top-centre showing the day the messages at the top of the view belong to ("Today", "Yesterday", or the full date; same formatting as the existing separators), and fades out ~1.2s after scrolling stops. In busy channels the in-flow day separators are often hundreds of messages above the viewport; this keeps the day visible without them. The separators themselves are untouched, nothing shifts, only the small transient capsule overlays content, and clicks pass through it.

Also fixes a pre-existing bug this feature would otherwise expose (reproducible on current main): per-channel Clear leaves orphaned day separators in the DOM: the clear loop matches only dataset.id, dividers carry only dataset.channel, and filterMessagesByChannel only toggles visibility. Cleared channels kept their old separators and duplicated one on the next message.

How it works

  • Host: <div id="day-float" aria-hidden="true"><span></span></div> as the first child of #timeline. It has zero height and position: sticky; top: 8px, so CSS keeps it pinned and centred (including during panel resizes) with no scroll-position bookkeeping. pointer-events: none on the host (inherited by the capsule) guarantees click-through; align-items: flex-start keeps the capsule's intrinsic padded height inside the zero-height flex line. z-index sits above message content and below panels/menus.
  • Label scan: a cached live HTMLCollection of .date-divider elements (getElementsByClassName on #messages; follows divider add/remove automatically, survives full clear since the container node persists). The scan runs at most once per requestAnimationFrame, triggered from the existing setupScroll listener; it skips other channels' hidden dividers and breaks at the first divider below the scrollport edge (<= so handoff lands exactly at the edge). Cost scales with day-divider count (tens), not message count (thousands).
  • Show/fade: scroll → label update + .visible class + 1200ms fade timer reset; opacity transition 0.25s. No divider above the viewport → hide immediately and cancel the timer.
  • Stale-state hooks: dayFloatRefresh() recomputes the label without starting the show/fade cycle; called at both exits of switchChannel (guarded typeof, since channels.js loads before chat.js) and after both clear paths, so a channel switch or clear can never leave a stale day on screen even when no scroll event fires.
  • Clear fix: the per-channel clear loop now removes elements that are either messages (dataset.id) or .date-dividers of the cleared channel; the next message re-creates exactly one divider (its lastMessageDates entry is reset, as before).
  • Cache-busts: ?v= bumped for style.css, channels.js, chat.js.

Scope: 4 static files, ≈110 lines, no server changes, no settings, no dependencies.

Test plan

  • node --check static/chat.js and node --check static/channels.js pass.
  • Live verification on a real multi-agent workspace (3000+ messages, 8 channels), all passing:
    1. correct day shown while scrolling, both directions, with clean handoff at day boundaries;
    2. fades out after scrolling stops; hidden at the very top of history (no day above the viewport);
    3. capsule background/border fully encloses the label;
    4. channel switch away/back shows no stale day;
    5. per-channel clear shows no cleared-history day, and orphaned separators no longer linger (bug above);
    6. pill never blocks clicks on messages/buttons beneath it;
    7. narrow-window layout stays centred and readable.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Hard to tell which day you're reading in a busy channel: add a floating day indicator (WhatsApp-style)

1 participant