Repository navigation
Comparing changes
Open a pull request
base repository: unlayer/elements
base: main
head repository: unlayer/elements
compare: dx/agent-friendly-props
- 10 commits
- 20 files changed
- 2 contributors
Commits on Jun 23, 2026
-
fix(elements): pin image display width for Builder round-trip
An explicit image width was emitted with autoWidth:true, so the Builder auto-sized the image to its natural width and dropped the intended width when the image was selected. Now an explicit width — passed inside `src`, as a flat `width=` prop, or via the `values.src` escape hatch — emits autoWidth:false + maxWidth:"<w>px", pinning the display width independent of the natural size. All user-provided src fields are merged (defensively; base.src may be a string), flat src props are no longer clobbered, an explicit maxWidth alone also pins, and an explicit autoWidth is honored. A string `values.src` is normalized to { url } before mapping so it is not character-spread when a flat src prop is also present. No explicit sizing stays responsive. Adds regression tests for the flat-prop and escape-hatch paths. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>Configuration menu - View commit details
-
Copy full SHA for 827c618 - Browse repository at this point
Copy the full SHA 827c618View commit details -
fix(elements): pin button width for Builder round-trip
Same class as the image fix: an explicit button width set size.width but left size.autoWidth:true, so the Builder auto-sized the button to its content and dropped the width on selection. The pin now reads the mapped size (covering the flat prop, nested prop, and `values` escape hatch) and sets size.autoWidth:false when a width is present, unless the user set autoWidth themselves. The size is guarded as a plain object before mutation so a malformed escape-hatch value is ignored rather than throwing. Adds regression tests. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Configuration menu - View commit details
-
Copy full SHA for d6d85e8 - Browse repository at this point
Copy the full SHA d6d85e8View commit details -
fix(elements): let an explicit maxWidth win over a natural width
src={{ url, width: 1600, maxWidth: "50%" }} serialized to maxWidth:"1600px", clobbering the caller's display width. width is the natural size and maxWidth is the display size, so an explicit maxWidth must take precedence — derive maxWidth from the numeric width only when no maxWidth was provided. Adds a regression test. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>Configuration menu - View commit details
-
Copy full SHA for 58e150a - Browse repository at this point
Copy the full SHA 58e150aView commit details
Commits on Jun 24, 2026
-
feat(elements): normalize CSS-idiom prop values so natural forms render
Authors (human and AI) reach for CSS habits that type-check but render blank or invalid because flat props are loosely typed. mapSemanticProps now coerces the natural form to the shape the exporters expect: - fontFamily: "Arial" -> { label, value } (a bare string was char-spread into the fontFamily group, dropping the font entirely) - fontWeight: "700" -> 700 (keyword strings like "bold" are left as-is) - fontSize / padding / borderRadius: bare number or unit-less string -> "<n>px" - lineHeight: 1.4 -> "1.4" Image sizing now accepts CSS-style width: a px string ("300px") and bare number pin the display width (autoWidth:false + maxWidth), and a percent ("50%") routes to the display maxWidth. Previously only a numeric width pinned, so width="300px" silently rendered full-width and re-triggered the select-resize round-trip. Runtime only; the types are tightened separately. Full suite green. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>Configuration menu - View commit details
-
Copy full SHA for e0e7d7d - Browse repository at this point
Copy the full SHA e0e7d7dView commit details -
feat(elements): agent-friendly prop types for the natural authoring f…
…orms The public prop types were generated from the canonical model, so the flattened semantic props were typed `any` (wrong forms type-checked and rendered broken) while the strict object forms rejected the documented/working code. Replace the `any` flat keys via Omit + re-declare with the real accepted unions: - Image `src` accepts a plain URL string or the value object; `width`/`maxWidth` accept a number, px, or percent. - Text components accept fontFamily as a string or { label, value }, fontWeight as a number/numeric-string/keyword, fontSize/lineHeight as number or string. - Heading gains the `level` alias and h1–h6 (was h1–h4); Paragraph types `text`. These pair with the runtime normalization so the natural form type-checks AND renders correctly, and clear garbage is now rejected. Adds dx-contract.test.tsx, a tsc-enforced guard (@ts-expect-error) over the should-pass / should-fail forms. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>Configuration menu - View commit details
-
Copy full SHA for 34760dc - Browse repository at this point
Copy the full SHA 34760dcView commit details -
fix(elements): make Table columns/rows render an empty grid instead o…
…f crashing The documented numeric API (columns/rows) type-checked but crashed: the flat `rows` prop collided with the nested `table.rows` data key, so the exporter iterated a number. Intercept `columns`/`rows` in the propMapper (like headers/data), set the top-level counts, and build an empty columns x rows grid when no data is given. headers/data shorthand is unchanged. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Configuration menu - View commit details
-
Copy full SHA for a936328 - Browse repository at this point
Copy the full SHA a936328View commit details -
docs(elements): document the accepted natural prop forms; add Spotify…
… example The README previously listed the CSS-idiom forms (string fontFamily, string fontWeight, numeric fontSize, padding "0", Paragraph text) as mistakes — they now work, so the guidance was actively steering authors away from working code. Updated the Critical Rules and Common Mistakes, and noted the recommended forms. Adds a Spotify Premium welcome story written in the natural form (string src + width="300px") as a living example. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Configuration menu - View commit details
-
Copy full SHA for e20a4cd - Browse repository at this point
Copy the full SHA e20a4cdView commit details -
fix(elements): treat Image width/maxWidth "100%" as responsive, not p…
…inned A "100%" display width means fill-the-container (the default responsive image behavior), so it should map to autoWidth:true rather than being pinned with autoWidth:false. Smaller percents and px widths still pin (autoWidth:false). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Configuration menu - View commit details
-
Copy full SHA for 40e9d26 - Browse repository at this point
Copy the full SHA 40e9d26View commit details -
feat(elements): loosen container padding type; add four agent example…
… stories Reconstructing the fresh-agent example templates surfaced one more footgun: an idiomatic multi-value padding with a bare 0 token ("0 48px", "8px 40px 0 40px") was type-rejected because the canonical padding type requires px on every token, even though it is valid CSS and renders fine. Loosen padding/containerPadding on Row/Column/Body to SizeInput (string | number) via Omit + re-declare. Adds four example stories under src/examples/ (Airbnb, Stripe, Nike, Linear) written in the natural authoring forms, as living proof the DX holds end to end. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>Configuration menu - View commit details
-
Copy full SHA for d802100 - Browse repository at this point
Copy the full SHA d802100View commit details -
fix(elements): handle JSX children, flat Column borders, and previewT…
…ext round-trip Three medium-severity gaps from the DX audit: - JSX/element children on text components stringified to "[object Object]". Flatten the children tree to its text content (framework-free duck-typing) so e.g. <Heading>Hi <b>x</b></Heading> renders "Hi x" instead of garbage. Use the `html` prop for inline formatting. - Flat Column border props (borderTopWidth, …) were dropped because the Column default ships an empty `border: {}` the nested-group detector can't read. Gather flat border-side props into `border` when the component declares that field. - previewText was excluded from renderToJson, so it never round-tripped to the editor. Map it to the schema's preheaderText in the body JSON. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>Configuration menu - View commit details
-
Copy full SHA for c81afda - Browse repository at this point
Copy the full SHA c81afdaView commit details
This comparison is taking too long to generate.
Unfortunately it looks like we can’t render this comparison for you right now. It might be too big, or there might be something weird with your repository.
You can try running this command locally to see the comparison on your machine:
git diff main...dx/agent-friendly-props