Skip to content

Theme the system navigation bar for edge-to-edge #110

Open

Description

@danielchalmers

Goal

On Android 15+ (we target SDK 36) the system status and navigation bars are transparent overlays. We want them to blend with the app's Material You theme in light and dark, including 3-button navigation mode where the navigation bar region is clearly visible.

Why this is blocked

Attempted in #107 (closed). The supported, no-custom-code approach does not fully work yet, and the gap is upstream in MAUI.

  • Direct bar coloring is gone on API 35+. Window.setStatusBarColor and setNavigationBarColor are deprecated no-ops. The only supported model is to render edge-to-edge (content under the bars) and let the page background show through the transparent bars.
  • Letterboxing leaves the nav bar black. With the supported SafeAreaEdges="All", MAUI pads around the BlazorWebView, so the page sits inset inside the bars. The transparent navigation bar then reveals the uncolored window background, which renders black. Setting the MAUI page BackgroundColor does not fill the region behind the system bars. This is the "nav bar is still black" symptom, most obvious with 3-button navigation.
  • True edge-to-edge in a Blazor Hybrid app is upstream-broken. Pushing the WebView content under the bars requires the DOM to pad itself with env(safe-area-inset-*), which is unreliable in Android WebView below Chromium 140, and MAUI's own Blazor Hybrid safe-area handling is broken: dotnet/maui#34462 (open, milestone .NET 10 SR9).
  • We prototyped a custom WindowInsets to CSS-variable bridge that did achieve true edge-to-edge, but chose not to maintain hand-rolled platform plumbing for something the framework is expected to handle.

What unblocks this

Revisit after upgrading to the .NET 10 SR9 servicing release (we are on 10.0.80 today), by which point Chromium 140+ WebViews are widespread. At that point true edge-to-edge should be reachable by flipping SafeAreaEdges to None and letting the env(safe-area-inset-*) variables already present in app.css pad the UI, with no custom platform code.

MAUI issues to subscribe to

  • dotnet/maui#34462 — Safe area handling broken on Android in Blazor Hybrid templates (open, .NET 10 SR9) — primary blocker
  • dotnet/maui#35568 — Edge-to-edge: Shell/NavigationPage bar colour not used for status bar (closed, SR9)
  • dotnet/maui#33344 — Bar background does not extend into the system navigation bar area in edge-to-edge (closed, SR6)
  • dotnet/maui#24742 — Android 15 / API 35 apps default to edge-to-edge (closed, SR1)

Notes for whoever picks this up

  • Reference implementation lives on the claude/edge-to-edge branch (PR Blend the system bars into the theme with native safe areas #107): both the custom insets bridge and the native letterbox with themed page approach.
  • Bar icon contrast (light/dark icons via WindowInsetsControllerCompat.AppearanceLight*Bars) works today and is independent of the background problem, so it can ship on its own.
  • Caveats observed in 10.0.80: SafeAreaEdges="SoftInput" incorrectly pads the status bar rather than only the keyboard, and SafeAreaEdges="None" disables MAUI's IME inset handling so the keyboard stops resizing the view.

Activity

  1. danielchalmers commented on Jul 17, 2026

    @danielchalmers
    OwnerAuthor

    Noted while testing the v12 polish pass on an API 35 emulator: when the system theme changes while the app is running, the navigation bar keeps the previous theme's tone (e.g. stays light after switching to dark) until the app is restarted. Fresh launches pick up the correct color, and the status bar follows the theme correctly at runtime, so it's just the nav bar with no supported recolor path on API 35+ (setNavigationBarColor is a deprecated no-op there). Folding this into the edge-to-edge work here rather than fighting it separately.

  2. changed the title [-]Theme the system navigation bar for edge-to-edge (blocked on MAUI Blazor safe-area support)[/-] [+]Theme the system navigation bar for edge-to-edge[/+] on Jul 17, 2026
  3. danielchalmers commented on Sep 17, 2026

    @danielchalmers
    OwnerAuthor

    Update after #116: edge-to-edge itself works now. The unblock was never the MAUI CSS fix, it was Android WebView 144+ forwarding the system bar insets to env(safe-area-inset-*) on its own. With SafeAreaEdges="None" on the page and the env() padding already in app.css, the page draws under both bars on Android 15 with no custom insets plumbing, and the keyboard dodge from #114 keeps working.

    What is still missing is a supported way to control the bars themselves. MAUI 10 has no public API for status or navigation bar icon appearance, and its own guess (ConfigureTranslucentSystemBars, internal) reads the theme's colorPrimary luminance once per activity and lands on light icons in both modes for us. Below Android 15 there is also no framework path to tint the opaque bars to the surface color. Making #116 work on 10.0.101 meant writing to WindowInsetsController on every resume, disabling the 3-button scrim by hand, and relying on a CommunityToolkit side effect to letterbox older web views. It works, but it is the kind of platform code we decided not to carry in #107.

    .NET 11 covers this properly: Window.StatusBarTheme (dotnet/maui#34902, merged in dotnet/maui#34903) gives the app the icon appearance knob, and dotnet/maui#36226 moves MAUI onto WindowCompat.EnableEdgeToEdge, makes the bars transparent below API 35 too, drops the 3-button scrim and re-applies the icon appearance on configuration changes. That removes nearly all of the code in #116 except the SafeAreaEdges="None" flip and the CSS.

    So this waits on .NET 11. Plan when it ships: bump MAUI, set SafeAreaEdges="None", keep the CSS from #116, set Window.StatusBarTheme from the in-app theme, and keep the WebView version guard that letterboxes anything below 144. The tested branch is claude/edge-to-edge-maui-5bb030 if anything from it is worth lifting.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions