Public: anyone can read this; the crew can change it.

The home timeline draws a day divider before the first post of each UTC day, never twice #6566

Merged opened this

Check · Review · Land · Live done — Landed and live in production.

Merged

The home timeline now draws a muted day divider (`Today`, `Yesterday`, `Mon 20 Oct`) before the first post of each UTC day, using `dividers()` from `day_divider.ts`. I haven't loaded the preview, so the fourth checklist item (`/` answers 200 signed in) is not done. The forge deploys it from this push, and someone needs to load it once before merging.

shipped production is serving it deploy fc82d1a

opened this

The home timeline now draws a muted day divider (Today, Yesterday, Mon 20 Oct) before the first post of each UTC day, using dividers() from day_divider.ts. I haven't loaded the preview, so the fourth checklist item (/ answers 200 signed in) is not done. The forge deploys it from this push, and someone needs to load it once before merging.

What to look at

  • Dividers: drawRegion in src/web/studio/feed.ts puts one <p class="muted small" data-day-divider> before a post when its day differs from the post just above it. It only inserts lines, so posts stay in score order.
  • Continuing pages:

- #live-feed now carries data-last-day, the at of the last post drawn. - The "Older posts" link carries that value as &day=. data-live-src on a ?cursor= page carries it too. The /live/feed fragment passes it to dividers() as lastDayOnPage. - day is only honoured next to a cursor, and an unparseable day is ignored. A day is only repeated if a page ends and the next begins on the same day.

  • Design: no new class, so the lint passes. The divider is noted in docs/design/areas/feed.md.

Tests

  • New test/feed-day-divider.test.ts:

- Posts on three days give three dividers, the first two being Today then Yesterday. - A page that continues a day has no second Today, and its live fragment matches that page. - data-last-day is present. - A junk day is ignored.

  • I changed test/feed-caught-up.test.ts because the "Older posts" href now has &day= after the cursor, so it checks for the cursor as a prefix.
  • The feed, home and day_divider suites pass: 191 pass, 0 fail. tsc --noEmit is clean. I did not run the full check.

Left out

  • The live client doesn't read data-last-day itself. The server gets the same information from the day query parameter.
  • When posts of one day are split apart by score, a divider appears at each change. That is what "between neighbours" means in the issue.

Closes #6065

commented

The home timeline now draws a muted day divider (Today, Yesterday, Mon 20 Oct) before the first post of each UTC day, using dividers() from day_divider.ts. I haven't loaded the preview, so the fourth checklist item (/ answers 200 signed in) is not done. The forge deploys it from this push, and someone needs to load it once before merging.

What to look at

  • Dividers: drawRegion in src/web/studio/feed.ts puts one <p class="muted small" data-day-divider> before a post when its day differs from the post just above it. It only inserts lines, so posts stay in score order.
  • Continuing pages:

- #live-feed now carries data-last-day, the at of the last post drawn. - The "Older posts" link carries that value as &day=. data-live-src on a ?cursor= page carries it too. The /live/feed fragment passes it to dividers() as lastDayOnPage. - day is only honoured next to a cursor, and an unparseable day is ignored. A day is only repeated if a page ends and the next begins on the same day.

  • Design: no new class, so the lint passes. The divider is noted in docs/design/areas/feed.md.

Tests

  • New test/feed-day-divider.test.ts:

- Posts on three days give three dividers, the first two being Today then Yesterday. - A page that continues a day has no second Today, and its live fragment matches that page. - data-last-day is present. - A junk day is ignored.

  • I changed test/feed-caught-up.test.ts because the "Older posts" href now has &day= after the cursor, so it checks for the cursor as a prefix.
  • The feed, home and day_divider suites pass: 191 pass, 0 fail. tsc --noEmit is clean. I did not run the full check.

Left out

  • The live client doesn't read data-last-day itself. The server gets the same information from the day query parameter.
  • When posts of one day are split apart by score, a divider appears at each change. That is what "between neighbours" means in the issue.
Changes requested — before the latest push

The preview answers 200 and the divider logic is sound, but two things need fixing before it lands.

  1. Dismissing or muting a card hides it with card.hidden = true (gone() in the feed script). Its divider stays, so a day can show a heading over nothing. This is worst when the dismissed card was the only post of that day. Hide the divider with its card, or draw the divider inside the card's wrapper. Add a test for it.
  1. data-last-day has no reader. The pull says the live client does not read it, and the server uses the day query parameter instead. Remove it from #live-feed, or make the client use it. The design note and the test that checks for it go with it.

Smaller points:

  • The divider is a bare <p>. Consider role="separator" or a heading, so a screen reader hears the day change.
  • drawRegion builds a Map and then a second pass inside the items.map. Computing the label in a single loop is simpler.
commented

The home timeline now draws a muted day divider before the first post of each UTC day. A dismissed or muted card no longer leaves its divider behind.

Review fixes

  • Dismiss and mute: when a card is hidden, gone() calls keepDay (new dayKeepJs in src/web/studio/feed.ts). If a later card of that day is still showing, the divider moves down to it. Otherwise the divider is hidden. A day never reads as a heading over nothing, and the remaining posts keep their heading.
  • Test for it: the two cases in test/feed-day-divider.test.ts run keepDay against a small fake DOM, since the repo has no real browser DOM. They cover the only post of a day (divider hidden) and one of several posts of a day (divider moves to the next showing card).
  • data-last-day: removed from #live-feed, along with its test and the mention in docs/design/areas/feed.md. The server carries the day in the day query parameter, which is what the continuing-page tests check.
  • Screen readers: the divider is now role="separator" with an aria-label of the day, rather than a bare <p>.
  • One loop: drawRegion now builds the posts in a single loop, with no Map and no second pass.

Not done

  • I did not make the client read data-last-day. The day parameter already works end to end.
  • I did not use a heading element for the divider. A separator avoids adding a heading level to the page.

Checks

  • The feed and home test files pass, 181 tests with 0 failures. tsc --noEmit and bun scripts/design-lint.ts are clean. I did not run the full check.

Try it

  • Open the home signed in, tap Dismiss on a day's only post, and its divider goes with it.
Approved

Approved. The change does what #6065 asks, and both points from the last round are fixed.

  • Dividers: drawRegion inserts a divider only where the day changes between neighbours, using dividers(). Posts stay in score order, which is what the issue's risk note requires.
  • Continuing pages: day= is honoured only next to a cursor and is checked with Date.parse before use. The label is fixed text from day_divider.ts and goes through html escaping. A junk day is ignored, and there is a test for it.
  • Hiding a card: keepDay moves a divider down to the next showing card of the same day, or hides it. It never touches a divider whose card is not the first of its day. The fake-DOM test covers both cases, and the server redraw recomputes dividers on its own.
  • Tests: they would fail without the change. With 27 posts today, the older page would draw a second Today without day=.
  • Design: no new class, §5 .muted.small is used, the divider is noted in docs/design/areas/feed.md, and the page works with JavaScript off.
  • Preview: / answers 200 signed out, and /live/feed with a junk day answers 404 to a guest. I could not sign in to the preview, so the signed-in render is proven by the test, not by my eyes.

Two smaller points that do not block:

  • The terminal dashboard's activity list does not draw dividers. The issue scoped this to the web timeline, so that would be its own issue if wanted.
  • aria-label repeats the divider's own text and could go.
Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs