From bd18d747175491ecd65d134ced65654a9ceecd8a Mon Sep 17 00:00:00 2001
From: Alessandro Casazza
Date: Fri, 22 May 2026 15:57:09 +0200
Subject: [PATCH 01/10] =?UTF-8?q?=E2=9C=A8=20feat(stories):=20add=20Hosted?=
=?UTF-8?q?Cart=20stories=20in=20document=20package?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Add DocsPage with ArgTypes, Source and 4 Canvas stories:
- Default (inline cart iframe)
- MiniCart (slide-in panel with open control)
- MiniCartOpenAdd (auto-opens on AddToCartButton)
- CustomDomain
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---
.../src/stories/cart/HostedCart.stories.tsx | 227 ++++++++++++++++++
1 file changed, 227 insertions(+)
create mode 100644 packages/document/src/stories/cart/HostedCart.stories.tsx
diff --git a/packages/document/src/stories/cart/HostedCart.stories.tsx b/packages/document/src/stories/cart/HostedCart.stories.tsx
new file mode 100644
index 00000000..996cab60
--- /dev/null
+++ b/packages/document/src/stories/cart/HostedCart.stories.tsx
@@ -0,0 +1,227 @@
+import { HostedCart, Order } from "@commercelayer/react-components"
+import { ArgTypes, Canvas, Source } from "@storybook/addon-docs/blocks"
+import type { Meta, StoryObj } from "@storybook/react-vite"
+import CommerceLayer from "../_internals/CommerceLayer"
+import {
+ AddSampleItems,
+ OrderStorage as OrderStorageHelper,
+} from "../_internals/OrderStorage"
+
+function HostedCartDocsPage(): JSX.Element {
+ return (
+ <>
+
HostedCart
+
+ {""} embeds the Commerce Layer hosted cart
+ micro-frontend as an {" inside your page. It
+ automatically resolves the cart URL from the access token and the current
+ order.
+
+
+ By default it renders as an inline cart — the iframe
+ fills the available container width while the height adjusts to its
+ content. Set type="mini" to switch to a{" "}
+ slide-in mini cart panel.
+
+
+
+ Must be a child of {""} (wrapped in{" "}
+ {""}). Requires a parent{" "}
+ {""} context for the access token.
+
+ Renders as an inline {" that fills the container
+ width. The height adjusts automatically to the cart content via{" "}
+ iframe-resizer.
+
+
+
+
Mini cart
+
+ Set type="mini" to render a fixed slide-in panel. Use the{" "}
+ open prop to control visibility and{" "}
+ handleOpen to toggle it from outside. Toggle{" "}
+ open in the Controls panel below to preview.
+
+
+
+
Mini cart — auto-open on add to cart
+
+ Set openAdd to true (requires{" "}
+ type="mini") so the panel opens automatically whenever an
+ item is added via {""}.
+
+
+
+
Custom domain
+
+ Use customDomain to point to a forked cart application
+ instead of the default Commerce Layer hosted micro-frontend.
+
+
+ >
+ )
+}
+
+const meta = {
+ title: "Components/Cart/HostedCart",
+ component: HostedCart,
+ parameters: {
+ docs: {
+ page: HostedCartDocsPage,
+ },
+ },
+ argTypes: {
+ type: {
+ control: "select",
+ options: [undefined, "mini"],
+ description:
+ 'Rendering mode. Leave `undefined` for an inline cart iframe, or set to `"mini"` for a fixed slide-in panel.',
+ },
+ open: {
+ control: "boolean",
+ description:
+ "Controls whether the mini cart panel is open. Only applies when `type=\"mini\"`.",
+ },
+ openAdd: {
+ control: "boolean",
+ description:
+ 'Automatically opens the mini cart when an item is added via ``. Only applies when `type="mini"`.',
+ },
+ handleOpen: {
+ control: false,
+ description:
+ 'Callback fired when the background overlay or close icon is clicked. Use this to sync `open` state from outside. Only applies when `type="mini"`.',
+ },
+ customDomain: {
+ control: "text",
+ description:
+ "Domain of a forked cart application. Overrides the default `.commercelayer.app` hostname.",
+ },
+ style: {
+ control: "object",
+ description:
+ "Style overrides for each part of the component. Accepts an object with keys `cart`, `container`, `background`, `icon`, and `iconContainer` — each a `CSSProperties` object.",
+ },
+ },
+} satisfies Meta
+
+export default meta
+type Story = StoryObj
+
+function Wrapper({ children }: { children: React.ReactNode }) {
+ return (
+
+
+ {children}
+
+
+ )
+}
+
+/**
+ * The default inline cart renders an `
-
Mini cart
-
- Set type="mini" to render a fixed slide-in panel. Use the{" "}
- open prop to control visibility and{" "}
- handleOpen to toggle it from outside. Toggle{" "}
- open in the Controls panel below to preview.
-
-
-
-
Mini cart — auto-open on add to cart
-
- Set openAdd to true (requires{" "}
- type="mini") so the panel opens automatically whenever an
- item is added via {""}.
-
-
-
Custom domain
Use customDomain to point to a forked cart application
@@ -106,27 +76,6 @@ const meta = {
},
},
argTypes: {
- type: {
- control: "select",
- options: [undefined, "mini"],
- description:
- 'Rendering mode. Leave `undefined` for an inline cart iframe, or set to `"mini"` for a fixed slide-in panel.',
- },
- open: {
- control: "boolean",
- description:
- "Controls whether the mini cart panel is open. Only applies when `type=\"mini\"`.",
- },
- openAdd: {
- control: "boolean",
- description:
- 'Automatically opens the mini cart when an item is added via ``. Only applies when `type="mini"`.',
- },
- handleOpen: {
- control: false,
- description:
- 'Callback fired when the background overlay or close icon is clicked. Use this to sync `open` state from outside. Only applies when `type="mini"`.',
- },
customDomain: {
control: "text",
description:
@@ -167,49 +116,6 @@ export const Default: Story = {
),
}
-/**
- * Set `type="mini"` to render a fixed slide-in panel. Toggle the `open` control
- * to preview the open and closed states. In a real app, bind `open` and
- * `handleOpen` to local state:
- *
- * ```tsx
- * const [isOpen, setIsOpen] = useState(false)
- * setIsOpen(o => !o)} />
- * ```
- */
-export const MiniCart: Story = {
- name: "Mini cart",
- args: {
- type: "mini",
- open: false,
- },
- render: (args) => (
-
-
-
- ),
-}
-
-/**
- * When `openAdd` is `true` the mini cart panel opens automatically after an
- * item is successfully added to the order via ``. Click the
- * button below to trigger the flow.
- */
-export const MiniCartOpenAdd: Story = {
- name: "Mini cart — auto-open on add",
- args: {
- type: "mini",
- openAdd: true,
- open: false,
- },
- render: (args) => (
-
-
-
-
- ),
-}
-
/**
* Pass `customDomain` to load a self-hosted or forked cart application
* instead of the default Commerce Layer hosted micro-frontend.
diff --git a/packages/document/src/stories/cart/MiniCart.stories.tsx b/packages/document/src/stories/cart/MiniCart.stories.tsx
new file mode 100644
index 00000000..55cb232f
--- /dev/null
+++ b/packages/document/src/stories/cart/MiniCart.stories.tsx
@@ -0,0 +1,172 @@
+import { HostedCart, Order } from "@commercelayer/react-components"
+import { ArgTypes, Canvas, Source } from "@storybook/addon-docs/blocks"
+import type { Meta, StoryObj } from "@storybook/react-vite"
+import CommerceLayer from "../_internals/CommerceLayer"
+import {
+ AddSampleItems,
+ OrderStorage as OrderStorageHelper,
+} from "../_internals/OrderStorage"
+
+function MiniCartDocsPage(): JSX.Element {
+ return (
+ <>
+
MiniCart
+
+ The mini cart is {""} — a fixed
+ slide-in panel that overlays the page from the right side. It loads the
+ same Commerce Layer hosted cart micro-frontend as the inline variant, but
+ in a drawer controlled by the open prop.
+
+
+
+ Must be a child of {""} (wrapped in{" "}
+ {""}). Pair it with a{" "}
+ {""} or your own trigger button
+ to manage the open state.
+
+ Toggle the open control in the Controls panel to preview
+ the open and closed states. In a real app bind open and{" "}
+ handleOpen to local state.
+
+
+
+
Auto-open on add to cart
+
+ Set openAdd to true so the panel opens
+ automatically whenever an item is added via{" "}
+ {""}. Click the button below to trigger
+ the flow.
+
+
+ >
+ )
+}
+
+const meta = {
+ title: "Components/Cart/MiniCart",
+ component: HostedCart,
+ parameters: {
+ docs: {
+ page: MiniCartDocsPage,
+ },
+ },
+ argTypes: {
+ open: {
+ control: "boolean",
+ description: "Controls whether the mini cart panel is open.",
+ },
+ openAdd: {
+ control: "boolean",
+ description:
+ 'Automatically opens the panel when an item is added via ``.',
+ },
+ handleOpen: {
+ control: false,
+ description:
+ "Callback fired when the background overlay or close icon is clicked. Use this to toggle `open` from outside.",
+ },
+ customDomain: {
+ control: "text",
+ description:
+ "Domain of a forked cart application. Overrides the default `.commercelayer.app` hostname.",
+ },
+ style: {
+ control: "object",
+ description:
+ "Style overrides for the panel parts: `cart`, `container`, `background`, `icon`, `iconContainer` — each a `CSSProperties` object.",
+ },
+ },
+} satisfies Meta
+
+export default meta
+type Story = StoryObj
+
+function Wrapper({ children }: { children: React.ReactNode }) {
+ return (
+
+
+ {children}
+
+
+ )
+}
+
+/**
+ * Set `type="mini"` to render a fixed slide-in panel. Toggle the `open` control
+ * to preview the open and closed states. In a real app, bind `open` and
+ * `handleOpen` to local state:
+ *
+ * ```tsx
+ * const [isOpen, setIsOpen] = useState(false)
+ * setIsOpen(o => !o)} />
+ * ```
+ */
+export const Default: Story = {
+ name: "Mini cart",
+ args: {
+ type: "mini",
+ open: false,
+ },
+ render: (args) => (
+
+
+
+ ),
+}
+
+/**
+ * When `openAdd` is `true` the mini cart panel opens automatically after an
+ * item is successfully added to the order via ``. Click the
+ * button below to trigger the flow.
+ */
+export const OpenOnAdd: Story = {
+ name: "Auto-open on add to cart",
+ args: {
+ type: "mini",
+ openAdd: true,
+ open: false,
+ },
+ render: (args) => (
+
+
+
+
+ ),
+}
From 54f3173dafeba331e4473f5d5ac3e358e487202a Mon Sep 17 00:00:00 2001
From: Alessandro Casazza
Date: Fri, 22 May 2026 16:35:51 +0200
Subject: [PATCH 04/10] =?UTF-8?q?=F0=9F=90=9B=20fix(stories):=20fix=20Mini?=
=?UTF-8?q?Cart=20stories=20=E2=80=94=20wire=20open=20state,=20use=20CartL?=
=?UTF-8?q?ink=20+=20AddToCartButton?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- Default story: use local useState + CartLink type='mini' as trigger,
wire handleOpen to toggle state so overlay/close button work correctly
- OpenOnAdd story: replace AddSampleItems (SDK only) with AddToCartButton
which publishes the 'open-cart' event that HostedCart openAdd listens for
- Fix DocsPage: add Canvas for both stories, mark open argType as control:false
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---
.../src/stories/cart/MiniCart.stories.tsx | 94 ++++++++++---------
1 file changed, 51 insertions(+), 43 deletions(-)
diff --git a/packages/document/src/stories/cart/MiniCart.stories.tsx b/packages/document/src/stories/cart/MiniCart.stories.tsx
index 55cb232f..a053faa4 100644
--- a/packages/document/src/stories/cart/MiniCart.stories.tsx
+++ b/packages/document/src/stories/cart/MiniCart.stories.tsx
@@ -1,28 +1,30 @@
-import { HostedCart, Order } from "@commercelayer/react-components"
+import {
+ AddToCartButton,
+ CartLink,
+ HostedCart,
+ Order,
+} from "@commercelayer/react-components"
import { ArgTypes, Canvas, Source } from "@storybook/addon-docs/blocks"
import type { Meta, StoryObj } from "@storybook/react-vite"
+import { useState, type JSX } from "react"
import CommerceLayer from "../_internals/CommerceLayer"
-import {
- AddSampleItems,
- OrderStorage as OrderStorageHelper,
-} from "../_internals/OrderStorage"
+import { OrderStorage as OrderStorageHelper } from "../_internals/OrderStorage"
function MiniCartDocsPage(): JSX.Element {
return (
<>
MiniCart
- The mini cart is {""} — a fixed
- slide-in panel that overlays the page from the right side. It loads the
- same Commerce Layer hosted cart micro-frontend as the inline variant, but
- in a drawer controlled by the open prop.
+ The mini cart is {''} — a fixed slide-in panel that
+ overlays the page from the right side. It loads the same Commerce Layer hosted cart
+ micro-frontend as the inline variant, but in a drawer controlled by the open{" "}
+ prop.
- Must be a child of {""} (wrapped in{" "}
- {""}). Pair it with a{" "}
- {""} or your own trigger button
- to manage the open state.
+ Must be a child of {""} (wrapped in {""}).
+ Pair it with a {''} or your own trigger button to
+ manage the open state.
@@ -61,18 +63,18 @@ function App() {
Mini cart
- Toggle the open control in the Controls panel to preview
- the open and closed states. In a real app bind open and{" "}
- handleOpen to local state.
+ Click the button to open the slide-in panel. The{" "}
+ handleOpen callback keeps external state in sync when the
+ overlay or close icon is clicked inside the cart.
Auto-open on add to cart
Set openAdd to true so the panel opens
- automatically whenever an item is added via{" "}
- {""}. Click the button below to trigger
- the flow.
+ automatically after {""} successfully adds
+ an item to the order. Click Add to cart below to
+ trigger the flow.
>
@@ -89,13 +91,12 @@ const meta = {
},
argTypes: {
open: {
- control: "boolean",
+ control: false,
description: "Controls whether the mini cart panel is open.",
},
openAdd: {
control: "boolean",
- description:
- 'Automatically opens the panel when an item is added via ``.',
+ description: "Automatically opens the panel when an item is added via ``.",
},
handleOpen: {
control: false,
@@ -129,43 +130,50 @@ function Wrapper({ children }: { children: React.ReactNode }) {
}
/**
- * Set `type="mini"` to render a fixed slide-in panel. Toggle the `open` control
- * to preview the open and closed states. In a real app, bind `open` and
- * `handleOpen` to local state:
- *
- * ```tsx
- * const [isOpen, setIsOpen] = useState(false)
- * setIsOpen(o => !o)} />
- * ```
+ * Controlled mini cart: `open` and `handleOpen` are wired to local state so the
+ * panel can be opened with the button and closed by clicking the overlay or the
+ * close icon inside the cart iframe.
*/
export const Default: Story = {
name: "Mini cart",
- args: {
- type: "mini",
- open: false,
+ render: () => {
+ const [isOpen, setIsOpen] = useState(false)
+ return (
+
+
+ setIsOpen((o) => !o)}
+ />
+
+ )
},
- render: (args) => (
-
-
-
- ),
}
/**
- * When `openAdd` is `true` the mini cart panel opens automatically after an
- * item is successfully added to the order via ``. Click the
- * button below to trigger the flow.
+ * When `openAdd` is `true` the panel opens automatically after
+ * `` successfully adds an item. The `"open-cart"` event is
+ * published internally by `AddToCartButton` on success.
*/
export const OpenOnAdd: Story = {
name: "Auto-open on add to cart",
args: {
type: "mini",
openAdd: true,
- open: false,
},
render: (args) => (
-
+
),
From 4cf455cce2e919d5483e0b772515938be0a803e1 Mon Sep 17 00:00:00 2001
From: Alessandro Casazza
Date: Fri, 22 May 2026 16:37:47 +0200
Subject: [PATCH 05/10] =?UTF-8?q?=E2=9C=A8=20feat(stories):=20add=20min-he?=
=?UTF-8?q?ight=20decorator=20to=20MiniCart=20stories=20canvas?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The mini cart panel is position:fixed so it doesn't affect document flow.
A 500px min-height decorator ensures the canvas always has visible space
regardless of whether the panel is open or closed.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---
packages/document/src/stories/cart/MiniCart.stories.tsx | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/packages/document/src/stories/cart/MiniCart.stories.tsx b/packages/document/src/stories/cart/MiniCart.stories.tsx
index a053faa4..f366a26b 100644
--- a/packages/document/src/stories/cart/MiniCart.stories.tsx
+++ b/packages/document/src/stories/cart/MiniCart.stories.tsx
@@ -84,6 +84,13 @@ function App() {
const meta = {
title: "Components/Cart/MiniCart",
component: HostedCart,
+ decorators: [
+ (Story) => (
+
+
+
+ ),
+ ],
parameters: {
docs: {
page: MiniCartDocsPage,
From 1f271c90a8372db2c0c20f8c5da4208b8b553683 Mon Sep 17 00:00:00 2001
From: Alessandro Casazza
Date: Fri, 22 May 2026 16:44:14 +0200
Subject: [PATCH 06/10] =?UTF-8?q?=E2=9C=A8=20feat(stories):=20add=20CartLi?=
=?UTF-8?q?nk=20story=20in=20document=20cart=20folder?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
DocsPage with ArgTypes, Source and 3 Canvas stories:
- Default (link to hosted cart)
- MiniCartTrigger (type='mini' + HostedCart integration with open state)
- ChildrenProps (render prop with custom trigger)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---
.../src/stories/cart/CartLink.stories.tsx | 190 ++++++++++++++++++
1 file changed, 190 insertions(+)
create mode 100644 packages/document/src/stories/cart/CartLink.stories.tsx
diff --git a/packages/document/src/stories/cart/CartLink.stories.tsx b/packages/document/src/stories/cart/CartLink.stories.tsx
new file mode 100644
index 00000000..840c1f17
--- /dev/null
+++ b/packages/document/src/stories/cart/CartLink.stories.tsx
@@ -0,0 +1,190 @@
+import { CartLink, HostedCart, Order } from "@commercelayer/react-components"
+import { ArgTypes, Canvas, Source } from "@storybook/addon-docs/blocks"
+import type { Meta, StoryObj } from "@storybook/react-vite"
+import { useState, type JSX } from "react"
+import CommerceLayer from "../_internals/CommerceLayer"
+import { OrderStorage as OrderStorageHelper } from "../_internals/OrderStorage"
+
+function CartLinkDocsPage(): JSX.Element {
+ return (
+ <>
+
CartLink
+
+ {""} generates a link to the Commerce Layer hosted cart
+ micro-frontend. Clicking it navigates the customer to their cart, or — when{" "}
+ type="mini" is set — opens the{" "}
+ {""} slide-in panel instead.
+
+
+
+ Must be a child of {""} (wrapped in{" "}
+ {""}). Requires a parent{" "}
+ {""} context for the access token.
+
+
+
+
+
+
+
+
+
+
+`}
+ />
+
+
Default — link to hosted cart
+
+ Renders an {""} tag that navigates to the Commerce Layer hosted cart
+ application when clicked.
+
+
+
+
Mini cart trigger
+
+ Set type="mini" to publish the "open-cart" event on click
+ instead of navigating. Place a {''} on the same page
+ to receive the event and open the slide-in panel.
+
+
+
+
Children render prop
+
+ Pass a function as children to take full control of the rendered trigger. The
+ render prop receives href, handleClick, orderId, and{" "}
+ accessToken.
+