# fix\(mobile\): the iPhone Duo searches from a field at the bottom of its list · PR \#23147 · pingdotgg/t3code

[View on GitCafe](https://git.cafe/pingdotgg/t3code/pull/23147)

Repository: [pingdotgg/t3code](https://git.cafe/pingdotgg/t3code)

Visibility: public

State: merged

Source repository: pingdotgg/t3code

Source branch: duo/search

Target branch: duo/sidebar

Head commit: 938862484c8f2c780419d0e1f0589720f5bffa3f

[Discussion and reviews](https://git.cafe/pingdotgg/t3code/pull/23147)

[Commits](https://git.cafe/pingdotgg/t3code/pull/23147/commits?format=markdown)

[Files changed](https://git.cafe/pingdotgg/t3code/pull/23147/diffs?format=markdown)

## Description

---

On the iPhone Duo, list search lived in the unfolded sidebar's bottom toolbar and moved to a navigation bar button when folded, because UIKit puts a folded column's toolbar in the vertical bar. Every fold re-placed the search controller, which replaces its search field, and a list hidden behind its detail during the fold needed a new controller.

The Duo now searches from a full-width field at the bottom of the list in every pose, using the glass field the custom workspace toolbar already drew. A fold only changes its width. The field rises only once the keyboard reaches it, because UIKit also reports keyboards without height, with a hardware keyboard and around a fold.

This layer also makes header actions update when only their contents change. React Navigation keeps a screen's descriptor, and with it the native header, while the options stay shallowly equal, and `NativeStackScreenOptions` keeps each option function's identity stable, so a re-application never reached the header. After an unfold and a fold, the thread list was left without Compose. A re-application now hands the header new function wrappers.

## Verification

- `NativeHeaderToolbar.test.tsx`: its navigation mock now skips shallowly equal options, as React Navigation does. All four tests fail without the fix.
- Recorded at this PR's base `c818e4b66e7` and head `aaad7cee174` (pre-restack commits; Screens t3.32 development client with a matching fingerprint). The thread list is unfolded, then folded:

![Before: unfolded search sits in the sidebar's bottom toolbar; folded, it becomes a header button](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/7ddaf7657fa412c0/pr23145-search-BEFORE-c818e4b66e7.mp4)

![After: the glass search field stays at the bottom of the list in both poses](https://gh-file-drop-api-prod-mi5fy3sowv63ufte.pinglabs.workers.dev/f/0851890bb720f45f/pr23145-search-AFTER-aaad7cee174.mp4)

- The header-action fix is covered by the test above. This recorded flow did not lose Compose at the base either, so the videos show only the search change.

Implemented with Claude Opus 5.5 in Claude Code, running in T3 Code.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

