Skip to content
shadcn.io

shadcn.io is not affiliated with official shadcn/ui

Cart Drawer Checkout Block for Ark UI

A cookware shop's cart sheet shown open: a cart pane with steppers, Remove and a subtotal, then a second pane in the same sheet for delivery, the saved card and a Pay button that adds up the total.

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

Let people pay without leaving the page they were shopping on, with this cart drawer for React with Ark UI. It opens from the Cookware page of Kiln and Kettle, a small shop for the stove and the oven: the page's header holds an outline Cart (3) Button, and the shop, six drawn pieces under a soft scrim, sits inside a hairline frame with a plus mark on each corner. The Sheet opens at the end of the page in two panes. The first is the cart: a row per item with a drawn thumbnail, a quantity stepper, a Remove that names the item and the line total, and the subtotal in the foot beside Continue, the only Shine Button. The second is quick checkout in the same sheet: two delivery choices as radio rows with their arrival days worked out from a fixed today (standard is free from $60, next day is $9.00), the saved card as an Item row, the total, a ghost Back to cart and the same Shine Button relabelled Pay $64.00. For preview the sheet is drawn open in place when the page loads; the header button opens the real Sheet, with the same panes. For shops, menus, tickets and any store with a cart that follows you.

FAQ

Why is the sheet already open, and what do I keep?

So you can see it without a click. On load the sheet is a copy drawn in place at the end of the frame: a native dialog element that isn't modal, so nothing is trapped, hidden or focused, and the page around the preview keeps working. The Cart button opens the real Sheet, modal, with its focus trap, Escape and focus return, and the copy stays closed until a reload. Both show the same CartBody and CartFoot components and share the block's state, so a quantity changed in the copy is changed in the real one. In your app keep the Sheet and drop the copy: the "in-place" state, the scrim and the dialog element inside the frame.

How do the two panes work, and where does focus go?

One state, pane, says which is showing, and the sheet's title and description follow it (Your cart, then Quick checkout). Continue moves to the second pane and focus goes to its label, "Delivery and payment"; Back to cart returns and focus goes to the cart's label. The footer keeps its height in both panes, with the same Shine Button: Continue in the first, Pay with the total in the second. Closing the sheet puts the cart pane back, so it always opens on the cart.

How are the delivery days and the total worked out?

From one fixed date, AS_OF, and each option's business days (standard four, next day one, weekends skipped), so the page reads the same on the server and in every time zone. Standard costs $4.90 under the free-delivery threshold (FREE_FROM, 6000 cents) and nothing above it, next day is $9.00 always, and the total is the subtotal plus the fee of the chosen option, all in whole cents. Change a quantity so the subtotal drops under $60 and the standard row changes to $4.90 at once.

Which side does the sheet open from?

From the end of the page's reading direction: the right in a left-to-right page and the left in a right-to-left one. The sheet's own sides are physical, so sideOf reads the page's direction when the sheet opens and passes the matching one. The copy shown on load uses logical positions, so it is already on the right side in either direction. On a phone the copy docks to the foot of the frame as a bottom sheet, and the real sheet is full width.

Is it accessible from the keyboard?

Yes. The real sheet is named by its title and described by its sentence, focus starts on the pane's label and stays inside until the sheet closes, and Escape and Close return focus to the Cart button. The steppers are groups named for their item, the delivery choices are native radios in a labelled group, and what changed is said in a polite message (the real sheet carries its own, because a modal hides the page's). The trigger is the button wrapped in SheetTrigger with asChild, and the sheet is controlled with open and onOpenChange. The copy shown on load moves no focus; Escape inside it and its close button close it and put focus on the button.

What stays local in the demo, and how do I wire it up?

Everything. The cart is typed in this file, Pay says "Paid ... in this demo. Nothing was charged" and closes the sheet while keeping the cart, and the saved card is a row of text. In your app read the cart from your store, price delivery on your server from the address, and have Pay create the order with your payment provider's saved-card token (never digits). Add an address step in front of the second pane if the shop needs one.