Skip to content

Type { anywhere a value belongs: answer recall in labels, explained picker everywhere - #65

Merged
AllTerrainDeveloper merged 3 commits into
mainfrom
feature/tag-picker-everywhere
Oct 8, 2026
Merged

AllTerrainDeveloper merged 3 commits into
mainfrom
feature/tag-picker-everywhere

Conversation

@AllTerrainDeveloper

Copy link
Copy Markdown
Owner

What was wrong

The { value picker only existed in Notifications, Confirmations and the formula box. Field labels, hints, headings and HTML blocks had nothing, either on the canvas or in the inspector. A {field:…} typed there would also have printed literally on the live form, because tags were only resolved after submission. Adding the picker alone would have offered values that do nothing, so this PR makes them work too.

What changes

Answer recall (new front-end feature)

  • {field:id} in a label, hint, heading, HTML block or consent text renders as an empty .atf-recall slot (alltfo_recall_markup(), which only touches text nodes, so an href in an HTML block stays intact). The form bundle fills the slot live from the visitor's answer. Choices show their label, composites show their non-empty parts, a total shows its computed value, and an unknown id stays visible as typed.
  • Password, file, signature and repeater answers are never echoed, on either side.
  • Server-side "X is required" errors read the label with the answer filled in (alltfo_recall_text()).
  • The client schema now carries choice labels, which recall needs.

The picker wherever it applies

  • Inspector Label, Hint, HTML and consent text: Insert an answer, with earlier answers first and later ones flagged "blank until they get there".
  • Canvas inline text (label, hint, heading, toggle/consent label): typing { opens a floating picker beside the text.
  • The success screen's button label now takes merge tags. The server already resolved them there.

Better explanations

  • Each row shows its explanation and an "e.g." example. The catalogue always had both, but the list used to throw them away. Search also matches the explanation, and a footer teaches the { shortcut.
  • Formula references say what they count as: a dropdown counts as its option's price, a switch as 1 or 0, a quiz as points. Repeater references explain sum() vs avg()/min()/max(). The formula editor explains every function on hover or focus.
  • The inspector's reference line named only {field:id}, which formulas don't accept. It now gives both forms.

Bug caught in QA
The canvas repaint after an autosave didn't count an open floating picker as "editing the canvas". With the picker open for more than 2.5 s, the text a pick was about to land in got detached. The repaint now waits for the picker (pickerOwner()).

Tests

  • Vitest: 541 total, 2 skipped, all others pass. New recall.test.ts covers formatting, catalogue order and exclusions, and live fill in the form bundle. Picker tests cover explanations, the canvas { flow and ownership. Formula-editor tests cover the explanations.
  • PHPUnit: 799 pass. New recall.php covers slots, attribute safety, rendered label/hint, choice labels in the client schema, the password guard and the validation message.
  • PHPCS clean for changed files. tsc clean.
  • Manual QA on the 8889 site with the "QA pickers" form:
    • The canvas picker opens on {.
    • A pick still lands after an autosave fires mid-pick.
    • The front-end preview fills "Hi {field:name}" as "Hi Ada" while typing.
    • All QA edits were reverted.

🤖 Generated with Claude Code

AllTerrainDeveloper and others added 3 commits October 8, 2026 12:30
…ery pick

The brace picker only existed in notification and confirmation boxes and the
formula input. Labels, hints, headings and HTML blocks — on the canvas and in
the inspector — had nothing, and a {field:…} typed there printed literally on
the live form, because tags only resolved after submission.

- Answer recall: {field:id} in a label, hint, heading, HTML block or consent
  text renders as an .atf-recall slot (alltfo_recall_markup, text nodes only)
  that the form bundle fills live from the visitor's answer, choices by label.
  Password/file/signature/repeater answers are never echoed. Server-side
  required errors read the recalled label ("Which size, Ada? is required").
- The picker everywhere it applies: inspector label/hint/HTML/consent text
  offer "Insert an answer" (earlier answers first, later ones flagged as blank
  until reached); canvas inline text gets the same { shortcut via a floating
  picker; the success screen's button label now takes merge tags too.
- Better explained: each row shows what the value is and an example, search
  matches the explanation, and a footer teaches the { shortcut. Formula
  references say what they count as (price, 1/0, points), repeater references
  explain sum vs avg/min/max, and the formula editor explains every function.
- The inspector's reference line now names both grammars ({field:id} for text,
  {id} for formulas) instead of only the one formulas reject.
- Canvas repaint after autosave waits for an open picker, which previously
  detached the text a pick was about to land in.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…t on Escape

- Placeholders recall answers too: the canvas placeholder box and the
  inspector's Placeholder offer the list, and the renderer carries the
  template in data-atf-recall-template (attributes and <option> text cannot
  hold a span) for the form bundle to fill live.
- The brace is detected by what landed before the caret, not by
  event.data === '{' alone, and compositionend is handled, so layouts that
  produce { through Option/AltGr or an input method open the list as well.
  Pastes, drops and the module's own synthetic input still never do.
- Escape on canvas text put the caret at the start of the text; it now goes
  back after the brace.
- Picker examples match the field type (a colour shows #3366ff, not "Ada").

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…d questions in lists

- Recall is live, so a hint under Name reading "We will write to you as
  {field:name}" fills in while they type. The picker now lists the field
  itself under "This question" — everywhere except its own placeholder,
  which disappears the moment there is an answer.
- A label that recalls an answer ("{field:name} choose the brand colour")
  reads as "‹Your name› choose the brand colour" in the recall picker, the
  formula picker and chips, and the server's merge-tag catalogue.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@AllTerrainDeveloper
AllTerrainDeveloper merged commit 0d2870e into main Oct 8, 2026
3 checks passed
@AllTerrainDeveloper
AllTerrainDeveloper deleted the feature/tag-picker-everywhere branch October 8, 2026 11:38
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