Skip to main content

Replace drawer menu page and menu items with custom components

Description

This document provides instructions on how to substitute the default drawer menu page and menu items with custom components. This is particularly valuable when you want to incorporate personalized elements into the dra`wer menu, such as a custom header, footer, or custom menu items.

Example

App ScreenshotApp Screenshot

Steps

  1. Create a page file named DrawerMenu.js in the src/pages folder.

  2. Add the following code to the DrawerMenu.js file.

src/pages/DrawerMenu.js
const DrawerMenu = {
parentID: "mainmenu",
id: "mainmenu",
blocks: [
// add your custom blocks here if any
{
name: "appmaker/core-menu",
clientId: "drawer-menu",
// Note: core-menu block will provide the menu items added in the appmaker dashboard
},
],
stickyFooter: [
// add your custom blocks here if any
],
attributes: {},
};

export default DrawerMenu;
  1. import the DrawerMenu page in the src/pages/index.js file.
src/pages/index.js
import DrawerMenu from "./DrawerMenu";

const pages = {
DrawerMenu,
};

export { pages };
info

Ensure that you include the pages module within the registerTheme function located in the src/index.js file.

  1. Create a component in src/components folder to represent the core menu items added in the appmaker dashboard.
Core menu (Sample Component)
src/components/CoreMenu.js
import React, { useState } from "react";
import {
FlatList,
Image,
Pressable,
StyleSheet,
Text,
View,
} from "react-native";
import Icon from "react-native-vector-icons/SimpleLineIcons";

const MenuItem = ({ item, onAction }) => {
const {
icon,
title,
action,
nodes = [],
fontColor,
badge,
badgeColor,
badgeText,
badgeTextColor,
dotIndicator,
dotIndicatorColor,
dotSize,
} = item;
const innerBlocks = nodes;
const [expandState, setExpandState] = useState(false);
return (
<View>
<Pressable
style={styles.pressableView}
onPress={() => {
if (innerBlocks.length > 0) {
setExpandState(!expandState);
} else {
onAction(action);
}
}}
>
<View style={styles.viewRow}>
{icon ? <Image source={{ uri: icon }} style={styles.image} /> : null}
<Text
numberOfLines={1}
style={[styles.textRow, { color: fontColor || "#5C5C5C" }]}
>
{title}
</Text>
{badge ? (
<View
style={[
styles.badgeTextContainer,
{
backgroundColor: badgeColor,
},
]}
>
<Text
style={[
styles.badgeText,
{
color: badgeTextColor,
},
]}
>
{badgeText}
</Text>
</View>
) : null}
{dotIndicator ? (
<View
style={[
styles.dotIndicator,
{
width: dotSize,
height: dotSize,
backgroundColor: dotIndicatorColor,
},
]}
/>
) : null}
</View>
{innerBlocks.length > 0 ? (
<Icon name={expandState ? "arrow-down" : "arrow-right"} size={12} />
) : null}
</Pressable>
{innerBlocks.length > 0 && expandState === true ? (
<FlatList
data={innerBlocks}
renderItem={({ item }) => (
<MenuItem item={item} onAction={onAction} />
)}
keyExtractor={(item) => item.id}
style={styles.innerContainer}
/>
) : null}
</View>
);
};

const CoreMenu = ({ attributes, onAction }) => {
const menuItems = attributes?.menuItems?.blocks;
return (
<FlatList
data={menuItems}
renderItem={({ item }) => <MenuItem item={item} onAction={onAction} />}
keyExtractor={(item) => item.id}
contentContainerStyle={styles.container}
/>
);
};

const styles = StyleSheet.create({
container: {
paddingHorizontal: 10,
},
pressableView: {
paddingVertical: 10,
flexDirection: "row",
justifyContent: "space-between",
alignItems: "center",
flex: 1,
},
viewRow: {
flexDirection: "row",
alignItems: "center",
flexShrink: 1,
},
image: {
width: 22,
height: 22,
marginRight: 10,
},
textRow: {
fontSize: 14,
marginRight: 5,
color: "#5C5C5C",
flexShrink: 1,
},
innerContainer: {
paddingLeft: 10,
},
badgeText: {
fontSize: 12,
},
badgeTextContainer: {
paddingHorizontal: 5,
paddingVertical: 2,
borderRadius: 5,
marginLeft: 5,
},
dotIndicator: {
borderRadius: 50,
marginLeft: 6,
},
});

export default CoreMenu;
  1. In the src/blocks/index.js file, please make sure to register the Menu component under the name appmaker/core-drawer-menu.
src/blocks/index.js
import CoreMenu from "../components/CoreMenu";

const blocks = [
{
name: "appmaker/core-drawer-menu",
View: CoreMenu,
},
];

export { blocks };
  1. The menu items you've added in the appmaker dashboard will be displayed within the drawer menu. Feel free to modify the CoreMenu component to tailor the menu items according to your specific needs.
caution

Please refrain from substituting the appmaker/core-menu block, as it is essential for displaying menu items in the appmaker dashboard. If you replace the appmaker/core-menu block, the menu items in the appmaker dashboard will no longer appear. Instead, consider replacing it with the appmaker/core-drawer-menu block if you wish to customize the menu items.

Customizing the drawer menu header

  1. Create a component in src/components folder to represent the drawer menu header.
Drawer menu header (Sample Component)
src/components/DrawerMenuHeader.js
import React from "react";
import { Pressable, StyleSheet, Text, View } from "react-native";
import Icon from "react-native-vector-icons/FontAwesome";
import { useUser } from "@appmaker-xyz/shopify";

const DrawerMenuHeader = (props) => {
const { isLoggedin, user } = useUser(props);

const firstName = user?.firstName;
const lastName = user?.lastName;
return (
<Pressable
onPress={() =>
isLoggedin
? props.onAction({ action: "OPEN_MY_ACCOUNT" })
: props.onAction({ action: "OPEN_LOGIN_PAGE" })
}
style={styles.container}
>
<Icon name="user-circle" size={24} color="#000000" style={styles.icon} />
{isLoggedin ? (
firstName || lastName ? (
<Text>
{firstName} {lastName}
</Text>
) : (
<Text>Welcome</Text>
)
) : (
<Text>Login</Text>
)}
</Pressable>
);
};

const styles = StyleSheet.create({
container: {
flexDirection: "row",
alignItems: "center",
padding: 10,
backgroundColor: "#f1f2f5",
},
icon: {
marginRight: 10,
},
});

export default DrawerMenuHeader;
info

The DrawerMenuHeader component uses the useUser hook to determine whether the user is logged in or not. If the user is logged in, the component will display the user's first name and last name. If the user is not logged in, the component will display the text "Login". Refer to the useUser hook documentation for more information.

  1. In the src/blocks/index.js file, please make sure to register the DrawerMenuHeader component under the name appmaker/drawer-menu-header.
src/blocks/index.js
import DrawerMenuHeader from "../components/DrawerMenuHeader";

const blocks = [
// other blocks
{
name: "appmaker/drawer-menu-header",
View: DrawerMenuHeader,
},
];

export { blocks };
  1. In the src/pages/DrawerMenu.js file, please make sure to add the appmaker/drawer-menu-header block to blocks array.
src/pages/DrawerMenu.js
const DrawerMenu = {
parentID: "mainmenu",
id: "mainmenu",
blocks: [
// other blocks
{
name: "appmaker/drawer-menu-header",
clientId: "drawer-menu-header",
},
],
stickyFooter: [
// other blocks
],
attributes: {},
};

export default DrawerMenu;
  1. The drawer menu header will be displayed within the drawer menu. Feel free to modify the DrawerMenuHeader component to tailor the menu items according to your specific needs.