fix(components): match full-screen picker bar icons to the runtime theme

A Compose Dialog owns its own Window whose status/navigation-bar icon
appearance is seeded from the XML theme, not from the host activity's
runtime edge-to-edge state. With decorFitsSystemWindows = false the
FullScreenPicker draws under the bars, exposing icons that don't match
the active theme — dark icons on a dark picker (near-invisible), and the
mirror-image nav-bar bug in light theme.

Expose the resolved light/dark decision from FloretExpressiveTheme as
LocalFloretDarkTheme and drive the dialog window's
isAppearanceLight{Status,Navigation}Bars from it, so the appearance
tracks the in-app light/dark choice even when it diverges from the
system night resource qualifier.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-24 17:11:16 +02:00
parent 75b90d1b3b
commit 9bbef911c0
3 changed files with 40 additions and 9 deletions

View File

@@ -13,6 +13,8 @@ import androidx.compose.ui.platform.LocalView
import androidx.compose.ui.window.Dialog
import androidx.compose.ui.window.DialogProperties
import androidx.compose.ui.window.DialogWindowProvider
import androidx.core.view.WindowCompat
import de.jeanlucmakiola.floret.identity.LocalFloretDarkTheme
/**
* Full-screen scaffold for selection pickers: a full-bleed [Dialog] that reuses
@@ -41,14 +43,28 @@ fun FullScreenPicker(
decorFitsSystemWindows = false,
),
) {
// The dialog window pans by default when the keyboard opens, which —
// A Compose Dialog owns a separate android.view.Window whose bar-icon
// appearance is seeded from the XML theme, not from the activity window's
// runtime edge-to-edge state — so with decorFitsSystemWindows = false it
// draws edge-to-edge under bars whose icons don't match the active theme
// (dark icons on a dark picker). Drive the appearance from the runtime
// [LocalFloretDarkTheme] so it tracks the in-app light/dark choice even
// when that diverges from the system night qualifier.
//
// Same window also pans by default when the keyboard opens, which —
// combined with the content's own imePadding — leaves a fixed black gap
// above the keyboard. Switch it to ADJUST_NOTHING so the window stays
// full-screen and imePadding alone lifts the focused field.
val view = LocalView.current
val darkTheme = LocalFloretDarkTheme.current
SideEffect {
(view.parent as? DialogWindowProvider)?.window
?.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING)
(view.parent as? DialogWindowProvider)?.window?.let { window ->
window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING)
WindowCompat.getInsetsController(window, view).apply {
isAppearanceLightStatusBars = !darkTheme
isAppearanceLightNavigationBars = !darkTheme
}
}
}
CollapsingScaffold(
title = title,