Polish message row hover states (#880)

This commit is contained in:
klopez4212
2026-06-05 20:32:35 +01:00
committed by GitHub
parent bc53008676
commit b84f8e6a01
6 changed files with 18 additions and 7 deletions

View File

@@ -6,7 +6,7 @@ export function DayDivider({ label }: { label: string }) {
data-testid="message-timeline-day-divider"
data-day-label={label}
>
<p className="shrink-0 rounded-full bg-background/90 px-2 py-0.5 text-[10px] font-medium tracking-[0.02em] text-muted-foreground/65 backdrop-blur-sm">
<p className="shrink-0 rounded-lg border border-border/70 bg-background/95 px-2 py-1 text-[10px] font-medium tracking-[0.02em] text-muted-foreground/70 shadow-xs backdrop-blur-sm">
{label}
</p>
</section>

View File

@@ -30,6 +30,7 @@ export const MessageRow = React.memo(
function MessageRow({
channelId = null,
highlighted = false,
hoverBackground = true,
isFollowingThread,
layoutVariant = "default",
message,
@@ -45,6 +46,7 @@ export const MessageRow = React.memo(
}: {
channelId?: string | null;
highlighted?: boolean;
hoverBackground?: boolean;
isFollowingThread?: boolean;
layoutVariant?: "default" | "thread-reply";
message: TimelineMessage;
@@ -314,7 +316,8 @@ export const MessageRow = React.memo(
<article
className={cn(
"group/message relative rounded-2xl px-2 py-1 transition-colors",
"group/message relative rounded-2xl px-3 py-2 transition-colors",
hoverBackground && "hover:bg-muted/50 focus-within:bg-muted/50",
"flex items-start gap-2.5",
highlighted
? "-mx-4 rounded-none px-6 before:absolute before:-inset-y-1.5 before:inset-x-0 before:animate-[route-target-highlight-fade_2s_ease-out_forwards] before:bg-primary/10 before:content-[''] motion-reduce:before:animate-none sm:-mx-6 sm:px-8"
@@ -448,6 +451,7 @@ export const MessageRow = React.memo(
prev.message.role === next.message.role &&
prev.message.personaDisplayName === next.message.personaDisplayName &&
prev.highlighted === next.highlighted &&
prev.hoverBackground === next.hoverBackground &&
prev.isFollowingThread === next.isFollowingThread &&
prev.layoutVariant === next.layoutVariant &&
prev.profiles === next.profiles &&

View File

@@ -309,11 +309,16 @@ export function MessageThreadPanel({
{threadReplies.map((entry) => {
return (
<div
className="flex flex-col gap-1"
className={cn(
"flex flex-col gap-1",
entry.summary &&
"group/message -mx-1 rounded-2xl px-1 py-1 transition-colors hover:bg-muted/50 focus-within:bg-muted/50",
)}
key={entry.message.id}
>
<MessageRow
channelId={channelId}
hoverBackground={!entry.summary}
layoutVariant="thread-reply"
message={entry.message}
onDelete={

View File

@@ -321,7 +321,7 @@ export const SystemMessageRow = React.memo(function SystemMessageRow({
return (
<div
className="group/message relative rounded-2xl px-2 py-1 transition-colors"
className="group/message relative rounded-2xl px-3 py-2 transition-colors hover:bg-muted/50 focus-within:bg-muted/50"
data-testid="system-message-row"
>
<div className="flex items-start gap-2.5">

View File

@@ -108,7 +108,7 @@ export const TimelineMessageList = React.memo(function TimelineMessageList({
<div
key={message.id}
className={cn(
"relative flex flex-col gap-0",
"group/message relative -mx-1 flex flex-col gap-0 rounded-2xl px-1 py-1 transition-colors hover:bg-muted/50 focus-within:bg-muted/50",
isHighlighted &&
"-mx-4 px-4 before:absolute before:-inset-y-1.5 before:inset-x-0 before:animate-[route-target-highlight-fade_2s_ease-out_forwards] before:bg-primary/10 before:content-[''] motion-reduce:before:animate-none sm:-mx-6 sm:px-6",
)}
@@ -116,6 +116,7 @@ export const TimelineMessageList = React.memo(function TimelineMessageList({
<MessageRow
channelId={channelId}
highlighted={false}
hoverBackground={false}
isFollowingThread={
isFollowingThreadById
? isFollowingThreadById(message.id)

View File

@@ -403,6 +403,7 @@ test("opens a single-level thread panel with inline expansion", async ({
const siblingReply = `Sibling threaded reply ${timestamp}`;
const nestedReply = `Nested threaded reply ${timestamp}`;
const nestedReplyFromBob = `Nested reply from Bob ${timestamp}`;
const nestedReplyVisibleTopMaxPx = 260;
const fillerReplies = Array.from(
{ length: 14 },
(_, index) => `Thread filler reply ${index} ${timestamp}`,
@@ -524,7 +525,7 @@ test("opens a single-level thread panel with inline expansion", async ({
return rowRect.top - bodyRect.top;
});
})
.toBeLessThanOrEqual(240);
.toBeLessThanOrEqual(nestedReplyVisibleTopMaxPx);
const firstReplyId = await firstReplyRow.getAttribute("data-message-id");
if (!firstReplyId) {
@@ -578,7 +579,7 @@ test("opens a single-level thread panel with inline expansion", async ({
return rowRect.top - bodyRect.top;
});
})
.toBeLessThanOrEqual(240);
.toBeLessThanOrEqual(nestedReplyVisibleTopMaxPx);
await firstReplySummaryRow.click();
await expect(