Found while implementing objectui#6250, and it constrained that PR's answer — recording it rather than resolving it there, because both halves are declaration-side calls.
Measured on 7975f2d85, packages/types built fresh
Direction 1 — read by the renderer, declared by no type
packages/components/src/renderers/feedback/toast.tsx:
<ButtononClick={showToast}variant={schema.buttonVariant}className={schema.className}> // :30
{schema.buttonLabel||'Show Toast'} // :31ToastSchema (packages/types/src/feedback.ts:115, mirror packages/types/src/zod/feedback.zod.ts:61) declares type, title, description, variant, duration, position, action, onDismiss. Neither buttonLabel nor buttonVariant.
The registry metadata in the same renderer file declares buttonLabel as an authoring input (:49, defaultValue: 'Show Toast') — so the designer offers a control for a key the shipped type does not have — and declares no buttonVariant input at all, so that one is read by the renderer and named by nothing.
SonnerSchema declares both (feedback.ts:204ff: buttonLabel?: string, buttonVariant?: 'default' | 'secondary' | 'destructive' | 'outline' | 'ghost' | 'link'). The two sibling components have the same trigger-button mechanism and only one of them declares it.
Direction 2 — declared by the type, read by no renderer
ToastSchema declares:
action?: { label: string; onClick: ()=>void};// feedback.ts:143
onDismiss?: ()=>void;// feedback.ts:150renderers/feedback/toast.tsx reads neither. Its whole body is toastFn(title, { description, duration }) plus the trigger <Button>, so there is no in-toast action button and no dismiss callback on this tree. The zod mirror widens action further (z.union([SchemaNodeSchema, z.array(SchemaNodeSchema)])), and onDismiss is a z.function() — one of the mirror keys objectui#6124 measures as unsatisfiable by any JSON document.
Why this is being filed rather than fixed
objectui#6250's charter is "docs teach only what runs", and it hit both halves at once:
- Direction 2 meant its "With Action" and "With Undo Action" demos had no working spelling — the toast renderer cannot draw an in-toast action button — so those demos were re-pointed at the
info and warning variants instead. sonner's "Promise Toast" demo went the same way, for the same reason. - Direction 1 meant the corrected toast demos could not author a per-demo trigger label the way the corrected sonner demos can, so all seven now render the default
Show Toast button. Teaching buttonLabel would have re-introduced an undeclared key into the very fixtures that card was cleaning; objectui#6161 already set the posture here — "a key a renderer genuinely reads would have been routed out as an undeclared capability rather than deleted".
This is that routing-out.
The two resolutions are opposite in kind
- Direction 1 is declare what already runs: add
buttonLabel / buttonVariant to ToastSchema and its mirror, matching SonnerSchema limb for limb. Cheap, and it makes the seven toast demos expressible. - Direction 2 is enforce or remove (ADR-0049 shape): either the renderer grows an action button and a dismiss callback — a capability expansion with zero runtime today, so implementation-first posture applies — or
action / onDismiss are retired from ToastSchema.
Unassigned; no grading — triage's call, and the second half may belong with the objectui#6182 / objectui#6124 handler-dialect family.
Refs: objectui#6250 · objectui#6124 · objectui#6161 · objectui#6157 · objectui#5250.
Filed by the objectui#6250 execution seat, session session_011SfZeFWrhGLHmfq61xbz4q.
Generated by Claude Code
Found while implementing objectui#6250, and it constrained that PR's answer — recording it rather than resolving it there, because both halves are declaration-side calls.
Measured on
7975f2d85,packages/typesbuilt freshDirection 1 — read by the renderer, declared by no type
packages/components/src/renderers/feedback/toast.tsx:ToastSchema(packages/types/src/feedback.ts:115, mirrorpackages/types/src/zod/feedback.zod.ts:61) declarestype,title,description,variant,duration,position,action,onDismiss. NeitherbuttonLabelnorbuttonVariant.The registry metadata in the same renderer file declares
buttonLabelas an authoring input (:49,defaultValue: 'Show Toast') — so the designer offers a control for a key the shipped type does not have — and declares nobuttonVariantinput at all, so that one is read by the renderer and named by nothing.SonnerSchemadeclares both (feedback.ts:204ff:buttonLabel?: string,buttonVariant?: 'default' | 'secondary' | 'destructive' | 'outline' | 'ghost' | 'link'). The two sibling components have the same trigger-button mechanism and only one of them declares it.Direction 2 — declared by the type, read by no renderer
ToastSchemadeclares:renderers/feedback/toast.tsxreads neither. Its whole body istoastFn(title, { description, duration })plus the trigger<Button>, so there is no in-toast action button and no dismiss callback on this tree. The zod mirror widensactionfurther (z.union([SchemaNodeSchema, z.array(SchemaNodeSchema)])), andonDismissis az.function()— one of the mirror keys objectui#6124 measures as unsatisfiable by any JSON document.Why this is being filed rather than fixed
objectui#6250's charter is "docs teach only what runs", and it hit both halves at once:
infoandwarningvariants instead.sonner's "Promise Toast" demo went the same way, for the same reason.Show Toastbutton. TeachingbuttonLabelwould have re-introduced an undeclared key into the very fixtures that card was cleaning; objectui#6161 already set the posture here — "a key a renderer genuinely reads would have been routed out as an undeclared capability rather than deleted".This is that routing-out.
The two resolutions are opposite in kind
buttonLabel/buttonVarianttoToastSchemaand its mirror, matchingSonnerSchemalimb for limb. Cheap, and it makes the seven toast demos expressible.action/onDismissare retired fromToastSchema.Unassigned; no grading — triage's call, and the second half may belong with the objectui#6182 / objectui#6124 handler-dialect family.
Refs: objectui#6250 · objectui#6124 · objectui#6161 · objectui#6157 · objectui#5250.
Filed by the objectui#6250 execution seat, session
session_011SfZeFWrhGLHmfq61xbz4q.Generated by Claude Code