Desde

Editor guide

Editing

Change text, props, styles and structure directly in the prototype: what each edit writes to source, and why some of them ask you a question first.

Every edit in Editor rewrites your source files. There is no Save button and no separate preview buffer: the change goes into the file, Vite's hot reload re-renders the prototype, and what you see is what is on disk.

This page assumes you can already select an element. See Select and inspect.

What happens when you make an edit#

  1. Editor locates the exact tag in source using the position it captured when you selected the element, and splices the new value in.
  2. The file is written to your working tree as an ordinary uncommitted change.
  3. Vite hot-reloads. Structural CSS like :last-child recomputes against the real new tree, because the tree really did change.

Typing in a text or prop field is debounced by half a second, so dragging a number or typing a word writes once when you settle rather than on every keystroke.

Nothing about this is a commit. Use Commit in the header when you want the changes in git, and the toolbar's Undo to step back through Editor's own edits. See branch mode for the full model, and deterministic editing for why the splice is exact rather than a search-and-replace.

Text#

The Inspector's DOM section lists the editable text on the selected element, one field per piece. Type in a field and the text is rewritten in source.

Where it lands depends on where the text came from. If your template contains the literal string, that string is rewritten. If the text is actually a prop being passed to a component (<KEmptyState title="No results"> renders "No results" but the text is not a child of the rendered element), Editor traces it back to the prop and rewrites the prop instead. You do not have to know which case you are in.

Some text renders read-only with a short reason. That means Editor can see the text but cannot resolve it to one unambiguous place in your source. Describing the change in chat is the way through.

Text produced by a ternary ({{ isNew ? 'New' : 'Existing' }}) gets its own Conditional text section with one field per branch, so you can edit the two strings independently.

Props#

The Variants and props section is built from the component's manifest, so the controls match the prop's real type:

  • Booleans get a switch.
  • Finite choices (the variant enums like appearance, size, state) get a dropdown containing exactly the values the component accepts. You cannot pick an invalid variant, and you do not have to remember what the valid ones are.
  • Strings and numbers get text and number fields.
  • Objects, arrays, events, functions, slots and token props are read-only. There is no control for them yet.

The value keeps its type on the way into source. Setting a number prop to 1 writes the bound form (:step="1"), not the string attribute step="1" that the framework would read as the literal text.

Where the enum values come from (and what happens when a component has no manifest) is covered in design-system grounding.

Styles#

The Spacing, Align & size, Color, Border, Typography and Shadow sections all write the same way: they compute the new class list for the element and splice it into source. The State bar and the toolbar's breakpoint decide which variant of the class you are editing, so picking hover and changing a colour writes the hover: class and leaves the resting one alone.

The Classes field in the DOM section is the escape hatch: edit the class list by hand.

Some style edits open a dialog before they apply. That is the next section.

Structure#

Structural edits come from right-clicking a row in the Structure tree, or from dragging.

Move. Drag a row in the Structure tree: drop on the top quarter of a row to go before it, the bottom quarter to go after it, the middle to nest inside it. With the Select tool active you can also drag the element directly in the prototype. Both are same-file only. A drop that resolves into a different component's source is refused with an explanation rather than attempted.

Insert child. A submenu of snippets to add as the last child of the row you right-clicked. Today that list is a small fixed catalog of HTML primitives (div, span, section, p, h1h3, button, a, ul, img, hr). It is not yet generated from your own design system. To insert one of your components, ask the agent, which resolves the tag from your manifest catalogue and adds the import.

Unwrap. Removes a wrapper element and promotes its children into its place (<div><span/><p/></div> becomes <span/><p/>). Refused when the target is self-closing or empty (you want Delete), and when unwrapping would leave the template with more than one root.

Delete. Removes the element. Refused for the template's only root element, since the framework requires one.

Flatten conditional. Collapses a v-if chain down to one branch. The applicator can keep any branch in the chain, but the menu offers two today: Keep this branch (v-if) and Keep else branch. A chain with v-else-if rungs still flattens. You just cannot pick a middle rung from the menu yet.

Detach and Swap are dormant: you will not see either control unless you opt in with lanes.detach and lanes.swap in desde.config.json. Both applicators are Vue-only with no React equivalent, and they were unused on Vue, so the offering was withdrawn rather than maintained; see Swap, Detach and the icon picker for the full reasoning and the config block. The icon picker is part of the same lanes.swap lane.

Once enabled: Detach inlines a component's markup at the call site, and is offered only for components authored in your own repo. Swap replaces one component with another: Editor scores the catalog for prop overlap, and once you pick a replacement it shows an editable prop mapping before writing anything.

All of these write immediately, like every other edit. There is no staging step to forget.

The scope dialogs#

Some edits are ambiguous in a way Editor cannot resolve on its own, not because the code is unusual, but because the screen and the source genuinely disagree about how many things you are pointing at. In those cases a dialog appears with the two or three edits that are actually expressible, and you pick.

This is deliberate. Every one of these dialogs sits where a plausible default would be silently wrong some of the time, and where the wrong answer changes code you were not looking at.

An item in a list#

You clicked item 3 of 8. On screen there are eight items. In source there is one template inside a loop, plus a data array with eight entries. Deleting one of them has two possible meanings, so the dialog asks: "Delete this item or all items?"

  • This item: remove one entry from the data array. The other seven stay.
  • All items: rewrite the template. Every item goes at once.

The dialog's description names which item you picked and how many there are: "This is item 3 of 8, rendered by a loop, and they all come from the same code." The same prompt covers delete, prop changes, duplicate, move, insert and text, and it asks every time. A scope choice is per-edit by nature, so there is no "remember this" option.

Every edit kind, including text, offers both choices. Editing one item's text patches only that item's data entry, the same as every other edit kind.

An element inside a reused component#

You deleted a heading that lives inside Card.vue, and Card.vue is used in nine places. There is no edit that removes that heading from only this one card, because the heading is written once. What you can express is:

  • Delete this instance: remove the whole <Card> usage from the page you are on. Other usages are untouched.
  • Delete from component: remove the heading from Card.vue. Every card loses it.

Either option is greyed out with a reason when its file is library source; Editor does not rewrite node_modules.

A token-driven or inherited style#

You changed a colour whose current value does not come from a class on this element: it comes from a design token, or it is inherited, or the element is rendered by a library. Splicing a class onto the element would either miss the mark or do nothing at all. The choices, with the provenance chain shown inline so you can see what you are deciding about:

  • This element: override the value here only.
  • This page: write a CSS rule that targets this element by its source position. On Vue the rule goes in the page's <style scoped> block; on React it goes in a project stylesheet your app already imports. Either way it can reach an element inside a component you do not own, which no source edit can.
  • The token: change the design token at its definition. The dialog reports how many places in the prototype reference that token.
  • The component: not wired yet; shown disabled rather than quietly missing.

Which options are available depends on the value and the project, not on the framework. "This page" needs somewhere to put the rule (a <style scoped> block on Vue, or a first-party stylesheet your page actually loads on React), and it needs the element's source position to still be on the page. "The token" needs the token to resolve to a stylesheet Editor can write. Unavailable options are shown disabled with the reason. Like the row-scope prompt above, this one asks every time.

When one rule would cover more than one element (which happens when several instances render from the same source position), Editor says how many, and says "at least", because it can only count the page you are looking at.

When a value is unambiguous, no dialog appears: the edit just applies.

An edit that landed on a shared template#

A fourth dialog, Resolve ambiguous edit, appears when a change made directly in the prototype landed on a row rendered by a loop and Editor could not tell which instance you meant. It shows the before and after text, offers this instance or all instances, and lets you discard the edit entirely. Until you answer, the edit is not written.

When the deterministic path refuses#

Editor rewrites source structurally, so it refuses rather than guesses when the source is too fuzzy to splice safely. The three common cases for a prop edit:

  • The prop is bound to an expression rather than a literal (:label="row.title"). The value you want to change lives somewhere else.
  • The element spreads props (v-bind="attrs") or uses a computed prop name.
  • A v-model could be supplying the value.

When that happens, Editor hands the edit to a bounded agent turn that can read across files to trace the binding to its definition and edit there. It is time-capped (about 90 seconds by default) and turn-capped, and the file is snapshotted first: if the agent reports success without actually changing anything, or leaves the file unparseable, the change is refused and the original restored.

Structural edits behave the same way. A move, delete, insert, unwrap or flatten-conditional that the deterministic applicator refuses automatically tries an AI repair pass, as do detach and swap, for a project that has enabled lanes.detach and lanes.swap. If both lanes fail you get the original, specific refusal, not a vague error. A dormant lane never reaches the repair pass at all: the AI fallback endpoint refuses it on the same config the deterministic one does.

Inline edits that the deterministic path refuses are parked in an AI queue and are only written to source when you flush it. While that queue is non-empty the header's Commit button is replaced by Apply N with AI. Committing first would leave those edits out of the commit, which is why the button changes rather than sitting there looking available.

An edit that needs interpretation rather than repair is handed to the chat panel instead, with a toast telling you it went there. The chat tab opens on its own so the handoff is not invisible.

Next#

  • Limits: the full list of what Editor refuses, and what to do instead
  • Chat: describing a change instead of clicking it
  • Git: committing, branching, merging and pushing