Screen
The unit of routing, and the place where mobile-app primitives live
<Screen> is what each route renders. It's a fixed-position container with slots for app bars,
navigation bars, and safe-area aware status bars, the same vocabulary you'd use building a
native app.
Anatomy
Status Bar
App Bar
Navigation Bar
System Navigation Bar
- Status Bar
Top safe area. Reserves space for the notch and dynamic island.
statusBarHeightstatusBarColorhideStatusBar- App Bar
Top bar. Set per-screen, or as a shared bar that stays mounted across transitions.
appBarsharedAppBar- Children
The screen body. Scrolls by default. Disable it only when you bring your own scroll container.
contentScrollable- Navigation Bar
Bottom bar. Same per-screen and shared options as App Bar.
navigationBarsharedNavigationBar- System Navigation Bar
Bottom safe area. Reserves space for Android's system navigation bar.
systemNavigationBarHeightsystemNavigationBarColorhideSystemNavigationBar
Per-screen vs shared
App bar and navigation bar can be set in two ways. They mount at different times and behave differently across transitions.
appBar/navigationBar: the bar belongs to that one screen. It mounts and unmounts with the screen. Use this for headers and actions that change page-by-page.sharedAppBar/sharedNavigationBar: the bar persists across screens. It stays put during push and pop transitions, so it never re-animates. Use this for global UI like a bottom tab bar or a fixed header. Pass the same node from each screen and flemo bridges it through the transition.
Minimum
<Screen>
<h1>Hello</h1>
</Screen>The content area scrolls by default. Background is white unless you change it.
App bar and navigation bar
Two slots, two flavors each: per-screen (appBar, navigationBar) and shared
(sharedAppBar, sharedNavigationBar).
The shared variants stay mounted across screen transitions, so the bar doesn't re-animate every push. Use them for global UI like a bottom tab bar.
<Screen
appBar={<TopBar title="Inbox" />}
navigationBar={<BottomActions />}
sharedNavigationBar={<TabBar />}
>
<MailList />
</Screen>Safe areas
<Screen> reserves the top and bottom safe areas itself (the notch / dynamic island up top,
Android's gesture or navigation bar at the bottom) through statusBarHeight and
systemNavigationBarHeight (with matching *Color and hide* props).
<Screen
statusBarHeight="env(safe-area-inset-top)"
statusBarColor="#000"
systemNavigationBarHeight="env(safe-area-inset-bottom)"
systemNavigationBarColor="#000"
>
…
</Screen>This pays off most when flemo runs inside a native / hybrid app (a WebView). The recommended
setup is to let the web own the safe areas end-to-end: turn the native side's top and bottom
safe-area handling off, and reserve them on <Screen> instead.
- Native shell: disable the top and bottom safe areas.
<Screen>: setstatusBarHeight/systemNavigationBarHeight(and the*Colorprops) to draw them.
That keeps the inset heights and colors under your control in one place, on the web side. They
animate and recolor with the rest of the screen during transitions, instead of being painted by
the native shell where your CSS can't reach. In a plain browser you can still pass
env(safe-area-inset-*) so the values track the device, but the native-app case is where
controlling them from the web really matters.
Pass hideStatusBar or hideSystemNavigationBar to collapse an area when you don't want it
reserved (e.g., a full-bleed media screen).
Background
<Screen backgroundColor="#0b0b0c">…</Screen>Defaults to "white". Any CSS color value works.
Disabling content scroll
If you're rendering your own scroll container, opt out of the built-in one:
<Screen contentScrollable={false}>
<CustomScrollArea />
</Screen>All Screen props
| Prop | Type | Default | Notes |
|---|---|---|---|
appBar | ReactNode | — | Per-screen top bar |
navigationBar | ReactNode | — | Per-screen bottom bar |
sharedAppBar | ReactNode | — | Top bar that survives transitions |
sharedNavigationBar | ReactNode | — | Bottom bar that survives transitions |
backgroundColor | string | "white" | CSS color |
statusBarHeight | string | — | CSS length, usually env(safe-area-inset-top) |
statusBarColor | string | — | CSS color |
hideStatusBar | boolean | false | Don't reserve the top safe area |
systemNavigationBarHeight | string | — | CSS length, usually env(safe-area-inset-bottom) |
systemNavigationBarColor | string | — | CSS color |
hideSystemNavigationBar | boolean | false | Don't reserve the bottom safe area |
contentScrollable | boolean | true | Whether the children area scrolls |
Shared-element morphs
When a thumbnail in a list should visually unfold into the hero image on the next screen,
reach for <LayoutScreen>, a <Screen> replacement from @flemo/react-layout that pairs elements
across the navigation via motion's layout engine. See the dedicated
LayoutScreen page for the full walkthrough.