aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMohamed Bassem <me@mbassem.com>2026-02-01 18:16:22 +0000
committerMohamed Bassem <me@mbassem.com>2026-02-01 18:31:18 +0000
commitbf5c99cb10a0b35b0101bf8f9858c176889a0284 (patch)
tree9f9181bac6218e5614ebf19c11fdd1d197147206
parentfc24cc3a14e7e2d853702a51204835d30ffca253 (diff)
downloadkarakeep-bf5c99cb10a0b35b0101bf8f9858c176889a0284.tar.zst
feat(mobile): use native tabs for mobile
-rw-r--r--apps/mobile/app/dashboard/(tabs)/_layout.tsx117
-rw-r--r--apps/mobile/components/navigation/tabs.tsx28
-rw-r--r--apps/mobile/components/ui/CustomSafeAreaView.tsx3
-rw-r--r--apps/mobile/package.json1
-rw-r--r--pnpm-lock.yaml3
5 files changed, 62 insertions, 90 deletions
diff --git a/apps/mobile/app/dashboard/(tabs)/_layout.tsx b/apps/mobile/app/dashboard/(tabs)/_layout.tsx
index 5cc6aa92..f3db822e 100644
--- a/apps/mobile/app/dashboard/(tabs)/_layout.tsx
+++ b/apps/mobile/app/dashboard/(tabs)/_layout.tsx
@@ -1,69 +1,62 @@
-import React, { useLayoutEffect } from "react";
-import { Tabs, useNavigation } from "expo-router";
-import { StyledTabs } from "@/components/navigation/tabs";
-import { useColorScheme } from "@/lib/useColorScheme";
+import React from "react";
import {
- ClipboardList,
- Highlighter,
- Home,
- Settings,
- Tag,
-} from "lucide-react-native";
+ Icon,
+ Label,
+ NativeTabs,
+ VectorIcon,
+} from "expo-router/unstable-native-tabs";
+import { useColorScheme } from "@/lib/useColorScheme";
+import MaterialCommunityIcons from "@expo/vector-icons/MaterialCommunityIcons";
export default function TabLayout() {
const { colors } = useColorScheme();
- const navigation = useNavigation();
- // Hide the header on the parent screen
- useLayoutEffect(() => {
- navigation.setOptions({
- headerShown: false,
- });
- }, [navigation]);
-
return (
- <StyledTabs
- tabBarClassName="bg-gray-100 dark:bg-background"
- sceneClassName="bg-gray-100 dark:bg-background"
- screenOptions={{
- headerShown: false,
- tabBarActiveTintColor: colors.foreground,
- }}
- >
- <Tabs.Screen
- name="index"
- options={{
- title: "Home",
- tabBarIcon: ({ color }) => <Home color={color} />,
- }}
- />
- <Tabs.Screen
- name="lists"
- options={{
- title: "Lists",
- tabBarIcon: ({ color }) => <ClipboardList color={color} />,
- }}
- />
- <Tabs.Screen
- name="tags"
- options={{
- title: "Tags",
- tabBarIcon: ({ color }) => <Tag color={color} />,
- }}
- />
- <Tabs.Screen
- name="highlights"
- options={{
- title: "Highlights",
- tabBarIcon: ({ color }) => <Highlighter color={color} />,
- }}
- />
- <Tabs.Screen
- name="settings"
- options={{
- title: "Settings",
- tabBarIcon: ({ color }) => <Settings color={color} />,
- }}
- />
- </StyledTabs>
+ <NativeTabs backgroundColor={colors.grey6} minimizeBehavior="onScrollDown">
+ <NativeTabs.Trigger name="index">
+ <Icon
+ sf="house.fill"
+ androidSrc={
+ <VectorIcon family={MaterialCommunityIcons} name="home" />
+ }
+ />
+ <Label>Home</Label>
+ </NativeTabs.Trigger>
+
+ <NativeTabs.Trigger name="lists">
+ <Icon
+ sf="list.clipboard.fill"
+ androidSrc={
+ <VectorIcon family={MaterialCommunityIcons} name="clipboard-list" />
+ }
+ />
+ <Label>Lists</Label>
+ </NativeTabs.Trigger>
+
+ <NativeTabs.Trigger name="tags">
+ <Icon
+ sf="tag.fill"
+ androidSrc={<VectorIcon family={MaterialCommunityIcons} name="tag" />}
+ />
+ <Label>Tags</Label>
+ </NativeTabs.Trigger>
+
+ <NativeTabs.Trigger name="highlights">
+ <Icon
+ sf="highlighter"
+ androidSrc={
+ <VectorIcon family={MaterialCommunityIcons} name="marker" />
+ }
+ />
+ <Label>Highlights</Label>
+ </NativeTabs.Trigger>
+
+ <NativeTabs.Trigger name="settings">
+ <Icon
+ sf="gearshape.fill"
+ androidSrc={<VectorIcon family={MaterialCommunityIcons} name="cog" />}
+ />
+ <Label>Settings</Label>
+ </NativeTabs.Trigger>
+ </NativeTabs>
);
}
diff --git a/apps/mobile/components/navigation/tabs.tsx b/apps/mobile/components/navigation/tabs.tsx
deleted file mode 100644
index 83b1c6a7..00000000
--- a/apps/mobile/components/navigation/tabs.tsx
+++ /dev/null
@@ -1,28 +0,0 @@
-import { ViewStyle } from "react-native";
-import { Tabs } from "expo-router";
-import { cssInterop } from "nativewind";
-
-function StyledTabsImpl({
- tabBarStyle,
- headerStyle,
- sceneStyle,
- ...props
-}: React.ComponentProps<typeof Tabs> & {
- tabBarStyle?: ViewStyle;
- headerStyle?: ViewStyle;
- sceneStyle?: ViewStyle;
-}) {
- props.screenOptions = {
- ...props.screenOptions,
- tabBarStyle,
- headerStyle,
- sceneStyle,
- };
- return <Tabs {...props} />;
-}
-
-export const StyledTabs = cssInterop(StyledTabsImpl, {
- tabBarClassName: "tabBarStyle",
- headerClassName: "headerStyle",
- sceneClassName: "sceneStyle",
-});
diff --git a/apps/mobile/components/ui/CustomSafeAreaView.tsx b/apps/mobile/components/ui/CustomSafeAreaView.tsx
index 33c9a765..8e7755c2 100644
--- a/apps/mobile/components/ui/CustomSafeAreaView.tsx
+++ b/apps/mobile/components/ui/CustomSafeAreaView.tsx
@@ -1,4 +1,5 @@
import { SafeAreaView } from "react-native-safe-area-context";
+import { useColorScheme } from "@/lib/useColorScheme";
import { useHeaderHeight } from "@react-navigation/elements";
export default function CustomSafeAreaView({
@@ -9,11 +10,13 @@ export default function CustomSafeAreaView({
edges?: ("top" | "bottom")[];
}) {
const headerHeight = useHeaderHeight();
+ const { colors } = useColorScheme();
return (
<SafeAreaView
style={{
flex: 1,
+ backgroundColor: colors.background,
paddingTop: edges.includes("top")
? headerHeight > 0
? headerHeight
diff --git a/apps/mobile/package.json b/apps/mobile/package.json
index 94ebc0e1..47ef533d 100644
--- a/apps/mobile/package.json
+++ b/apps/mobile/package.json
@@ -16,6 +16,7 @@
},
"dependencies": {
"@expo/metro-runtime": "~6.1.2",
+ "@expo/vector-icons": "^15.0.3",
"@karakeep/shared": "workspace:^0.1.0",
"@karakeep/shared-react": "workspace:^0.1.0",
"@karakeep/trpc": "workspace:^0.1.0",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index a1ceb31e..44e8e6b0 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -317,6 +317,9 @@ importers:
'@expo/metro-runtime':
specifier: ~6.1.2
version: 6.1.2(expo@54.0.31)(react-dom@19.2.3(react@19.2.3))(react-native@0.81.5(@babel/core@7.26.0)(@types/react@19.2.5)(react@19.2.3))(react@19.2.3)
+ '@expo/vector-icons':
+ specifier: ^15.0.3
+ version: 15.0.3(expo-font@14.0.10(expo@54.0.31)(react-native@0.81.5(@babel/core@7.26.0)(@types/react@19.2.5)(react@19.2.3))(react@19.2.3))(react-native@0.81.5(@babel/core@7.26.0)(@types/react@19.2.5)(react@19.2.3))(react@19.2.3)
'@karakeep/shared':
specifier: workspace:^0.1.0
version: link:../../packages/shared