Skip to content
shadcn.io

shadcn.io is not affiliated with official shadcn/ui

Ecommerce Cart Skeleton Block for React

A shopping bag that loads in place: the heading, total labels and buttons stay while bars become three drawn products, options, prices and totals that add up.

Framework
UI library

Preview

Preview width

Installation

Part of Pro
Pro unlocks the code and one-line install of every Pro button and text effect, plus the MCP for your AI editor.
Have Pro already? Sign in to open it.Opens here as soon as you're Pro.

Overview

Show a shopping bag while its items load, then swap the items in without moving anything, with this ecommerce cart skeleton for React with Base UI. A hairline frame with a plus mark on each corner holds a heading row, three bag lines, the totals and a foot, all from Repousse, a hand-made-goods shop. The heading, the Subtotal, Shipping and Total labels and both buttons are real from the first paint; each line's drawn picture, name, option, quantity and price, and the three amounts, are Skeleton bars that become the data in the same cell, line by line, when you press Load. The amounts are worked out from the lines in whole cents. Checkout is the one Shine Button and pays nothing: it says so. On a phone a line's price drops under its name. It's built from Skeleton, Shine Button, Button and Guides, with a CSS entrance only. For carts, bags and baskets that wait for a query.

FAQ

What stays local, and how do I wire it to a real cart?

Nothing is fetched. The three lines are typed in LINES, Load starts a 700 millisecond timer, and when it ends the phase becomes ready and the data swaps in; Reload goes back to the bars and in again. To wire it for real, delete the timer, the Load button and the polite line, and set data-state (loading or ready) and aria-busy on the region from your query's pending state, or use the bars as a Suspense fallback and render the real data when it arrives. The bars are derived from the same data as the content, so keep one component for both. Checkout and Continue shopping only say they are not wired; connect them to your own checkout route.

How are the totals worked out?

Every amount is an integer number of cents in the typed data and is worked out from the lines in code (the subtotal sums price times quantity, and the total adds the flat shipping), so the amounts always add up and no rounding drifts. They are written only by one usd helper that turns cents into dollars for display, as $48.00. A price is one left-to-right span so it keeps its shape in right-to-left languages.

Does the bag keep its height while it loads?

Each bar and its data sit in one grid cell, so the larger of the two sets the cell's box and the swap changes nothing around it. Every line holds a picture of fixed size and three short text lines, so a line is as tall as its bars. The frame, the labels and the buttons are real in both phases, and the polite line reserves two lines, so the panel is exactly as tall before, during and after loading at every width.

Are the pictures photographs?

They are drawn: each product is a few filled shapes in an SVG on a muted ground, tinted from the foreground token so they follow light and dark mode. There are no photos. To use real pictures, replace the Art component with an <img> of the same box (keep its size classes) and keep the bar the same size.

Is it accessible?

The region is marked busy while it loads and carries a screen-reader-only "Loading your bag…", and the polite line announces what loaded once. The bars are hidden from assistive technology and the layer that isn't showing is invisible, so it is neither read nor focusable. The pulse stops when the data is in, and under reduced motion there is no pulse, no spinner and no stagger: the swap is instant. Checkout and Continue shopping stay in the page but are marked disabled while the bag loads, and a press explains why.

How does it look on a phone?

The picture keeps its size at the start and the text moves beside it; the price drops under the quantity instead of sitting at the end, and the two buttons stack with Checkout on top at full width.