diff --git a/src/screens/EmailListScreen.tsx b/src/screens/EmailListScreen.tsx index 3c95066d..68de068d 100644 --- a/src/screens/EmailListScreen.tsx +++ b/src/screens/EmailListScreen.tsx @@ -46,6 +46,9 @@ function isPinned(email: Email): boolean { return !!email.keywords?.$important; } +// Height of the sender line when the avatar is hidden (extra-compact density), +// used to anchor the unread dot on that first line. +const UNREAD_DOT_TEXT_LINE = 20; const EmailRow = React.memo(function EmailRow({ item, @@ -92,7 +95,14 @@ const EmailRow = React.memo(function EmailRow({ onLongPress={handleLongPress} delayLongPress={300} > - {unread && } + {unread && ( + + )} {selectionMode && ( {selected ? ( @@ -1369,11 +1379,12 @@ function makeStyles(c: ThemePalette) { // Mirrors the webmail's unread indicator: an 8px filled circle at the row's // start edge, vertically centered (email-list-item.tsx, fill-unread). The // weight/color change alone is too subtle on some device fonts (#27). + // `top` is set per row: the dot is anchored on the row's *first* line (top + // padding + half an avatar), not on the row's midpoint, which would drop it + // a full line below the checkbox and avatar it reads as a column with. unreadDot: { position: 'absolute', left: 4, - top: '50%', - marginTop: -4, width: 8, height: 8, borderRadius: 4, diff --git a/src/screens/UnifiedInboxScreen.tsx b/src/screens/UnifiedInboxScreen.tsx index b5796730..a6081c37 100644 --- a/src/screens/UnifiedInboxScreen.tsx +++ b/src/screens/UnifiedInboxScreen.tsx @@ -221,12 +221,13 @@ function makeStyles(c: ThemePalette) { }, rowPressed: { backgroundColor: c.surfaceHover }, // Same unread indicator as the mailbox list (and the webmail): an 8px - // filled circle in the start gutter, vertically centered (#27). + // filled circle in the start gutter (#27). Anchored on the row's *first* + // line — top padding + half an avatar — because centring it on the row + // drops it a full line below the avatar it reads as a column with. unreadDot: { position: 'absolute', left: 4, - top: '50%', - marginTop: -4, + top: spacing.md + componentSizes.avatarMd / 2 - 4, width: 8, height: 8, borderRadius: 4,