react-navigation / react-navigation/react-navigation

Allow per-jump animation control for TabView / Material Top Tabs

Open
#13,095 3 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

platform:android platform:ios repro provided
Dominant language
TypeScript
Stars
24.5k
Forks
5.1k
Avg merge
1d 5h
Merged PRs (30d)
18

Description

Current behavior

react-native-tab-view exposes animationEnabled as a global boolean. This is enough to always animate or never animate tab changes, but it doesn't let a custom tab bar decide that a specific jumpTo call should skip animation.

The underlying native primitive, react-native-pager-view, already supports both behaviors with setPage(index) and setPageWithoutAnimation(index). PagerViewAdapter currently selects between them based on the global animationEnabled prop.

This comes up in apps with heavy top-level tabs and a custom tab bar. A normal tab press should still animate, but if the user rapidly presses between tabs, the second/third press should be able to cancel or skip the in-flight animation and jump immediately to the requested tab. The current public API doesn't provide a way to do that without either:

  • setting animationEnabled: false for all tab presses/programmatic changes, or
  • patching PagerViewAdapter internally to use setPageWithoutAnimation conditionally.

Related prior issues:

Issue #1371 / PR #1388 solved the coarse version of this by adding animationEnabled. This request is for the next layer: per-jump animation policy.

Expected behavior

Would maintainers be open to a patch that allows jumpTo to opt out of animation for a specific tab change, while preserving current behavior by default?

One possible API shape:

type JumpToOptions = {
  animated?: boolean;
};

type SceneRendererProps = {
  // Backwards compatible: existing `jumpTo(key)` calls keep using `animationEnabled`.
  jumpTo: (key: string, options?: JumpToOptions) => void;
};

Then a custom tab bar could do something like:

const isRapidPress = Date.now() - lastTabPressAt.current < 250;
lastTabPressAt.current = Date.now();

jumpTo(route.key, { animated: !isRapidPress });

Internally, PagerViewAdapter could choose between setPage(index) and setPageWithoutAnimation(index) based on options?.animated ?? animationEnabled. The web / pan responder adapter could use the same optional argument to choose whether to animate the jump.

This would avoid app-level patches while keeping the existing global animationEnabled prop as the default policy.

I am happy to put together a PR if this API direction seems acceptable. If maintainers would prefer a different shape, such as an animationEnabled callback or a shouldAnimateJump(fromIndex, toIndex) prop, I'm glad to adapt before implementing.

Reproduction

https://github.com/tian000/react-navigation-tabview-rapid-jump-repro

This is a minimal Expo repro using the latest @react-navigation/native, @react-navigation/material-top-tabs, and react-native-tab-view versions currently published on npm.

The repro renders two sections:

  1. react-native-tab-view: rapid tab presses are detected, but the custom tab bar can only call jumpTo(route.key). The desired jumpTo(route.key, { animated: !isRapidPress }) API is shown in a code comment.
  2. direct react-native-pager-view: rapid tab presses call setPageWithoutAnimation; normal tab presses call setPage, demonstrating that the lower-level primitive supports the behavior.

Run:

npm install
npm run android

or:

npm install
npm run ios

Then rapidly press Home, Trade, and Explore in both sections.

Platform
  • Android
  • iOS
  • Web
  • Windows
  • MacOS
Packages
  • '@react-navigation/material-top-tabs'
  • 'react-native-tab-view'
Environment

Verified with the repro app:

package version
@react-navigation/native 7.2.2
@react-navigation/material-top-tabs 7.4.24
react-native-tab-view 4.3.0
react-native-pager-view 6.9.1
react-native 0.81.5
expo 54.0.33

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Review the PagerViewAdapter and the web/pan responder adapter entry points described in the issue, then run the linked rapid-jump repro with npm install and the Android or iOS command. Define the API direction with maintainers first; done should preserve animationEnabled as the default while allowing an individual jump to select animated or non-animated behavior across the relevant adapters.

Written by the indexing model from the issue text.

Assessment

Tech stack
react-native, typescript
Domain
frontend, mobile
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.