Skip to content

docs(objectui): remove phantom tab-level lazy/source and badge/badgeVariant from layout-dsl - #8402

Merged
qq9340100 merged 1 commit into
mainfrom
claude/issue-8303-layout-dsl-tab-family
Aug 13, 2026
Merged

docs(objectui): remove phantom tab-level lazy/source and badge/badgeVariant from layout-dsl#8402
qq9340100 merged 1 commit into
mainfrom
claude/issue-8303-layout-dsl-tab-family

Conversation

@qq9340100

Copy link
Copy Markdown
Collaborator

Fixes#8303

The Tabs family in content/docs/protocol/objectui/layout-dsl.mdx taught four keys that exist on no schema, plus a wrapper shape the form schema rejects. Fixed by removal/rewrite following PR #8301's shape on this same page — including its "loud absence" style — never by widening a schema.

Premise re-verified on origin/main (not taken on trust)

Measured against packages/spec/authorable-surface/7840 authorable keys across all shards, 1049 in the ui shard (matches the count carried by the absorbed duplicate).

keyhitswhere
lazy0nowhere in the entire authorable surface
source19ui/Page, ui/PageVariable, ui/InterfacePageConfig, + 16 non-ui — no tab, no section
badge8all NavItem (ui/ObjectNavItem and siblings) — app navigation
badgeVariant8same 8 NavItem surfaces
pagination2ui/ListView, ui/ObjectListView (positive control)

The positive controls establish the instrument sees keys before any zero was trusted. The lazySchema grep trap is real and I walked into it deliberately: a bare grep for lazy in packages/spec/src/ui/view.zod.ts returns ~40 hits, every one the lazySchema(() => …) import helper wrapping a schema declaration. Judged by position, not count — there is no lazy: property key.

Two counts differ slightly from the issue body: source is 19 whole-surface (issue said 20) and badgeVariant/badge are 8 (as stated). The direction is unchanged and immaterial — none of the source entries is a tab or a section.

ui/ViewTab declares exactly nine keysfilter, icon, isDefault, label, name, order, pinned, view, visible — confirmed against the current generated surface. It is a list view surface (ListViewSchema.tabs, UserFiltersSchema.tabs), not a form surface, so the page's form-tab examples could never have reached it.

The wrapper was wrong independently of the leaf keys.FormViewSchema.layout is z.enum(['vertical','horizontal','inline','grid']) and FormViewSchema declares no tabs key at all. The real shape is type: tabbed + sections, each section rendering as its own tab, with defaultTab naming a section and tabPosition placing the strip — exactly as content/docs/protocol/objectui/index.mdx ("In tabbed forms each section renders as its own tab") and examples/app-showcase/src/ui/views/task.view.ts already author it. ViewTabSchema, FormViewSchema and FormSectionSchema are all strictObject, so every one of these was a parse rejection, not a silent strip.

What changed

  • ### Basic Tabs — rewritten from the rejected layout: { mode: tabbed, tabs: [...] } wrapper to the accepted type: tabbed + sections shape. Dropped the per-tab icon: too: FormSectionSchema declares no icon key, so carrying it over would have planted a fresh phantom.
  • ### Lazy-Loaded Tabs and ### Tab Badges and Counters — deleted; both were built entirely on phantom keys.
  • ### A tab carries no options of its own — new, in the loud-absence style, naming the real section surface and pointing counter-badge seekers at the NavItem surfaces where badge/badgeVariant genuinely live, and tab-option seekers at ui/ViewTab on list views.

The page's internal inconsistency is gone as a side effect: ## Performance stated an absence that an earlier passage demonstrated as working syntax. That section is untouched — I did not weaken or revert #8301's work.

Verification

All five gates green locally (re-derived against the actual changed path via scripts/pm/dispatch-gates.mjs — identical to the dispatched list, no delta):

  • check:doc-formula-expressions — 24 self-test cases; 22 formula examples across 395 files / 1410 TS blocks judged clean
  • check:docs-audit-scope — 56 + 22 self-test cases; 179 hand-written docs in sync
  • check:quick-reference-counts — 22 self-test cases pass
  • check:role-word — OK, no new occurrences
  • check:nul-bytes — 7589 files scanned, no raw control bytes

Its first run failed on ERR_MODULE_NOT_FOUND for @objectstack/formula/dist — the fresh-worktree stale-build trap, not this change. Green after pnpm --filter '@objectstack/lint^...' build.

MDX compiles (@mdx-js/mdx 3.1.1). Instrument proven both ways: a deliberately broken closing tag fails the compile, and the compiled output contains badge: { count, variant } and mode: tabbed, tabs: [...] as literal text — the braces inside inline code are not parsed as JSX expressions, matching 62 existing Callout precedents in content/docs.

Scope

Declared file surface content/docs/protocol/objectui/layout-dsl.mdx only — respected, no breach. Docs-only, no user-visible runtime change ⇒ skip-changeset, no changeset file.

One out-of-scope phantom found on the same page and filed separately rather than fixed here: the Console Template example (~line 142) authors properties: { tabs: [...] } on a record:details component, and ui/RecordDetailsProps — also strictObject — declares no tabs key (aria, columns, fields, hideFields, inlineEdit, sections, showHeader, + retired layout). Different family, different schema, outside this card's fence.


Generated by Claude Code

…ariant from layout-dsl
The Tabs family in content/docs/protocol/objectui/layout-dsl.mdx taught four
keys that exist on no schema, plus a wrapper shape the form schema rejects.
Measured against packages/spec/authorable-surface/ (7840 authorable keys):
- `lazy` returns 0 hits across the ENTIRE authorable surface, not just ui.
Positive controls, same command shape: `source` 19, `badge` 8,
`badgeVariant` 8, `pagination` 2 - the instrument plainly sees keys.
(A bare grep for `lazy` in packages/spec/src/ui/view.zod.ts hits only the
`lazySchema` import helper - position, not count.)
- All 8 `badge` / `badgeVariant` entries are on NavItem surfaces
(ui/ObjectNavItem and siblings) - app navigation, never a form tab.
None of the 19 `source` entries is a tab or a section.
- ui/ViewTab declares exactly nine keys: filter, icon, isDefault, label,
name, order, pinned, view, visible - and it is a LIST view surface
(ListViewSchema.tabs / UserFiltersSchema.tabs), not a form surface.
- FormViewSchema.layout is a string enum (vertical/horizontal/inline/grid)
and FormViewSchema declares no `tabs` key at all, so the
`layout: {mode: tabbed, tabs: [...]}` wrapper was wrong independently of
the leaf keys. The real shape is `type: tabbed` + `sections`, each section
rendering as its own tab (defaultTab / tabPosition), as
content/docs/protocol/objectui/index.mdx and
examples/app-showcase/src/ui/views/task.view.ts already author it.
ViewTabSchema, FormViewSchema and FormSectionSchema are all strictObject, so
these were parse REJECTIONS, not silent strips.
Fixed by removal/rewrite following PR #8301's shape on this same page,
including its "loud absence" style - never by widening a schema. The page's
internal inconsistency is gone as a side effect: its ## Performance section
stated an absence an earlier passage demonstrated as working syntax.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Jqe56GnYFddggeAyfkZFVz
@vercel

vercelBot commented Aug 13, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
ProjectDeploymentActionsUpdated (UTC)
objectstackIgnoredIgnoredAug 13, 2026 11:06am

Request Review

@github-actionsgithub-actionsBot added size/m documentation Improvements or additions to documentation labels Aug 13, 2026
@qq9340100qq9340100 added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Aug 13, 2026 — with Claude
@qq9340100
qq9340100 marked this pull request as ready for review August 13, 2026 11:18
@qq9340100
qq9340100 added this pull request to the merge queueAug 13, 2026
Merged via the queue into main with commit 563b345Aug 13, 2026
25 checks passed
@qq9340100
qq9340100 deleted the claude/issue-8303-layout-dsl-tab-family branch August 13, 2026 11:36
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentationImprovements or additions to documentationsize/mskip-changesetPR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

docs: layout-dsl.mdx teaches tab-level lazy/source and badge/badgeVariant keys that exist on no schema

2 participants

@qq9340100@claude