fix(mobile): keep Android content clear of the navigation bar
Android 15+ enforces edge-to-edge, and Capacitor stops padding the WebView once it can hand the insets to the page instead — so the app draws under the gesture/navigation bar. Only the top inset was ever consumed: full cover surfaces ignored the bottom one entirely, which is why a settings list ran under the bar, and the chat shell reserved half of it, which is enough for a home indicator but not for a bar that swallows taps. Reserve the full inset in the shell on Android and give the surfaces that own the bottom edge — fullscreen surfaces, the workspace drawer, bottom sheets — an opt-in class that pads them. The sessions drawer already did this through its footer, so it stays as it is. Capacitor reports a zero bottom inset while the keyboard is up, so none of this stacks with the keyboard inset. iOS deliberately keeps its softer visual inset. Testing: package type-check and lint; drove the mobile surface in a browser with the Android platform class and a simulated 48px inset (shell and surfaces reserve exactly that, drawer footer unchanged, and removing the class returns every surface to zero).
This commit is contained in:
@@ -175,7 +175,7 @@ export const MobileFullscreenSurface: React.FC<MobileFullscreenSurfaceProps> = (
|
||||
'flex flex-col bg-background text-foreground',
|
||||
isDialog
|
||||
? 'h-[min(88dvh,860px)] w-full max-w-[720px] overflow-hidden rounded-2xl border border-border/70 shadow-[0_24px_64px_rgb(0_0_0_/_0.32)]'
|
||||
: 'oc-keyboard-inset-surface fixed inset-0 z-50',
|
||||
: 'oc-keyboard-inset-surface oc-bottom-safe-surface fixed inset-0 z-50',
|
||||
)}
|
||||
style={isDialog ? {
|
||||
// Scale/fade instead of the push slide: the card is not a navigation
|
||||
@@ -249,7 +249,7 @@ export const MobileFullscreenSurface: React.FC<MobileFullscreenSurfaceProps> = (
|
||||
|
||||
return createPortal(
|
||||
<div
|
||||
className="oc-keyboard-inset-surface fixed inset-0 z-50 flex items-center justify-center p-4 transition-opacity duration-200 ease-out"
|
||||
className="oc-keyboard-inset-surface oc-bottom-safe-surface fixed inset-0 z-50 flex items-center justify-center p-4 transition-opacity duration-200 ease-out"
|
||||
style={{
|
||||
background: 'rgb(0 0 0 / 0.45)',
|
||||
opacity: entered ? 1 : 0,
|
||||
|
||||
@@ -295,7 +295,7 @@ export const MobileWorkspaceDrawer: React.FC<{
|
||||
aria-modal="true"
|
||||
aria-label={t('mobile.header.openWorkspaceAria')}
|
||||
aria-hidden={!open}
|
||||
className="oc-keyboard-inset-surface fixed inset-0 z-50 flex flex-col bg-background text-foreground"
|
||||
className="oc-keyboard-inset-surface oc-bottom-safe-surface fixed inset-0 z-50 flex flex-col bg-background text-foreground"
|
||||
style={{
|
||||
paddingTop: 'var(--oc-safe-area-top, 0px)',
|
||||
// Settled state drops the transform entirely so the drawer isn't kept
|
||||
|
||||
Reference in New Issue
Block a user