mirror of
https://github.com/movie-web/native-app.git
synced 2025-09-13 16:43:25 +00:00
feat: always focus input when search tab is pressed
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import { useRef } from "react";
|
||||
import { Platform, View } from "react-native";
|
||||
import { Tabs } from "expo-router";
|
||||
|
||||
@@ -6,87 +7,102 @@ import Colors from "@movie-web/tailwind-config/colors";
|
||||
import { MovieWebSvg } from "~/components/Icon";
|
||||
import SvgTabBarIcon from "~/components/SvgTabBarIcon";
|
||||
import TabBarIcon from "~/components/TabBarIcon";
|
||||
import SearchTabContext from "./search/SearchTabContext";
|
||||
|
||||
export default function TabLayout() {
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||
const focusSearchInputRef = useRef(() => {});
|
||||
|
||||
return (
|
||||
<Tabs
|
||||
sceneContainerStyle={{
|
||||
backgroundColor: Colors.background,
|
||||
}}
|
||||
screenOptions={{
|
||||
headerShown: false,
|
||||
tabBarActiveTintColor: Colors.primary[100],
|
||||
tabBarStyle: {
|
||||
backgroundColor: Colors.secondary[700],
|
||||
borderTopColor: "transparent",
|
||||
borderTopRightRadius: 20,
|
||||
borderTopLeftRadius: 20,
|
||||
paddingBottom: Platform.select({ ios: 100 }),
|
||||
height: 80,
|
||||
},
|
||||
tabBarItemStyle: {
|
||||
paddingVertical: 18,
|
||||
height: 82,
|
||||
},
|
||||
tabBarLabelStyle: [
|
||||
{
|
||||
marginTop: 2,
|
||||
<SearchTabContext.Provider value={{ focusSearchInputRef }}>
|
||||
<Tabs
|
||||
sceneContainerStyle={{
|
||||
backgroundColor: Colors.background,
|
||||
}}
|
||||
screenListeners={({ route }) => ({
|
||||
tabPress: () => {
|
||||
switch (route.name) {
|
||||
case "search":
|
||||
focusSearchInputRef.current();
|
||||
break;
|
||||
}
|
||||
},
|
||||
],
|
||||
}}
|
||||
>
|
||||
<Tabs.Screen
|
||||
name="index"
|
||||
options={{
|
||||
title: "Home",
|
||||
tabBarIcon: ({ focused }) => (
|
||||
<TabBarIcon name="home" focused={focused} />
|
||||
),
|
||||
})}
|
||||
screenOptions={{
|
||||
headerShown: false,
|
||||
tabBarActiveTintColor: Colors.primary[100],
|
||||
tabBarStyle: {
|
||||
backgroundColor: Colors.secondary[700],
|
||||
borderTopColor: "transparent",
|
||||
borderTopRightRadius: 20,
|
||||
borderTopLeftRadius: 20,
|
||||
paddingBottom: Platform.select({ ios: 100 }),
|
||||
height: 80,
|
||||
},
|
||||
tabBarItemStyle: {
|
||||
paddingVertical: 18,
|
||||
height: 82,
|
||||
},
|
||||
tabBarLabelStyle: [
|
||||
{
|
||||
marginTop: 2,
|
||||
},
|
||||
],
|
||||
}}
|
||||
/>
|
||||
<Tabs.Screen
|
||||
name="downloads"
|
||||
options={{
|
||||
title: "Downloads",
|
||||
tabBarIcon: ({ focused }) => (
|
||||
<TabBarIcon name="download" focused={focused} />
|
||||
),
|
||||
}}
|
||||
/>
|
||||
<Tabs.Screen
|
||||
name="search"
|
||||
options={{
|
||||
title: "Search",
|
||||
tabBarLabel: "",
|
||||
tabBarIcon: ({ focused }) => (
|
||||
<View
|
||||
className={`android:top-2 ios:top-2 flex h-14 w-14 items-center justify-center overflow-hidden rounded-full ${focused ? "bg-primary-300" : "bg-primary-400"} text-center align-middle text-2xl text-white`}
|
||||
>
|
||||
<TabBarIcon name="search" color="#FFF" />
|
||||
</View>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
<Tabs.Screen
|
||||
name="movie-web"
|
||||
options={{
|
||||
title: "movie-web",
|
||||
tabBarIcon: ({ focused }) => (
|
||||
<SvgTabBarIcon focused={focused}>
|
||||
<MovieWebSvg />
|
||||
</SvgTabBarIcon>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
<Tabs.Screen
|
||||
name="settings"
|
||||
options={{
|
||||
title: "Settings",
|
||||
tabBarIcon: ({ focused }) => (
|
||||
<TabBarIcon name="cog" focused={focused} />
|
||||
),
|
||||
}}
|
||||
/>
|
||||
</Tabs>
|
||||
>
|
||||
<Tabs.Screen
|
||||
name="index"
|
||||
options={{
|
||||
title: "Home",
|
||||
tabBarIcon: ({ focused }) => (
|
||||
<TabBarIcon name="home" focused={focused} />
|
||||
),
|
||||
}}
|
||||
/>
|
||||
<Tabs.Screen
|
||||
name="downloads"
|
||||
options={{
|
||||
title: "Downloads",
|
||||
tabBarIcon: ({ focused }) => (
|
||||
<TabBarIcon name="download" focused={focused} />
|
||||
),
|
||||
}}
|
||||
/>
|
||||
<Tabs.Screen
|
||||
name="search"
|
||||
options={{
|
||||
title: "Search",
|
||||
tabBarLabel: "",
|
||||
tabBarIcon: ({ focused }) => (
|
||||
<View
|
||||
className={`android:top-2 ios:top-2 flex h-14 w-14 items-center justify-center overflow-hidden rounded-full ${focused ? "bg-primary-300" : "bg-primary-400"} text-center align-middle text-2xl text-white`}
|
||||
>
|
||||
<TabBarIcon name="search" color="#FFF" />
|
||||
</View>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
<Tabs.Screen
|
||||
name="movie-web"
|
||||
options={{
|
||||
title: "movie-web",
|
||||
tabBarIcon: ({ focused }) => (
|
||||
<SvgTabBarIcon focused={focused}>
|
||||
<MovieWebSvg />
|
||||
</SvgTabBarIcon>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
<Tabs.Screen
|
||||
name="settings"
|
||||
options={{
|
||||
title: "Settings",
|
||||
tabBarIcon: ({ focused }) => (
|
||||
<TabBarIcon name="cog" focused={focused} />
|
||||
),
|
||||
}}
|
||||
/>
|
||||
</Tabs>
|
||||
</SearchTabContext.Provider>
|
||||
);
|
||||
}
|
||||
|
8
apps/expo/src/app/(tabs)/search/SearchTabContext.tsx
Normal file
8
apps/expo/src/app/(tabs)/search/SearchTabContext.tsx
Normal file
@@ -0,0 +1,8 @@
|
||||
import React from "react";
|
||||
|
||||
const SearchTabContext = React.createContext({
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||
focusSearchInputRef: { current: () => {} },
|
||||
});
|
||||
|
||||
export default SearchTabContext;
|
@@ -1,10 +1,12 @@
|
||||
import { useCallback, useRef, useState } from "react";
|
||||
import { useCallback, useContext, useEffect, useRef, useState } from "react";
|
||||
import { TextInput, View } from "react-native";
|
||||
import { useFocusEffect } from "expo-router";
|
||||
import { FontAwesome5 } from "@expo/vector-icons";
|
||||
|
||||
import Colors from "@movie-web/tailwind-config/colors";
|
||||
|
||||
import SearchTabContext from "./SearchTabContext";
|
||||
|
||||
export default function Searchbar({
|
||||
onSearchChange,
|
||||
}: {
|
||||
@@ -13,6 +15,14 @@ export default function Searchbar({
|
||||
const [keyword, setKeyword] = useState("");
|
||||
const inputRef = useRef<TextInput>(null);
|
||||
|
||||
const { focusSearchInputRef } = useContext(SearchTabContext);
|
||||
|
||||
useEffect(() => {
|
||||
focusSearchInputRef.current = () => {
|
||||
inputRef.current?.focus();
|
||||
};
|
||||
}, [focusSearchInputRef]);
|
||||
|
||||
useFocusEffect(
|
||||
useCallback(() => {
|
||||
// When the screen is focused
|
||||
|
Reference in New Issue
Block a user