# Preview editing

## Connect markup to the shared editor

GrowSite parses Loom output into supported React elements. Text, cards, images and icons can use the platform's editor integration. A schema exposes fields in the inspector; HTML bindings identify nodes for direct editing on the preview.

```html
<article data-canvas-card="[[ block.field_path ]].card">
  <h2 data-text-field="[[ block.settings_path ]].title" gs-text="block.settings.title"></h2>
  <p data-text-field="[[ block.settings_path ]].text" gs-text="block.settings.text"></p>
</article>
```

`settings_path` points to values, such as `loom.blocks.first.settings`. `field_path` identifies the instance, such as `loom.blocks.first`. They change with nesting. Never hardcode `first`, array offsets or another instance's path.

## Inline text and card styling

Use recognized text field names such as `title`, `text`, `label`, `eyebrow`, `badge` and `meta`. Other schema settings remain available through inspector controls. `data-text-field` connects rich text selection and persistence. `data-canvas-card` enables card appearance controls.

Provide real template defaults for colors and dimensions. A client override belongs to that instance, not the shared source definition. Test both schema changes and rich text editing: changing schema text should not leave an old rich text override hiding the new value.

## Integration elements

| Element | Purpose | Important boundary |
| --- | --- | --- |
| `gs-icon` | Shared icon renderer and editor | Uses the existing icon catalog and content field |
| `gs-image` | Image rendering, framing and editing | Reads a content path and adjacent alt/frame data |
| `gs-canvas` | Existing canvas nodes | Primarily used by compatibility adapters |
| `gs-slot` | Host-provided React content | Requires a platform adapter to supply a slot |

```html
<gs-icon name="shield" field="items.0.icon"></gs-icon>
<gs-image field="image_url"></gs-image>
```

These paths refer to GrowSite section content. `gs-image` uses adjacent `image_alt` and `image_frame`. For a new native theme using a schema image URL, ordinary image markup can display it; that alone does not provide media-browser or crop integration.

## Links, forms and safety

Render link destinations through `safe_url`:

```html
<a href="[[ safe_url(block.settings.url) ]]" gs-text="block.settings.label"></a>
```

Use `mailto:hello@example.com`, `tel:+31201234567`, `https://wa.me/31201234567`, `/#contact` or an HTTPS URL as appropriate. Do not attach inline JavaScript handlers. A Loom link does not automatically opt into every legacy button editor behavior.

Forms, cookie consent, subscriptions and plugin actions are platform integrations. The renderer does not execute arbitrary scripts or arbitrary embedded form controls. Use an existing adapter for these features; a snippet cannot create a backend endpoint.

## Preview acceptance checks

Check hover selection, click selection, default values, saved values, reload, public rendering and mobile. Drag an editor window, then change dimensions: the content may resize, but the window should stay where the user placed it. Shared UI behavior belongs in the platform, not a theme-specific copy of its controls.


## Element appearance on the preview

Buttons, cards and sections use `data-canvas-surface="loom-surfaces.stable-key"`. Preserve this key across template updates. Clicking empty space opens background, color, border, radius and spacing controls; inner text retains inline editing. Declare a button URL binding with `data-loom-link-field="loom.settings.url_1"` and its label with `data-text-field="loom.settings.text_8"`. Icons use `data-element-icon` and retain their original artwork until replaced. Images use `data-loom-image-field` and optionally `data-loom-alt-field`. Appearance and cropping are stored in `content.canvas.elements`, outside schema settings. Use unique keys for repeated elements. Editing changes the draft; publishing is a separate action.


### Custom artwork instead of an icon

Choose “Choose or upload a custom icon” in icon settings. This opens the current site’s file library with upload, using its standard limits and supported image formats. The image preserves its aspect ratio. Size, background, spacing and radius remain editable; the color control does not recolor image pixels. Selecting a built-in symbol replaces the image, “No icon” hides it and “Default” restores the template icon. The existing canvas element/node `icon` field stores `image:/path/file.png` or `image:https://…`. The renderer treats the asset as an image, never executable HTML.
