Draw the route-target highlight on the row's hover pill

The deep-link highlight swapped the row to a full-bleed band geometry
(negative margins, square corners, wider padding). That widened the text
column by ~8px, so long lines could rewrap and change the row's measured
height — in the virtualized timeline that makes Virtua re-measure and nudge
the scroll, once when the highlight appears and again when it clears.

Paint the tint on a before: pseudo sized to the row's own rounded-2xl hover
pill instead, so highlighted and idle rows are geometrically identical.
Share the class between MessageRow and the thread-summary wrapper so the
two can't drift again.

Signed-off-by: morgmart <98432065+morgmart@users.noreply.github.com>
This commit is contained in:
morgmart
2026-08-22 21:46:29 -07:00
parent 8290827192
commit 73f3a9a24b
3 changed files with 18 additions and 5 deletions

View File

@@ -55,6 +55,7 @@ import {
MessageMetaSegments,
} from "./MessageHeader";
import { MessageTimestamp } from "./MessageTimestamp";
import { ROUTE_TARGET_HIGHLIGHT_CLASS } from "./routeTargetHighlight";
import { SentFromThreadLine } from "./SentFromThreadLine";
import { WaveMessageAttachment } from "./WaveMessageAttachment";
import { Tooltip, TooltipContent, TooltipTrigger } from "@/shared/ui/tooltip";
@@ -892,9 +893,7 @@ export const MessageRow = React.memo(
"flex gap-2.5",
isDisplayedAsContinuation ? "items-center" : "items-start",
hasActiveReminder ? "bg-blue-500/10" : "",
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"
: "",
highlighted ? ROUTE_TARGET_HIGHLIGHT_CLASS : "",
)}
data-message-id={message.id}
data-testid="message-row"

View File

@@ -9,6 +9,7 @@ import type { UserProfileLookup } from "@/features/profile/lib/identity";
import { cn } from "@/shared/lib/cn";
import { MessageRow } from "./MessageRow";
import { MessageThreadSummaryRow } from "./MessageThreadSummaryRow";
import { ROUTE_TARGET_HIGHLIGHT_CLASS } from "./routeTargetHighlight";
import { SystemMessageRow } from "./SystemMessageRow";
type ToggleReaction = (
@@ -137,8 +138,7 @@ export function MessageRowItem({
<div
className={cn(
"group/message relative mx-1 mb-1 flex flex-col gap-0 rounded-2xl px-0 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",
isHighlighted && ROUTE_TARGET_HIGHLIGHT_CLASS,
)}
>
<MessageRow

View File

@@ -0,0 +1,14 @@
/**
* Classes that paint the "you were sent here" tint on a timeline row.
*
* The tint is drawn on a `before:` pseudo-element sized to the row's own
* hover pill (same `rounded-2xl` radius, no margin/padding change), so turning
* the highlight on or off never alters the row's geometry. In the virtualized
* timeline a geometry change would rewrap text, change the row's measured
* height, and make Virtua nudge the scroll position — once on arrival and
* again when the highlight clears.
*
* Hosts must be `relative` and use the `rounded-2xl` hover pill geometry.
*/
export const ROUTE_TARGET_HIGHLIGHT_CLASS =
"before:pointer-events-none before:absolute before:inset-0 before:rounded-2xl before:animate-[route-target-highlight-fade_2s_ease-out_forwards] before:bg-primary/10 before:content-[''] motion-reduce:before:animate-none";