shadcn.io is not affiliated with official shadcn/ui
Persistent Summary Checkout Block for Radix UI
A long checkout form with a side summary that stays in view: eight fields in the main cell, and beside them the lines, shipping, state tax, total, what you have entered read back, a done count with a bar and a link to the next missing field.
Installation
Overview
Keep the order in sight while a long form scrolls, with this persistent-summary checkout for React with Radix UI. A header from Wick and Wren, a candle shop, sits over a hairline frame with a plus mark on each corner. The main cell holds eight fields in three groups: email and phone; name, street, city, a state Native Select and ZIP; and a card as one joined control from Input Group. The side cell sticks to the top of the screen as you scroll on a desktop and holds the order lines with drawn thumbnails, then subtotal, shipping and tax at the chosen state's rate, then the total, worked out in whole cents. Under the totals it reads back what you have entered, a count ("3 of 8 fields done") with a Progress bar, and a button that names the next missing field and moves focus to it. Pay, in the foot, is the only Shine Button; a press with problems names each one under its field and never disables the button. On a phone the summary follows the form and the foot stays pinned to the bottom of the screen. For long forms, shipping-heavy shops and any checkout where the total changes as you fill it in.
FAQ
How is 3 of 8 fields done worked out?
Each of the eight fields (email, phone, name, street, city, state, ZIP and the card) has a small check. A field is done when its check passes; the card is one field and is done when its number, expiry and CVC all pass. The count, the bar and the next-field button are all derived from the same list of problems, so they cannot disagree. Problems are shown under a field only after the first press of Pay, and then update as you type.
What does the next-field button do?
It names the first field in reading order that is not done ("Next: Phone") and moves focus to it. When all eight are done it reads "All eight fields are done" and rests. It is a normal button, reachable by keyboard, so you can work down the form without scrolling to find what is missing.
Where does the tax come from?
From the state you choose. Each state in REGIONS has a rate in basis points (625 is 6.25%); the tax is the goods subtotal times the rate, rounded half up to the cent. Until a state is chosen the line says "Tax, choose a state" and adds nothing. Shipping is a flat 650 cents here. Replace both with your tax and shipping service and keep the rounding on the server.
Can I use this to take real card payments?
No, and the code says so. It checks a card in the tab's memory (brand by the first digits, the Luhn sum, the expiry against a fixed month) so you can see the pattern. A real page never lets card digits reach its own code: it uses the fields your payment provider hosts, an iframe of theirs, with this layout, labels and error wording around them and the real autocomplete tokens (cc-number, cc-exp, cc-csc, cc-name) that those fields set themselves. Autocomplete is off in the demo so a browser never offers a real saved card to it. Test card 4242 4242 4242 4242 passes with any future expiry (checked against October 2026); a number that fails the Luhn sum, a past expiry or a CVC of the wrong length says so under the field.
What stays local, and how do I connect it for real?
Everything: Pay waits 700 ms and shows a result; the card digits are cleared once it answers and only the brand and last four stay. To connect it, mount your provider's hosted card fields in the card group's place, send the order with their token, and show their error in the same status line. The summary's sticky behaviour is CSS only (sticky from the medium breakpoint).