Repository navigation
docs(layout): each page snippet names the pageType that draws its heading, or puts it in a page:header block (objectui#11423) - #11435
Conversation
…ding, or puts the heading in a page:header block (objectui#11423) A page with no pageType is a record page, and PageRenderer leaves a record page's h1 to a page:header block and never draws its description. Four passages of the layout guide set title (one with description) and no pageType, so the copied snippet drew neither. - Basic Usage names pageType app; With Action Buttons and Best Practices 3 name list. Each now draws its title, and Basic Usage its description. - Detail Page with Actions is a record page: it names pageType record and moves its heading into a page:header block's properties.title. - Basic Usage says what pageType decides; the Schema API comments on title, description and pageType say the same. New render pin guide-layout-page-headings-11423 runs every page fence of the guide that authors a heading through the real SchemaRenderer and asserts one h1 with that text, with two live controls replaying the old shapes. Ledger row added to scripts/markdown-test-inputs.mjs. Claude-Session: https://claude.ai/code/session_01YLg8XqWGJ785fwQ5v4pH37 Co-authored-by: Claude <noreply@anthropic.com>
…nd test only) Claude-Session: https://claude.ai/code/session_01YLg8XqWGJ785fwQ5v4pH37 Co-authored-by: Claude <noreply@anthropic.com>
|
changeset-claim-re-read
|
✅ Console Performance Budget
The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it. 📦 Bundle Size Report
Size Limits
|
|
Every other check on this head is green or an expected skip. The review record is on the card (objectui#11423, ACCEPT Generated by Claude Code |
Fixes #11423
Clause-②: no
What changed
content/docs/guide/layout.mdhad four page snippets that settitle(one also setdescription) and named nopageType. A page with nopageTypeis arecordpage.PageRendererleaves a record page'sh1to apage:headerblock and never draws itsdescription, so each copied snippet drew no heading. Each passage now names the page type it teaches:"pageType": "app"appis the spec's "App-level page with navigation context", and the Page Header reference's "Usage in a Page" already usesappfor a Users page."pageType": "list"listkind, "Record list/grid surface with switchable visualizations + quick actions"."pageType": "record"named; the page-leveltitleremoved; the heading moved into apage:headerblock ("properties": { "title": "Acme Corporation" }) after the breadcrumbpage:header. The buttons stayaction:buttonnodes inchildren: headeractionsare action ids resolved against a bound object, and this snippet binds none."pageType": "list"Prose: Basic Usage gains a short paragraph on what
pageTypedecides and what a page without one draws. The Detail passage says why its heading is apage:headerblock. With Action Buttons and Best Practices 3 each gain one clause. The Schema API block's comments ontitle,descriptionandpageTypenow say that arecordpage draws neither key.Every value taught is a member of the spec's
PageTypeSchema(record, home, app, utility, list).Measured first
These are one-time render probes through the real
SchemaRendererand the real renderers. The probe file was not committed.At BASE
a1a44d621, each fence verbatim:data-page-type="record"with noh1, and the description is not drawn. The only text is "User list goes here".recordwith noh1. Their buttons are drawn.pageTypeset to app, list, utility or home, the Basic Usage document draws theh1"User Management" and the description. Withrecordit draws neither.On the corrected shapes:
recordand thepage:headerblock, draws exactly oneh1, "Acme Corporation", inside the header block. Its only buttons are Edit and Delete.page:headerwithtitlewritten flat on the node is refused by both faces (invalid_unionatchildren). That is why the snippet uses thepropertiesbag shown in the guide's Page Header section.safeValidateSchemaandStrictAnyComponentSchema) accept all four corrected documents.page-width-padding-refusal-11318.test.tsalready runs every page fence of the guide through both faces, unchanged and green.The pin
New file
packages/components/src/__tests__/guide-layout-page-headings-11423.test.tsx. It derives everytype: "page"JSON fence of the guide that authors a heading, either as the page'stitleor as a titledpage:headerblock in its children. Each one is rendered through the realSchemaRendererand must draw exactly oneh1with that text. A heading drawn by apage:headerblock must sit inside that block; a heading the page draws itself must not. The four corrected passages are pinned by heading text, so the population cannot shrink to empty. Beside the render:descriptionmust draw it.titleordescriptionon a page whose effectivepageTypeisrecord.pageTypedraws neither heading nor description.h1, while its buttons still draw.The claim expected the pin in
packages/typesorpackages/layout. It landed inpackages/componentsbecause the assertion is a render. It needs React, a DOM project andPageRenderer, which lives in@object-ui/components.@object-ui/typesis zero-dependency with no React, and its tests run in the nodeunitproject. The sibling render pin for this guide's action passages,guide-layout-page-buttons-7926.test.tsx, sits in the same folder. The ledger row for the new reader is inscripts/markdown-test-inputs.mjs. An empty-frontmatter changeset declares that this releases nothing.Reverse verification
Each leg ran from committed head
f06910103. Each restore was proven by blob == HEAD and an emptygit diff HEAD. Mutations went through objectstack'sablation-replace.mjs, whose anchors had to hit. The predicted direction for every leg was red."pageType": "app",line (anchor 1 → 0): 4 failed / 9 passed. The failures are that fence's render, the description test, the static read and live control A.page:headerblock: 2 failed / 10 passed (12). The failures are the population pin and live control B. The fence drops out of the render population, which is the case the population pin exists for.a1a44d621: 8 failed / 5 passed. The failures are the four corrected passages' renders, the description test, the static read and both live controls.node scripts/markdown-test-inputs.mjs --auditexits 1 and names the pin (unadjudicated-test). My first attempt removed only the row's inner lines, which crashed the script instead of giving a verdict, so I redid it with the whole row.#page-header-pageheaderlink at a wrong slug makesscripts/check-doc-links.mjsreport a broken[anchor]link. Restored afterwards.Tests and gates (final head
01e353fa0)pnpm exec vitest runover the new pin, every ledger reader oflayout.mdandscripts/__tests__/markdown-test-inputs.test.ts: Test Files 13 passed (13), Tests 173 passed (173). The new pin alone has 13 tests and runs in thedomproject.pnpm exec turbo run build --filter='@object-ui/components^...' --concurrency=2: 7 successful.pnpm --filter @object-ui/components type-checkexits 0, and the test program (tsc -p tsconfig.test.json --listFilesOnly) includes the new pin.pnpm check:doc-types,check:doc-fences,check:doc-example-ids,check:control-bytes,check:test-path-roots,check:pending-changeset-literals,check:doc-example-readersandcheck:unreferenced-sourcesall exit 0.check:new-line-citations: 0 new citations.node scripts/check-doc-links.mjs: links valid across 17 scan roots.node scripts/markdown-test-inputs.mjs --audit: all adjudicated.node scripts/check-changeset-presence.mjs,check-changeset-no-major,check-changeset-fixed,check-changeset-overwrite,check-type-check-coverageandcheck-lint-coverageall exit 0.node scripts/check-governed-queue-guard.mjs --testover the 4 paths: NOT GOVERNED.--no-inline-config --format jsonover the 2 changed lintable files: 2 files, 0 errors, 0 warnings. The narrowing is proven:--print-configgives 119 rules for the test file and 0 forscripts/markdown-test-inputs.mjs, which is outside the linted population.eslint.config.jssets noparserOptions.projectorprojectService, and no custom rule reads the filesystem, so verdicts on untouched files cannot move.NOT MEASURED:
pnpm check:doc-snippetsandpnpm check:doc-examples: exit 2, PRECONDITION NOT MET. The 34-package build closure does not fit the foreground cap, so this is a declared narrowing. These gates judge ts/tsx/typescript fences and JSDoc@exampleblocks. The diff adds or removes none of either, and the onetypescriptfence it edits (Schema API) is a declareddoc-snippet: fragment. The unbuilt run's findings are 34unbuilt-packageand nothing about any document. CI runs both.packages/componentssuite: exit 124 at 560 s with--maxWorkers=2, past the foreground cap, so this is also a declared narrowing. The diff adds one test file and changes no source in the package. Every reader of the edited guide ran above. CI runs the full suite.Acceptance notes
Found while measuring and not fixed here; reported to the seat:
examples/schema-catalog/src/schemas/components-layout-page/settitleanddescriptionand nopageType. They are the live examples on the publishedcontent/docs/components/layout/page.mdx, one of them under "With Title and Description". Rendered through the realSchemaRenderer, each draws noh1and no description. WithpageType: "app", each draws both. That page's Schema block also omitspageType. Not fixed in place: it is another producer, and its catalog tests are a verification surface this card does not carry.content/docs/api/schema-reference.md(PageNodeSchema) teaches"pageType": "detail", and its table listslist,detail,form,dashboard,reportandcustom. Both faces refusedetail,customanddashboardwithinvalid_valueatpageType. The declared set is record, home, app, utility and list, plus the visualization aliases.titleanddescriptionon a record page pass both faces and draw nothing, and no diagnostic says so. The producers that taught the shape are this guide, now corrected, and the catalog above. A named diagnostic would be a new gate. Carrier: none.Concurrency: draft PR objectui#11069 also edits
layout.md, so whichever lands second mergesmain.mainhas moved since BASE, but none of the files this PR reads or edits changed.Session:
https://claude.ai/code/session_01YLg8XqWGJ785fwQ5v4pH37(dispatched os-dev run,domain:uiseat 1).Generated by Claude Code