Cart
Add to bag button, bag icon with a live count and a cart drawer or page. Handles optimistic quantities with rollback, undo on remove and free shipping progress.
Cart is the add-to-bag flow of a store: AddToCartButton on the product page, CartTrigger in the header, and CartDrawer, which slides in from the right on desktop and up from the bottom on phones. CartPanel shows the same cart as a full page.
Every change applies at once. Pressing plus updates the quantity, line total and subtotal straight away, and the request runs behind it. Quick presses are merged into one request for the final quantity. If your callback throws, the line goes back to the last confirmed quantity and shows your message, such as “Only 2 left in Sand / Large”. The same logic is exported as useOptimisticCart for your own layouts.
Removing a line collapses it into a “Removed Ring Vase · Undo” row for five seconds, and the lines below slide up. Undo puts the line back where it was. Lines can also show that their price changed since they were added, or that they sold out, which blocks checkout until they are removed.
The free shipping bar shows how much is left to spend and plays one short moment when the threshold is crossed. AddToCartButton keeps its width while it moves from the label to a spinner (only after 300ms) to a drawn check, and the bag badge rolls only the digit that changed.
HextaUI Pro'yu alın
Tek bir ödeme, gelecekte eklenecekler dahil tüm blokların kilidini açar. Fiyatları görün.
Pro registry'yi components.json dosyasına ekleyin
components.json Token'ınızı ekleyin
Hesap sayfanızda bir token oluşturun ve
.env.localdosyasınaHEXTAUI_PRO_TOKENolarak ekleyin.Bloğu ekleyin
pnpm dlx shadcn@latest add @hextaui-pro/cart
Shopify Storefront API
Map the Storefront cart to Cart and call cartLinesUpdate, cartLinesRemove and cartLinesAdd from the callbacks. A userErrors message is thrown, so it shows under the line and the quantity rolls back.
Next.js server actions
Pass server actions straight to the callbacks and keep the returned cart in state. The bag button in the header and the add button on the product page share that state.
Full cart page
CartPanel lays the same lines out as a page with a sticky summary, for stores where the bag icon links to /cart instead of opening a drawer.
Yapı
Dıştan içe doğru birleştirdiğiniz parçalar.
| Parça | Açıklama |
|---|---|
AddToCartButton | The add button with its pending, added and error states. |
CartTrigger | The bag icon button with a rolling count badge. |
CartDrawer | The cart in a sheet: free shipping, lines, recommendations and summary. |
CartPanel | The same cart laid out as a page with a sticky summary. |
QuantityStepper | Minus, typed quantity and plus. Minus turns into remove at one. |
FreeShippingProgress | The amount left to free shipping and its progress bar. |
useOptimisticCart | Optimistic quantities, rollback, removal with undo and announcements, without the UI. |
lineFromVariant, setLineQuantity, removeLine, restoreLine, getCartCost | Cart helpers shared with the checkout blocks. |
| Prop | Tür | Varsayılan |
|---|---|---|
cartThe cart from your server. Lines, prices and discounts as Money. | Cart | – |
onUpdateLineCalled after a stepper change. The new quantity shows at once; throw to roll it back with your message under the line. Rapid changes are coalesced to the latest quantity. | (lineId: string, quantity: number) => Promise<Cart | void> | – |
onRemoveLineCalled when a line is removed. The line collapses at once and comes back with an error if this throws. | (lineId: string) => Promise<Cart | void> | – |
onUndoRemoveRe-adds a removed line. When set, a removed line leaves a “Removed · Undo” row for undoTimeout. | (line: CartLine, index: number) => Promise<Cart | void> | – |
onAddLineAdds a recommended product. Its line appears at once as pending. | (line: CartLine) => Promise<Cart | void> | – |
onCheckoutCalled by Checkout after every pending change has synced. The button shows a spinner while it runs. | (cart: Cart) => unknown | – |
onContinueShoppingCalled by Continue shopping. The drawer also closes. | () => void | – |
freeShippingThresholdShows the free shipping bar and the amount left to reach it. | Money | null | – |
recommendationsProducts for the empty state and the “You might also like” row. Items already in the cart are hidden. | CartRecommendation[] | – |
upsellsShow the recommendation row when the cart has items. | boolean | true |
undoTimeoutHow long the undo row stays, in ms. Hovering or focusing it pauses the timer. | number | 5000 |
localeLocale for money and numbers. | Intl.LocalesArgument | "en-US" |
trailingZerosSet false to show $38 instead of $38.00 for whole amounts. | boolean | true |
labelsEvery user-facing string, including announcements. | Partial<CartLabels> | – |
openControlled open state. | boolean | – |
defaultOpenInitial open state when uncontrolled. | boolean | false |
onOpenChangeCalled when the drawer opens or closes. | (open: boolean) => void | – |
triggerAn element that opens the drawer, usually CartTrigger. Focus returns to it on close. | React.ReactElement | – |
sideWhere the drawer comes from. auto uses the bottom on screens under 640px. | "auto" | "right" | "bottom" | "auto" |
CartPanel
Also takes section props.
| Prop | Tür | Varsayılan |
|---|---|---|
cartThe cart from your server. Lines, prices and discounts as Money. | Cart | – |
onUpdateLineCalled after a stepper change. The new quantity shows at once; throw to roll it back with your message under the line. Rapid changes are coalesced to the latest quantity. | (lineId: string, quantity: number) => Promise<Cart | void> | – |
onRemoveLineCalled when a line is removed. The line collapses at once and comes back with an error if this throws. | (lineId: string) => Promise<Cart | void> | – |
onUndoRemoveRe-adds a removed line. When set, a removed line leaves a “Removed · Undo” row for undoTimeout. | (line: CartLine, index: number) => Promise<Cart | void> | – |
onAddLineAdds a recommended product. Its line appears at once as pending. | (line: CartLine) => Promise<Cart | void> | – |
onCheckoutCalled by Checkout after every pending change has synced. The button shows a spinner while it runs. | (cart: Cart) => unknown | – |
onContinueShoppingCalled by Continue shopping. The drawer also closes. | () => void | – |
freeShippingThresholdShows the free shipping bar and the amount left to reach it. | Money | null | – |
recommendationsProducts for the empty state and the “You might also like” row. Items already in the cart are hidden. | CartRecommendation[] | – |
upsellsShow the recommendation row when the cart has items. | boolean | true |
undoTimeoutHow long the undo row stays, in ms. Hovering or focusing it pauses the timer. | number | 5000 |
localeLocale for money and numbers. | Intl.LocalesArgument | "en-US" |
trailingZerosSet false to show $38 instead of $38.00 for whole amounts. | boolean | true |
labelsEvery user-facing string, including announcements. | Partial<CartLabels> | – |
headingThe page heading. | React.ReactNode | "Bag" |
AddToCartButton
Also takes Button props such as size, variant and disabled.
| Prop | Tür | Varsayılan |
|---|---|---|
onAddAdds the item. Return a promise to show progress, throw to show the error under the button, or return false to cancel quietly, for example when a size is missing. | () => unknown | – |
itemUsed for the announcement “Added Ring Vase, Sand / Small to your bag”. | { title: string; variantTitle?: string } | – |
childrenThe idle label. | React.ReactNode | "Add to bag" |
spinnerDelayHow long to wait before showing the spinner, in ms. | number | 300 |
successDurationHow long “Added” stays, in ms. | number | 1200 |
labelsThe added label, error fallback and announcement. | Partial<AddToCartLabels> | – |
CartTrigger
Also takes Button props.
| Prop | Tür | Varsayılan |
|---|---|---|
countItems in the cart. The badge appears at one and hides at zero. | number | – |
maxCounts above this show as 99+. | number | 99 |
labelsThe accessible name, “Bag, 3 items” by default. | Partial<CartTriggerLabels> | – |
QuantityStepper
Also takes div props.
| Prop | Tür | Varsayılan |
|---|---|---|
valueThe current quantity. | number | – |
onValueChangeCalled right away for plus and minus, and 250ms after typing stops. | (value: number) => void | – |
onRemoveCalled by minus at the minimum or a typed 0. | () => void | – |
minThe lowest quantity. | number | 1 |
maxThe highest quantity. Plus is disabled there. | number | – |
titleThe item name used in button labels. | string | – |
debounceTyping delay before a typed value is applied, in ms. | number | 250 |
FreeShippingProgress
Also takes div props.
| Prop | Tür | Varsayılan |
|---|---|---|
subtotalThe current subtotal. | Money | – |
thresholdThe free shipping threshold. | Money | – |
celebratedSet true to skip the unlock moment, for example after it played once. | boolean | – |
onUnlockCalled when the subtotal first crosses the threshold. | () => void | – |
useOptimisticCart
useOptimisticCart(cart, handlers, { labels, locale }) returns the optimistic cart and its actions.
| Prop | Tür | Varsayılan |
|---|---|---|
cartThe optimistic cart to render. | Cart | – |
rowsLines and removed rows in display order. | CartRow[] | – |
updateLine, removeLine, undoRemove, addLineActions that update the view at once and call your handlers. | functions | – |
syncingTrue while any change is waiting for the server. | boolean | – |
announcementText for a polite live region. | string | – |
flushResolves once every pending change has settled. | () => Promise<void> | – |
| Tuş | Action |
|---|---|
| EnterSpace | On Add to bag, adds the item. Presses while it’s adding are ignored. |
| ArrowUpArrowDown | In the quantity field, changes the quantity. |
| Enter | In the quantity field, applies a typed value right away. |
| Escape | Closes the drawer and returns focus to the bag button. |
- The bag button is named with its count, “Bag, 3 items”. Changes are announced in one polite live region: “Removed Ring Vase. Undo available.”, the new quantity with the subtotal, and unlocking free shipping.
- Each stepper is a labelled group with “Decrease quantity of Ring Vase”, “Increase quantity of Ring Vase” and a numeric text field that selects its value on focus. Failed updates are announced with role alert.
- After a removal, focus moves to Undo. After undo, it returns to the restored line. When an undo row expires with focus in it, focus moves to the next line.
- The free shipping bar is a progressbar with a value such as “$134.00 of $150.00 toward free shipping”. All motion has a reduced-motion version that only fades.
Şunlarla geliştirildi
Cart bloğunun yapıldığı ücretsiz HextaUI bileşenleri. Her biri tek başına yüklenir.
Kod
10 dosya, components/blocks/cart konumuna eklendi.