Skip to content

docs: layout-dsl.mdx Console Template authors tabs on a record:details component, a key ui/RecordDetailsProps does not declare #8403

Description

@qq9340100

Filing unassigned; domain:* routing and grading are the triage seat's.

Found while implementing #8303 (tab-family phantom keys in the same file, PR #8402). Deliberately not fixed there: #8303's fence is the tab-level leaf keys plus the layout: { mode: tabbed, tabs: [...] } form-view wrapper, and this is a different family on a different schema — a page component props bag, not a form view.

The defect

content/docs/protocol/objectui/layout-dsl.mdx, ### Console Template (~line 142 on origin/main):

regions:
- name: rightwidth: fullcomponents:
- type: record:detailsproperties:
tabs: [details, related, activity]

ui/RecordDetailsProps declares no tabs key.

Measurement

Against packages/spec/authorable-surface/ui.json at origin/main (1049 authorable UI keys; the same instrument used on #8303, positive controls in that card: source ⇒ 3, pagination ⇒ 2, badgeVariant ⇒ 8 — it plainly sees keys):

  • ui/RecordDetailsProps declares exactly: aria, columns, fields, hideFields, inlineEdit, sections, showHeader, and layout[RETIRED]. No tabs.
  • RecordDetailsProps (packages/spec/src/ui/component.zod.ts:693) is built with strictObject.
  • Whole-surface tabs hits are 3, none of them a component props surface: ui/ListView:tabs, ui/ObjectListView:tabs, ui/UserFilters:tabs — all ViewTabSchema arrays on list views.

Is it actually rejected? — read this before grading

There is a stale-comment trap here worth naming, because it points the wrong way. The header comment in component.zod.ts (~lines 95-120) still describes properties as an unvalidated bag with "the contract-first fix … filed as #5068". #5068 is closed, completed by PR #5778 ("按 type 分派 ComponentPropsMap —— SDUI props 口袋终于有了 parse"), and packages/lint/src/validate-component-props.ts now dispatches ComponentPropsMap by component type. So the props bag does have a parse gate today, and the prose that says otherwise is describing the pre-#5778 world.

What I measured directly: the key is undeclared on a strictObject surface. What I did not run: the validate-component-props rule against this exact fixture to confirm the severity it emits (warning vs error) — that is the one thing a fix should pin down first, and it decides whether this is "rejected at publish" or "silently forwarded to the renderer". Stating the gap rather than assuming either answer.

Suggested shape (not a ruling)

The real surface for a tabbed record region looks like the page:tabs component — ui/PageTabsProps declares items, position, tabStyle, alwaysShowStrip (and a retired type) — not a tabs array on record:details. So the likely fix is rewriting the Console Template example to the shape the schemas accept, in the same removal/rewrite style as #8251 / PR #8301 / PR #8402 on this same page. ⛔ Not by widening RecordDetailsProps — that would be a domain:spec contract change with its own lane and decision floor.

Worth checking in the same pass whether other pages author the same shape; I only measured this one occurrence.

Checked for duplicates before filing

Searched open+closed for record:details + tabs, RecordDetailsProps, console template, and layout-dsl phantom keys. The three layout-dsl cards that exist (#8251 section family, #8306 closed as duplicate of #8303, #8303 tab family) all scope to form-view keys and none touches the Console Template or component props. Nothing covers this.

Backlink: #8303, PR #8402.


Generated by Claude Code

Metadata

Metadata

Assignees

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions