Skip to content

Offline mode banner overlaps the navigation title and hides toolbar actions (missing on visionOS) #415

Open

Description

@jlipworth

Problem

Seen in TestFlight 1.8.0 (1541) on iPhone. When Labstream cold-launches into the restricted Offline surface (#259), the "Offline mode" banner is pinned to the top of the screen and covers the navigation bar:

  • The large Offline title is clipped to its bottom half on the first frame.
  • The navigation bar's Sign In and Settings toolbar buttons are hidden behind the banner on iPhone and iPad, so the only ways to sign in again or open Settings are not visible.
  • The secondary line ("Your server could not be reached. Completed downloads remain available.") wraps onto 2–3 lines on iPhone. At accessibility text sizes the banner fills about 40% of the screen and "Reconnect" hyphenates to "Recon-/nect".

Root cause

Labstream/Shared/UI/OfflineLaunchView.swift mounts offlineStatusBanner with .safeAreaInset(edge: .top) outside the NavigationStack. On iOS/iPadOS the inset is added above the stack's content, but the navigation bar still lays out at the top of the window, so the banner (.regularMaterial) sits on top of the bar's inline row and the top of the large title. The banner is also a separate, one-off status pattern: OfflineLibraryView already shows inline notice rows (startup-recovery "Retry Recovery", upgrade notice "Dismiss") in a different layout.

Per-platform findings

Reproduced headlessly with a local DEBUG-only --ui-testing --ui-testing-fixture offline launch, which mounts OfflineLaunchView directly with no server. Screenshots are kept locally (gitignored artifacts/agent-sim-runs/offline-banner/) and are not uploaded.

Platform Banner visible? Result
iPhone (iOS 27 sim) Yes Large title clipped; Sign In/Settings hidden; copy wraps to 3 lines; at AX sizes the banner takes ~40% of the screen and the title is gone. Matches the TestFlight report.
iPad (iPadOS 27 sim) Yes Large title not clipped (the bar is taller), but Sign In/Settings are still hidden under the banner. Single-line copy.
visionOS (27 sim) No Title and Sign In/Settings ornaments render, but the banner is not visible at all. The user gets no offline explanation and no Reconnect control.
macOS Not verified The host session's screen was locked, so no window could be captured. From the code, the same safeAreaInset sits below the unified titlebar/toolbar, so overlap is less likely, but the copy and pattern are the same. Needs a run on an unlocked host.
tvOS N/A Streaming-only: ContentView compiles the Offline surface out and routes .offline to LoginView. No banner exists.

Proposed direction

Replace the free-floating top inset with a platform-native status treatment that never overlaps navigation chrome:

  1. Keep the offline state inside the navigation hierarchy, either as a navigation subtitle plus a toolbar Reconnect action, or as the first row of the Offline list using the same notice-row pattern as the existing recovery/upgrade notices. Do not inset it outside the NavigationStack.
  2. Shorten the copy to a context line that never wraps (for example "Server unreachable"). The longer explanation can go in the accessibility label or a details affordance.
  3. Make it visible on visionOS (it is currently missing) and confirm macOS.
  4. Have one notice-row pattern shared by offline / startup-recovery / upgrade-notice states, so color and button style carry one meaning each.

HTML mockups of 2–3 options are being reviewed before implementation.

Acceptance

  • iPhone (default and AX text sizes): no overlap with title or toolbar; Sign In and Settings reachable.
  • iPad: same.
  • visionOS: offline state and Reconnect visible.
  • macOS: verified on an unlocked host via scripts/deploy-macos-to-host.sh.
  • tvOS unaffected (no Offline surface).
  • A DEBUG offline UI fixture is kept so this surface can be screenshot-tested headlessly.

Activity

  1. jlipworth commented on Oct 18, 2026

    @jlipworth
    OwnerAuthor

    Implemented option A in 4dc82ed (merged into downloads/overhaul, not main):

    • iPhone/iPad/macOS: Server unreachable is a navigation subtitle under the Offline title. Reconnect is a prominent toolbar button next to Sign In and Settings, and its accessibility hint has the full explanation.
    • visionOS has no navigation subtitle, so the status is a toolbar label next to Reconnect. Both are now visible; before, nothing showed.
    • The top safeAreaInset banner is gone.
    • --ui-testing-fixture offline (DEBUG, not tvOS) mounts the surface without a server. The new mobile UI test testOfflineLaunchKeepsToolbarActionsReachable asserts Reconnect, Sign In and Settings stay hittable.

    Verified headlessly:

    • iPhone and iPad: UI test passes. Screenshots at default and AX text sizes show no overlap (screenshots kept local).
    • visionOS: the status and Reconnect render in the toolbar ornament.
    • macOS: builds and runs with no crash. Not visually checked because the host screen was locked.
    • tvOS: builds; there is no Offline surface.
    • PMSKit tests and ci-hygiene pass.

    Left open until physical acceptance on the next internal TestFlight build, plus a macOS visual check.

  2. added a commit that references this issue on Oct 18, 2026
    4dc82ed
  3. jlipworth commented on Nov 5, 2026

    @jlipworth
    OwnerAuthor

    Landed on main in #425 (0b7f3fcb, tag v1.8.0). Any device or live acceptance gate already noted here still applies; the issue stays open until it's checked.

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

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions