shadcn.io is not affiliated with official shadcn/ui
Saved Carts Storefront Block for React Aria
Named baskets you can rename, load and merge: a list of three saved baskets with counts and totals, the chosen basket's lines, Load to replace the bag, Merge to add to it, and Delete with an Undo in the list.
Installation
Overview
Let repeat shoppers keep a basket for each errand, with these saved carts for React with React Aria. A header names the shop, Sundry & Sons, and says what the block is. A hairline frame with a plus mark on each corner opens with a heading row that keeps the bag's count and subtotal, then a stage of fixed height: at its start a list of three saved baskets (Weekly shop, Birthday party, Camping), each with its item count and total, and at its end the chosen basket's lines with a drawn product, size, quantity and price. Rename swaps the name for an Input: Enter or Save commits, Escape or Cancel keeps the old name, and an empty name is refused with a reason. Load replaces the bag with the basket, Merge adds the basket to it, and both say how many items the bag gained or lost. Delete keeps the row in the list as "Deleted. Undo". Load is the one Shine Button. It's built from Input, Button, Empty, Shine Button and Guides, with a CSS entrance only. For a grocery or provisions shop, a reorder page or any shop with repeat baskets.
FAQ
How do I fill it with my own baskets?
Edit GOODS (each with an id, a name, a unit, a price in whole cents and a kind for its drawing) and BASKETS (each with an id, a name and a list of { id, qty } lines). BAG is the bag the visitor arrives with. Counts and totals are derived from the lines, so a basket's line in the list always matches its detail.
What is the difference between Load and Merge?
Load replaces the bag with the basket, so the bag becomes exactly the basket's lines. Merge keeps the bag and adds the basket to it: a product in both gets its quantities added, a product in only one stays. Either way the status line says the new item count, how much it changed by, and the new subtotal.
How does renaming work?
Rename turns the basket's name into a field with focus in it. Enter or the Save button commits the name, Escape or the Cancel button keeps the old one, and the focus goes back to Rename. A blank name is refused with a short reason under the field, and the field is marked invalid and keeps focus. The row in the list follows at once.
What happens when I delete a basket?
The row stays in the list as "Deleted Camping." with an Undo button that takes focus, and the stage shows the next basket that is still there. Undo brings the basket back and selects it. If every basket is deleted the detail shows an empty state and the Undo buttons stay in the list, so the panel keeps its height.
What stays local, and how do I wire it to real baskets?
Baskets and the bag live in the component's state and nothing is saved or sent. To wire it up, load BASKETS from your account API, and replace load, merge, remove, undo and commitRename with calls that change the basket or the bag on the server and set the state from the response.
Is it accessible?
The list of baskets uses buttons with aria-current on the chosen one, the name field is labelled and described by its problem line, the detail lines are a labelled scroll region you can reach with the keyboard, and a polite status line announces every result. Focus moves to the field on Rename, back to Rename after it, and to Undo after a delete.