Skip to content
shadcn.io

shadcn.io is not affiliated with official shadcn/ui

Product Customization Checkout Block for React

A made-to-order pendant as a ledger: four options each with an Edit that opens its field in place, price lines and a lead time that follow every change, and a returns checkbox that gates the Add to order button.

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 people what a custom order commits them to, with this product customization for React with Base UI. A compact header from Alderfold, a maker of engraved pendants, sits over a hairline frame with a plus mark on each corner. The main cell lists four options as rows of a description list, size, colour, material and engraving, each with an Edit Button that opens the row's one field in place: a Native Select for the three choices, an Input for up to twelve characters of engraving (Enter or Done keeps it, Escape puts the old text back). Under them the price lines are worked out in whole cents, with the total counting to its new value (Counting Number). The side cell says what the order commits you to: how many business days it takes and the day it should arrive, counted from a fixed today, with the days each choice adds, and a Checkbox in a Field, "I understand custom items cannot be returned". Add to order, the only Shine Button, stays in place but says why while the box is unticked, and moves focus to it. There is no picture of the pendant: the page is the ledger. On a phone the options come first and the made-to-order cell follows them. It's built from Native Select, Input, Checkbox, Field, Counting Number, Button, Shine Button and Guides, with a CSS entrance only. For engraved, monogrammed, tailored and any made-to-order goods.

FAQ

How do I fill it with my own options and prices?

Edit the constants at the top. SIZES, COLOURS and MATERIALS are lists of choices with an id, a label and what each adds to the price in cents (plus); BASE is the price before any option and ENGRAVING_PLUS what engraving adds. For the lead time, MAKING_DAYS, SILVER_DAYS and ENGRAVING_DAYS are business days. The price lines, the total, the days and the arrival day are all worked out from those and the current choices, so nothing is typed twice.

How do the in-place editors work?

Edit swaps the row's value for its field and the button for Done, in the same height, and moves focus to the field. A select keeps each choice the moment you make it. The engraving field holds a draft: Enter or Done keeps it, Escape puts the old text back, and text with characters an engraver cannot cut (anything but letters, numbers, spaces and a few marks) is refused with the reason in the line under the list and focus stays in the field. Emptying the field removes the engraving and its $8.

How is the arrival day worked out?

From one fixed date, AS_OF, plus business days: eight to make the pendant, two more for sterling silver and two more for engraving, skipping weekends. The page reads the same on the server and in every time zone and never changes when you reload it on another day. In your app compute it from the order date and your workshop's calendar, and show the date as a range if you cannot promise a day.

Why can I press Add to order without the box ticked?

Because a disabled button explains nothing. The button is marked aria-disabled, stays focusable and pressable, and a press without the box ticked says in the polite status line to tick the box about returns and puts focus on it. Ticking it says the pendant can be added. Changing an option does not untick it; the commitment is about the kind of order, not the choices.

How does it look on a phone?

The options come first, each row with its name and Edit on one line and the value or editor under it, then the price lines, then the made-to-order cell with its top rule and the checkbox. The foot is pinned to the bottom of the screen while you scroll, with the status line above a full-width Add to order, and settles at the panel's end from the medium breakpoint.

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

Everything. The options live in the block's state and Add to order only says that nothing was ordered. In your app send the choices to your server in add, price and date them there (the figures here are a preview of the same sums), keep the returns acknowledgement with the order, and show a server error in the same status line.