From 98bb9ad3de896e4669771966fa4d3fc96ea44bcd Mon Sep 17 00:00:00 2001 From: Oleksandr Zavarzin Date: Tue, 8 Sep 2026 17:19:31 +0200 Subject: [PATCH 1/3] fix(expo-template): render tab bar icons on Android --- .changeset/expo-template-android-tab-icons.md | 5 ++++ .../docs/guides/usage-with-expo-router.mdx | 20 ++++++++++---- packages/expo-template/app/(tabs)/_layout.tsx | 26 +++++++++++++++--- packages/expo-template/assets/icons/house.png | Bin 0 -> 800 bytes packages/expo-template/assets/icons/send.png | Bin 0 -> 1229 bytes 5 files changed, 42 insertions(+), 9 deletions(-) create mode 100644 .changeset/expo-template-android-tab-icons.md create mode 100644 packages/expo-template/assets/icons/house.png create mode 100644 packages/expo-template/assets/icons/send.png diff --git a/.changeset/expo-template-android-tab-icons.md b/.changeset/expo-template-android-tab-icons.md new file mode 100644 index 00000000..1b83da2a --- /dev/null +++ b/.changeset/expo-template-android-tab-icons.md @@ -0,0 +1,5 @@ +--- +'@bottom-tabs/expo-template': patch +--- + +Render tab bar icons on Android, and apply the template's own colors to the tab bar diff --git a/docs/docs/docs/guides/usage-with-expo-router.mdx b/docs/docs/docs/guides/usage-with-expo-router.mdx index 865c8e42..7413bb55 100644 --- a/docs/docs/docs/guides/usage-with-expo-router.mdx +++ b/docs/docs/docs/guides/usage-with-expo-router.mdx @@ -6,7 +6,7 @@ First install `@bottom-tabs/react-navigation` which provides a native bottom tab -Next, create a custom layout adapter for the native bottom tabs using `withLayoutContext` from Expo Router: +Next, create a custom layout adapter for the native bottom tabs using `withLayoutContext` from Expo Router. Put it in `components/bottom-tabs.tsx` and export the navigator, so your layouts can import it: ```tsx import { withLayoutContext } from 'expo-router'; @@ -19,7 +19,7 @@ import { ParamListBase, TabNavigationState } from '@react-navigation/native'; const BottomTabNavigator = createNativeBottomTabNavigator().Navigator; -const Tabs = withLayoutContext< +export const Tabs = withLayoutContext< NativeBottomTabNavigationOptions, typeof BottomTabNavigator, TabNavigationState, @@ -32,6 +32,8 @@ const Tabs = withLayoutContext< Then, use the `Tabs` navigator in your app: ```tsx +import { Platform } from "react-native"; + import { Tabs } from "@/components/bottom-tabs"; export default function TabLayout() { @@ -41,14 +43,20 @@ export default function TabLayout() { name="index" options={{ title: "Home", - tabBarIcon: () => ({ sfSymbol: "house" }), + tabBarIcon: () => + Platform.OS === "ios" + ? { sfSymbol: "house" } + : require("@/assets/icons/house.png"), }} /> ({ sfSymbol: "person" }), + tabBarIcon: () => + Platform.OS === "ios" + ? { sfSymbol: "person" } + : require("@/assets/icons/person.png"), }} /> @@ -56,7 +64,9 @@ export default function TabLayout() { } ``` -For props and more information, see the [React Navigation integration guide](/docs/guides/usage-with-react-navigation). +> [!NOTE] SF Symbols are only available on Apple platforms. On Android and web, pass an image with `require()` or a `{ uri }` object instead — a tab given only an `sfSymbol` renders without an icon there. + +For props and more information, see the [React Navigation integration guide](/docs/guides/usage-with-react-navigation), which documents every accepted `tabBarIcon` source. Example: [okwasniewski/ExpoNativeTabs](https://github.com/okwasniewski/ExpoNativeTabs) diff --git a/packages/expo-template/app/(tabs)/_layout.tsx b/packages/expo-template/app/(tabs)/_layout.tsx index e92284f5..afa9f305 100644 --- a/packages/expo-template/app/(tabs)/_layout.tsx +++ b/packages/expo-template/app/(tabs)/_layout.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import { Platform } from 'react-native'; import { withLayoutContext } from 'expo-router'; import { createNativeBottomTabNavigator, @@ -7,6 +7,9 @@ import { } from '@bottom-tabs/react-navigation'; import { ParamListBase, TabNavigationState } from '@react-navigation/native'; +import { Colors } from '@/constants/Colors'; +import { useColorScheme } from '@/hooks/useColorScheme'; + const BottomTabNavigator = createNativeBottomTabNavigator().Navigator; const Tabs = withLayoutContext< @@ -16,21 +19,36 @@ const Tabs = withLayoutContext< NativeBottomTabNavigationEventMap >(BottomTabNavigator); +// SF Symbols are only available on Apple platforms, everything else uses images. +const supportsSFSymbols = Platform.OS === 'ios'; + export default function TabLayout() { + const colorScheme = useColorScheme() ?? 'light'; + const colorTheme = Colors[colorScheme]; + return ( - + ({ sfSymbol: 'house.fill' }), + tabBarIcon: () => + supportsSFSymbols + ? { sfSymbol: 'house.fill' } + : require('@/assets/icons/house.png'), }} /> ({ sfSymbol: 'paperplane.fill' }), + tabBarIcon: () => + supportsSFSymbols + ? { sfSymbol: 'paperplane.fill' } + : require('@/assets/icons/send.png'), }} /> diff --git a/packages/expo-template/assets/icons/house.png b/packages/expo-template/assets/icons/house.png new file mode 100644 index 0000000000000000000000000000000000000000..525bd3196bfc05786f23d8da6a905c3f037e5c1b GIT binary patch literal 800 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD1|%QND7Ro>V7lt*;uuoF_-0nF-(dp*7jE^( z&t!OwgoHR=T{~OX6DxPB>p?~Np3j?p9(~;^znYn0!>#(AK;3EVXFmBbFr49=@pL8w z!wgx2)5eSp2G$AF{?8XqF#EgQhM{g(;*R^W2Yx@C`RK>i=Ua^%`VW8FzW&1B!rk|` zDl^QiJ6o{!<;^gWGUf&6dy`T&&C_%{KRxohOidwOPH*#cRHIi?{3Q>xd# zPrVk#zTkZ4qcw@ALg$>-KOZgWa7}uRX29Aa7p{PWc%YiFGI zxc8D}!x8C&;*G-v4Dt+apgoGz=`O3QD#O!Z@! zW}b7X`F^wstJUlGUnlLiX4qmj<;5h07jHUM|4&=RwxBTVPw2g5*YxlybGHdOoR$uG zcBVYhx3TJHT;+pz_pWgX%nV?h2&p_>dQ>$xKC2)x6X%6ZUeDJi z>nAL8*t;y`48w$~1yj~lb#XLR@vlr}@Q^(jVE*^y!+XXIU$*~s>0&TA%mR-J5sM9h zo@xhpxEa9Fk&1UFNkHnvxxosLzsc#|No%4<;#JVvVjsfGegcThlA16^aOw+ N44$rjF6*2UngDlyQPltd literal 0 HcmV?d00001 diff --git a/packages/expo-template/assets/icons/send.png b/packages/expo-template/assets/icons/send.png new file mode 100644 index 0000000000000000000000000000000000000000..635bf4b8d144cbe743dd0409bb902d2aeecf5c81 GIT binary patch literal 1229 zcmV;;1Ty=HP)E3`Q3^po60WN`MZa11NzGpaVL94xj_*fD)htI^gtfPBYG)C)xF{Z0lwnJIW@u zzb8vd=ALi<*Hr-r&{h6za{vyYvjUx`_Y>d%IxEn5dOraUptAywUFOY^IM0x1BP_NP1m z;;Zz2WhjseK&N~!13>(d{!W@-Cl$yApwl5f5P$&`wR?Xg%X$VVzpbzanjwnzA zfKJ0n00bxFZrjxCeW*Z906LF{CsiWSw*U}MOIYGmP(_9IWyh@nsL*_m00fP(+L!Bl z0SJZWGysCr5!#m+TL7R!FPXG00Z1PDOX#fPLL$+AwN&&E6$u}{CKt9Uzf71G0WoNFMv`YZk zZ}*EBUP#juG7FF@NxKFB(f;Dv1NnUM>X=UmOGUy{3jlkGKZ!w42PXwUVjA+w4o^J* zgi4bu2vG`zTtZF>?-^m79G-du*o#XwMO8I25DiaMQTzQpd2S8BlLgLhum<3j2(BJP zlH>nMiL+uJ=Ay{p1iv}5;@$ud{JSg^v1z|$JeuILBZWYI=D zDF9{_9L;{o1ESLy%hS473V^yR>htLuX7Ku^D_9u-@tnAhw^t1_*NCnNfC>iDsc5Kd zuIW?#wUq!+vm-oxbzzTAFgpM|98X7hJpZUJ&F-5OfF@O9Jh8r+pl2tV4FFXP-rg*! zo)vt5{|o@A*Abn@c)v%}&qoHJVFs@^E%LR+jRt^tPF%;^hY2$?0HA_FbSfGun`?U- z>NV>pfSMiQ>4y^b=wdAbz{Bx$gvaxb?q$gPECJA@N{lDg4=L!`MOy$s6@#}=kyJ+k zK)sIWG{$GwJ Date: Wed, 9 Sep 2026 12:14:28 +0200 Subject: [PATCH 2/3] fix(expo-template): update usage-with-expo-router doc Co-authored-by: Thiago Brezinski --- docs/docs/docs/guides/usage-with-expo-router.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/docs/guides/usage-with-expo-router.mdx b/docs/docs/docs/guides/usage-with-expo-router.mdx index 7413bb55..111025c3 100644 --- a/docs/docs/docs/guides/usage-with-expo-router.mdx +++ b/docs/docs/docs/guides/usage-with-expo-router.mdx @@ -64,7 +64,7 @@ export default function TabLayout() { } ``` -> [!NOTE] SF Symbols are only available on Apple platforms. On Android and web, pass an image with `require()` or a `{ uri }` object instead — a tab given only an `sfSymbol` renders without an icon there. +> [!NOTE] SF Symbols are only available on Apple platforms. On Android and web, pass an image with `require()` or a `{ uri }` object instead. For props and more information, see the [React Navigation integration guide](/docs/guides/usage-with-react-navigation), which documents every accepted `tabBarIcon` source. From d4054bf4722154c6fc6ef1465632b5aff4b7db36 Mon Sep 17 00:00:00 2001 From: Oleksandr Zavarzin Date: Wed, 9 Sep 2026 12:15:53 +0200 Subject: [PATCH 3/3] fix(expo-template): replace const with inline platform check --- packages/expo-template/app/(tabs)/_layout.tsx | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/packages/expo-template/app/(tabs)/_layout.tsx b/packages/expo-template/app/(tabs)/_layout.tsx index afa9f305..7b392cbb 100644 --- a/packages/expo-template/app/(tabs)/_layout.tsx +++ b/packages/expo-template/app/(tabs)/_layout.tsx @@ -19,9 +19,6 @@ const Tabs = withLayoutContext< NativeBottomTabNavigationEventMap >(BottomTabNavigator); -// SF Symbols are only available on Apple platforms, everything else uses images. -const supportsSFSymbols = Platform.OS === 'ios'; - export default function TabLayout() { const colorScheme = useColorScheme() ?? 'light'; const colorTheme = Colors[colorScheme]; @@ -36,7 +33,7 @@ export default function TabLayout() { options={{ title: 'Home', tabBarIcon: () => - supportsSFSymbols + Platform.OS === 'ios' ? { sfSymbol: 'house.fill' } : require('@/assets/icons/house.png'), }} @@ -46,7 +43,7 @@ export default function TabLayout() { options={{ title: 'Explore', tabBarIcon: () => - supportsSFSymbols + Platform.OS === 'ios' ? { sfSymbol: 'paperplane.fill' } : require('@/assets/icons/send.png'), }}