Inspector Attributes

The pairs nobody could have put in the panel in advance: data-* hooks, an ARIA relationship, a custom property, an og: name. Two text fields per line and nothing else, with no reordering and no per-row editor. Duplicate names are marked rather than refused, since an edit passes through one on its way.

Installation

Adds the component and everything it depends on to your project.

npx shadcn add https://ui.beste.co/component/r-base/inspector-attributes

New here? Read the installation guide.

Usage

The import and the props worth knowing about, in one place.

import {
  InspectorAttributes,
  attributesToRecord,
} from "@/components/beste/component/inspector-attributes";

<InspectorAttributes
  label="Attributes"
  defaultValue={[{ key: "data-analytics-id", value: "hero-cta" }]}
  // Pressable chips under the pairs: one press adds the name with an empty value,
  // and a name already in the list drops out of the row
  suggestions={["data-testid", "data-analytics-id", "aria-describedby", "rel"]}
/>

<InspectorAttributes
  label="Meta tags"
  value={attributes}                 // [{ key, value }]
  onValueChange={setAttributes}
  onOpenChange={(open) => console.log("editor open:", open)}
  keyPlaceholder="property"
  valuePlaceholder="content"
  max={12}
  tone="outline"                     // "muted" (default) | "outline" | "ghost"
  size="sm"                          // "sm" | "default" | "lg"
/>

// The pairs as the object they are for. Empty names are dropped: a half-typed
// line is not an attribute yet.
<div {...attributesToRecord(attributes)} />

Playground

Turn the props on the right; the snippet under them is what you would write to get what you see.

Usage
import { InspectorAttributes } from "@/components/beste/component/inspector-attributes";

<InspectorAttributes
  label="Attributes"
  className="w-72"
  defaultValue={[{"key":"data-analytics-id","value":"hero-cta"},{"key":"aria-describedby","value":"hero-note"}]}
  suggestions={["data-testid","data-analytics-id","aria-describedby","rel"]}
/>

Keyboard and gestures

Every one of these is in the component already. They are listed because a props table cannot mention a gesture, so nothing else on this page can tell you they exist.

Enter / SpaceOpen the editor from the row
TabWalks name, value, remove, then the next line
Typing a nameDrops anything that cannot be in one, spaces included

Props

Read from the component's own type, so this cannot drift from what it accepts.

PropTypeDefaultDescription
label*stringLabel rendered on the left, inside the row.
iconLucideIconOptional leading icon shown before the label.
valueAttribute[]Controlled value. Pair it with `onValueChange`.
defaultValueAttribute[]Initial value in uncontrolled mode.
onValueChange(value: Attribute[]) => void
onOpenChange(open: boolean) => voidFires when the editor opens or closes.
keyPlaceholderstringGhost text for the two fields.
valuePlaceholderstring
suggestionsstring[]Names worth offering, shown as pressable chips under the pairs: one press adds that name with an empty value. Names already in the list drop out of the row, so it also says what is left. They stay suggestions rather than becoming a menu of allowed names — the point of this row is the names nobody anticipated.
maxnumberCeiling on how many pairs there may be.
disabledbooleanBlock interaction and dim the row.
tone"muted" | "outline" | "ghost""muted"Surface treatment: filled (default), hairline outline, or bare until hover.
size"sm" | "default" | "lg""default"Row height preset.
classNamestring
aria-labelstringAccessible name. Falls back to `label`.

More Inspector components

View all Inspector
Applies to every breakpoint.

Inspector Note

The line of prose that belongs between rows: what a setting is for, why one is switched off, what a value will cost. Four tones, each with its own mark, and the same text size as the rows around it.

Inspector Aspect

Settings row for a ratio: the row prints it and draws it, and opens an editor with the ratios worth a name plus both sides always editable. It is kept as two numbers rather than as their quotient, since 16:9 is what a reader recognises.

Inspector Variants

The choice that has to be seen to be made: a template, a layout, a chart type. Each option is a picture, normally a rendered screenshot passed as a URL, or markup for the choices no photograph would show. The row is the trigger, the grid is width-matched to it, and the captions under the pictures can be dropped for a set whose pictures say everything.

Inspector Unit

A number and the unit that gives it meaning, in one row: px, rem, a percentage, or a keyword like auto that is the whole value on its own. Each unit may bring its own range, so a percentage stops at 100 while pixels do not.

px

Inspector Dimensions

Width and height on one row, with the lock between them: while it is closed, editing one scales the other by the ratio the pair had when the lock closed. Both fields are as wide as the largest number they can hold, so typing never shifts the row.

Inspector Tracks

The columns of a grid as a list of lengths: the row shows the CSS it comes to, the editor holds one length per line with a picture of the shares above them. There is no reordering on purpose, because a track's place in the list is its place in the grid.