Skip to content

Mirror default Navigation3 push/pop transitions on iOS in RTL layouts - #3346

Open
Mohamad Jaber (mhammadjaber00) wants to merge 1 commit into
JetBrains:jb-mainfrom
mhammadjaber00:fix/navigation3-ios-rtl-transitions
Open

Mirror default Navigation3 push/pop transitions on iOS in RTL layouts#3346
Mohamad Jaber (mhammadjaber00) wants to merge 1 commit into
JetBrains:jb-mainfrom
mhammadjaber00:fix/navigation3-ios-rtl-transitions

Conversation

@mhammadjaber00

@mhammadjaber00 Mohamad Jaber (mhammadjaber00) commented Aug 26, 2026

Copy link
Copy Markdown

The iOS defaultTransitionSpec() and defaultPopTransitionSpec() in NavDisplay.ios.kt slide using the physical SlideDirection.Left/Right, which ignore the composition's LayoutDirection. In an RTL layout (Arabic/Hebrew locales) a push therefore enters from the physical right — exactly as in LTR — while a native UINavigationController push mirrors and enters from the left. To an RTL user the default push animation reads as a back navigation.

This replaces Left/Right with the direction-aware Start/End:

  • push: incoming slides toward Start; outgoing slides toward Start with the existing it / 4 parallax and veilOut
  • pop: the mirror with End, keeping initialOffset = { it / 4 } and unveilIn

Start/End resolve through LayoutDirection and flip the computed offsets automatically, so the offset lambdas, duration, and easing are untouched. LTR behavior is pixel-identical (Start == Left, End == Right in LTR). defaultPredictivePopTransitionSpec() is already direction-aware via the swipe edge parameter (made RTL-correct for the gesture in #3196) and is not changed. The other platform actuals are unaffected: the Android default is a fade, and desktop/macOS/web use EnterTransition.None / ExitTransition.None.

Adds NavDisplayLayoutDirectionTest in a new iosTest source set for :navigation3:navigation3-ui, asserting the incoming entry's edge for default push and pop under both LTR and RTL (frame-stepped clock, unclipped bounds). The ui-test dependency is wired the same way :navigation:navigation-compose wires project(":compose:ui:ui-test") for its compose tests.

Fixes: https://youtrack.jetbrains.com/issue/CMP-10703/Navigation3-default-push-pop-transitions-on-iOS-are-not-mirrored-in-RTL-layouts

Testing

  • Regression test: NavDisplayLayoutDirectionTest (iosTest) — default push/pop enter edges under LTR and RTL. Run on an iOS simulator against the currently published navigation3-ui defaults, both LTR cases pass and both RTL cases fail (push incoming appears a full width off the right edge, pop incoming a quarter width off the left), demonstrating the test catches the bug; with this change all four pass.
  • Manually reproduced on a physical iPhone with an Arabic locale: before the change a push enters from the right in RTL; after, it enters from the left, matching UIKit.
  • Spec-level verification against Compose Multiplatform 1.12.0: the same ContentTransforms driven through AnimatedContent under LTR and RTL — Left/Right specs animate identically in both directions, Start/End specs keep LTR unchanged and mirror in RTL.

Release Notes

Fixes - iOS

  • Default Navigation3 push and pop transitions now follow the layout direction: in RTL layouts a push enters from the left edge and a pop reveals the previous entry from the right edge, matching native UINavigationController behavior

The iOS defaultTransitionSpec/defaultPopTransitionSpec slid with the
physical SlideDirection.Left/Right, ignoring LayoutDirection, so an RTL
push entered from the right like in LTR while a native
UINavigationController push mirrors. Use Start/End, which resolve
through LayoutDirection and flip the parallax offsets automatically;
LTR behavior is unchanged. The predictive pop spec is already
direction-aware via its swipe edge parameter and other platform
defaults do not slide.

Test: NavDisplayLayoutDirectionTest (iosTest) asserts the incoming
entry's edge for default push and pop under LTR and RTL.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant