Skip to content

showBorder on record:details sections is the same divergence #7129 just ruled on, one key over — spec REFUSES it, @object-ui/types declares it, the zod mirror declares it, the renderer honours it #7465

Description

@os-project-manager

Found while executing the #7129 ruling (retiring DetailViewSection.hideEmpty). ⛔ Recording only — no assignee, not claimed.

#7129 converged one of the three keys that packages/plugin-detail/src/__tests__/recordDetailsInputs.spec-parity.test.ts names as RENDERER_ONLY_SECTION_KEYS. The other two are still divergent, and showBorder is divergent in a way hideEmpty was not.

Measured on the installed @objectstack/spec 17.2.0

RecordDetailsProps.safeParse({ sections: [{ label: 'C', fields: ['phone'], showBorder: true }] })
  -> success: false, issues: [{ code: 'unrecognized_keys', keys: ['showBorder'] }]

RecordDetailsProps.safeParse({ sections: [{ label: 'C', fields: ['phone'], title: 'T' }] })
  -> success: false, issues: [{ code: 'unrecognized_keys', keys: ['title'] }]

⚠️ Control in the same probe: columns: 2 parses and the value survives — so this is about the keys, not a broken probe.

party hideEmpty (before #7129) showBorder (today)
@objectstack/spec RecordDetailsProps ⛔ refuses ⛔ refuses
@object-ui/types DetailViewSection ✅ declared (views.ts) ✅ declares (views.ts:198)
zod/views.zod.ts DetailViewSectionSchema absent declares (views.zod.ts:70)
RecordDetailsRenderer ✅ honoured ✅ honours (s.showBorder ?? (translatedTitle ? true : false))

The third row is why this is not just "#7129 again". hideEmpty's mirror was absent, so retiring the declaration made all four agree by subtraction and the mirror needed no edit. showBorder is mirrored, so three local contracts agree with each other and only the published spec disagrees. Whatever the answer is, it costs an edit somewhere that #7129's did not.

Why it is worth a decision rather than a quiet retirement

showBorder is not inert the way hideEmpty was. The renderer derives a real default from it (showBorder ?? (translatedTitle ? true : false)) and DetailSection reads it twice more (section.showBorder === false gates the flat/borderless render). So unlike hideEmpty — whose authored false provably did nothing — an authored showBorder: false does change the render. It just cannot be authored on any spec-validated page, because the document fails to parse first.

That is the shape #7129's ruling called out: a capability that exists in the renderer and is unreachable through the contract.

Options (⛔ not a recommendation from a ruling — this seat is recording)

title — related but a different question, listed so it is not conflated

DetailViewSection.title is also declared, also mirrored, also spec-refused — but since objectui#6190 it is a renderer-internal slot, not an authoring key: RecordDetailsRenderer writes title: translatedTitle from the authored label, and DetailSection reads it. So "retire it" is not the same action there. Whoever picks this up should decide the two separately.

Where the existing coverage stands

recordDetailsInputs.spec-parity.test.ts already pins the refusal of all three keys, and its RENDERER_ONLY_SECTION_KEYS docstring is explicit that membership means "keys the spec refuses that the description must not advertise", not "keys the renderer reads". So the divergence is recorded today; it is not resolved. Nothing here is a regression from #7129 — that card is complete as ruled.

Related

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

    Labels

    domain:specobjectui spec stream: fix lands on packages/types, schema corpus or spec pin coupling — spec lanefindingpm:queuepriority:p3

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions