Skip to content

finding(types,components,docs): page.actions has no reader on the page node — the array renders nothing and leaks onto the wrapper element as actions="[object Object]", while guide/layout.md teaches it in three passages #7926

Description

@os-sam

Observation-class finding, measured on f5d2acc35 while repairing objectui#7898's nine button-key sites in content/docs/guide/. Filed unassigned — recording, not claiming; grading and domain:* are the triage seat's.

What was measured

PageNodeSchema (packages/types/src/zod/layout.zod.ts) does not declare actions — it is absent from the shape, and an authored value survives a parse only because BaseSchema is .passthrough():

PageNodeSchema.shape has `actions`: false
PageNodeSchema.safeParse({ type: 'page', title: 'Products',
                           actions: [{ type: 'button', label: 'Add Product' }] }).success === true

PageRenderer (packages/components/src/renderers/layout/page.tsx, 708 lines) has zero read points for it — grep -ni action page.tsx returns only the PageVariableActionBridge import and its render. Repo-wide, every .actions reader is a different declaration: objectDef.actions (server-declared object actions — DeclaredActionsBar, ObjectView, InterfaceListPage), page:header.actions (containers.tsx, and those are ACTION IDS, not nodes — objectui#7182), notification.actions, HeaderBarSchema.actions.

Rendered, through the real SchemaRenderer and the real renderers:

page node with actions: [ {type:'button',label:'Add Product'}, {type:'button',label:'Export'} ]
  -> buttons found in the DOM: 0
  -> "Add Product" appears anywhere in the DOM: false

the SAME two buttons moved into page.body
  -> buttons found in the DOM: 2   texts: ["Add Product","Export"]

The second half — it does not just vanish, it lands on the DOM

page.tsx does not use pickDomProps / toFormControlDomProps; it destructures a hand-maintained list of PageSchema descriptors out of props and spreads the remainder onto the wrapper element. actions is not on that list, so the array is stringified into an invalid HTML attribute. Measured attributes on the wrapper:

class="min-h-full w-full bg-background p-3 md:p-4 lg:p-6"
data-page-type="record"
data-obj-type="page"
actions="[object Object],[object Object]"

That is the exact class objectui#4425 closed for SDUI widgets by promoting the whitelist out of packages/fieldspage.tsx is one of the surfaces still closing its DOM leak by hand, and the enumeration has fallen behind the schema.

Where it is taught

content/docs/guide/layout.md teaches page.actions in three passages — "With Action Buttons", "Detail Page with Actions", and best-practice 3 "Action Buttons in Headers". objectui#7898's PR repairs the button keys inside those fences (text is not a ButtonSchema key; a top-level onClick is refused by name) and deliberately stops there: whether the page node should GROW an actions reader, or the pages should be rewritten onto body / regions + page:header, is a capability decision, not a documentation fix. That card's dispatch is explicit — a site teaching a capability that does not exist at all is reported, never routed around in prose.

Related, not duplicates

  • objectui#7469 — AppComponentSchema.actions[] (AppAction) has no reader. Same class, different declaration: that is the app node, this is the SDUI page node.
  • objectui#7693 — the alert-dialog fixtures author an actions array no surface carries. Same class, third surface.
  • objectui#4425 — the DOM pass-through whitelist; page.tsx never adopted it, which is why this key leaks rather than being dropped.
  • objectui#5250 — the instrument-level card: JSON doc snippets are judged by nothing, and .passthrough() is why a naive gate would be vacuous.

How to re-measure

git grep -n "actions" packages/components/src/renderers/layout/page.tsx
node -e "import('./packages/types/dist/zod/layout.zod.js').then(m=>console.log(Object.keys(m.PageNodeSchema.shape).includes('actions')))"

Filed by the os-dev seat working objectui#7898; session https://claude.ai/code/session_01KbJQ1y1J12nZxYzFWhP8Q3

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions