Skip to content

Replace modal screens with modals from @react-navigation #53493

@chrispader

Description

@chrispader

P/S Slack thread: expensify.slack.com/archives/C01GTK53T8Q/p1733938583809829

Problem

As discussed in this issue and this Slack thread we should replace modal screens (navigation screens/routes, that only render a modal) and modals that stay open when the containing screen gets unmounted.

The current modals use react-native-modal which uses RN internal Modal under the hood. Using these modals with @react-navigation/native-stack poses issues with animations and navigation, as these modals cannot animate in/out, due to the screen mounting/unmounting at the same time. Additionally, the animations will not look the same as the rest of the screen animations, which doesn't look very nice.

Solution

Replace the following types of modals with modal (screens) from @react-navigation

  • screens/routes that only render a modal
  • modals on screens, that are navigated back from while the modal is still open or animating out at the same time

cc @mountiny


List of components and screens to migrate to @react-navigation modal screens

Tracking my progress on an exhaustive list of components and screens that can/should be migrated to modal screens.

The list of components/screens (and other files) are triaged/prioritized as follows:
(File names are listed without file ending, usually .tsx)

  • 🔴 HIGH: Should definitely be migrated, due to current issues with animations and navigation.

    These modals are already causing issues with animations, because

    • they are animating in while a new screen is still mounting
    • they are still open/displayed while the old screen unmounting

    causing no or cut off animations.

  • 🟡 MEDIUM: Not causing any issues at the moment, but still worth to migrate to modal screens since the behave "like a screen", to achieve consistent animations and generally improve navigation. (gestures, native feel)

    This includes modals that are either

    • animated in from right-to-left (like a screen) or
    • that are part of another screen with animation: none,
    • etc.
  • 🟢 LOW: These screens are animated in from bottom-to-top like actual modals and are never (un-)mounted while at the same time as the screen. Migrating these modals to modal screens (and extra navigation routes) would make animations more consistent with the other screens, but it is not necessary and might not be worth the effort.

    Using a custom modal implementation or something like gorhom/react-native-bottom-sheet probably makes more sense.

Base components to (potentially) re-write

BaseModal
  • Affected modals:
    • TransactionStartDateSelectorModal
    • PaymentCardCurrencyModal
    • AmountSelectorModal
    • AttachmentModal
    • AvatarCropModal
    • CategorySelectorModal
    • ConfirmModal
    • CountrySelectorModal
    • YearPickerModal
    • DecisionModal
    • FeatureTrainingModal
    • PushRowModal
    • RequireTwoFactorAuthenticationModal
    • SearchRouterModal
    • StateSelectorModal
    • TestToolsModal
    • TextSelectorModal
    • ValueSelectorModal
    • BusinessTypeSelectorModal
    • NetSuiteCustomListSelectorModal
    • ExpenseLimitTypeSelectorModal
    • TransactionStartDateSelectorModal
    • UnitSelectorModal
    • WorkspaceMemberDetailsRoleSelectionModal
    • InitialListValueSelectorModal
    • TypeSelectorModal
  • Pages:
    • EditReportFieldDate
    • SetDatePage
    • DateOfBirthPage
    • SearchSelectedNarrow
  • Components:
    • SearchDateFilterBase
    • DateOfBirthStep
    • DebugDetailsDateTimePickerPage
    • AdditionalDetailsStep
    • IncorporationDateBusiness
    • IOURequestStepDate
Popover (uses Modal)
  • Comment: Uses Modal under the hood
  • Components:
    • EmojiPicker
    • PopoverMenu
    • PopoverWithMeasuredContent
    • PopoverReportActionContextMenu
    • BasePopoverReactionList
    • ProcessMoneyReportHoldMenu
    • WorkspaceCardsListLabel
    • AccountSwitcher
    • AddPaymentMethodMenu
    • AvatarWithImagePicker
    • AttachmentPickerWithMenu

Triaging

Modals only visible on native platforms (Android & iOS) are marked with 📱.

🔴 HIGH: Modals causing issues at the moment

Modals animating in from the bottom are marked with ⬆️, modals animating in from the right with ⬅️

AttachmentModal ⬅️ (screen recordings attached)
  • Comment: Add one or many extra routes?

  • Components:

    • AvatarWithImagePicker
    • ReportAvatar
    • TransactionReceiptPage
    • ReportActionCompose
    • ReportAttachments
    • ProfileAvatar
    • WorkspaceAvatar
  • iOS: Animating in not working, because the modal is animating at the same time, as a new screen with animation: none is mounting.

    Simulator.Screen.Recording.-.iPhone.16.Pro.-.2025-01-05.at.14.21.11.mp4
  • Android: Animation out is not working, probably due to the screen unmounting before the modal can animate out

    Screen.Recording.2025-01-05.at.14.20.52.mov
ConfirmModal ⬆️ (screen recordings attached)
  • Comment: Not all ConfirmModals are causing issues

  • Screens, where we navigate back while also animating the modal out:

    • TagSettingsPage (Remove tag)
    • WorkspaceEditTaxPage (Remove tax)
    • CategorySettingsPage (Remove category)
    • PolicyDistanceRateDetailsPage (Remove distance rate)
  • iOS: Modal not able to animate out, because the screen that wraps the modal is already unmounting:

    Simulator.Screen.Recording.-.iPhone.16.Pro.-.2025-01-05.at.14.24.29.mp4
  • Android: Same issue, though less obvious:

    Screen.Recording.2025-01-05.at.14.24.47.mov

🟡 MEDIUM: Screen-like modals - Animating in from right-to-left

SearchRouterModal
  • Pages:
    • AuthScreens
AmountSelectorModal -> AmountPicker
  • Pages:
    • Form
    • WorkspaceCreateTaxPage
AvatarCropModal -> AvatarWithImagePicker
  • Pages:
    • NewChatConfirmPage
    • ReportDetailsPage
    • ProfilePage
    • WorkspaceProfilePage
CategorySelectorModal
  • Pages:
    • WorkspaceCategoriesSettingsPage
  • Components:
    • CategorySelector
      • Pages:
        • PolicyDistanceRatesSettingsPage
        • WorkspacePerDiemSettingsPage (unused?)
YearPickerModal -> CalendarPicker -> DatePicker
  • Comment: Didn't test all flows
  • Pages:
    • SearchDateFilterBase
    • DateOfBirthStep
    • DebugDetailsDateTimePickerPage
    • EditReportFieldDate
    • AdditionalDetailsStep
    • IncorporationDateBusiness
    • IOURequestStepDate
    • SetDatePage
    • DateOfBirthPage
  • Components:
    • TransactionStartDateSelectorModal
TextSelectorModal -> TextPicker
  • Pages:
    • CreateReportFieldsPage
    • WorkspaceCreateTaxPage
  • Components:
    • Form
ValidateCodeActionModal
  • Pages:
    • MissingPersonalDetailsContent (multiple occurrences)
    • BankAccountStep
    • ContactMethodDetailsPage (multiple occurrences)
    • NewContactMethodPage
    • DelegateMagicCodeModal
    • CodesStep
    • BaseGetPhysicalCard
    • ExpensifyCardPage
    • ReportCardLostPage
    • ReportVirtualCardFraudPage
    • VerifyAccountPage
    • ConfirmationStep
ValueSelectorModal -> ValuePicker
  • Pages:
    • WorkspaceNewRoomPage
  • Components:
    • Form (multiple occurrences)
FeatureTrainingModal
  • Pages:
    • TrackTrainingPage
  • Components:
    • ExplanationModal
    • MigratedUserWelcomeModal
    • OnboardingWelcomeVideo
PaymentCardCurrencyModal
ConnectToQuickbooksOnlineFlow 📱
ConnectToXeroFlow 📱
CardAuthenticationModal
  • Pages:
    • PaymentCard
    • WorkspaceOwnerChangeWrapperPage
NetSuiteCustomListSelectorModal -> NetSuiteCustomListPicker
  • Pages:
    • ChooseCustomListStep
ExpenseLimitTypeSelectorModal -> ExpenseLimitTypeSelector
  • Pages:
    • CategoryFlagAmountsOverPage
TransactionStartDateSelectorModal
  • Components:
    • TransactionStartDateStep
UnitSelectorModal -> UnitSelector
  • Pages:
    • PolicyDistanceRatesSettingsPage
WorkspaceMemberDetailsRoleSelectionModal
  • Pages:
    • WorkspaceMemberDetailsPage (multiple occurrences)
InitialListValueSelectorModal -> InitialListValueSelector
  • Pages:
    • CreateReportFieldsPage
TypeSelectorModal -> TypeSelector
  • Pages:
    • CreateReportFieldsPage

🟢 LOW: Contained modals - Only visible as part of the current screen, animating in from bottom-to-top

ConfirmModal
  • Comment: We will need to decide about creating an extra route for every screen individually.
  • Screens:
    • EditReportFieldPage
    • ReportDetailsPage
    • ReportParticipantDetailsPage
    • ReportParticipantsPage
    • RoomMemberDetailsPage
    • RoomMembersPage
    • EmptySearchView
    • ConsolePage
    • InitialSettingsPage
    • ContactMethodDetailsPage
    • VisibilityPage
    • CloseAccountPage
    • SecuritySettingsPage
    • TroubleshootPage
    • WalletPage
    • WorkspaceInitialPage
    • WorkspaceMembersPage
    • WorkspaceMoreFeaturesPage
    • WorkspaceProfilePage
    • WorkspacesListPage
    • PolicyAccountingPage
    • SageIntacctEditUserDimensionsPage
    • NetSuiteImportCustomFieldView
    • ImportedCategoriesPage
    • WorkspaceCategoriesPage
    • WorkspaceCompanyCardDetailsPage
    • WorkspaceCompanyCardsSettingsPage
    • PolicyDistanceRatesPage
    • WorkspaceEditCardLimitPage
    • WorkspaceEditCardLimitTypePage
    • WorkspaceExpensifyCardDetailsPage
    • WorkspaceExpensifyCardPageEmptyState
    • WorkspaceInvoiceVBASection
    • ImportedMembersPage
    • WorkspaceMemberDetailsPage
    • ImportedPerDiemPage
    • WorkspacePerDiemDetailsPage
    • WorkspacePerDiemPage
    • ReportFieldsListValuesPage
    • ReportFieldsSettingsPage
    • ReportFieldsValueSettingsPage
    • WorkspaceReportFieldsPage
    • ImportedTagsPage
    • WorkspaceTagsPage
    • WorkspaceViewTagsPage
    • WorkspaceTaxesPage
    • WorkspaceWorkflowsPage
    • WorkspaceWorkflowsApprovalsEditPage
  • Components:
    • Expensify
    • AccountSwitcher
    • AccountingConnectionConfirmationModal
    • AttachmentModal
    • ConfirmModal
    • DelegateNoAccessModal
    • FocusModeNotification
    • ImportSpreadsheet
    • LocationPermissionModal
    • MoneyReportHeader
    • ExportWithDropdownMenu
    • SearchPageHeader
    • SupportActionRestrictedModal
    • BaseUpdateAppModal
    • HeaderView
    • PopoverReportActionContextMenu
    • ReportDetailsExportPage
    • FloatingActionButtonAndPopover
    • IOURequestStepScan
    • IOURequestStepWaypoint
    • CardSection
    • WorkspaceResetBankAccountModal
  • Hooks:
    • useDeleteSavedSearch
DecisionModal
  • Pages:
    • SearchPageHeader
    • ReportDetailsPage (multiple occurrences)
    • WorkspaceMembersPage (multiple occurrences)
    • WorkspaceCategoriesPage (multiple occurrences)
    • WorkspaceTagsPage
  • Components:
    • BaseImportOnyxState
    • ProcessMoneyReportHoldMenu
SelectionListModal -> SelectionListWithModal
  • Pages:
    • Search
    • ReportParticipantsPage
    • RoomMembersPage
    • WorkspaceMembersPage
    • WorkspaceCategoriesPage
    • PolicyDistanceRatesPage
    • WorkspacePerDiemPage
    • ReportFieldsListValuesPage
    • WorkspaceReportFieldsPage
    • WorkspaceTagsPage
    • WorkspaceViewTagsPage
    • WorkspaceTaxesPage
RequireTwoFactorAuthenticationModal
  • Components:
    • Expensify (multiple occurrences)
TestToolsModal
  • Pages:
    • AuthScreens
SearchSelectedNarrow -> SearchPageHeader
  • Pages:
    • SearchPage
    • SearchSelectionModaHeader

❓ Unknown: Unable to test because the modal is either missing or not accessible

CountrySelectorModal -> CountryPicker -> Address
  • Pages:
    • MissingPersonalDetailsContent -> MissingPersonalDetails (unused?)
StateSelectorModal -> StatePicker -> Address
  • Components:
    • MissingPersonalDetailsContent -> MissingPersonalDetails (unused?)
PushRowModal -> PushRowWithModal (unused?)
  • Pages:
    • ReimburseAccountPage
    • AddressFormFields
    • BusinessType
    • IncorporationLocation
    • PaymentVolume
    • Confirmation
BusinessTypeSelectorModal -> BusinessTypePicker
  • Pages:
    • ReimburseAccountPage
    • BusinessInfo
Issue OwnerCurrent Issue Owner: @mountiny

Metadata

Metadata

Labels

BugSomething is broken. Auto assigns a BugZero manager.PlanningChanges still in the thought processWeeklyKSv2

Type

No type
No fields configured for issues without a type.

Projects

Status
LOW

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions