diff --git a/src/apps/mobile/android/app/src/main/kotlin/com/openbitfun/mobile/app/ui/shell/OpenBitFunCompactDrawer.kt b/src/apps/mobile/android/app/src/main/kotlin/com/openbitfun/mobile/app/ui/shell/OpenBitFunCompactDrawer.kt index c5a5f04ed4..2a7a8589e0 100644 --- a/src/apps/mobile/android/app/src/main/kotlin/com/openbitfun/mobile/app/ui/shell/OpenBitFunCompactDrawer.kt +++ b/src/apps/mobile/android/app/src/main/kotlin/com/openbitfun/mobile/app/ui/shell/OpenBitFunCompactDrawer.kt @@ -35,6 +35,7 @@ import com.openbitfun.mobile.app.ui.theme.MotionDrawerHideMillis import com.openbitfun.mobile.app.ui.theme.MotionDrawerOpenMillis import com.openbitfun.mobile.app.ui.theme.MotionDrawerRevealMillis import com.openbitfun.mobile.app.ui.theme.MotionDrawerScrimMillis +import com.openbitfun.mobile.app.ui.theme.openBitFunColors import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.flow.first import kotlinx.coroutines.launch @@ -218,7 +219,21 @@ internal fun OpenBitFunCompactDrawer( } Box(Modifier.fillMaxSize()) { + // The open drawer's fill is a floor under the whole shell, not a panel + // the width of the sidebar. The content card's rounded corners have to + // curve onto something: a fill that stopped at the card's left edge + // left them curving onto the page white, so a square-cornered grey + // block sat against a rounded card with a white wedge between them. + // Driven by contentProgress rather than drawerProgress so the floor is + // never thinner than the card has already moved, in either direction. if (compact && drawerComposed) { + Box( + Modifier + .fillMaxSize() + .background(openBitFunColors.sidebar.background) + .graphicsLayer { alpha = contentProgress.value }, + ) + Box( modifier = Modifier .width(drawerWidth) diff --git a/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/AppShell.ets b/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/AppShell.ets index ef319b5dfd..3a22388991 100644 --- a/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/AppShell.ets +++ b/src/apps/mobile/harmonyos/entry/src/main/ets/pages/components/AppShell.ets @@ -12,6 +12,7 @@ import { PAGE_BG, SCRIM, SHELL_SCRIM, + SIDEBAR_BG, TRANSPARENT, } from './Theme'; @@ -48,6 +49,26 @@ export struct AppShell { } }) + // The open drawer's fill is a floor under the whole shell, not a panel + // the width of the sidebar. The content card's rounded corners have to + // curve onto something: when the fill stopped at the card's left edge + // they curved onto the page white instead, so a square-cornered grey + // block sat against a rounded card with a white wedge between them. + Column() + .width('100%') + .height('100%') + .backgroundColor(SIDEBAR_BG) + .expandSafeArea([SafeAreaType.SYSTEM], [SafeAreaEdge.TOP, SafeAreaEdge.BOTTOM]) + .hitTestBehavior(HitTestMode.None) + .opacity((this.allowSidebar && this.shellState.showSidebar) ? 1 : 0) + // Matched to the content card rather than to the sidebar panel: the + // card must never finish moving before the floor it curves onto has + // finished fading, in either direction. + .animation({ + duration: (this.allowSidebar && this.shellState.showSidebar) ? 320 : 250, + curve: Curve.EaseOut + }) + Column() { // The drawer is a compact affordance. Wide layouts put the same session // list in the master pane instead, and this copy stayed mounted behind diff --git a/src/apps/mobile/ios/OpenBitFun/Features/Shell/MobileShellView.swift b/src/apps/mobile/ios/OpenBitFun/Features/Shell/MobileShellView.swift index 4bf74f7aea..00091ffaac 100644 --- a/src/apps/mobile/ios/OpenBitFun/Features/Shell/MobileShellView.swift +++ b/src/apps/mobile/ios/OpenBitFun/Features/Shell/MobileShellView.swift @@ -176,7 +176,25 @@ struct MobileShellView: View { let compactSidebarWidth = min(280, max(220, viewportWidth * 0.68)) ZStack(alignment: .leading) { + // The open drawer's fill is a floor under the whole shell, not a + // panel the width of the sidebar. The content card's rounded + // corners have to curve onto something: a fill that stopped at the + // card's left edge left them curving onto the page white, so a + // square-cornered grey block sat against a rounded card with a + // white wedge between them. if !sidebarVisible { + OpenBitFunTheme.sidebarBg + .ignoresSafeArea() + .opacity(model.drawerOpen ? 1 : 0) + .allowsHitTesting(false) + // Matched to the content card rather than to the sidebar + // panel: the card must never finish moving before the floor + // it curves onto has finished fading, in either direction. + .animation( + .easeOut(duration: model.drawerOpen ? 0.32 : 0.25), + value: model.drawerOpen + ) + SidebarView(model: model) .frame(width: compactSidebarWidth) .opacity(model.drawerOpen ? 1 : 0)