authorgravatar for julius0216@outlook.comJulius Marminge <julius0216@outlook.com> 2026-10-13 21:18:29-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2026-10-13 21:18:29-07:00
log107f6024ea4786a58a83c921728a113b849de192
tree4ebb9d7a5f132431bc9d09ae13ecb58dfef3677f
parent6002c5c68c637de2cd2557bd6c40e46c153e39b1
signature Signed by PGP key B5690EEEBB952194

fix(mobile): search bar animates in on iOS 26+ instead of popping (#19209)


1 files changed, 26 insertions(+), 14 deletions(-)

apps/mobile/src/features/workspace/WorkspaceToolbar.ios.tsx+26-14
......@@ -4,6 +4,7 @@ import { Platform } from "react-native";
44import { useNativeLayoutMetrics } from "../../native/native-layout-metrics";
55import type { SearchBarCommands } from "react-native-screens";
66
7import { NATIVE_LIQUID_GLASS_SUPPORTED } from "../../native/native-glass";
78import { NativeHeaderToolbar, NativeStackScreenOptions } from "../../native/StackHeader";
89import { NativeWorkspaceTabActivityContext } from "../../native/v5-workspace-context";
910import { useHardwareKeyboardCommand } from "../keyboard/hardwareKeyboardCommands";
......@@ -26,8 +27,7 @@ export function WorkspaceToolbar(props: {
2627 const searchRef = useRef<SearchBarCommands>(null);
2728 const tab = workspace.state.tabs[workspace.state.selectedTab];
2829 const selectedTab = workspace.state.selectedTab;
29 const focusSearch = useCallback(() => {
30 if (!workspace.isTabActive(selectedTab)) return false;
30 const enterSearch = useCallback(() => {
3131 workspace.dispatch({
3232 type: "scroll",
3333 tab: selectedTab,
......@@ -35,9 +35,14 @@ export function WorkspaceToolbar(props: {
3535 });
3636 workspace.dispatch({ type: "search", tab: selectedTab });
3737 if (props.sidebar && !panes.primarySidebarVisible) togglePrimarySidebar();
38 }, [workspace, selectedTab, props.sidebar, panes.primarySidebarVisible, togglePrimarySidebar]);
39 const focusSearch = useCallback(() => {
40 if (!workspace.isTabActive(selectedTab)) return false;
41 // A mounted bar enters search from its own onFocus.
42 if (!NATIVE_LIQUID_GLASS_SUPPORTED) enterSearch();
3843 searchRef.current?.focus();
3944 return true;
40 }, [workspace, selectedTab, props.sidebar, panes.primarySidebarVisible, togglePrimarySidebar]);
45 }, [workspace, selectedTab, enterSearch]);
4146 useHardwareKeyboardCommand("focusSearch", focusSearch);
4247 const restoreSearch = useCallback(() => {
4348 if (isTabActive(selectedTab) && tab.searchMode !== "resting")
......@@ -59,8 +64,10 @@ export function WorkspaceToolbar(props: {
5964 <NativeStackScreenOptions
6065 optionsVersion={[selectedTab, tab.searchMode]}
6166 options={{
67 // Liquid Glass keeps search mounted as UIKit's own header button, which
68 // morphs into the field; swapping a stacked bar in and out cannot animate.
6269 headerSearchBarOptions:
63 tab.searchMode !== "resting"
70 NATIVE_LIQUID_GLASS_SUPPORTED || tab.searchMode !== "resting"
6471 ? {
6572 ref: searchRef,
6673 autoFocus: tab.searchMode === "active",
......@@ -68,12 +75,15 @@ export function WorkspaceToolbar(props: {
6875 hideNavigationBar: false,
6976 hideWhenScrolling: false,
7077 obscureBackground: false,
71 placement: "stacked",
72 allowToolbarIntegration: false,
78 placement: NATIVE_LIQUID_GLASS_SUPPORTED ? "integratedButton" : "stacked",
79 allowToolbarIntegration: NATIVE_LIQUID_GLASS_SUPPORTED,
7380 placeholder:
7481 selectedTab === "pullRequests" ? "Search pull requests" : "Search threads",
7582 cancelButtonText: "✕",
76 onFocus: () => workspace.dispatch({ type: "search", tab: selectedTab }),
83 onFocus: () =>
84 tab.searchMode === "resting"
85 ? enterSearch()
86 : workspace.dispatch({ type: "search", tab: selectedTab }),
7787 onBlur: () => workspace.dispatch({ type: "expand", tab: selectedTab }),
7888 onSearchButtonPress: () => searchRef.current?.blur(),
7989 onChangeText: ({ nativeEvent }) =>
......@@ -102,13 +112,15 @@ export function WorkspaceToolbar(props: {
102112 })
103113 }
104114 />
105 <NativeHeaderToolbar.Button
106 accessibilityLabel={
107 selectedTab === "pullRequests" ? "Search pull requests" : "Search threads"
108 }
109 icon="magnifyingglass"
110 onPress={focusSearch}
111 />
115 {NATIVE_LIQUID_GLASS_SUPPORTED ? null : (
116 <NativeHeaderToolbar.Button
117 accessibilityLabel={
118 selectedTab === "pullRequests" ? "Search pull requests" : "Search threads"
119 }
120 icon="magnifyingglass"
121 onPress={focusSearch}
122 />
123 )}
112124 </NativeHeaderToolbar>
113125 <NativeHeaderToolbar placement="bottom">
114126 {nativeToolbarCompose ? <NativeHeaderToolbar.Spacer flexible /> : null}