Typography round 5 (owner): drop the message count + active-row weight; ISO dates

Three declutter moves, all trivially reversible:

- The meta line drops the message count (idle meta is now just how long
  ago). The count informed no decision — clutter. messageCount still
  rides the API payload, so this is a one-line flip in sessionMeta if
  it's ever wanted.
- The active row is marked by the background alone: weight was a second
  channel doing the same job, and the flip made selected titles jump.
- Dates beyond the week render ISO (YYYY-MM-DD, zero-padded) instead of
  M/D/YYYY — the US convention swapped for the international standard:
  unambiguous in any locale, sorts lexically. A user-locale setting can
  come later — it's a format-function swap.

Also dropped the row's vestigial text-sm: both lines carry explicit
sizes now (16px title, 11px meta).

Live: active weight 400 + bg-accent, metas '17m ago' /
'Waiting for your answer · 1d ago', no counts. Gates: typecheck, lint,
469/469.
This commit is contained in:
amosblomqvist
2026-09-17 13:48:04 +03:00
parent 2a8554af27
commit 70ddc21610
2 changed files with 26 additions and 13 deletions
+9 -5
View File
@@ -86,26 +86,30 @@ describe("SessionRow", () => {
const working = render(item({ busy: true }));
assert.ok(working.includes("Teacher is working…"), "working meta");
// Owner, typography round 5: the message count is dropped — it
// informed no decision. Idle meta is just how long ago.
const idle = render(item({ title: "Partial derivatives", messageCount: 7 }));
assert.ok(idle.includes("Partial derivatives"));
assert.match(idle, /7 messages · \d{1,2}\/\d{1,2}\/\d{4}/, "idle keeps the count");
assert.ok(!idle.includes("messages"), "the count is gone (flip-flop: one line in sessionMeta)");
assert.match(idle, /\d{4}-\d{2}-\d{2}/, "idle shows the ISO date");
});
it("active row is visually marked", () => {
it("active row is visually marked by the background alone (owner, round 5: no weight change)", () => {
const html = render(item({}), true);
assert.ok(html.includes("font-medium"), "active emphasis");
assert.ok(html.includes("bg-accent"), "active background");
assert.ok(!html.includes("font-medium"), "weight is not a second channel doing the same job");
});
});
describe("timeAgo", () => {
const now = new Date("2026-01-02T12:00:00.000Z");
it("just now / minutes / hours / days, then falls back to a date", () => {
it("just now / minutes / hours / days, then the ISO date (owner, round 5)", () => {
assert.equal(timeAgo("2026-01-02T11:59:30.000Z", now), "just now");
assert.equal(timeAgo("2026-01-02T11:55:00.000Z", now), "5m ago");
assert.equal(timeAgo("2026-01-02T09:00:00.000Z", now), "3h ago");
assert.equal(timeAgo("2025-12-31T12:00:00.000Z", now), "2d ago");
assert.match(timeAgo("2025-06-02T12:00:00.000Z", now), /\d/, "beyond a week: a date");
assert.equal(timeAgo("2025-06-02T12:00:00.000Z", now), "2025-06-02", "beyond a week: ISO — unambiguous, sortable");
});
it("negative drift (clock skew) reads as just now, never a future date", () => {