The screen opened with a tall filter card, so messages started below the fold,
and each message was a bordered card capped at max-w-sm, fitting three or four
per mobile screen.
List:
- Messages are now rows grouped under day headings (Today, Yesterday, then the
date). Roughly triples what fits on a phone, and scanning by time is how
people actually look for a message.
- Rows are buttons, so the list is keyboard navigable, with relative times
that reveal the exact timestamp on hover.
- Direction now comes from the `type` the API returns. It was inferred from
whether `sender` was present, which is only a proxy; the old check survives
as a fallback for rows written before `type` existed.
- Pagination renders only when there is more than one page.
- A search that matches nothing is a different state from a device with no
messages, and offers a way back.
Filter bar collapsed into one compact row: search, device, refresh, and auto
refresh moved into a dropdown instead of four inline buttons occupying a whole
row for a rarely-changed setting.
Details dialog reordered around why it is opened: the message body first, then
metadata, then errors, then actions. The exact timestamp is text here because
the list tooltip is hover-only and unreachable on touch.
Composer dialog gains real field labels (it used placeholders as labels, which
vanish on focus and are not reliably announced) and the same segment counter
bulk send has.
Two fixes found along the way:
- Reply passed message.device?._id with no fallback. The endpoint does
populate device, but if it were ever absent the composer would open with no
device and could not send. It now falls back to the device being viewed.
- The device-defaulting effect became derived state, so the list no longer
renders once with no device selected before correcting itself.
Segment helpers moved to lib/sms.ts now that the send page, bulk send and the
composer all use them. Fixtures now carry the populated `device` and relative
dates, so the mocked path matches production and exercises day grouping.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>