Fix #133: app-wide relative date design #138

Merged
crueber merged 2 commits from fix/issue-133 into main 2026-09-05 15:28:15 +00:00
Owner

Fixes #133.

Every timestamp in the UI now renders through one shared component (web/src/components/DateTime.jsx) backed by headless-testable helpers in web/src/lib/format.js (fmtDate/fmtDateTitle/ordinal, Intl only — no new deps):

  • <1 day: relative only — 'just now' (<60s), 'N minute(s) ago', 'N hour(s) ago'
  • 1–30 days: 'N day(s) ago - {ordinal} of {Month}' (e.g. '3 days ago - 2nd of September')
  • 31+ days: '{Month} {ordinal}, {Year}' (e.g. 'September 28th, 2024')
  • All cases: hover title is the user-local wall time 'YYYY-MM-DD HH:MM ' with the real zone abbreviation from Intl short zone name (e.g. '2025-03-04 08:23 UTC'), never UTC-suffixed
  • Swept every date display app-wide (issues, pulls, commits, releases, checks, comments, WAL, settings history, keys, orgs); removed the per-page UTC formatters and the Keys toLocaleString; ThreadTimeline takes no more fmtDate prop
  • Invalid/missing dates keep the old fallbacks ('' / raw string); future timestamps clamp to 'just now'; text-only change so dark/light themes are unaffected

Decisions (documented in format.js): 31-day fixed month boundary (not calendar month); future clamp; fixed English month names for deterministic tier text; GMT offset fallback when Intl yields no zone name. docs/go/12_web_ui.md pins no date display, so no doc change.

Tests: node --test web/test/unit/*.test.js 308/308 green (new dates.test.js: 59s/1h/23h/24h/30d/31d/1y boundaries, ordinals incl. 11/12/13, future, invalid). vite build clean (117 modules). Browser spot-check via CDP on a real server (dark+light, /, /setup, repo commits + commit detail): zero console/page errors; live

Fixes #133. Every timestamp in the UI now renders through one shared component (`web/src/components/DateTime.jsx`) backed by headless-testable helpers in `web/src/lib/format.js` (`fmtDate`/`fmtDateTitle`/`ordinal`, Intl only — no new deps): - <1 day: relative only — 'just now' (<60s), 'N minute(s) ago', 'N hour(s) ago' - 1–30 days: 'N day(s) ago - {ordinal} of {Month}' (e.g. '3 days ago - 2nd of September') - 31+ days: '{Month} {ordinal}, {Year}' (e.g. 'September 28th, 2024') - All cases: hover title is the user-local wall time 'YYYY-MM-DD HH:MM <zone>' with the real zone abbreviation from Intl short zone name (e.g. '2025-03-04 08:23 UTC'), never UTC-suffixed - Swept every date display app-wide (issues, pulls, commits, releases, checks, comments, WAL, settings history, keys, orgs); removed the per-page UTC formatters and the Keys toLocaleString; ThreadTimeline takes no more fmtDate prop - Invalid/missing dates keep the old fallbacks ('' / raw string); future timestamps clamp to 'just now'; text-only change so dark/light themes are unaffected Decisions (documented in format.js): 31-day fixed month boundary (not calendar month); future clamp; fixed English month names for deterministic tier text; GMT offset fallback when Intl yields no zone name. docs/go/12_web_ui.md pins no date display, so no doc change. Tests: node --test web/test/unit/*.test.js 308/308 green (new dates.test.js: 59s/1h/23h/24h/30d/31d/1y boundaries, ordinals incl. 11/12/13, future, invalid). vite build clean (117 modules). Browser spot-check via CDP on a real server (dark+light, /, /setup, repo commits + commit detail): zero console/page errors; live <time> verified ('just now'->'1 minute ago', local title).
Every timestamp renders through a shared <DateTime> component backed by
headless-testable helpers in web/src/lib/format.js: <1 day relative
('just now'/'N minutes ago'/'N hours ago'), 1-30 days relative plus
ordinal day ('3 days ago - 2nd of September'), 31+ days absolute
('September 28th, 2024'); hover title is the user-local wall time
'YYYY-MM-DD HH:MM <zone>' via Intl short zone name. Sweeps all
fmtDate/toLocaleString call sites (issues, pulls, commits, releases,
checks, comments, WAL, settings history, keys, orgs).
Sign in to join this conversation.
No description provided.