docs(types): align two layout @default docblocks with the renderer fallbacks - #7736
Merged
Conversation
…fallbacks `ContainerSchema.maxWidth` documented `@default 'lg'` while `container.tsx` applies `schema.maxWidth ?? 'xl'`, and the shared `FlexLayoutProps.align` documented `@default 'center'` while `flex.tsx` applies `schema.align || 'start'` and `stack.tsx` applies `schema.align || 'stretch'`. The renderers are the authority — they are what runs — so only the docblocks moved; changing the reads would relayout every existing page that omits either key, which is a behaviour change and a separate ruling. `align` is the structural half: the member is declared once on `FlexLayoutProps` (objectui#6151) but its two consumers deliberately diverge, so no single `@default` value can be correct. Its tag is replaced by prose naming both consumers rather than by a second wrong single value. Pinned by `layout-default-jsdoc-7361.test.ts`, which derives each expected value by reading the renderer source off disk, so the pin turns red if either side moves. Card objectui#7361. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01BAZFhALsQsGqxui8sNqM8s
Contributor
✅ 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
|
os-justin
marked this pull request as ready for review
September 5, 2026 15:24
This was referenced Sep 5, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #7361
Two published
@defaultdocblocks inpackages/types/src/layout.tsdescribed a default that no renderer ever applies. The renderers are the authority — they are what runs — so only the docblocks moved. Changing the reads to match the tags would relayout every existing page that omits either key, which is a behaviour change and a separate ruling (the triage said so explicitly).Row 1 —
ContainerSchema.maxWidth@default 'lg'became@default 'xl', with the read site named in prose:container.tsxappliesschema.maxWidth ?? 'xl', so acontainerthat omits the key rendersmax-w-xl.Three other surfaces already agreed with the renderer and only the JSDoc dissented, which is why
'xl'is not a judgement call:container.tsxread?? 'xl'inputs[].defaultValue'xl'defaultProps.maxWidth'xl''lg'Row 2 —
FlexLayoutProps.align, and why shape (a) rather than (b)The dispatch allowed two shapes and preferred (b) — moving the tag onto
FlexSchemaandStackSchema— if those types carry a docblock where a tag can live without redeclaring the member. They do carry docblocks, but the condition is about where a tag can live as a tag for that member, and it fails:@defaultis a member-level tag. Placed on an interface docblock it attaches to the interface reflection, not toalign. TypeDoc would render it as a default value forFlexSchemaitself, and editor hover overalignon aflexnode resolves to the declaring member onFlexLayoutPropsand never sees the consuming interface's docblock. Shape (b) would therefore have replaced a wrong-value tag with a wrongly-placed one — a fresh instance of the same family the card is about, a declaration whose tooling behaviour does not match its apparent promise.So shape (a): the member keeps its single declaration (objectui#6151 —
StackSchemacannot derive it through anOmitwithout erasing every named member), and the docblock now carries no@defaulttag at all, stating both consumers in prose instead:flex.tsxreadsschema.align || 'start'stack.tsxreadsschema.align || 'stretch'("Stack items usually stretch")Dropping the tag rather than writing a tag whose text is not a value expression is the point: one shared member serving two deliberately divergent types cannot carry a single correct machine-readable default, and publishing one that is only conditionally true is what this card exists to stop. The prose still renders in hover and in the generated API reference.
Triage boundary 3 — does the tag reach anything downstream? Measured
The card's stated route is that
sdui-parserserializes the tag intosdui.manifest.jsonandsdui-intrinsics.d.ts. That is not the actual route, and the correction matters for how much this change is worth:scripts/dump-public-manifest.mjsbuilds the manifest from runtime registrations (config.inputs, viamanifestFromConfigs, read out of a real browser). Its own header says it records what each registration declares. It never opens a TypeScript source file.packages/sdui-parser/src/codegen.tsgenerates the intrinsics declaration from that manifest, not from JSDoc.git ls-filesreturns nothing for either; the manifest is written intopackages/console/distat build time), so there was nothing to regenerate here.getJSDocTags, nojsDocTags, no@microsoft/tsdoc. The only matches for those names are prose mentions of "TSDoc" inside comments.What the tag does reach is real, just different: TypeDoc is wired up (
typedoc.json, thedocs:apiscript, and the devDependency), andpackages/typesis its first entry point — its output directory is gitignored, so it is regenerated on demand. And the docblock ships: the emittedpackages/types/dist/layout.d.tscarries both corrected blocks verbatim, which is what editor hover reads for every consumer of the published package.So: no generator consumes the tag, and the card's premise that it "reaches downstream" holds for the shipped declaration file, the API reference and IDE hover — not for the serialized SDUI artefacts.
Triage boundary 4 — the census, with its denominator
layout.tsdeclares 24@defaulttags. 14 are cleanly comparable against a fallback the matching renderer actually applies; the other 10 declare a default no renderer applies as a fallback at all, so they are not comparable rather than wrong. Of the 14, 3 disagreed:ContainerSchema.maxWidth'lg'container.tsx:xlFlexLayoutProps.align'center'flex.tsx:start,stack.tsx:stretchFlexLayoutProps.direction'row'flex.tsx:row,stack.tsx:colThe remaining 11 agree. The census was matched per component type rather than by member name — several names (
variant,size,orientation,gap) recur across unrelated schemas, and a name-only sweep produces false pairs.Out-of-scope findings filed (not touched here)
FlexLayoutProps.directioncarries a shared@default 'row'that is right forflexand wrong forstack, whose renderer reads|| 'col'under the comment "Default to column for Stack". Structurally identical to row 2 and on the same interface; left alone because the dispatch drew the file surface at exactly two docblocks.packages/types/src/zod/layout.zod.tscarries.optional().default(VALUE)on these same members, and.default()substitutes at parse time. Measured through the builtsafeValidateSchema: a barecontainernode parses tomaxWidth: "lg"and a bareflexnode parses toalign: "center"— values the renderers never apply. A node that has been through the mirror therefore renders differently from the same node authored as-is. Deliberately untouched here: the dispatch ruled out moving any default VALUE, and both candidate remedies change published behaviour, so it needs a ruling rather than a patch.Both were deduplicated against open and closed issues before filing, with a known-hit control query to prove the search channel was live in this session.
Verification
All runs foreground; heavy runs through the container's shared verify lock; exit codes captured before any pipe. Everything below was re-run on the merged head
243236eaunless noted.pnpm exec vitest run --maxWorkers=2 packages/types/pnpm --filter @object-ui/types buildpnpm --filter @object-ui/types type-checkpnpm lint(whole repo)node scripts/check-changeset-presence.mjs@object-ui/types: patchcheck-changeset-fixed/-no-major/-overwritecheck-control-bytescheck-spec-symbol-derivationThe new pin is inside
tsconfig.test.json's program, proven with--listFilesOnlyrather than assumed.The pin, and its ablation
packages/types/src/__tests__/layout-default-jsdoc-7361.test.tsderives every expected value by reading the renderer sources off disk with narrow regexes and comparing them against the docblock text extracted fromlayout.ts. Nothing is written from memory, so it turns red if either side moves — a renderer changing its fallback without the docblock following is the same defect in the other direction. The regexes are guarded by explicit positive controls, because a regex that quietly matches nothing would make every assertion vacuous.Ablation, with the fix committed first, trap-guarded, absolute paths, and the mutation proven to have reached the disk before anything was read:
The pin reads source off disk rather than a built artefact, so no rebuild is needed for the mutation to take effect and the dist preflight that guards dist-resolved ablations does not apply.
Notes
layout.ts:113(alignonTextSchema, text alignment) is a different member and was left alone; it carries no@defaulttag at all.🤖 Generated with Claude Code
https://claude.ai/code/session_01BAZFhALsQsGqxui8sNqM8s
Generated by Claude Code