Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add tab bar header navigation #5082

Merged
merged 33 commits into from
Mar 20, 2024
Merged

feat: add tab bar header navigation #5082

merged 33 commits into from
Mar 20, 2024

Conversation

MuckT
Copy link
Collaborator

@MuckT MuckT commented Mar 13, 2024

Description

Adds the top navigation for tab navigation screens. In the screen shots below, the header is the main point of focus as different wallets were used to take enabled and disabled screenshots. Header icons were adjusted to allow for ripples on tap on Android and a few changes had to be made to keep alignment with the existing side DrawerTopBar.tsx.

Screenshots

Android Disabled Android Enabled iOS Disabled iOS Enabled

Test plan

  • Tested locally on iOS
  • Tested locally on Android
  • Unit tests added

Related issues

Backwards compatibility

Yes

Network scalability

N/A

Copy link

codecov bot commented Mar 13, 2024

Codecov Report

Attention: Patch coverage is 91.13924% with 7 lines in your changes are missing coverage. Please review.

Project coverage is 85.58%. Comparing base (409ace7) to head (f155a47).
Report is 3 commits behind head on main.

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #5082      +/-   ##
==========================================
+ Coverage   85.55%   85.58%   +0.02%     
==========================================
  Files         725      730       +5     
  Lines       29754    29843      +89     
  Branches     5138     5148      +10     
==========================================
+ Hits        25457    25541      +84     
- Misses       4061     4066       +5     
  Partials      236      236              
Files Coverage Δ
src/analytics/Events.tsx 100.00% <100.00%> (ø)
src/analytics/Properties.tsx 100.00% <ø> (ø)
src/components/QrScanButton.tsx 100.00% <100.00%> (ø)
src/components/TokenBalance.tsx 98.00% <ø> (ø)
src/home/NotificationBell.tsx 100.00% <100.00%> (ø)
src/icons/AccountCircle.tsx 100.00% <100.00%> (ø)
src/navigator/Headers.tsx 59.57% <100.00%> (+3.25%) ⬆️
src/navigator/TabNavigator.tsx 100.00% <100.00%> (ø)
src/navigator/TopBarButton.tsx 96.55% <ø> (ø)
src/notifications/NotificationList.tsx 100.00% <ø> (ø)
... and 6 more

... and 4 files with indirect coverage changes


Continue to review full report in Codecov by Sentry.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 409ace7...f155a47. Read the comment docs.

@MuckT MuckT marked this pull request as ready for review March 15, 2024 20:09

return (
<View style={styles.container}>
<Touchable
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Touchable used here and in other added icons instead of TopBarButton.tsx to better handle ripple on Android.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this something TopBarIconButton can support? if not, is there a purpose of keeping TopBarIconButton around?

EscrowedPaymentListScreen.navigationOptions = titleWithBalanceNavigationOptions(
i18n.t('escrowedPaymentReminder')
)
EscrowedPaymentListScreen.navigationOptions = () => ({
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed due to a failing test case in 2aeef88.

@@ -96,6 +98,27 @@ function WalletHome({ route }: Props) {
)
}

// Scroll Aware Header
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be worth abstracting this as we are now using the same pattern in two places.

@@ -33,13 +31,6 @@ export function NotificationList<T>(props: Props<T>) {
)
}

export function titleWithBalanceNavigationOptions(title: string) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused after 2aeef88.

@@ -205,7 +205,7 @@ function AssetsScreen({ navigation, route }: Props) {
}

return (
<>
<Animated.View>
Copy link
Collaborator Author

@MuckT MuckT Mar 15, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A weird edge case, Android only, were an animated view wrapped in a fragment can cause transparency issues.

Copy link

emerge-tools bot commented Mar 18, 2024

1 build increased size

Name Version Download Change Install Change Approval
⚠️ Celo (test)
org.celo.mobile.test
1.80.0 (145) 26.5 MB ⬆️ 2.4 MB (9.82%) 63.1 MB ⬆️ 2.7 MB (4.47%) N/A

Celo (test) 1.80.0 (145)
org.celo.mobile.test

⚖️ Compare build
📦 Install build
⏱️ Analyze build performance

Total install size change: ⬆️ 2.7 MB (4.47%)
Total download size change: ⬆️ 2.4 MB (9.82%)

Largest size changes

Item Install Size Change
📝 splashBackground@3x.jpg ⬆️ 600.2 kB
📝 background@3x.jpg ⬆️ 368.6 kB
📝 boost-rewards@3x.png ⬆️ 188.4 kB
📝 background@2x.jpg ⬆️ 176.1 kB
📝 boost-rewards@2x.png ⬆️ 90.1 kB
View Treemap

Image of diff


🛸 Powered by Emerge Tools

@@ -47,6 +48,8 @@ export default function TabNavigator({ route }: Props) {
options={{
tabBarLabel: t('bottomTabsNavigator.wallet.tabName') as string,
tabBarIcon: Wallet,
tabBarTestID: 'Tab/Wallet',
...(tabHeader as NativeStackHeaderProps),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

since this is the same across all screens, I think we can just set it once in the screenOptions prop of Tab.Navigator. Also is it possible to avoid the as casting?

Copy link
Collaborator Author

@MuckT MuckT Mar 18, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved to screenOptions in d5cc11c.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All of our headers using the NativeStackNavigationOptions, but screenOptions in Tab.Navigator expects a type of NativeStackHeaderProps. I believe this is due with our nested navigators, but it works in all the cases I tested. I tried avoiding the type casting and using a ts-expect-error, but that wasn't working.

}

const handleScroll = useAnimatedScrollHandler((event) => {
Animated.event([{ nativeEvent: { contentOffset: { y: scrollPositionValue } } }])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what's the purpose of this here? Seems like this returns an event handler function (that extracts contentOffset.y and sets it on scrollPositionValue) which should directly be passed to onScroll / other events so is this getting invoked actually? Seems like this also causes an error when scrolling

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved to calling onScroll in e2846b7 and I no longer see the error.

import { StackParamList } from 'src/navigator/types'
import { useDispatch, useSelector } from 'src/redux/hooks'
import colors from 'src/styles/colors'
import fontStyles from 'src/styles/fonts'
import colors, { Colors } from 'src/styles/colors'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: could we just use the default export or the named export? I believe both point to the same object

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Switched to using the named export in 74a55b5.

}

const handleScroll = useAnimatedScrollHandler((event) => {
Animated.event([{ nativeEvent: { contentOffset: { y: scrollPositionValue } } }])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same question as above

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved to calling onScroll in e2846b7 and I no longer see the error.

@@ -266,8 +267,8 @@ AssetsScreen.navigationOptions = {
const styles = StyleSheet.create({
listHeaderContainer: {
...getShadowStyle(Shadow.SoftLight),
paddingHorizontal: Spacing.Thick24,
paddingTop: Spacing.Smallest8,
paddingHorizontal: Spacing.Regular16,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we keep these at 24 for now, since the token balance items are spaced at 24?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Made it conditional base on the new tab view in 54e3825. The difference in header placement was a bit to noticeable in my opinion. Once we have a follow up PR to adjust padding we can remove the non tab navigator path.

jest.clearAllMocks()
jest
.mocked(getFeatureGate)
.mockImplementation((featureGate) => featureGate !== StatsigFeatureGates.USE_TAB_NAVIGATOR)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

personally not a fan of this pattern as it sets every other gate to true, but I guess this is good enough for documenting what gate we really care about in these tests.

Copy link
Collaborator Author

@MuckT MuckT Mar 18, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am open to other suggestions. It looks like mockImplementation always expects a boolean value returned so it's a bit tricky.

@@ -244,10 +262,12 @@ export function HeaderTitleWithTokenBalance({

export function HeaderTitleWithSubtitle({
title,
titleStyle,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wonder if we should just update this universally instead of a prop. Maybe worth checking with design?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Made it an optional prop to avoid impact on any of the existing screens. Currently this is used by the useScrollAwareHeader.tsx.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was actually proposing changing every screen to the new style. Seems low risk to me, and avoids another style prop which has to be passed down 2 layers deep, and this would be something that is never cleaned up.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed all the title styles in beb06fe. A quick look through the app didn't reveal any issues with this change on both large and default fonts.


export default function AccountCircleButton({ style, size, testID }: Props) {
const onPress = () => {
navigate(Screens.ProfileMenu)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we add an analytics event for this?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added in c4cf8fe!


return (
<View style={styles.container}>
<Touchable
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this something TopBarIconButton can support? if not, is there a purpose of keeping TopBarIconButton around?

@MuckT
Copy link
Collaborator Author

MuckT commented Mar 18, 2024

@satish-ravi in regards to keeping the TopBarIconButton.tsx it was used in too many other places to justify removing it in this PR. The main reason not to use is its lack of handing Android ripples. There are some notes in src/components/BackButton.tsx from @jeanregisser about what it took to get the ripple correct and it requires placement specific styling and seems like a general hassle. In my opinion we should create a better Icon wrapper and deprecate TopBarIconButton.tsx in a separate PR / ticket.

@@ -244,10 +262,12 @@ export function HeaderTitleWithTokenBalance({

export function HeaderTitleWithSubtitle({
title,
titleStyle,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was actually proposing changing every screen to the new style. Seems low risk to me, and avoids another style prop which has to be passed down 2 layers deep, and this would be something that is never cleaned up.

}

const handleScroll = useAnimatedScrollHandler((event) => {
onScroll
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this statement doing anything? onScroll I believe is a function, so this seems like just a line that references the function and doesn't invoke it.
Also, I think you should be able to use a single event handler instead of the 2 different handlers based on the gate. I believe both are just extracting event.contentOffset.y and setting it into a variable. onScroll sets it on the scrollPositionValue (of type Animated.Value) and handleScroll sets it on scrollPosition (of type SharedValue). We could just make all consumers use the SharedValue or just have a single handler that sets both variables.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried conditionally setting the scroll in fc03d3e. It looks like the other scroll is only being used by the drawer header so cleaning this up might be easier once that is removed. Perhaps a ticket to clean-up the drawer header and add todo's linked to that?

@satish-ravi
Copy link
Contributor

@satish-ravi in regards to keeping the TopBarIconButton.tsx it was used in too many other places to justify removing it in this PR. The main reason not to use is its lack of handing Android ripples. There are some notes in src/components/BackButton.tsx from @jeanregisser about what it took to get the ripple correct and it requires placement specific styling and seems like a general hassle. In my opinion we should create a better Icon wrapper and deprecate TopBarIconButton.tsx in a separate PR / ticket.

that sounds good. Can we mark this deprecated now and link to a placeholder issue so no new stuff is added that uses this?

@MuckT MuckT enabled auto-merge March 20, 2024 00:09
@MuckT MuckT disabled auto-merge March 20, 2024 00:14
@MuckT MuckT enabled auto-merge March 20, 2024 00:21
@MuckT MuckT added this pull request to the merge queue Mar 20, 2024
Merged via the queue into main with commit f529920 Mar 20, 2024
16 checks passed
@MuckT MuckT deleted the tomm/act-1108 branch March 20, 2024 01:46
shottah pushed a commit to zed-io/kolektivo that referenced this pull request May 15, 2024
### Description

Adds the top navigation for tab navigation screens. In the screen shots
below, the header is the main point of focus as different wallets were
used to take enabled and disabled screenshots. Header icons were
adjusted to allow for ripples on tap on Android and a few changes had to
be made to keep alignment with the existing side `DrawerTopBar.tsx`.

#### Screenshots

| Android Disabled | Android Enabled | iOS Disabled | iOS Enabled |
| ----- | ----- | ----- | ----- |
|
![](https://github.com/valora-inc/wallet/assets/26950305/51005dd6-ceaf-43a3-8e98-a46902cdae63
"Android Tab Nav Disabled") |
![](https://github.com/valora-inc/wallet/assets/26950305/db0630b1-c0bb-44a4-8720-427f2f5599bf
"Android Tab Nav Enabled") |
![](https://github.com/valora-inc/wallet/assets/26950305/cddf91e4-9eab-4d25-8e8d-2629d53ebc13
"iOS Tab Nav Disabled") |
![](https://github.com/valora-inc/wallet/assets/26950305/d2ad89d8-9a9f-4bcd-8621-a298f1916f7c
"iOS Tab Nav Enabled") |

### Test plan

- [x] Tested locally on iOS
- [x] Tested locally on Android
- [x] Unit tests added

### Related issues

- Fixes #ACT-1108

### Backwards compatibility

Yes

### Network scalability

N/A
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.

2 participants