flemo

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

Childrenscrollable

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>: set statusBarHeight / systemNavigationBarHeight (and the *Color props) 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

PropTypeDefaultNotes
appBarReactNodePer-screen top bar
navigationBarReactNodePer-screen bottom bar
sharedAppBarReactNodeTop bar that survives transitions
sharedNavigationBarReactNodeBottom bar that survives transitions
backgroundColorstring"white"CSS color
statusBarHeightstringCSS length, usually env(safe-area-inset-top)
statusBarColorstringCSS color
hideStatusBarbooleanfalseDon't reserve the top safe area
systemNavigationBarHeightstringCSS length, usually env(safe-area-inset-bottom)
systemNavigationBarColorstringCSS color
hideSystemNavigationBarbooleanfalseDon't reserve the bottom safe area
contentScrollablebooleantrueWhether 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.

On this page