A self-contained cart summary widget that displays line items, calculates subtotals, accepts promotional codes, and provides a checkout call-to-action. The widget is headless with respect to cart state management, accepting items and callbacks via props so consumers own their data layer.
Introduction
Overview
E-commerce and SaaS checkout flows need a consistent, accessible cart summary panel. This widget encapsulates the presentation of cart contents, pricing math, promo-code entry, and the primary checkout action into a single composable unit.
Goals
Provide a drop-in cart summary panel that works with any cart state manager.
Support line-item display with quantity, unit price, and line total.
Accept and validate promo codes via a consumer-supplied callback.
Render a configurable checkout CTA button.
Ship with Storybook stories covering empty, single-item, multi-item, and promo-applied states.
Non-Goals
Cart state management or persistence (consumer responsibility).
Rebuilding cart summaries per project with inconsistent accessibility and styling
Design-system consumers
No reusable cart pattern exists; teams copy-paste from checkout-form widget
End users (shoppers)
Inconsistent cart experiences across product surfaces
Definitions
Term
Definition
Line item
A single product or service entry in the cart with quantity and price
Promo code
A string token that maps to a discount applied server-side
Subtotal
Sum of all line-item totals before discount and tax
CTA
Call to action; the primary button driving the user to the next step
Current State
No dedicated cart summary widget exists. The checkout-form.tsx widget includes inline cart rendering, but it is tightly coupled to the form’s payment flow and cannot be used standalone. Teams duplicate cart display logic across projects.
Proposed Solution
Create a CartSummary widget at src/components/widgets/cart-summary.tsx that:
Accepts an array of CartLineItem objects and renders them in a list.
Computes and displays subtotal, optional discount, optional tax, and total.
Includes an inline promo-code input that calls onApplyPromo(code: string) => Promise<PromoResult>.
Renders a checkout CTA button wired to onCheckout.