In order for you to not re-create the entire Cart Summary component, you can reuse the native Cart Summary as a children of your custom component, because the Cart Summary component is the default content of the Cart Sidebar Totalizer slot.You can declare a {children} component directly in the HTML of your custom component.
In order to see the children feature in action let’s create the Free Shipping Progress Bar and after that make the changes to include the children component.
This tutorial assumes you are able to create a custom component and also know how to use the React Hooks available in our SDK.
1
Basic Free Shipping Progress Bar Component
Use this boilerplate as the base for your component
index.tsx
Copy
import React from "react";import { useCheckoutSession } from "@ollie-shop/sdk";import styles from "./styles.module.css";interface FreeShippingProgressProps extends React.HTMLAttributes<HTMLElement> { target?: number}const FreeShippingProgress: React.FC<FreeShippingProgressProps> = ({ target = 99}) => { const { rawSession: rawCart, updateSession } = useCheckoutSession() as { rawSession?: any; updateSession?: (...args: any[]) => any; }; // Safely extract items total value (in cents) from the raw cart const itemsTotalCents: number = (() => { const totalizers = rawCart?.totalizers; if (!Array.isArray(totalizers)) return 0; const t = totalizers.find( (x: any) => x?.id === "Items" || x?.name === "Items Total" ); return typeof t?.value === "number" ? t.value : 0; })(); // Convert cents -> currency units const currentValue = itemsTotalCents / 100; // Protect against zero or invalid target const percentage = typeof target === "number" && target > 0 ? Math.min((currentValue / target) * 100, 100) : 0; const missing = Math.max(target - currentValue, 0); const format = (value: number) => new Intl.NumberFormat("en-US", { style: "currency", currency: "USD", }).format(value); // styles might not include shippingDetailBar in your CSS module mapping, // so we cast to any when referencing it to prevent TS errors. const shippingDetailBarClass = // prefer typed property if present, otherwise fallback to empty string (styles as any).shippingDetailBar ?? ""; return ( <> <section className={styles.shippingBar}> <div className={styles.shippingBarProgress}> <div className={`${styles.shippingFill} ${shippingDetailBarClass}`} style={{ width: `${percentage}%` }} aria-valuenow={percentage} aria-valuemin={0} aria-valuemax={100} role="progressbar" /> </div> <p> {missing > 0 ? `You are ${format(missing)} away from receiving Free Shipping` : "🎉 Congratulations, you have received free shipping!"} </p> </section> </> );};export default FreeShippingProgress;
2
Declare the children type
The children is also a react component, so we must also declare it as an interface
Include the children in the HTML part of your component (as in the beginning of this tutorial)
index.tsx
Copy
...return ( <> {children} // declare your children component <section className={styles.shippingBar}> <div className={styles.shippingBarProgress}> <div className={`${styles.shippingFill} ${shippingDetailBarClass}`} style={{ width: `${percentage}%` }} aria-valuenow={percentage} aria-valuemin={0} aria-valuemax={100} role="progressbar" /> </div> <p> {missing > 0 ? `You are ${format(missing)} away from receiving Free Shipping` : "🎉 Congratulations, you have received free shipping!"} </p> </section> </> );
4
Declare which native component is the children
You must have noticed that until know we don’t actually know what is the component that is the children.When you upload your component you’ll assign the component to a Slot, the native component in this slot will become your children