Skip to content

finding(types,examples): every toast demo hangs an action object off onClick, which is declared as a function and read by no dispatcher #6250

Description

@yinlianghui

Found while implementing #6157 (correcting the invented keys the live SchemaExample fixtures teach). #6157 corrects a value inside this payload; this card is about the payload's envelope, which is a larger question and was deliberately left alone there.

⚠️Dedup caveat, stated up front: the GitHub search API was rate-limited for this session at filing time, so the usual "search open issues before filing" step could not be completed. If this duplicates an existing card, close it as such — the measurement below is the part worth keeping.

Measured on e3354ba08, with packages/types built fresh

All seven components-feedback-toast/* fixtures are { "type": "button", … } with an action object hung off onClick:

{
"type": "button",
"label": "Destructive Toast",
"variant": "destructive",
"onClick": { "action": "toast", "variant": "error", "title": "Error", "description": "Something went wrong." }
}

1. The shipped type says onClick is a function.ButtonSchema.onClick is () => void | Promise<void> (form.d.ts:56), and the zod mirror is z.function(). So ButtonSchema.safeParse() on either fixture is RED — not on any variant, on the envelope:

{"code":"invalid_type","expected":"function","path":["onClick"],
"message":"Invalid input: expected function, received object"}

Control: the same object with onClick removed parses green, so this is a key-by-key result and not a schema that refuses everything.

2. No dispatcher reads it. Grepped packages/** for case 'toast', action === 'toast', === 'toast', schema.onClick and .onClick as: the only hits are ActionRunner's action.onClick() (which calls a function, the legacy callback slot) and schema-builder's setter. packages/components/src/renderers/form/button.tsx never forwards schema.onClick to the rendered Button at all. So on this tree, clicking the demo button fires nothing.

Why it matters more than one demo

This is the SDUI idiom the docs teach for "button that raises a toast" — seven fixtures on the toast page alone, plus the same shape elsewhere in the catalog — and it is declared nowhere and executed nowhere. That combination is the objectui#5250 hole at its widest: BaseSchema.passthrough() means objectui validate accepts the fixture, the docs render it, an AI few-shot retriever is invited to copy it, and nothing ever runs it.

The interesting question for triage is which way the divergence should close:

  • the fixtures are wrong — the demos should use { "type": "toast", … } (a registered component with a real renderer, renderers/feedback/toast.tsx) and stop teaching a button/action-payload shape the engine has no dispatcher for; or
  • the surface is wrong — the action-object form is the intended SDUI authoring shape, in which case ButtonSchema.onClick needs to declare the action union (it currently declares only the function) and something needs to execute it.

That is a contract question, not a fixture typo, which is why it was not folded into #6157. Note that #6157 already corrects the toast variant value inside these payloads against ToastSchema — the nearest governing declaration — and that correction stands under either resolution here.

#6157 remains open on its own scope and is not addressed by this card.

Refs: #5250 · #6157 · #6143.

Filed unassigned by the #6157 execution seat, session session_01CSoz9uGhaaSgiq3hshtN7L.

Metadata

Metadata

Assignees

Labels

documentationImprovements or additions to documentationdomain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatpm:dispatched

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions