Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion src/components/LegendList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -518,7 +518,14 @@ const LegendListInner = typedForwardRef(function LegendListInner<T>(
}

const resolvedOffset = initialScroll.contentOffset ?? resolveInitialScrollOffset(ctx, initialScroll);
return usesBootstrapInitialScroll && state.initialScrollSession?.kind === "bootstrap" && Platform.OS === "web"
// For a horizontal RTL *bootstrap* scroll (initialScrollIndex / initialScrollAtEnd),
// this seed is a logical (LTR) offset; feeding it to the native `contentOffset`
// unconverted lands on the RTL mirror. Skip the seed and let the bootstrap
// dispatch (which converts) position the list. Scoped to bootstrap sessions so
// offset-only initial scrolls still apply their offset.
return usesBootstrapInitialScroll &&
((state.initialScrollSession?.kind === "bootstrap" && Platform.OS === "web") ||
isHorizontalRTLProps({ horizontal, rtl }))
? undefined
: resolvedOffset;
}, [usesBootstrapInitialScroll]);
Expand Down
13 changes: 10 additions & 3 deletions src/core/checkFinishedScroll.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { initialScrollCompletion, initialScrollWatchdog } from "@/core/initialSc
import { Platform } from "@/platform/Platform";
import { getContentSize } from "@/state/getContentSize";
import type { StateContext } from "@/state/state";
import { toNativeHorizontalOffset } from "@/utils/rtl";

type ActiveScrollTarget = NonNullable<StateContext["state"]["scrollingTo"]>;
const INITIAL_SCROLL_MAX_FALLBACK_CHECKS = 20;
Expand Down Expand Up @@ -151,10 +152,16 @@ function checkFinishedScrollFrame(ctx: StateContext) {
}

function scrollToFallbackOffset(ctx: StateContext, offset: number) {
ctx.state.refScroller.current?.scrollTo({
const state = ctx.state;
const isHorizontal = !!state.props.horizontal;
// `offset` is a logical (LTR) offset. The normal dispatch path converts it to
// the native RTL coordinate; do the same here so the watchdog/retry doesn't
// dispatch an unconverted offset and land on the RTL mirror index.
const x = isHorizontal ? toNativeHorizontalOffset(state, offset, getContentSize(ctx)) : 0;
state.refScroller.current?.scrollTo({
animated: false,
x: ctx.state.props.horizontal ? offset : 0,
y: ctx.state.props.horizontal ? 0 : offset,
x,
y: isHorizontal ? 0 : offset,
});
}

Expand Down