Navigation should preserve the platform's spatial model. Use a push for a new place in the hierarchy, a sheet for a bounded task over the current context, and native tab or toolbar primitives for persistent destinations and actions. The presentation is part of the information architecture, not a decorative transition chosen at the end.
Match Presentation to Context
| Presentation | Use when | Avoid when |
|---|---|---|
| Stack push | Opening another object or moving deeper in a hierarchy | The task is temporary and belongs to the current screen |
| Modal | The user must complete or dismiss a focused mode | The parent context should remain visually useful |
| Form sheet | A bounded form or subtask benefits from visible parent context | The task needs the full viewport |
| Native tab | Switching among stable top-level destinations | Representing a transient action or deep hierarchy |
| Bottom toolbar | Actions apply to the current screen or selection | The control represents a persistent destination |
Choose the lightest presentation that communicates the state change correctly. A full-screen push for every subtask forces the user to reconstruct context on return.
Prefer Native Navigation Surfaces
Native tabs and toolbars inherit system placement, safe-area behavior, accessibility, transitions, and new platform treatments. A hand-built imitation must continually chase those behaviors.
Use native primitives when the control is part of navigation chrome. Keep custom React Native surfaces for branded content where exact visual authorship matters.
Version-sensitive APIs such as Expo Router native tabs may remain under an unstable import path. Isolate their configuration in layout modules, check the installed Expo Router documentation during upgrades, and do not spread experimental types through feature code.
Give Tabs Stable Destinations
Every tab represents a place the user can return to, not a button that performs a one-off command.
- Use short labels alongside recognizable icons.
- Preserve each tab's navigation state when switching.
- Reserve platform roles such as search for destinations that actually behave like that role.
- Let the platform adapt tab placement for tablets and other device classes.
- Do not hide essential destinations behind a custom overflow interaction without a clear reason.
If a tab launches a camera, composer, or creation flow instead of selecting a destination, verify that the platform role and behavior make that distinction clear.
Put Screen Actions in the Toolbar
Toolbar actions belong to the visible screen. Their availability should reflect the current selection or mode.
- Place primary screen actions where the platform expects them.
- Use a bottom toolbar for image, media, or selection actions that need thumb reach.
- Hide unavailable actions without causing unrelated content to jump.
- Give icon-only actions accessible labels and keep destructive actions visually and spatially distinct.
- Use menus when several secondary actions share one scope; do not crowd the bar with equal-weight icons.
A tab answers “where am I going?” A toolbar button answers “what can I do here?” Do not swap those roles.
Use Sheets to Preserve Context
Form sheets are useful for sign-in, filtering, short editors, and other bounded tasks. Choose detents from the content's useful resting sizes rather than arbitrary percentages.
- The initial detent should reveal the task's primary content and action.
- Allow expansion when the content genuinely benefits from it.
- Keep persistent actions in the sheet footer so scrolling does not hide completion.
- Account for the keyboard and safe areas at every detent.
- Avoid placing long, branching workflows in a sheet simply to keep the parent visible.
On larger devices, a platform may present the same route differently. Test semantic behavior instead of assuming a phone-sized bottom sheet everywhere.
Use Shared-Element Motion for Real Continuity
A zoom transition works when the destination is the same object shown with more detail: a photo thumbnail opening into a viewer, a card opening into its detail view, or an item expanding into an editor.
Do not use it between unrelated screens. The motion promises object continuity; breaking that promise makes the transition feel ornamental and disorienting.
The source and target should:
- identify the same stable object
- use compatible aspect ratios or intentional crop behavior
- remain available for interactive dismissal
- fall back to a normal navigation transition on unsupported platforms
- respect reduced-motion preferences
Make Deep Links Enter the Same State Model
A deep link is another entrance into navigation, not a separate routing system. Parse external input into the same typed route parameters used by in-app links.
- Validate every route parameter before fetching or rendering.
- Resolve authentication before showing protected content.
- Preserve a meaningful back destination when the app opens directly into a deep route.
- Handle missing, deleted, or unauthorized objects with a useful recovery action.
- Test custom schemes, universal links, cold starts, and already-running app states.
Do not pass large objects through route parameters. Pass stable identifiers and load current data at the destination.
Gate Routes Around Session Resolution
Keep public and protected routes in separate Expo Router route groups, with a layout that owns the session boundary. While stored credentials are being restored, render an intentional launch state rather than briefly exposing the wrong route tree.
- Redirect signed-out users to the sign-in group and preserve a validated return destination.
- Redirect signed-in users away from authentication screens when appropriate.
- Let the server enforce authorization; a client-side route guard is only presentation and navigation control.
- Clear sensitive cached state when the active account changes or signs out.
Keep authentication provider details behind a session adapter. Route layouts should consume status, user, signIn, and signOut, not know how tokens are refreshed.
Model Roles as Capabilities
Role-based navigation can hide destinations a user cannot use, but it must not be the security boundary. Convert backend claims into explicit capabilities such as canManageTeam or canViewBilling; use the same capability vocabulary for tabs, actions, and route guards.
Handle stale or downgraded access at the destination. A deep link or restored navigation state may point to a route the current session can no longer open, so show a stable fallback rather than looping redirects.
Add Haptics for Meaning, Not Decoration
Haptics can reinforce a successful selection, boundary, or mode change. They should not fire simply because every tap can make a vibration.
For native tabs, prefer the current router event API when it exposes a tab-press listener. Avoid patching dependencies when an upstream event exists. Test haptics on a physical device and keep frequent navigation feedback subtle.
Checklist
- Push, modal, and sheet presentations match the task's context
- Stable destinations use tabs; current-screen actions use toolbars
- Native chrome is preferred over visual imitations
- Experimental router APIs are isolated behind layout modules
- Sheets use content-driven detents and keyboard-safe actions
- Shared-element motion connects the same object across screens
- Every motion path has reduced-motion and platform fallbacks
- Deep links validate input and enter the normal navigation state model
- Session restoration completes before protected routing decisions
- Client route visibility and server authorization use the same capability model
- Direct entry provides a useful back or recovery destination
- Haptics reinforce meaningful events and are tested on hardware
Sources
Check version-sensitive behavior against the current Expo Router documentation for file-based routing, protected routes, native tabs, and linking.