mirror of
https://github.com/bulwarkmail/webmail.git
synced 2026-10-31 08:13:50 +00:00
fix(list): align the unread dot with the first line, not the row midpoint
The dot is absolutely positioned with `top-1/2`, so it centres on the whole row. In the default multi-line layout (sender / subject / preview) that puts it a full line below the checkbox and the avatar it reads as a column with — visibly out of line, and worse the taller the row. Anchor it on the first line instead: top padding + half an avatar, per density. Same fix for the messages of an expanded thread. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FTRyrFCR2N9qkpKK37GgWb
This commit is contained in:
co-authored by
Claude Opus 5
parent
fc7fec44a8
commit
7d868caae1
@@ -137,9 +137,14 @@ export function ThreadEmailItem({
|
||||
</button>
|
||||
)}
|
||||
|
||||
{/* Unread indicator */}
|
||||
{/* Unread indicator — anchored on the first line (top padding + half a
|
||||
small avatar), not on the row's midpoint, so it stays in line with
|
||||
the checkbox and avatar when the row wraps to a second line. */}
|
||||
{isUnread && (
|
||||
<div className="absolute start-7 top-1/2 -translate-y-1/2">
|
||||
<div
|
||||
className="absolute start-7 -translate-y-1/2"
|
||||
style={{ top: `calc(var(--density-item-py) + ${density === 'extra-compact' ? '0.625rem' : '1rem'})` }}
|
||||
>
|
||||
<Circle className="w-1.5 h-1.5 fill-unread text-unread" />
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -20,6 +20,27 @@ import { ThreadEmailItem } from "./thread-email-item";
|
||||
import { EmailHoverActions } from "./email-hover-actions";
|
||||
import { useTranslations } from "next-intl";
|
||||
|
||||
/**
|
||||
* Unread bullet in the row gutter.
|
||||
*
|
||||
* It is absolutely positioned so it never widens the row, which means it has
|
||||
* to be told where the row's *first* line sits: centring it on the row (the
|
||||
* old `top-1/2`) drifts down as soon as the row grows a second and third line,
|
||||
* leaving it visibly out of line with the checkbox and the avatar it reads as
|
||||
* a column with. Anchor = top padding + half an avatar.
|
||||
*/
|
||||
function UnreadDot({ density, compactAvatar }: { density: string; compactAvatar: boolean }) {
|
||||
const halfFirstLine = density === 'extra-compact' ? '0.625rem' : compactAvatar ? '1rem' : '1.25rem';
|
||||
return (
|
||||
<div
|
||||
className="absolute start-0.5 -translate-y-1/2"
|
||||
style={{ top: `calc(var(--density-item-py) + ${halfFirstLine})` }}
|
||||
>
|
||||
<Circle className="w-2 h-2 fill-unread text-unread" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Small chip showing the originating folder of a message, rendered in the
|
||||
* aggregate "All …" views (All Mail / unified / cross-account) where rows come
|
||||
@@ -244,9 +265,7 @@ const SingleEmailItem = React.forwardRef<HTMLDivElement, SingleEmailItemProps>(
|
||||
)}
|
||||
|
||||
{isUnread && (
|
||||
<div className="absolute start-0.5 top-1/2 -translate-y-1/2">
|
||||
<Circle className="w-2 h-2 fill-unread text-unread" />
|
||||
</div>
|
||||
<UnreadDot density={density} compactAvatar={isFocusedMailLayout} />
|
||||
)}
|
||||
|
||||
{density !== 'extra-compact' && (
|
||||
@@ -683,9 +702,7 @@ export const ThreadListItem = React.forwardRef<HTMLDivElement, ThreadListItemPro
|
||||
)}
|
||||
|
||||
{hasUnread && (
|
||||
<div className="absolute start-0.5 top-1/2 -translate-y-1/2">
|
||||
<Circle className="w-2 h-2 fill-unread text-unread" />
|
||||
</div>
|
||||
<UnreadDot density={density} compactAvatar={isFocusedMailLayout} />
|
||||
)}
|
||||
|
||||
{density !== 'extra-compact' && (
|
||||
|
||||
Reference in New Issue
Block a user