Customize Bottom Bar
The Bottom Bar is used to display the navigation options in the bottom of the app which can be enabled and edited from the dashboard.
Steps to customize the Bottom Bar
1. Create a Component BottomTabBar.js
in the src/components
folder.
2. Copy the following code in the BottomTabBar.js
file.
src/components/BottomTabBar.js
import React from "react";
import { StyleSheet, View, Text, Pressable, Image } from "react-native";
import Icon from "react-native-vector-icons/Feather";
import { useAppStorage } from "@appmaker-xyz/core";
import { isEmpty } from "lodash";
import { handleAction } from "@appmaker-xyz/react-native";
function CartCount({ countStyle }) {
const count = useAppStorage((state) => {
let totalQuantity = 0;
if (state.checkout?.lineItems?.edges?.length > 0) {
state.checkout?.lineItems?.edges?.forEach((item) => {
totalQuantity += item?.node?.quantity;
});
}
return totalQuantity || 0;
});
return <Text style={[styles.count, countStyle]}>{count}</Text>;
}
function MenuImage({
isFocused,
activeImage,
defaultImage,
defaultbase64Icon,
activebase64Icon,
size = 19,
}) {
const activeImageUrl = activeImage?.url || activebase64Icon;
const defaultImageUrl = defaultImage?.url || defaultbase64Icon;
return (
<Image
style={[styles.animatedImage, { height: size, width: size }]}
source={{
uri: isFocused ? activeImageUrl : defaultImageUrl,
}}
/>
);
}
function BottomBarIcon(params) {
const {
route,
descriptors,
navigation,
state,
index,
fontSize = 11,
iconSize = 18,
handleAction,
} = params;
const { options } = descriptors[route.key];
const label =
options.tabBarLabel !== undefined
? options.tabBarLabel
: options.title !== undefined
? options.title
: route.name;
const {
iconName,
defaultColor = "#4f4f4f",
activeColor = "#3380FF",
customStyle,
count,
defaultbase64Icon,
activebase64Icon,
activeImage,
defaultImage,
toolBarCustomStyles,
enableIndividualIconSize = false,
individualIconSize,
} = options;
const isFocused = state.index === index;
const onPress = () => {
const event = navigation.emit({
type: "tabPress",
target: route.key,
});
if (!isFocused && !event.defaultPrevented) {
if (!isEmpty(route.params?.appmakerAction)) {
handleAction(route.params.appmakerAction);
} else if (route?.params?.openSeperatePage) {
navigation.navigate("BlockScreen", {
pageId: route.params.pageId,
});
} else {
navigation.navigate(route.name);
}
}
};
const onLongPress = () => {
navigation.emit({
type: "tabLongPress",
target: route.key,
});
};
return options.hideTabBar ? null : (
<Pressable
accessibilityRole="button"
accessibilityState={isFocused ? { selected: true } : {}}
accessibilityLabel={options.tabBarAccessibilityLabel}
testID={options.tabBarTestID}
onPress={onPress}
onLongPress={onLongPress}
activeOpacity={0.9}
style={styles.tab}
>
<View style={[styles.tabInner, customStyle]}>
{count ? (
<CartCount countStyle={toolBarCustomStyles?.countStyle} />
) : null}
{!isEmpty(activeImage) || !isEmpty(defaultbase64Icon) ? (
<MenuImage
isFocused={isFocused}
activeImage={activeImage}
defaultImage={defaultImage}
defaultbase64Icon={defaultbase64Icon}
activebase64Icon={activebase64Icon}
size={enableIndividualIconSize ? individualIconSize : iconSize}
/>
) : (
<Icon
name={iconName}
size={enableIndividualIconSize ? individualIconSize : iconSize}
color={isFocused ? activeColor : defaultColor}
/>
)}
{label ? (
<Text
numberOfLines={1}
style={[
styles.tabText,
{
color: isFocused ? activeColor : defaultColor,
fontSize: fontSize,
},
toolBarCustomStyles?.textStyle,
]}
>
{label}
</Text>
) : null}
</View>
</Pressable>
);
}
export default function BottomTabBar({
state,
descriptors,
navigation,
tabBackgroundColor = "#ffffff",
iconSize = 18,
fontSize = 11,
customTabStyles = {},
}) {
return (
<View
style={[
customTabStyles,
styles.tabContainer,
styles.shadow,
{ backgroundColor: tabBackgroundColor },
]}
>
{state.routes.map((route, index) => (
<BottomBarIcon
key={`tab-${index}`}
route={route}
index={index}
descriptors={descriptors}
navigation={navigation}
state={state}
iconSize={iconSize}
fontSize={fontSize}
/>
))}
</View>
);
}
const styles = StyleSheet.create({
tabContainer: {
flexDirection: "row",
paddingHorizontal: 6,
paddingVertical: 12,
},
shadow: {
shadowColor: "#000",
shadowOffset: {
width: 0,
height: 6,
},
shadowOpacity: 0.25,
shadowRadius: 3.84,
elevation: 5,
},
tab: {
flex: 1,
position: "relative",
justifyContent: "center",
},
tabInner: {
flexDirection: "column",
alignItems: "center",
justifyContent: "center",
position: "relative",
},
specialBg: {
position: "absolute",
height: 60,
width: 60,
borderRadius: 60,
},
count: {
borderRadius: 10,
fontSize: 10,
paddingHorizontal: 4,
position: "absolute",
top: -6,
right: 20,
zIndex: 10,
},
tabText: {
marginTop: 2,
},
animatedImage: {
resizeMode: "contain",
},
});
3. import the BottomTabBar
component in the src/index.js
file.
4. replace the existing BottomTabBar
component using filter in the activate function of the src/index.js
file.
src/index.js
import { addFilter } from "@appmaker-xyz/core";
import BottomTabBar from "./components/BottomTabBar";
// ...
export function activate(params) {
// Add filter to replace the bottom bar component
addFilter("home-custom-bottom-tab", "theme-id", () => {
return BottomTabBar;
});
}
// ...