- Ya
- 5 Agosti 2026, 22:37 UTC
- Mwandishi
- kamo
- Ahadi ya
- 1783e03
Every person shown in a read view was a dead end. To and Cc rendered as displayNameFor(a).join(', ') — a comma wall of display names with no address, no hover, no actions. Three things were wrong with that. The address was unrecoverable, and display names are attacker-controlled header text, so two people called Chris were indistinguishable and copying the address of someone who was CC'd meant opening a reply and inspecting the chip. Everything the organization already knows about that person — colleague records, address books, avatars, live presence — resolves by address and none of it reached the screen. And a fourteen-recipient thread rendered as one unreadable line. Hovering a name now opens a card. The address plate is its centrepiece rather than a grey subtitle, because the address is what the card exists to hand over: full width, mono, local part in ink and domain lighter, the whole plate a copy control that sweeps the messages accent across itself on success, and still selectable for anyone who would rather drag. Around it, only rows that have something in them: job title, employer, department, numbers that dial the softphone, a colleague's extension, and their local time before you call them. Colleagues carry a live presence dot from the existing presence and availability contexts. Automated senders say so, and a no-reply address does not offer a reply the mailbox would refuse. Recipient lists past five names collapse behind a count. The mechanics live in useHoverCard, away from the card, because none of it is about people: hover intent so a pointer crossing a header does not fire cards, a close grace period so the diagonal path to the card does not dismiss it, one card open at a time, re-measurement when the pane scrolls or the record lands, and real buttons so keyboard and touch reach it at all. Only keyboard focus opens — acting on click focus would open the card in the same tick the click toggles it shut, and the chip would look inert to a mouse. Records come from correspondentStore, keyed by address and never merged onto message objects: both list views poll every thirty seconds and replace their message array wholesale, which would wipe anything carried there twice a minute. Unlike avatars they resolve lazily — a whole header is prefetched when a message opens, and hovering covers anything that missed — so the card is normally already filled when it animates in. formatAgo moves out of MemberItem so the roster and the card describe the same absence the same way.