shadcn.io is not affiliated with official shadcn/ui
Recurring Order Checkout Block for Radix UI
A bread subscription where each item has its own rhythm, 2, 4 or 8 weeks: a grid of the next eight Mondays shows what arrives, shared boxes ship free, and the average per four weeks is on the button.
Installation
Overview
Let people set up a standing order whose items arrive on their own schedules, with this subscription builder for React with Radix UI. A compact header holds the title and one sentence from Oatcake Co, a bread subscription that bakes on Mondays. Inside a hairline frame with a plus mark on each corner, a list shows three items, a sourdough loaf, a seeded rye and a box of oat cakes, each with a drawn thumbnail, its price at the chosen rhythm and a Native Select to repeat every 2, 4 or 8 weeks (5, 10 or 15 percent off the price of one). Under it, the next eight Mondays are a grid of dated cells sharing hairlines, each listing the items that arrive that day: two or more items on the same Monday share a box, which ships free, and a lone item pays $4.50 delivery. Changing a rhythm redraws the grid, and a week with nothing to deliver says so in the same cell height. A row of figures counts the deliveries, the eight weeks added up in whole cents, what the rhythms save against paying full price and the average per four weeks, which is the figure on Start, the only Shine Button. For bakeries, coffee, pet food and any subscription with more than one item.
FAQ
How is the delivery grid worked out?
The first delivery is a fixed Monday, FIRST (19 October 2026), and week n is that date plus n times seven days, written without Intl so the server and the browser agree. An item arrives on week n when n is a multiple of its rhythm, so every 2 weeks lands on weeks 0, 2, 4 and 6, every 4 on weeks 0 and 4 and every 8 only on week 0. A cell is the items that arrive, the shipping (free when two or more share it, LONE_SHIPPING otherwise) and the total, all from one pure cellOf helper that the figures below also read.
Why are prices in cents, and what is the average per four weeks?
Floating-point dollars drift, so every price is an integer number of cents; the price at a rhythm is the unit price less its percentage, rounded half up, and usd is the only place cents become text. Eight weeks is two periods of four, so the average per four weeks is the eight-week total halved, rounded half up. The "saved" figure is the full price of the same boxes minus what you pay, with the same shipping on both sides.
What if no item arrives in a week?
If every item is on an 8-week rhythm, weeks 1 to 7 have no box: the cell still draws its date, says "No delivery" and shows $0.00 in the muted colour, at the same height as the others, so choosing a rhythm never moves the page. The count above the grid says how many deliveries there are.
How does it look on a phone?
Each item becomes two rows, the thumbnail and name on the first and the select full width on the second. The grid is two cells across instead of four, still in date order, and the foot stays at the bottom of the screen with the status line above a full-width Start.
Is it accessible from the keyboard?
Yes. Each rhythm is a native select with a visible label, "Repeat", described by the item's name, the grid is a list of dated cells with real time elements, and one polite status message in the foot reports each change (the item, its new rhythm, the deliveries and the eight-week total).
What stays local in the demo, and how do I wire it up?
Everything. The rhythms live in the block's state and Start only says that the order started and when the first box would arrive; nothing is charged or scheduled. In your app save the rhythm per item with your subscription provider, take the delivery dates and shipping from the server (holidays and cut-off times move them), and let Start create the subscription with the payment method on file.