shadcn.io is not affiliated with official shadcn/ui
Add to Cart Dialog Block for React
A stool shop's product page with its add-to-cart dialog shown open: two heights that redraw the stool and move the price, three finishes with a sentence each, a quantity that stops at the stock left, and a total that follows the choices.
Installation
Overview
Let a shopper settle the details before the cart, with this add-to-cart dialog for React with Base UI. It opens from the Linnet stool's page at Stoolwright, a workshop that turns oak stools by hand: the header holds an outline Add to cart Button, and the shop itself is drawn under a soft scrim inside a hairline frame with a plus mark on each corner, a cart chip at its top end. The dialog is a split. At the start the stools are drawn at their two heights with the chosen one in full strength. At the end a Toggle Group picks Counter or Bar, a Radio Group picks Oiled, Waxed or Raw with a sentence and a price change under each, and a Number Input sets the quantity, which stops politely at what is in stock. The total beside it is quantity times unit price and moves with every choice. Add to cart, the only Shine Button, raises the cart chip's count and closes. For preview the dialog is drawn open in place when the page loads; the header button opens the real Dialog, with the same fields and the same choices. For shops, quick-view modals and any product with variants and limited stock.
FAQ
Why is the dialog already open, and what do I keep?
So you can see it without a click. On load the dialog is a copy drawn in place over the shop: a native dialog element that isn't modal, so nothing is trapped, hidden or focused, and the page around the preview keeps working. The Add to cart button in the header opens the real Dialog, modal, with its focus trap, Escape and focus return, and the copy stays closed until a reload. Both show the same CartFields component and share the block's state, so a height picked in the copy is there in the real one. In your app keep the Dialog and drop the copy: the "in-place" state, the scrim and the dialog element inside the frame.
How do the choices change the price?
HEIGHTS holds each height's price and stock, and FINISHES holds what each finish adds or takes off, so the unit price is the height's price plus the finish's change, and the total is the quantity times that. The stool at the start of the dialog redraws from the same height, and the finish rows show their change in dollars next to their name, so the number never surprises. Prices are whole dollars formatted with Intl.NumberFormat; swap in the currency and cents your shop uses.
What happens when someone asks for more than is in stock?
The quantity is kept between 1 and the stock of the chosen height, and the line under the field says so in words ("Only 2 in stock. That is the most you can add.") whether the number was typed or stepped to the limit. The total always uses the kept number, and switching to a height with less stock pulls the quantity down with it. The line is a hint linked to the field, two lines high, so it never moves the total. In your app read the stock when the dialog opens and say if it changed before the order is placed.
What does Add to cart do, and how do I wire it up?
Here it adds the quantity to the cart chip's count in local state, closes the dialog, and says in a polite status message what was added and that nothing was ordered in this demo. No request goes out and nothing is stored. In your app send the height, finish and quantity to your cart in add, update the cart from the response, and if the server refuses because the stock changed, show its reason in the stock line and keep the dialog open.
Is it accessible from the keyboard?
Yes. The real dialog is named by its title and described by its sentence, focus starts on the height choices and stays inside until it closes, and Escape, Cancel and the close button all return focus to Add to cart. The height is a labelled group of two toggles, the finish a labelled radio group read as one question with a sentence per option, and the quantity a labelled number field with the stock line as its description. The trigger is passed to DialogTrigger through render, and the dialog is controlled with open and onOpenChange. The copy shown on load moves no focus; Escape inside it, Cancel and its close button close it and put focus on Add to cart.
How does it look on a phone?
The copy shown on load docks to the foot of the page as a bottom sheet, its actions pinned at the bottom with Add to cart on top, and the fields scroll above them. The stools shrink to a short strip over the fields instead of a column beside them. The real dialog keeps the Dialog's own phone layout: a sheet stuck to the bottom of the screen.
Related
- Pro
A hardware shop's quantity dialog shown open: a number field with a button on each side over a four-tier price ladder that follows it, a hint to the next tier and totals worked out in whole cents.
- Pro
Apply Coupon Dialog
Payments and plansA cookware shop's basket with its promo-code dialog shown open: one field that judges five typed codes with five different answers, applied codes kept as removable chips, and a summary that is worked out again after every change.
- Pro
Add Card Dialog
Payments and plansA transit wallet's payment methods page with its add-card dialog shown open: a card drawn in greys that fills in as you type, a number that groups itself and names its network, checks on the number, expiry and code, and an Add card button that keeps only the last four digits.
- Pro
Guest Checkout Dialog
Payments and plansA cart with its identify-step dialog shown open: Guest, Sign in and Create account swap the fields under a segmented control, one button names the mode, and the cart's stepper moves on to Shipping once you continue.
- Pro
A homeware shop's shipping dialog shown open: four delivery methods with arrival dates counted in business days from a fixed order date, prices in whole cents, a free-shipping bar and a button that names the choice.
- Pro
Billing Address Dialog
Payments and plansAn invoice page with its billing-address dialog shown open: the form relabels, reorders and revalidates for the United States, the United Kingdom, Germany and Japan, a switch fills the company's address, and the address is printed the way an envelope would carry it.