fix(desktop): remount timeline scroll node per channel (#1147)

Signed-off-by: npub1t2tgm7d8f995uqvmnm8h88sg3wnpp9a5xysjf6dg3tjmgt3ltulqdp8ehr <5a968df9a7494b4e019b9ecf739e088ba61097b4312124e9a88ae5b42e3f5f3e@sprout-oss.stage.blox.sqprod.co>
Co-authored-by: npub1t2tgm7d8f995uqvmnm8h88sg3wnpp9a5xysjf6dg3tjmgt3ltulqdp8ehr <5a968df9a7494b4e019b9ecf739e088ba61097b4312124e9a88ae5b42e3f5f3e@sprout-oss.stage.blox.sqprod.co>
This commit is contained in:
Tyler
2026-06-19 15:31:25 -04:00
committed by GitHub
parent 39626197c0
commit 0c5dbf3452
2 changed files with 8 additions and 1 deletions

View File

@@ -264,7 +264,7 @@ export const ChannelPane = React.memo(function ChannelPane({
useComposerHeightPadding(
timelineScrollRef,
composerWrapperRef,
`${isSinglePanelView}:${hasMainComposerOverlay}`,
`${activeChannelId}:${isSinglePanelView}:${hasMainComposerOverlay}`,
);
const clearWelcomeComposerDismissTimer = React.useCallback(() => {

View File

@@ -205,6 +205,12 @@ const MessageTimelineBase = React.forwardRef<
const scrollRestorationId = targetMessageId
? `message-timeline:${channelId ?? "none"}:target:${targetMessageId}`
: `message-timeline:${channelId ?? "none"}`;
// Keep the scroll node's DOM lifetime scoped to a channel. TanStack Router's
// scroll-restoration listener runs outside React and may write a saved
// scrollTop into the current scroll element during navigation; reusing the
// same node across channel routes can leave the newly-loaded message list
// painted at a stale offset until the user's next scroll event forces layout.
const scrollContainerDomKey = channelId ?? "none";
const timelineBodySurface = selectTimelineBodySurface({
deferredCount: deferredMessages.length,
@@ -339,6 +345,7 @@ const MessageTimelineBase = React.forwardRef<
)}
data-scroll-restoration-id={scrollRestorationId}
data-testid="message-timeline"
key={scrollContainerDomKey}
onScroll={onScroll}
ref={scrollContainerRef}
>