[Bug]: iPhone compose button covers the last tab when the exact size check drops a tab button#32974

opened2d agobySSARAsBooks

Before submitting

  • I searched existing issues and did not find a duplicate.
  • I included enough detail to reproduce or investigate the problem.

Area

apps/mobile

Steps to reproduce

Found independently by joaoheusi, whose writeup in joaoheusi/t3code#93 has before/after screenshots and a fix. Their repro is on upstream's own four-item bar.

  1. Run the iOS app on a 393pt-wide iPhone on iOS 26, such as an iPhone 15 Pro (the simulator works).
  2. Open the workspace with the compact glass tab bar, with Chats selected so compose shows.
  3. Look at the compose button beside the tab bar.

It doesn't happen on a 402pt iPhone 17 Pro. In a fork with a fifth item (four sections plus Settings), I see it on a 402pt iPhone 16 Pro. With a sixth item on the same phone, compose is never placed.

Expected behavior

Compose sits 16pt to the right of the tab bar.

Actual behavior

Compose is drawn over the last tab (Settings).

WorkspaceTabBar.layoutSubviews (T3SidebarTabBarView.swift#L14, added in #28955) keeps only the tab buttons that pass an exact size check:

swift
1let buttons = candidates.filter { convert($0.bounds, from: $0).size == $0.bounds.size }

The check exists to skip the glass lens's magnified copy of the row. But converting a translated rect isn't exact, so at some bar widths a real button fails it from rounding alone.

  • When the last button fails, row ends one tab early, and compose is placed over that tab.
  • When every button fails, row is null, onContentLayout never fires, and compose stays unplaced (zero size, at the top-left).

More items means more fractional widths, so more failures. The four-item bar fails at some widths, and the fork's five- and six-item bars fail on the 402pt iPhone 16 Pro.

See joaoheusi/t3code#93 for screenshots.

Impact

Minor bug or occasional failure

Version or commit

main @ 8a84e94

Environment

iPhone 15 Pro simulator, iOS 26.5, four items (from joaoheusi/t3code#93). iPhone 16 Pro, iOS 26, Release build, five and six items (fork).

Logs or stack traces

shell
1

Screenshots, recordings, or supporting files

No response

Workaround

None in the app. A tolerance in the filter fixes it and still excludes the lens copy, which is magnified by much more than 1pt. This is joaoheusi/t3code#93's fix:

swift
1let buttons = candidates.filter {
2 let size = convert($0.bounds, from: $0).size
3 return abs(size.width - $0.bounds.width) < 1 && abs(size.height - $0.bounds.height) < 1
4}

A one-sided width tolerance (width <= bounds.width + 0.5) also placed compose correctly with five and six items in testing. Context: comment on #28955.