Skip to main content

Footer Tab Bar with a Free Shipping Message

A Footer that shows a bottom tab bar built from the merchant's menuItems, with a slim message above it telling the shopper how much more they need to add for free shipping - visible on every page, and updated live as the cart changes.

Settings panel​

The free shipping threshold is configurable. menuItems is added automatically for footers, so it isn't declared here:

configurationSchema.json
[
{ "type": "number", "name": "freeShippingThreshold", "label": "Free shipping threshold" }
]
data.json
{
"freeShippingThreshold": 50
}

Example​

index.tsx
import React from 'react';
import { Actionable, Box, Flexbox, Icon, Text } from '@evlop/native-components';
import { CustomBlock, Money, useCart, useMenuItemsForFooterTabs } from '@evlop/shopify';
import { useSafeAreaInsets } from 'react-native-safe-area-context';

const FreeShippingFooter: CustomBlock.Footer = ({ data = {} }) => {
const { menuItemsWithActionsUpdated: menuItems } = useMenuItemsForFooterTabs(data.menuItems, { isGlobal: true });
const insets = useSafeAreaInsets();
const cart = useCart();

const threshold = Number(data.freeShippingThreshold) || 0;
const total = +(cart?.totalPrice?.amount ?? 0);
const currencyCode = cart?.totalPrice?.currencyCode ?? 'USD';
const hasItems = (cart?.lineItems?.length ?? 0) > 0;
const remaining = threshold - total;

return (
<Box bg="footer-background" style={{ paddingBottom: insets.bottom }}>
{threshold > 0 && hasItems ? (
<Box bg="primary-500" py={6} px={16}>
<Text fontSize="xs" color="gray-0" textAlign="center">
{remaining > 0 ? (
<>
Add <Money amount={remaining.toFixed(2)} currencyCode={currencyCode} /> more for free shipping
</>
) : (
'You get free shipping!'
)}
</Text>
</Box>
) : null}

<Flexbox flexDirection="row" alignItems="center" height={56}>
{menuItems.map((item) => (
<Actionable
key={item.id}
action={item.action}
pressEffect="shrink"
style={{ flex: 1, alignItems: 'center', justifyContent: 'center', height: '100%' }}
>
<Icon icon={item.icon} size={22} color="footer-tint" />
<Text fontSize="xs" color="footer-tint">{item.label}</Text>
</Actionable>
))}
</Flexbox>
</Box>
);
};

export default FreeShippingFooter;

How it works​

  • useCart() returns the live cart and re-renders the footer whenever it changes, so the message updates as soon as the shopper adds or removes something - see Reward Progress Bar Based on Live Cart State for more on useCart().
  • The message only shows when it's useful - when a threshold is set and the cart isn't empty - so the footer is just the tab bar the rest of the time.
  • <Money amount={...} currencyCode={...} /> formats the remaining amount in the cart's currency. toFixed(2) turns the computed number back into the amount string Money expects.
  • useMenuItemsForFooterTabs() wires up each tab's action for a bottom tab bar - see the Footer page. It also returns activeIndexAnimated if you want to highlight the active tab.
  • number field values are converted with Number(...) before comparing, so an empty field safely becomes 0 and hides the message.