Skip to main content

Cart

Headless cart component for managing shopping cart functionality with complete UI customization.

Purpose

This library provides a complete cart management system with components for displaying cart items, shipping lines, totals, and cart operations. It's designed as a headless component that provides all the logic while allowing complete UI customization. The Cart component wraps and extends the OrderLines component to provide cart-specific functionality for managing the active order.

Features

  • Complete cart state management
  • Order line display and manipulation
  • Shipping line management
  • Cart totals and summary calculations
  • Empty cart handling

Installation

npm install @haus-storefront-react/cart

Note: This is not a public package. Contact the Haus Tech Team for access.

API Reference

Cart.Root

The main container component that provides cart context and state management. Must wrap all other Cart components.

Props

PropTypeRequiredDefaultDescription
childrenChildrenProps<CartContextValue>No-Render prop or React node that receives cart context

Cart.Empty

Displays content when the cart is empty. Automatically hides when the cart has items.

PropTypeRequiredDefaultDescription
childrenReact.ReactNodeNo-Content to display when cart is empty
asChildbooleanNofalseRender as child element instead of div
...WebDivPropsNo-Additional div props (className, style, etc.)

Cart.Items

Container for cart items. Renders an OrderLines.Root component internally. Must be used within Cart.Root.

PropTypeRequiredDefaultDescription
childrenReact.ReactNodeNo-Cart item components
orderCodestringNo-Optional order code for fetching specific order
callbacks{ preAdjust?: (orderLineId: string, quantity: number) => Promise<void>; preRemove?: (lineId: string) => Promise<void> }No-Optional callbacks forwarded to OrderLines.Root

Cart.Items.Item

Individual cart item component. Wraps OrderLines.Item. Must be used within Cart.Items.Root.

PropTypeRequiredDefaultDescription
childrenReact.ReactNodeNo-Item subcomponents
orderLineOrderLineYes-The order line data to display

Cart.Items.Image

Displays the product image for the order line. Must be used within Cart.Items.Item.

PropTypeRequiredDefaultDescription
altstringNoorderLine.productVariant.nameAlt text for the image
asChildbooleanNofalseRender as child element instead of img
...ImgHTMLAttributes<HTMLImageElement>No-Additional img element props

Cart.Items.Price

Displays price information for the order line. Must be used within Cart.Items.Item.

PropTypeRequiredDefaultDescription
childrenChildrenProps<{...}>No-Render prop receiving price information
withDiscountPricebooleanNofalseWhether to show discounted price information

Cart.Items.Quantity.Root

Container for quantity controls. Must be used within Cart.Items.Item.

PropTypeRequiredDefaultDescription
childrenReact.ReactNodeNo-Quantity control subcomponents
minnumberNo0Minimum quantity
maxnumberNo-Maximum quantity
stepnumberNo1Step size for quantity changes

Subcomponents:

  • Cart.Items.Quantity.Decrement - Decrease quantity button
  • Cart.Items.Quantity.Input - Quantity input field
  • Cart.Items.Quantity.Increment - Increase quantity button

Cart.Items.Remove

Remove item button. Must be used within Cart.Items.Item.

PropTypeRequiredDefaultDescription
childrenReact.ReactNodeNo-Button content
asChildbooleanNofalseRender as child element instead of button
...ButtonHTMLAttributes<HTMLButtonElement>No-Additional button element props

Cart.ShippingLines

Container for shipping lines. Automatically hides when there are no shipping lines. Must be used within Cart.Root.

PropTypeRequiredDefaultDescription
childrenReact.ReactNodeNo-Shipping line components
asChildbooleanNofalseRender as child element instead of div
...WebDivPropsNo-Additional div props

Cart.ShippingLine

Individual shipping line component. Must be used within Cart.ShippingLines.

PropTypeRequiredDefaultDescription
shippingLineShippingLineTypeYes-The shipping line data to display
childrenReact.ReactNodeNo-Shipping line subcomponents
asChildbooleanNofalseRender as child element instead of div
...WebDivPropsNo-Additional div props

Cart.ShippingLine.Name

Displays the shipping method name. Must be used within Cart.ShippingLine.

PropTypeRequiredDefaultDescription
shippingLineIdstringYes-ID of the shipping line
asChildbooleanNofalseRender as child element instead of span
...WebSpanPropsNo-Additional span props

Note: This component automatically finds the shipping line by ID from the cart context.

Cart.ShippingLine.Price

Displays price information for the shipping line. Must be used within Cart.ShippingLine.

PropTypeRequiredDefaultDescription
childrenChildrenProps<{...}>No-Render prop receiving price information
shippingLineIdstringYes-ID of the shipping line

Cart.Summary

Cart totals and checkout summary. Automatically hides when cart is empty. Must be used within Cart.Root.

Props

PropTypeRequiredDefaultDescription
childrenChildrenProps<{...}>No-Render prop receiving summary data
asChildbooleanNofalseRender as child element instead of div
...WebDivProps (except children)No-Additional div props

Returns

PropertyTypeDescription
totalPricenumberOrder total price (without tax)
totalWithTaxnumberOrder total price (with tax)
subTotalnumberOrder subtotal (without tax)
subTotalWithTaxnumberOrder subtotal (with tax)
shippingnumberShipping cost (without tax)
shippingWithTaxnumberShipping cost (with tax)
taxSummaryOrderTaxSummary[]Array of tax summary entries
currencyCodeCurrencyCodeCurrency code for the order

useCartProps

Hook that provides cart context value. Used internally by Cart.Root.

Returns

Return ValueTypeDescription
dataOrder | nullThe current order/cart data or null
isLoadingbooleanLoading state flag
errorError | nullError object if cart loading failed
totalItemsnumberTotal number of items in cart
totalPricenumberTotal price of cart items
currencyCodeCurrencyCodeCurrency code for the cart

Basic Usage

Simple Cart Display

Loading cart...

Your cart is empty

Add some items to get started

import { Cart } from '@haus-storefront-react/cart'
import { formatPrice } from '@haus-storefront-react/common-utils'

function ShoppingCart() {
return (
<Cart.Root>
{({ isLoading, error, totalItems }) => (
<div>
{isLoading && <div>Loading cart...</div>}
{error && <div>Error: {error.message}</div>}

{totalItems > 0 ? (
<>
<Cart.Items.Root>
{({ orderLines }) =>
orderLines?.map((orderLine) => (
<Cart.Items.Item key={orderLine.id} orderLine={orderLine}>
<Cart.Items.Image />
<Cart.Items.Price />
<Cart.Items.Quantity.Root>
<Cart.Items.Quantity.Decrement />
<Cart.Items.Quantity.Input />
<Cart.Items.Quantity.Increment />
</Cart.Items.Quantity.Root>
<Cart.Items.Remove>Remove</Cart.Items.Remove>
</Cart.Items.Item>
))
}
</Cart.Items.Root>

<Cart.Summary>
{({ subTotal, subTotalWithTax, currencyCode }) => (
<div className='cart-summary'>
<div>Subtotal: {formatPrice(subTotal, currencyCode)}</div>
<div>Total: {formatPrice(subTotalWithTax, currencyCode)}</div>
<button>Checkout</button>
</div>
)}
</Cart.Summary>
</>
) : (
<Cart.Empty>
<h2>Your cart is empty</h2>
<p>Add some items to get started</p>
<button>Browse Products</button>
</Cart.Empty>
)}
</div>
)}
</Cart.Root>
)
}

Advanced Usage

Complex Cart with Custom Styling

import { Cart } from '@haus-storefront-react/cart'
import { QuantityButtons, Price } from '@haus-storefront-react/common-ui'

function CustomCart() {
return (
<Cart.Root>
{({ data: order, totalItems }) => (
<div className='cart-container'>
<h1>Shopping Cart ({totalItems} items)</h1>

{totalItems > 0 ? (
<div className='cart-content'>
<Cart.Items.Root>
{({ orderLines }) =>
orderLines?.map((orderLine) => (
<div key={orderLine.id} className='cart-item'>
<Cart.Items.Item orderLine={orderLine}>
<Cart.Items.Image className='item-image' />

<div className='item-details'>
<h3>{orderLine.productVariant.product.name}</h3>
<p>{orderLine.productVariant.name}</p>

<Cart.Items.Price asChild>
<Price.Root
price={orderLine.unitPrice}
priceWithTax={orderLine.unitPriceWithTax}
currencyCode={order.currencyCode}
className='item-price'
>
<Price.Amount />
</Price.Root>
</Cart.Items.Price>
</div>

<div className='item-controls'>
<Cart.Items.Quantity.Root asChild>
<QuantityButtons.Root
value={orderLine.quantity}
onValueChange={(qty) =>
adjustQuantity(orderLine.id, qty)
}
min={1}
max={99}
>
<QuantityButtons.Decrement className='qty-btn' />
<QuantityButtons.Input className='qty-value' />
<QuantityButtons.Increment className='qty-btn' />
</QuantityButtons.Root>
</Cart.Items.Quantity.Root>

<Cart.Items.Remove asChild>
<button className='remove-btn'>Remove</button>
</Cart.Items.Remove>
</div>
</Cart.Items.Item>
</div>
))
}
</Cart.Items.Root>

<Cart.ShippingLines className='shipping-section'>
<h3>Shipping</h3>
{order?.shippingLines.map((shippingLine) => (
<Cart.ShippingLine
key={shippingLine.id}
shippingLine={shippingLine}
>
<div className='shipping-line'>
<Cart.ShippingLine.Name
shippingLineId={shippingLine.id}
className='shipping-name'
/>
<Cart.ShippingLine.Price
shippingLineId={shippingLine.id}
asChild
>
<Price.Root
price={shippingLine.price}
priceWithTax={shippingLine.priceWithTax}
currencyCode={order.currencyCode}
className='shipping-price'
>
<Price.Amount />
</Price.Root>
</Cart.ShippingLine.Price>
</div>
</Cart.ShippingLine>
))}
</Cart.ShippingLines>

<Cart.Summary className='cart-summary'>
{({
totalPrice,
totalWithTax,
subTotal,
subTotalWithTax,
shipping,
shippingWithTax,
taxSummary,
currencyCode,
}) => (
<div className='summary-details'>
<div className='summary-line'>
<span>Subtotal:</span>
<Price.Root
price={subTotal}
priceWithTax={subTotalWithTax}
currencyCode={currencyCode}
>
<Price.Amount />
</Price.Root>
</div>

{shipping > 0 && (
<div className='summary-line'>
<span>Shipping:</span>
<Price.Root
price={shipping}
priceWithTax={shippingWithTax}
currencyCode={currencyCode}
>
<Price.Amount />
</Price.Root>
</div>
)}

{taxSummary.length > 0 && (
<div className='tax-summary'>
{taxSummary.map((tax, index) => (
<div key={index} className='summary-line'>
<span>{tax.description}:</span>
<Price.Root
price={tax.taxTotal}
priceWithTax={tax.taxTotal}
currencyCode={currencyCode}
>
<Price.Amount />
</Price.Root>
</div>
))}
</div>
)}

<div className='summary-line total'>
<span>Total:</span>
<Price.Root
price={totalPrice}
priceWithTax={totalWithTax}
currencyCode={currencyCode}
>
<Price.Amount />
</Price.Root>
</div>

<button className='checkout-btn'>
Proceed to Checkout
</button>
</div>
)}
</Cart.Summary>
</div>
) : (
<Cart.Empty className='empty-cart'>
<div className='empty-content'>
<h2>Your cart is empty</h2>
<p>Looks like you haven't added any items to your cart yet.</p>
<button className='browse-btn'>Browse Products</button>
</div>
</Cart.Empty>
)}
</div>
)}
</Cart.Root>
)
}

Conditional Rendering Patterns

import { Cart } from '@haus-storefront-react/cart'
import { formatPrice } from '@haus-storefront-react/common-utils'

function ConditionalCart() {
return (
<Cart.Root>
{({ data: order, isLoading, totalItems }) => {
if (isLoading) {
return <div className='loading'>Loading cart...</div>
}

if (!order || totalItems === 0) {
return (
<Cart.Empty>
<h2>Your cart is empty</h2>
<button>Start Shopping</button>
</Cart.Empty>
)
}

return (
<div className='cart-full'>
<Cart.Items.Root>
{({ orderLines }) =>
orderLines?.map((orderLine) => (
<Cart.Items.Item key={orderLine.id} orderLine={orderLine}>
<Cart.Items.Image />
<div>
<h3>{orderLine.productVariant.product.name}</h3>
<Cart.Items.Price />
</div>
<Cart.Items.Quantity.Root>
<Cart.Items.Quantity.Decrement />
<Cart.Items.Quantity.Input />
<Cart.Items.Quantity.Increment />
</Cart.Items.Quantity.Root>
<Cart.Items.Remove>Remove</Cart.Items.Remove>
</Cart.Items.Item>
))
}
</Cart.Items.Root>

<Cart.Summary>
{({ totalWithTax, currencyCode }) => (
<div className='checkout-section'>
<div>Total: {formatPrice(totalWithTax, currencyCode)}</div>
<button>Checkout</button>
</div>
)}
</Cart.Summary>
</div>
)
}}
</Cart.Root>
)
}

Made with ❤️ by Haus Tech Team