shadcn.io is not affiliated with official shadcn/ui
Attribute Editor CRUD Block for Vue
A product's attributes as rows of key, type and value, where the value's control follows its type, changing a type converts the value and says what happened, and a band adds a snake_case key that no other row uses.
Installation
Overview
Edit the facts of a product without a form per type, with this attribute editor for Vue with Ark UI. A hairline frame with a plus mark on each corner holds one product, Oak side table, as six rows of key, type and value in a frame of fixed height: the type is a Native Select, and the value is a different control for each type, an Input for text, a Number Input with its steppers, a Switch for yes or no and a date field. Change a row's type and the value is converted, with the polite line saying what happened ("weight_kg: 14 kept as text." or "Cannot convert Solid oak to a number: reset to 0."). Under the frame a band adds an attribute: a snake_case key that no other row uses, a type and a value, and a refusal appears under the fields with its reason. Remove leaves a placeholder in the row's place, "Removed finish", with an Undo, and removing every row shows an Empty state without the frame changing height. Add is the only Shine Button, and the bands are ruled by Guides. For product catalogues, spec sheets, metadata panels and any record with typed properties.
FAQ
How do I fill it with my own attributes?
Edit ATTRS. Each has an id, a snake_case key, a kind of text, number, flag or date, and a value held as a string (yes or no for a flag, an ISO date for a date). The count in the band, the table caption and the limit of ten attributes are derived from that list, and new rows take their id from a counter held in state.
What happens to the value when I change a type?
It is converted by a small pure function, never lost silently. Text that starts with a number becomes that number ("12 kg" becomes 12), words like yes, true or on become Yes, an ISO date typed as text becomes a date, and a number or a flag shown as text keeps its reading. When there is nothing sensible, the value is reset (a number to 0, yes or no to No, a date to empty) and the polite line says so by name.
Which keys are refused?
A new key must be snake_case (lowercase letters, digits and underscores, starting with a letter), at most 24 characters, and different from every other row's key. The reason shows under the fields in a slot that is always there, so the band never changes height, and focus returns to the key field. A product also holds at most ten attributes, and the refusal says to remove one first.
What does Undo restore?
The last removed row, in the same position, with its type and value. The placeholder stays in the row's place until you press Undo or remove another row, so nothing moves under your pointer. Focus goes to the Undo button when a row is removed and to the restored row's type when it comes back.
What stays local, and how do I wire a real save?
The attributes live in React state in this tab and a reload brings the originals back; nothing is sent. In your app, call your API in add, changeKind, changeValue and remove, take the converted value from the response so the server stays the authority, and show a server refusal in the same slot the block already has for key problems.
How does it look on a phone?
Each row becomes a small grid: the key with its type under it at the start, the value beside them and the remove button at the end, with the column heads read aloud only. The frame still scrolls inside itself, so the page stays short, and the add band stacks its key, type, value and button.