Skip to content

ChatChannelView floating composer leaves extra bottom gap in iOS 26 tabViewBottomAccessory hosts #1381

@kdbrooks

Description

@kdbrooks

Updated findings

  • This does not reproduce in the stock Stream demo app.
  • The issue appears when stock ChatChannelView is embedded under a root TabView that uses iOS 26 tabViewBottomAccessory.
  • The same class of regression can also be triggered by applying .toolbar(.hidden, for: .tabBar) on the pushed channel screen.
  • If chat bypasses the accessory shell and we do not hide the tab bar from the channel screen, the layout looks correct.
  • So this now looks less like a generic “floating composer always reserves space” bug and more like a compatibility issue between ChatChannelView's floating composer layout and Apple’s new tab accessory / tab-bar visibility environment.

What did you do?

  • Presented stock ChatChannelView full-screen in SwiftUI.
  • Used composerPlacement = .floating.
  • Tested on the current Stream v5 beta line (develop branch revisions listed below).
  • Reproduced inside a host app whose root TabView uses iOS 26 tabViewBottomAccessory.
  • Also tested the same host flow with .toolbar(.hidden, for: .tabBar) on the pushed channel screen.
  • Compared against the stock Stream demo app and against a host configuration where chat bypasses the accessory shell.

What did you expect to happen?

  • With composerPlacement = .floating, the newest message should rest directly under the visible floating composer chrome, without a persistent reserved bottom band.
  • The composer should still remain correctly positioned above the keyboard.
  • ChatChannelView should coexist with tabViewBottomAccessory just as it does in a normal tab/push setup.

What happened instead?

  • In the accessory-hosted configuration, the transcript keeps an extra bottom band/gap under the latest message.
  • Hiding the tab bar on the pushed channel screen with .toolbar(.hidden, for: .tabBar) can trigger the same class of regression.
  • If the host forces .ignoresSafeArea(edges: .bottom) to remove the band, the keyboard can cover the composer.
  • If chat bypasses the accessory shell, the gap disappears.

Current findings

  • MessageListConfig.handleTabBarVisibility alone is not the fix.
  • This is not fundamentally caused by modal vs push navigation.
  • This is not caused by our extra wrapper chrome; a slimmed-down wrapper still reproduces if chat is routed through the accessory shell.
  • During SDK-side instrumentation, tabViewBottomAccessoryPlacement was nil from inside ChatChannelView during the bad host repro, so detecting accessory presence from that environment alone may not be sufficient.
  • We also observed cases where the floating transcript inset tracked the raw measured composer container height (76pt) rather than the visible overlap (48pt), suggesting the composer/list inset logic may be sensitive to container state and/or padded composer measurements in this environment.

Minimal repro shape

  1. App root has a TabView.
  2. TabView applies tabViewBottomAccessory.
  3. One tab contains Stream channel list and pushes into stock ChatChannelView.
  4. ChatChannelView uses composerPlacement = .floating.
  5. Observe extra space under the floating composer.
  6. Remove the accessory or bypass it for chat, and the gap disappears.

GetStream Environment

GetStream Chat version: v5 beta line from develop
GetStream Chat frameworks: StreamChat, StreamChatSwiftUI
iOS version: iOS 26.4
Swift version: Apple Swift 6.3
Xcode version: Xcode 26.4
Device: iPhone 17 Simulator

Additional context

  • composerPlacement = .floating
  • Exact revisions in our repro:
    • StreamChatSwiftUI: d46ad84161a8d69f913fd160c5a707e6afb244c4
    • StreamChat: dd9866b59db06bcadca614892b2ed006297ac73b
  • These develop revisions are ahead of the 5.0.0-beta tag, so this repro is on the current v5 beta line rather than the exact beta tag.
  • Current local workaround: bypass the shell modifier that applies tabViewBottomAccessory for chat, keep handleTabBarVisibility enabled, and avoid .toolbar(.hidden, for: .tabBar) on the channel screen.
  • This now appears upstream-relevant as a compatibility issue between Stream’s floating composer layout and Apple’s iOS 26 tab accessory / tab-bar visibility model, rather than just a missing public underlap hook.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions