Skip to content
shadcn.io

shadcn.io is not affiliated with official shadcn/ui

Expired Holds Empty Cart Error Block for React

A cart page that is empty because its 30-minute hold ran out: the two released items, one still in stock and one sold out, with Add back, Tell me when it is back, a subtotal and a bar to free delivery.

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

Say why a cart is empty instead of leaving a visitor with a bare basket, with this expired holds cart page for React with Base UI. It's the screen of Teaspoon & Tin, a tea shop: a whole page with the page's rails and one band across it, split in two by a hairline drawn with Guides. At the start, the heading ("Your cart is empty"), one sentence saying that the 30-minute hold on two items ended at 14:30 UTC, what the cart holds now (items and subtotal, worked out in whole cents) and a Progress bar to the $25.00 free-delivery line. At the end, in a framed list, the two items the hold released: a drawn tin that is still in stock with an outline Button, Add back, and a tin that is sold out with Tell me when it is back. Adding the first one back turns the heading into "Your cart has 1 item", moves the subtotal and the bar, and the one Shine Button, a link, changes from Continue shopping to Check out; Put back takes it out again. It's built from Progress, Button, Shine Button and Guides, with a CSS entrance only. For shops that hold stock for a few minutes while someone checks out.

FAQ

How are the items and totals worked out?

From the typed HELD list: each item has a price in whole cents, a stock count (0 is sold out) and a name. The subtotal, the item count, the amount to free delivery, the width of the bar and the label of the main button are all computed from the items in the cart, so the words and the bar agree. The hold itself (30 minutes, ended at 14:30 UTC) is typed text. Change HELD, FREE_DELIVERY and the hold times to your own.

What stays in the page, and how do I wire it?

All of it. Add back and Put back change this page's cart and say so in a polite status line; Tell me when it is back records a watch in the page and says plainly that this demo sends nothing. Replace the handlers where the code says so: put the item back in the cart through your shop's API (and check the stock again on the server, since a hold can fail), and add the visitor's address to a back-in-stock list.

Why can the sold-out item not be added back?

Because there is nothing to add: it sold out while the hold was over. The honest action is a notification, so its button offers Tell me when it is back and toggles to Stop watching. The row says Sold out in words with an icon, never only a color.

Why does the main button change its label?

The page has one main action, and it depends on the cart: with an empty cart it is Continue shopping, with something in it it is Check out. It is the same link in the same place, so focus never moves; it points to # here, so point it at your shop and your checkout. It's a Shine Button with render set to an a element and nativeButton={false}.

Does the page move when the cart changes?

No. Every changing sentence (the heading's sentence, each item's stock line and each button label) is drawn over an unseen copy of the other state in the same cell, so the longer of the two sets the size. Rows, bar and buttons keep their places.

How does it look on a phone?

The message, the two facts, the bar and the main button come first and end on the first screen; the list of released items follows under them, each button full width under its item. The mark tile is hidden on a phone to save room.

  • Pro

    A wishlist page that is empty because everything saved on it was discontinued: three struck items with their end dates, a button for a close match on each, and Save it to keep one.

  • Pro

    Seats Full Error

    Plans and checkout

    A panel for an invite that can't go out because every seat is taken: six seat cells, two inactive members to remove, and one button that reads Add seats until a seat is free and then Send the invite.

  • Pro

    A panel for a vault that is over its storage: one bar on a fixed axis with the trash and a hatched overshoot, a table whose states are worked out from the numbers, and a Shine Button that empties the trash and redraws everything.

  • Pro

    A results panel for filters that match nothing: three toggle chips over 24 kits, a table of how many kits each pair of filters shares, the empty pair ringed, and a chip off to bring results back.

  • Pro

    A team inbox that is empty because an account is not synced: two accounts with state, last-checked time, a sync switch and Sync now, a dashed tray that becomes three messages, and one button to sync all.

  • Pro

    A project tracker window whose current workspace has no projects: a sidebar of workspaces with counts, radio rows for the other workspaces, a Switch button that follows the choice, and the projects once you switch.