Found while fixing objectui#8197 (the collapsible.mdx content-slot row), which asked whoever picked it up to check the rest of that fence against the declaration. Measured on origin/main f57ca757b.
The reading
packages/types/src/disclosure.ts:119-122 declares:
/**
* Controlled open state
*/
open?: boolean;
and the zod twin agrees — packages/types/src/zod/disclosure.zod.ts:55 is open: z.boolean().optional().describe('Controlled open state'), so an authored open validates.
packages/components/src/renderers/disclosure/collapsible.tsx:23 is:
<Collapsible defaultOpen={schema.defaultOpen} disabled={hostDisabled} className={className} {...props}>
schema.open appears nowhere. grep -rn 'schema\.open\b' packages/ returns hits only in plugin-form (ObjectForm.tsx, ModalForm.tsx, DrawerForm.tsx) and a designer test mock — none of them the collapsible renderer. The {...props} spread carries the renderer's props, not the schema, so it does not smuggle it in either.
⇒ open is authorable on both declaration faces, accepted by the validator, and inert. An author who reaches for controlled open state gets silence: no error, no effect.
Why this was filed and not folded into objectui#8197
That card's slot is the content row. This is a declaration-side question with more than one defensible answer, and picking one is not a docs edit:
- Wire it — read
schema.open in the renderer and pass it to Radix Collapsible's open. But controlled open without a matching onOpenChange is a Radix anti-pattern, and onOpenChange is a runtime slot the zod twin refuses by name (objectui#6124), so a JSON author has no way to supply the other half. This route probably ends at "controlled open is not authorable in SDUI".
- Retire it — ADR-0049 enforce-or-remove: drop
open from the interface and the twin, leaving defaultOpen as the only authorable open state.
The second looks right, but it is a contract decision, not a mechanical fix.
Deliberately not documented on content/docs/components/disclosure/collapsible.mdx: adding a row for an inert key is the same trap objectui#8197 removed. The page stays a list of keys the renderer reads until this card resolves.
Class
Same shape as objectui#6158 (RadioGroupSchema.orientation declared on both faces, read by nothing) and objectui#5667 (CalendarViewSchema declares 9 of 13 keys the renderer never reads). objectui#4631 is the standing card about nothing reconciling the three declared surfaces.
Found while fixing objectui#8197 (the
collapsible.mdxcontent-slot row), which asked whoever picked it up to check the rest of that fence against the declaration. Measured onorigin/mainf57ca757b.The reading
packages/types/src/disclosure.ts:119-122declares:and the zod twin agrees —
packages/types/src/zod/disclosure.zod.ts:55isopen: z.boolean().optional().describe('Controlled open state'), so an authoredopenvalidates.packages/components/src/renderers/disclosure/collapsible.tsx:23is:schema.openappears nowhere.grep -rn 'schema\.open\b' packages/returns hits only inplugin-form(ObjectForm.tsx,ModalForm.tsx,DrawerForm.tsx) and a designer test mock — none of them thecollapsiblerenderer. The{...props}spread carries the renderer's props, not the schema, so it does not smuggle it in either.⇒
openis authorable on both declaration faces, accepted by the validator, and inert. An author who reaches for controlled open state gets silence: no error, no effect.Why this was filed and not folded into objectui#8197
That card's slot is the content row. This is a declaration-side question with more than one defensible answer, and picking one is not a docs edit:
schema.openin the renderer and pass it to RadixCollapsible'sopen. But controlledopenwithout a matchingonOpenChangeis a Radix anti-pattern, andonOpenChangeis a runtime slot the zod twin refuses by name (objectui#6124), so a JSON author has no way to supply the other half. This route probably ends at "controlled open is not authorable in SDUI".openfrom the interface and the twin, leavingdefaultOpenas the only authorable open state.The second looks right, but it is a contract decision, not a mechanical fix.
Deliberately not documented on
content/docs/components/disclosure/collapsible.mdx: adding a row for an inert key is the same trap objectui#8197 removed. The page stays a list of keys the renderer reads until this card resolves.Class
Same shape as objectui#6158 (
RadioGroupSchema.orientationdeclared on both faces, read by nothing) and objectui#5667 (CalendarViewSchemadeclares 9 of 13 keys the renderer never reads). objectui#4631 is the standing card about nothing reconciling the three declared surfaces.