feat(mobile): document react-navigation modal pattern using ModalContext#756
Open
adrienzheng-cb wants to merge 2 commits into
Open
feat(mobile): document react-navigation modal pattern using ModalContext#756adrienzheng-cb wants to merge 2 commits into
adrienzheng-cb wants to merge 2 commits into
Conversation
Adds a recommended pattern for using Modal sub-components (ModalHeader, ModalBody, ModalFooter) inside react-navigation modal screens, without introducing a new public component. Co-authored-by: Cursor <cursoragent@cursor.com>
Collaborator
🟡 Heimdall Review Status
🟡
|
| Code Owner | Status | Calculation | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| ui-systems-eng-team |
🟡
0/1
|
Denominator calculation
|
Co-authored-by: Cursor <cursoragent@cursor.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What changed? Why?
Background
This PR addresses the mobile Modal refresh goal of enabling Modal sub-components (
ModalHeader,ModalBody,ModalFooter) to be used inside react-navigation modal screens — wherereact-navigationowns the overlay, transition animation, and swipe-to-dismiss gesture, making the existingModalcomponent inappropriate.Decision process: why no new component
The initial approach explored introducing a new component (variously named
ModalContent,NavigationModal, andModalLayout) to serve as a layout wrapper for navigation screens. After iterating on the design, we decided against it for the following reasons:Modaldoesn't own its children's structure.Modalis a pure overlay mechanism — it renders whatever children are passed to it verbatim. Introducing a companion layout component (ModalLayout) that does dictate structure would be philosophically inconsistent.The wrapper adds very little value. When examined closely, any such component would reduce to a thin
ModalContext.Providerwrapper around aVStack. The animation andSafeAreaViewlayers insideModalare overlay-specific and can't be cleanly shared. Making them conditional would leakModal's concerns into the layout component.@coinbase/cds-commonis accessible to consumers. TheModalContextthat sub-components depend on lives in@coinbase/cds-common, which consumers typically install alongside@coinbase/cds-mobile. The package exposes a./*wildcard export, so@coinbase/cds-common/overlays/ModalContextis a valid public import path — no re-export needed.Consistent with web precedent. On web,
FullscreenModalandFullscreenModalLayoutare composed independently — the overlay component doesn't force a specific chrome structure on consumers.What changed
Docs (
apps/docs/docs/components/overlay/Modal/_mobileExamples.mdx): Added a "Using with react-navigation" section documenting the recommended pattern: wrap screen content withModalContext.Provider+VStack, composeModalHeader/ModalBody/ModalFooterdirectly. NoModalwrapper needed.test-expostory (packages/mobile/src/overlays/__stories__/ModalNavigation.stories.tsx): NewModalNavigationstory that demonstrates the pattern as a real react-navigation modal screen (presented withpresentation: "modal"). Deep link:testexpo:///DebugModalNavigation.test-exporoutes (apps/expo-app/src/routes.ts): AddedModalNavigationroute withpresentation: 'modal' as const.PlaygroundRoutetype (apps/expo-app/src/playground/PlaygroundRoute.ts): Added optionaloptionsandhideFromListfields to support per-route navigation options.Playground(apps/expo-app/src/playground/Playground.tsx): Updated to passroute.optionstoStack.Screenand filter hidden routes from the list.UI changes
Simulator.Screen.Recording.-.iPhone.17.Pro.-.2026-06-12.at.14.30.33.mov
Testing
How has it been tested?
Testing instructions
yarn nx run expo-app:starttestexpo:///DebugModalNavigationnavigation.goBack()Change management
type=routine
risk=low
impact=sev5
automerge=false
Made with Cursor