Skip to content

Instantly share code, notes, and snippets.

@ivanmercedes
Last active March 24, 2025 17:28
Show Gist options
  • Select an option

  • Save ivanmercedes/f4de9324944701e0c75cc2e0e090ec45 to your computer and use it in GitHub Desktop.

Select an option

Save ivanmercedes/f4de9324944701e0c75cc2e0e090ec45 to your computer and use it in GitHub Desktop.
Global BottomSheet react native
import BottomSheetGlobal from "@/components/BottomSheetGlobal";
import { BottomSheetModalProvider } from "@gorhom/bottom-sheet";
import { Stack } from "expo-router";
import { GestureHandlerRootView } from "react-native-gesture-handler";
import "react-native-reanimated";
import { SafeAreaView } from "react-native-safe-area-context";
export default function RootLayout() {
return (
<GestureHandlerRootView>
<BottomSheetModalProvider>
<SafeAreaView className="flex-1 bg-black">
<Stack>
<Stack.Screen name="index" options={{ headerShown: false }} />
<Stack.Screen name="(tabs)" options={{ headerShown: false }} />
<Stack.Screen name="(auth)" options={{ headerShown: false }} />
<Stack.Screen name="+not-found" />
</Stack>
</SafeAreaView>
<BottomSheetGlobal />
</BottomSheetModalProvider>
</GestureHandlerRootView>
);
}
import { useBottomSheetStore } from "@/store/useBottomSheetStore";
import { BottomSheetModal, BottomSheetView } from "@gorhom/bottom-sheet";
import { useEffect, useRef } from "react";
export default function BottomSheetGlobal() {
const bottomSheetRef = useRef<BottomSheetModal>(null);
const { isOpen, content, closeBottomSheet } = useBottomSheetStore();
useEffect(() => {
if (isOpen) {
requestAnimationFrame(() => bottomSheetRef.current?.present());
} else {
bottomSheetRef.current?.dismiss();
}
}, [isOpen]);
return (
<>
<BottomSheetModal
ref={bottomSheetRef}
index={1}
snapPoints={["90%"]}
enablePanDownToClose
onDismiss={closeBottomSheet}
backgroundStyle={{ backgroundColor: "#242424" }}
handleStyle={{ backgroundColor: "#242424", borderRadius: 20 }}
handleIndicatorStyle={{ backgroundColor: "#fff" }}
>
<BottomSheetView className="p-5">{content}</BottomSheetView>
</BottomSheetModal>
</>
);
}
import { TouchableOpacity } from "react-native";
import { useBottomSheetStore } from "@/store/useBottomSheetStore";
import { Feather } from "@expo/vector-icons";
const Test = () => {
const openBottomSheet = useBottomSheetStore((state) => state.openBottomSheet);
return (
<TouchableOpacity
onPress={() =>
openBottomSheet(
<View className="p-5">
<Text className="text-white">Hola desde el Bottom Sheet 🎉</Text>
</View>
)
}
>
<View className="flex-1 rounded-md border-2 border-[#666] border-dashed mr-7 justify-center items-center p-10">
<Feather name="plus" size={24} color="#ccc" />
</View>
</TouchableOpacity>
);
}
export default Test;
import { ReactNode } from 'react';
import { create } from 'zustand';
interface BottomSheetState {
isOpen: boolean;
content: ReactNode | null;
openBottomSheet: (component: ReactNode) => void;
closeBottomSheet: () => void;
}
export const useBottomSheetStore = create<BottomSheetState>((set) => ({
isOpen: false,
content: null,
openBottomSheet: (component) =>
set(() => ({ isOpen: true, content: component })),
closeBottomSheet: () =>
set(() => ({ isOpen: false, content: null })),
}));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment