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
  statusBarHeight="env(safe-area-inset-top)"
  statusBarColor="#000"
  systemNavigationBarHeight="env(safe-area-inset-bottom)"
  systemNavigationBarColor="#000"
>

</Screen>

Pass hideStatusBar or hideSystemNavigationBar to collapse the 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