Commit 6e825ea
authored
feat(Android, Tabs): partially implement RFC-1028 for Tabs on Android (#3776)
## Description
> [!note]
> I'll wait with landing this PR until I get approvals on
#3781.
These two should be landed in tandem.
Partially implements
[RFC-1028](#3702)
for the Tabs component on Android. This PR changes the communication
model between the native and JS sides of the Tabs implementation,
switching from *controlled mode* to *managed mode*, and introduces a
richer event payload for tab change events.
This is part of a broader refactor series for the Tabs component. State
conflict resolution algorithm (as described in RFC-1028) is deferred to
a follow-up PR.
Related to #3702.
Closes
software-mansion/react-native-screens-labs#990
## Changes
### Android (native)
- **Switched from *controlled* to *managed* mode**: The container now
first updates its model and then sends events to the Element realm,
rather than waiting for JS to confirm state.
- **Replaced `TabsHostNativeFocusChangeEvent` with
`TabsHostTabChangeEvent`**: The new event carries an extended payload
(`selectedScreenKey` + `provenance`) aligned with RFC-1028 model.
- **Moved menu model construction out of appearance update**:
Previously, `BottomNavigationMenuView` model was built inside
`updateBottomNavigationViewAppearance`. It's now a separate step that
happens before any container update is triggered, which is
architecturally cleaner and required by the new update flow.
- **Streamlined container update logic**: Native update now begins with
`TabsContainer::onMenuItemSelected` (triggered by `OnMenuItemClicked`
listener). JS-initiated update begins with `TabsHost` setting an
operation on `TabsContainer` and flushing it, which in turn triggers
`onMenuItemSelected` via `bottomNavigationView.menu.selectedItemId`
assignment.
- **Removed `ContainerUpdateCoordinator`**: Replaced with the stack
model — operations are flushed on `UIManagerListener.didMountItems`
callback, aligning with how Stack works on Android and iOS.
- **`TabsScreen` no longer tracks its own selection state**: `isFocused`
prop has been removed. Selection state is now passed to the native side
via the new `navState` prop on `TabsHost`.
- **Added `TabsContainerDelegate`** and **`MenuHelpers`** as supporting
infrastructure.
### JS / TypeScript
- **`onNativeFocusChange` replaced with `onTabChange`**: New event name
follows RFC-1028. The payload is richer, providing more context. This is
a **breaking change** — downstream code will need to adapt.
- **`navState` prop added to `TabsHost`**: Carries `selectedScreenKey`
and `provenance`, enabling the managed mode operation flow.
- **`isFocused` removed from `TabsScreen`**: Screen no longer manages
its own focus awareness.
- **Updated JS `TabsContainer` example implementation**:
- Distinguishes between `native-tab-change` and `js-tab-change` dispatch
actions.
- Introduces `confirmedState` (state confirmed as displayed by native
side) and `suggestedState` (state sent to native but not yet confirmed).
- Prevents user-defined `onTabChange` callback from overriding
`TabsContainer`'s internal handler.
## Test plan
- Tested manually using
`apps/src/tests/single-feature-tests/tabs/test-tabs-simple-nav.tsx` on
Android.
- Verified basic tab navigation works in managed mode (native-initiated
and JS-initiated tab changes).
## Checklist
- [x] Included code example that can be used to test this change.
- [ ] Updated / created local changelog entries in relevant test files.
- [ ] For visual changes, included screenshots / GIFs / recordings
documenting the change.
- [x] For API changes, updated relevant public types.
- [ ] Ensured that CI passes1 parent 17a6682 commit 6e825ea
30 files changed
Lines changed: 669 additions & 420 deletions
File tree
- android/src/main/java/com/swmansion/rnscreens/gamma/tabs
- appearance
- container
- host
- event
- screen
- apps/src
- tests/single-feature-tests/tabs
- src
- components/tabs
- host
- screen
- fabric/tabs
Lines changed: 5 additions & 8 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
15 | 15 | | |
16 | 16 | | |
17 | 17 | | |
18 | | - | |
19 | 18 | | |
20 | 19 | | |
21 | 20 | | |
22 | 21 | | |
23 | | - | |
| 22 | + | |
24 | 23 | | |
25 | 24 | | |
26 | 25 | | |
| |||
33 | 32 | | |
34 | 33 | | |
35 | 34 | | |
36 | | - | |
| 35 | + | |
| 36 | + | |
37 | 37 | | |
38 | | - | |
39 | | - | |
40 | | - | |
| 38 | + | |
41 | 39 | | |
42 | 40 | | |
43 | 41 | | |
| |||
115 | 113 | | |
116 | 114 | | |
117 | 115 | | |
118 | | - | |
| 116 | + | |
119 | 117 | | |
120 | | - | |
121 | 118 | | |
122 | 119 | | |
123 | 120 | | |
| |||
Lines changed: 16 additions & 22 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
2 | 2 | | |
3 | 3 | | |
4 | | - | |
5 | 4 | | |
6 | | - | |
7 | 5 | | |
8 | | - | |
| 6 | + | |
| 7 | + | |
9 | 8 | | |
10 | 9 | | |
11 | 10 | | |
12 | | - | |
| 11 | + | |
13 | 12 | | |
14 | 13 | | |
15 | 14 | | |
16 | 15 | | |
17 | 16 | | |
18 | 17 | | |
19 | 18 | | |
20 | | - | |
| 19 | + | |
21 | 20 | | |
22 | | - | |
23 | | - | |
24 | | - | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
25 | 25 | | |
26 | 26 | | |
27 | 27 | | |
28 | 28 | | |
29 | | - | |
| 29 | + | |
30 | 30 | | |
31 | | - | |
32 | | - | |
33 | | - | |
34 | | - | |
35 | | - | |
36 | 31 | | |
37 | | - | |
38 | | - | |
39 | | - | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
40 | 39 | | |
41 | 40 | | |
42 | 41 | | |
| |||
50 | 49 | | |
51 | 50 | | |
52 | 51 | | |
53 | | - | |
54 | | - | |
55 | | - | |
56 | | - | |
57 | | - | |
Lines changed: 31 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
0 commit comments