A buttery-smooth animated bottom tab bar for Expo Router with a morphing popup panel.
- 🎯 Drop-in
tabBarforexpo-router's<Tabs> - 🪄 Morphing popup panel per tab with shared-element feel
- 🎨 Themeable palette & custom popup bodies
- 🧩 TypeScript-ready
git clone https://github.com/rit3zh/expo-motion-tabs
cd expo-motion-tabs
bun startiphone-usage.mov
Note
Android preview is TODO
import { Tabs } from "expo-router";
import { AnimatedTabBar } from "@/motion-tabs";
import { ExamplePopupBody } from "@/motion-tabs/examples/example-popup-body";
import { TabIcon } from "@/components/tab-icon";
export default function TabsLayout() {
return (
<Tabs
screenOptions={{ headerShown: false, tabBarStyle: { height: 0 } }}
tabBar={(props) => (
<AnimatedTabBar {...props} renderPopupBody={ExamplePopupBody} />
)}
>
<Tabs.Screen
name="home"
options={{
tabBarLabel: "Home",
tabBarIcon: ({ color, size }) => (
<TabIcon name="home" color={color} size={size} />
),
}}
/>
<Tabs.Screen name="search" options={{ tabBarLabel: "Search" }} />
<Tabs.Screen name="profile" options={{ tabBarLabel: "Profile" }} />
</Tabs>
);
}import type { IPopupRenderContext } from "@/motion-tabs";
function MyPopupBody(ctx: IPopupRenderContext) {
switch (ctx.activeView) {
case "home":
return <HomePanel {...ctx} />;
case "search":
return <SearchPanel {...ctx} />;
case "profile":
return <ProfilePanel {...ctx} />;
}
}Expo 55 · React Native 0.83 · Reanimated 4 · Gesture Handler 2 · Expo Router