Skip to content

Fix iOS PWA safe area handling for dynamic island and bottom home indicator #244

@shuv1337

Description

@shuv1337

Problem/Context

The PWA on iOS has two critical layout issues:

  1. Top: Content hidden under Dynamic Island - The app menu bar and content at the top of the screen are positioned behind the Dynamic Island safe area, making them inaccessible or partially obscured
  2. Bottom: Wasted space gap - There's a significant gap of wasted space at the bottom of the app where the status bar used to be. The chat box and submit button should be positioned just above the rounded bottom edge of the screen, but instead there's unnecessary padding

Current State

The app has partial safe area support implemented in packages/app/src/index.css:

  • CSS variables are defined: --safe-area-inset-top, --safe-area-inset-bottom, etc.
  • PWA-specific offsets exist: --pwa-top-offset, --pwa-bottom-offset
  • viewport-fit=cover is correctly set in index.html
  • apple-mobile-web-app-status-bar-style is set to black-translucent

However, these CSS variables are not being applied to the main layout containers - they're only used in a few isolated components like dialogs and pull-to-refresh.


Acceptance Criteria

  • App menu bar (header) is fully visible below the Dynamic Island on all iPhone models
  • Chat input box and submit button sit just above the home indicator rounded edge
  • No wasted vertical space at top or bottom in PWA standalone mode
  • Layout works correctly in both portrait and landscape orientations
  • No regression on desktop or non-PWA mobile browsers
  • Works on iPhone X through iPhone 15 Pro Max (all notch/Dynamic Island variants)

Implementation Details

Technical Approach

The fix requires applying safe area insets to the root layout containers in PWA mode:

1. Update Root Layout (packages/app/src/pages/layout.tsx)

The main layout wrapper at line ~1071 needs safe area padding:

// Current (line 1071):
<div class="relative flex-1 min-h-0 flex flex-col select-none ...">

// Should apply padding-top for Dynamic Island in PWA mode

2. Update Header Component (packages/app/src/components/header.tsx)

The header at line 34 needs top margin/padding in PWA mode:

// Current (line 34):
<header class="h-12 shrink-0 bg-background-base border-b border-border-weak-base flex" ...>

// Should include: style={{ "padding-top": "var(--pwa-top-offset, 0px)" }}
// Or use a CSS class that applies in PWA mode

3. Update Session Page Input Area (packages/app/src/pages/session.tsx)

The chat input at the bottom needs bottom padding in PWA mode to sit above the home indicator.

4. CSS Approach (Recommended)

Add to packages/app/src/index.css:

/* PWA standalone mode - root layout safe area handling */
@media (display-mode: standalone) {
  /* Header should clear the Dynamic Island */
  header[data-tauri-drag-region] {
    padding-top: var(--safe-area-inset-top);
    /* Optionally increase height to accommodate */
    height: calc(3rem + var(--safe-area-inset-top));
  }
  
  /* Main content area should account for top offset */
  main {
    /* Content starts after header with safe area */
  }
  
  /* Bottom input area should clear home indicator */
  [data-component="prompt-input-container"],
  .prompt-input-wrapper {
    padding-bottom: var(--safe-area-inset-bottom);
  }
}

Files to Modify

File Line(s) Change
packages/app/src/index.css 90-104 Add header and input safe area styles for PWA mode
packages/app/src/components/header.tsx 34 Add data-pwa-header attribute or inline style
packages/app/src/pages/layout.tsx 1071-1077 Ensure main layout respects safe areas
packages/app/src/pages/session.tsx ~1200+ Bottom input area needs safe area padding

Reference Implementations

From industry best practices:

Discord's approach (discord-api-docs):

:root {
  --sait: var(--discord-safe-area-inset-top, env(safe-area-inset-top));
  --saib: var(--discord-safe-area-inset-bottom, env(safe-area-inset-bottom));
}

Apple's recommended pattern:

header {
  padding-top: constant(safe-area-inset-top); /* iOS 11.0 */
  padding-top: env(safe-area-inset-top); /* iOS 11.2+ */
}

footer {
  padding-bottom: constant(safe-area-inset-bottom);
  padding-bottom: env(safe-area-inset-bottom);
}

Using max() for minimum padding:

@supports(padding: max(0px)) {
  .input-area {
    padding-bottom: max(16px, env(safe-area-inset-bottom));
  }
}

Tasks

  • Add PWA-specific header height adjustment in CSS
  • Apply padding-top: var(--safe-area-inset-top) to header in standalone mode
  • Apply padding-bottom: var(--safe-area-inset-bottom) to prompt input container
  • Test on iOS Simulator with various iPhone models (X, 11, 12, 13, 14, 15 series)
  • Test in both portrait and landscape orientations
  • Verify no regression in desktop browser or Android PWA
  • Verify dialogs/modals still work correctly with safe areas

Related Code

  • packages/app/src/index.css:7-15 - Safe area CSS variable definitions
  • packages/app/src/index.css:90-104 - PWA standalone mode styles
  • packages/app/index.html:7 - viewport-fit=cover meta tag
  • packages/app/index.html:21-22 - iOS PWA meta tags
  • packages/app/src/components/pull-to-refresh.tsx:99 - Example of safe area usage
  • packages/app/src/components/askquestion-wizard.tsx:336 - Example of bottom safe area usage

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingenhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions