**ShapeDivider Component — LLM Reference** `ShapeDivider` renders a decorative wave/curve/zigzag/slant/clouds transition between two colored sections — 2 or 3 stacked layers, each independently colored, with configurable position, amplitude, frequency, phase, stacking order, and flip. Unlike `Divider` (a plain straight line, rendered live as HTML/CSS), `ShapeDivider`'s visible content is a **rasterized PNG image** — its `config` carries both the generation parameters (`params`) and a resolved, hosted image URL (`src`) that must be produced by a render call before anything appears. --- ## The two-step workflow — read this before using this component A `ShapeDivider` node is only ever visible once `config.src` points at a real, hosted PNG that matches `config.params`. There is no way to derive the image from `params` alone at render time (email clients can't rasterize SVG/canvas on the fly) — you must render it explicitly: 1. **Render**: `POST` your desired `params` to the shape-divider render endpoint for the current template: - MCP: `POST /api/mcp/v1/teams/{idOrSlug}/templates/{templateId}/shape-dividers` (PAT scope `assets:write`) - Body: `{ "params": { ...ShapeDividerOptions } }` - Response: `{ "data": { "id": "...", "url": "https://...png", "width": 1200, "height": 240, ... } }` 2. **Reference**: set the component's `config` to `{ src: , assetId: , params: , width: "100%" }` — all four fields together, via `add_component`/`update_component_config` (or the equivalent tree-ops/field-ops call). **Never set `params` without also re-rendering and updating `src`/`assetId` to match.** A `config.params` that disagrees with what `config.src` actually shows is a real, visible bug, not a cosmetic one — the node will keep displaying the *old* image until the next render call succeeds. If you only need to reposition/resize an *existing* divider without changing its look, you can change `width` (display width) alone — that doesn't require a re-render, since `params.width`/`params.height` (the image's own generation size) are independent of the display `width`. If a document summary shows a `ShapeDividerComponent` with no `src` (or the docSummary note "no image rendered yet"), it needs step 1 run before it will show anything. --- ## Position in the Document Tree ``` DocumentTree └── Section └── Container └── Column └── Text └── ShapeDivider ← decorative image transition └── Button ``` `ShapeDivider` is a leaf node (no children). Like `Divider` and `Spacer`, it can only be placed inside a `Row` or a `Column` — never directly inside a `Container`. --- ## ComponentNode JSON Structure ```json { "id": "unique-string-id", "type": "ShapeDividerComponent", "config": { "src": "https://your-bucket.s3.amazonaws.com/.../shape-divider-abc123.png", "assetId": "cktr0abcd1234", "width": "100%", "params": { "width": 600, "height": 120, "middleEnabled": false, "stackingOrder": "topToBottom", "topColor": "#1E293B", "topOpacity": 100, "topTrans": false, "middleColor": "#06B6D4", "middleOpacity": 100, "middleTrans": false, "bottomColor": "#38BDF8", "bottomOpacity": 100, "bottomTrans": false, "shape1Style": "wave", "shape1Position": 50, "shape1Amplitude": 25, "shape1Frequency": 2, "shape1Phase": 0, "middleMode": "linked", "ribbonThickness": 12, "shape2Style": "wave", "shape2Position": 60, "shape2Amplitude": 20, "shape2Frequency": 2, "shape2Phase": 0, "flipH": false, "flipV": false } } } ``` --- ## `ShapeDividerConfig` — Full Property Reference | Property | Type | Required | Description | |------------|---------------------|----------|-------------| | `src` | `string` | No* | Hosted PNG URL from a render call. *Effectively required — without it, nothing renders. | | `assetId` | `string` | No | Asset id backing `src`. Always set together with `src`. | | `width` | `string` | No | Display width — `"100%"` (default, responsive) or a fixed px value. Independent of `params.width`. | | `params` | `ShapeDividerOptions` | Yes | Full generation parameters — see below. | ### `ShapeDividerOptions` (the `params` object) | Property | Type | Bounds/Notes | |------------------|----------------------------------------------------------|--------------| | `width` | `number` | 200–2400 (px, integer). The image's own generation size — also becomes the email ``'s Outlook-width attribute. | | `height` | `number` | 20–800 (px, integer). | | `middleEnabled` | `boolean` | `true` = 3-layer divider (top/middle/bottom); `false` = 2-layer (top/bottom only). | | `stackingOrder` | `"topToBottom" \| "bottomToTop"` | Which layer sits furthest back. | | `topColor`, `middleColor`, `bottomColor` | `string` (hex, e.g. `"#1E293B"`) | Solid hex only — no alpha/rgba, same rule as every other component's color fields. | | `topOpacity`, `middleOpacity`, `bottomOpacity` | `number` | 0–100. | | `topTrans`, `middleTrans`, `bottomTrans` | `boolean` | When `true`, that layer is fully transparent (its color/opacity are ignored). | | `shape1Style`, `shape2Style` | `"wave" \| "curve" \| "zigzag" \| "slant" \| "clouds"` | `shape2*` fields only matter when `middleEnabled` is `true` and `middleMode` is `"independent"`. | | `shape1Position`, `shape2Position` | `number` | 0–100 (% of height). | | `shape1Amplitude`, `shape2Amplitude` | `number` | 0–150 (px). | | `shape1Frequency`, `shape2Frequency` | `number` | 1–12. Ignored for `"curve"` and `"slant"` styles. | | `shape1Phase`, `shape2Phase` | `number` | 0–360 (degrees). Ignored for `"curve"` and `"slant"` styles. | | `middleMode` | `"linked" \| "independent"` | Only meaningful when `middleEnabled` is `true`. `"linked"`: the bottom boundary is boundary 1 offset by `ribbonThickness` (constant-thickness ribbon). `"independent"`: the bottom boundary is its own shape (`shape2*`). | | `ribbonThickness`| `number` | 2–100 (px). Only used when `middleMode` is `"linked"`. | | `flipH`, `flipV` | `boolean` | Mirrors the whole divider horizontally/vertically. | --- ## Common Patterns & Presets Four ready-made parameter sets exist (used by the builder's own preset buttons) — reuse one wholesale as a starting point instead of hand-tuning every field from scratch: - **`simpleWave`** — 2-layer, dark navy over sky blue, gentle sine wave. - **`sharpZigzag`** — 2-layer, dark navy over rose, sharp angular zigzag. - **`neonRibbon`** — 3-layer linked ribbon, dark navy / cyan / slate, smooth wave. - **`sunsetGlow`** — 3-layer independent shapes, pink / orange / gold, single arc curves. ### Minimal 2-layer wave (render params) ```json { "width": 600, "height": 120, "middleEnabled": false, "stackingOrder": "topToBottom", "topColor": "#1E293B", "topOpacity": 100, "topTrans": false, "middleColor": "#06B6D4", "middleOpacity": 100, "middleTrans": false, "bottomColor": "#38BDF8", "bottomOpacity": 100, "bottomTrans": false, "shape1Style": "wave", "shape1Position": 50, "shape1Amplitude": 25, "shape1Frequency": 2, "shape1Phase": 0, "middleMode": "linked", "ribbonThickness": 12, "shape2Style": "wave", "shape2Position": 60, "shape2Amplitude": 20, "shape2Frequency": 2, "shape2Phase": 0, "flipH": false, "flipV": false } ``` --- ## Data Bindings Not typically bound — a `ShapeDivider`'s look is a design choice, not per-recipient data. `bindings.visible` is still supported like any leaf component if the user explicitly wants to hide it conditionally; `propertyMap` on `config.params.*` is technically possible but almost never useful, since a bound color/shape value still wouldn't trigger a re-render (see the two-step workflow above) — a data-driven divider look isn't a supported pattern. --- ## Rules & Constraints - `config.src` is the only thing actually rendered — `config.params` alone produces nothing. - Always set `src`, `assetId`, and `params` together, from the same render-call response. - Colors must be solid hex (`#RRGGBB` or `#RGB`) — no alpha, no `rgba()`/`rgb()`/named colors. - `shape1Frequency`/`shape1Phase` (and their `shape2*` counterparts) have no effect when the corresponding style is `"curve"` or `"slant"` — don't bother setting them in that case. - Like `Divider` and `Spacer`, this component can only go inside a `Row` or a `Column`, never directly inside a `Container`.