Skip to content
shadcn.io

shadcn.io is not affiliated with official shadcn/ui

Stock Ledger Inventory CRUD Block for React

A cafe's stock as a ledger: pick an item, read its movements newest first with the count after each, add a receive, issue or count that cannot take more than is on hand, edit a note in place and reverse a movement with Undo.

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

Keep stock honest by recording what moved, not by typing a number, with this inventory ledger for React with Base UI. A Native Select names the item with its count ("Oat milk, on hand 14"), and beside it four figures read the on-hand count, the opening count, the reorder level and whether it is time to order. The count is never stored: it is the opening count plus every movement, worked out each time. A native table in a frame of fixed height lists the movements newest first with a Receive, Issue or Count badge, the quantity, the count after it and a note that edits in place with Editable. Quantities do not change; to fix one, Reverse the movement and enter it again. The form that closes the panel has a Segment Group for the kind, a quantity and a note, and its Add movement button is the only Shine Button. An issue larger than the count is refused with "Only 14 on hand". The panel is ruled by Guides and the foot says what happened, with Undo. For stock rooms, parts bins and any count that has to be explained.

FAQ

How do I fill it with my stock?

Edit ITEMS (each has a name, a unit, an opening count and a reorder level) and LINES, one movement per line as item|date|kind|quantity|note, oldest first, where the kind is receive, issue or count. A count sets the balance to the number counted; a receive adds and an issue subtracts. Dates are ISO days compared with AS_OF, never read from the clock.

What stops a wrong movement?

A quantity must be a whole number up to 9999, at least 1 for a receive or an issue, and an issue can't take more than is on hand, so the form says "Only 14 on hand" under the field and moves focus to it. A note is trimmed and kept to 60 characters. The reason is in a line that is always there, so nothing shifts when it appears.

What does Reverse do, and when is it refused?

It removes the movement and the count recomputes from the rest; the status line says "Reversed Issue 6" and offers Undo. If taking a movement away would leave a later issue short, for example reversing the delivery that stocked it, the button stays but is marked unavailable, the row says "A later issue needs it" and pressing it says the same in the status line.

Why can I edit the note but not the amount?

A ledger is only trusted if its lines are not rewritten, so the amount stays as entered and only the note, which changes no count, edits in place. Enter saves, Escape cancels, and the status line says the note was saved with an Undo that puts the old one back.

What stays local, and how do I wire a real save?

Everything lives in state in this tab and a reload restores the opening ledger; nothing is sent. In your app post each movement from add, reverse and editNote, keep the count derived on the server as well, and refuse an issue the server's count can't cover.

How does it look on a phone?

The count-after column goes and the figures wrap in two columns above the ledger. Reverse shrinks to its icon, still named for its movement, the ledger scrolls inside its frame, and the form's fields stack with the button last.