AppmakerDeveloper

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;
  });
}
// ...

5. Save the changes and run the app.

6. Make changes in the BottomTabBar component as per your requirement.