Skip to content

Make every setting a field type declares reachable from the builder - #2

Merged
AllTerrainDeveloper merged 1 commit into
mainfrom
wysiwyg-polish
Aug 15, 2026
Merged

AllTerrainDeveloper merged 1 commit into
mainfrom
wysiwyg-polish

Conversation

@AllTerrainDeveloper

Copy link
Copy Markdown
Owner

What was wrong

A field type declares what it supports; the inspector decides what to draw. Nothing joined those two, so thirty-two supported settings had no control anywhere in the builder.

The heading level on a heading. The markup in an HTML block. The file types a file field accepts. How many rows a repeater allows. The words on the ends of a scale. The button at the bottom of a page break — which is where this started, because a multi-page form in any language other than English shipped a button saying Next and there was nothing to be done about it.

Every one of them worked perfectly once set. That is why nobody noticed: the renderer honoured them, the schema stored them, the tests passed. The only way to set one was to export the form as JSON, edit it by hand, and import it back.

What this does

The join is a table. One line per setting, and tests/vitest/field-settings.test.ts reads the PHP registrations and fails when a flag has no control and no stated reason to lack one. A list kept by hand here would agree with itself forever while disagreeing with the plugin.

The visible parts are edited where they appear. The hint under any control that offers one, the page break's own Next and Back buttons, the repeater's Add button, the name of the step. Both panes stay in step by naming the property they edit — data-atfb-bind — rather than by two hand-kept lists of keys.

Bugs found on the way

  • prevLabel never rendered. A page's Back button read the break that closes that page, but the wording belongs to the break that opened it — the same one whose Next brought the visitor there. On a two-page form the setting was unreachable by construction.
  • The form title was outside the theme. It sits outside .atf-form, where the tokens were scoped, so every var( --atf-* ) on it was invalid — taking its font, size, colour and bottom margin with it. It had been wearing the site theme's h2 and sitting flush against the step indicator. Tokens are now scoped to the wrapper, which carries the instance id anyway.
  • A switch rendered as a tick box. It now draws a switch, and the canvas tells a switch from a consent box the same way the front end does.
  • A toggle drew its label twice — once as the field label, once beside the control.
  • The hint sat above the control on the canvas and below it on the page.
  • Eight flags promised settings nothing read — calc, confirm, counter, searchable, disabledays, defaultcountry, explanation, and a rating icon. Removed rather than given controls that would do nothing.

The one that could have corrupted data

Likert statements are edited one per line. A row is { key, label }, and the key is what every answer is stored against. Writing them as plain strings — which the first version of this did — would have meant that correcting a typo in a statement detached every answer already given to it, in entries collected months ago that nobody looks at again until an export. Nothing would error; the matrix would just start counting from zero. Keys now survive rewording, and new lines never reuse a retired key.

Verified

  • 480 PHPUnit, 194 Vitest, PHPCS clean.
  • End to end in the browser: a Next button renamed on the canvas updates the inspector as it is typed, and the published two-page form shows ["Continuar","Atras","Send"].
  • Every field type's inspector inspected in a real builder window; all 32 settings now appear, with the address parts arriving through atf_address_parts rather than a copy.

🤖 Generated with Claude Code

https://claude.ai/code/session_0119U4sRRWGcTQdwYreTwpAp

A field type says what it supports; the inspector decides what to draw.
Nothing joined those two, and the result was not a bug anybody could see:
thirty-two supported settings had no control anywhere. The heading level on
a heading. The markup in an HTML block. The file types a file field accepts.
How many rows a repeater allows. The words on the ends of a scale. The
button at the bottom of a page break — which is where this started, because
a multi-page form in any language other than English shipped a button
saying "Next" and there was nothing to be done about it.

Every one of them worked perfectly once set, which is exactly why nobody
noticed: the renderer honoured them, the schema stored them, the tests
passed, and the only way to set one was to export the form as JSON, edit it
by hand, and import it back.

The join is now a table — one line per setting — and a test that reads the
PHP registrations and fails when a flag has no control and no stated reason
to lack one. A hand-kept list here would have agreed with itself forever
while disagreeing with the plugin.

On the canvas, the settings that are visible parts of the field are edited
where they appear: the hint under any control that offers one, the page
break's own Next and Back buttons, the repeater's Add button, the name of
the step. Both panes stay in step by naming the property they edit rather
than by two hand-kept lists of keys, which is one list fewer to forget.

Also fixed, all found while doing the above:

- `prevLabel` never rendered. A page's Back button read the break that
  *closes* that page, but the wording belongs to the break that opened it —
  the same one whose Next brought the visitor there. On a two-page form the
  setting was unreachable by construction.
- The form title sat outside `.atf-form`, where the theme's tokens are
  scoped, so every `var( --atf-* )` on it was invalid — taking its font,
  size, colour and bottom margin with them. It had been wearing the site
  theme's `h2` and sitting flush against the step indicator. The tokens are
  now scoped to the wrapper, which is what the instance id is on anyway.
- A switch rendered as a tick box. It now draws a switch, and the preview
  tells the two apart the same way the front end does.
- A toggle drew its label twice, once as the field label and once beside
  the control.
- The hint sat above the control on the canvas and below it on the page.
- `calc`, `confirm`, `counter`, `searchable`, `disabledays`,
  `defaultcountry`, `explanation` and a rating `icon` were declared and
  read by nothing. Removed rather than given controls that would do
  nothing.

Likert statements are edited as one per line, and a row's key is what its
answers are stored against — so keys survive rewording. Correcting a typo
in a statement must not detach every answer already given to it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0119U4sRRWGcTQdwYreTwpAp
@AllTerrainDeveloper
AllTerrainDeveloper merged commit fe88de3 into main Aug 15, 2026
3 checks passed
@AllTerrainDeveloper
AllTerrainDeveloper deleted the wysiwyg-polish branch August 15, 2026 23:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant