docs(layout): PageHeader 的 Styling/Container 按代码改写,并把它的 live demo 换成真组件 (#3786, #3787) - #3905
Merged
Merged
Conversation
…ke its demo use the component (#3786, #3787) #3786 — `content/docs/layout/page-header.mdx` Styling -> Container restated three values the component does not have. Rewritten against `packages/layout/src/PageHeader.tsx:210-211`: `pb-4` with no responsive variant (the section promised `pb-8` on desktop), `gap-3` on the outer column with the title row's own `gap-x-4 gap-y-2` spelled out (it said `gap-4`), and the undocumented `border-b` added. Readers of this section are override authors using the public `className` seam, so the old numbers produced wrong layouts. #3787 — the page's only runnable example hand-rolled a header out of `div`/`text`/`button` with Tailwind classes copied from `PageHeader.tsx`. It taught authors to bypass the component, exercised none of `page-header`'s rendering, and held a third (already drifted) copy of the spacing numbers. It is now a real `page-header` node with `title`/`subtitle`/`icon` and the two buttons as schema children, which deletes that third copy. Rendering the node needed a registration the docs site never had: nothing pulled in `@object-ui/layout`, so `page-header` produced the red "Unknown component type" panel (OBJUI-001). Added as a site dependency plus `registerLayoutBlocks.ts`, imported by all three hosts that render catalog examples — `SchemaThumbnail` renders the whole catalog on `/docs/guide/schema-catalog`, so a page-local loader would have left that index broken for the same example. The registrar is called explicitly because `@object-ui/layout` declares `sideEffects: false`. Measured, not assumed: `children` do reach the right-hand slot even though the registration has no `isContainer: true` (that flag is registry metadata the render path never consults), while the first-class `actions` form renders "Unknown component type: record:quick_actions" here because `record:quick_actions` lives in `@object-ui/plugin-detail`, which the site also does not depend on. Hence the children form.
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
Contributor
✅ Console Performance Budget
📦 Bundle Size Report
Size Limits
|
Collaborator
Author
|
✅ 验收(PM,session 实物核验:头 裁定要点:
转 ready 并挂 auto-merge。越界 #3899(sideEffects vs 自动注册,两个语义相反修向归维护者)/#3900(isContainer 契约)/#3902(假断言第四份副本,<2 行)/#3903(缩略图嵌套 button hydration,先于本 PR)/#3904(Playground 第四宿主 + transpilePackages 漂移)归分诊席。 Generated by Claude Code |
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 #3786
Fixes #3787
两单结对一 PR(PR #3826 先例):它们是同一组样式数值的两份漂移副本。demo 手抄的正是 #3786 那三条已漂的数值,分开修会互相踩;demo 换成组件节点后,那组数值的第三份副本自然消灭(下面「第三份副本」一节)。
自
origin/main显式 shaa0693d531094dc7f23b8ccd992539c796b9af6e7切出。#3786 面 —— Styling → Container 三条
packages/layout/src/PageHeader.tsx:210的根 class 现状(动笔前在 origin/main 复核过,与单里一致):content/docs/layout/page-header.mdx的 Container 小节按此改写,三条对三条:pb-4on mobile,pb-8on desktoppb-4,无任何断点变体pb-4at every breakpoint — there is no responsive variantgap-4between elementsgap-3;标题行gap-x-4 gap-y-2(:211)gap-3on the outer column;标题行的gap-x-4 gap-y-2一并写明border-bborder-balong the bottom edge内层
gap-x-4 gap-y-2选择如实展开而不是略过:这一节的读者是拿公开className口子做覆盖的作者,只知道外层gap-3仍会算错标题与右槽之间的横向间距。同小节的 Title(
:231)与 Subtitle(:233)两块复核后与代码一致,未动。「把样式数值文档改成指向代码」的根治方向按单里的裁定未搭车。#3787 面 —— 先量再写
单里写明这是要看运行环境的活,所以第一步是两点实测。两点的结论都和单里的猜测不同,记在这里:
实测 1:
children能进右槽,isContainer与渲染无关单里担心
page-header注册没有isContainer: true(packages/layout/src/index.ts:50-58)会让右槽空掉。实测:不会。isContainer在渲染路径上没有任何消费者 —— 全仓消费者只有packages/sdui-parser/src/validate.ts:89的not-a-container诊断、Studio 调色板元数据(page.tsx:464/react-page.tsx:66)和 codegen 的文档表格。真正的通路是另外两处配合:SchemaRenderer把children从 React props 里剥掉,但始终把整个节点作为schema传下去(packages/react/src/SchemaRenderer.tsx:396、:456),PageHeader再自己把schema.children渲染回右槽(PageHeader.tsx:182-190、:207)。浏览器读数(
page-header节点 + 两个 button children):这条通路横跨两个文件、靠注释维系,所以配了 pin(见下)。
实测 2:
actions形态在无后端 gallery 渲染不出 —— 但卡点不是 record 上下文单里推测第一等
actions委派record:quick_actions需要 record 上下文。实测卡在更前一层:record:quick_actions住在@object-ui/plugin-detail,而文档站不依赖它。把 demo 写成actions形态的实际读数是右槽里套一块红面板:(
record:quick_actions本身对内联 ActionDef 数组并不需要 record 上下文 ——needsLookup只在 actions 是字符串 id 时才要objectName。但这里够不到那一步。)按单里的规则(两条都能用才二选一,拿不到就选 children):选 children 形态,标题「With Actions」的语义由右槽两个按钮保留。
实测 3(单里没要求,但决定了这个 PR 的面):demo 换成组件节点后根本渲染不出来
单里提议的那份 JSON 直接落上去,文档页上是一块红面板:
原因:
@object-ui/layout既不是apps/site的依赖,也没有任何代码 import 它(apps/site/node_modules/@object-ui/下没有 symlink;next.config.mjs的transpilePackages倒是列着它 —— 一条不生效的配置,已另立 #3904)。page-header的占位符也接不住:它在placeholders.tsx里属于 opt-in 名单,只有apps/console调registerPlaceholders()。也就是说 #3787 无法只靠改一份 JSON 关掉。本 PR 补上最小的注册面:
apps/site/package.json加@object-ui/layout依赖(+ lockfile)apps/site/app/components/registerLayoutBlocks.ts,由三个渲染 catalog 示例的宿主 import:InteractiveDemo、SchemaThumbnail、LiveSplitDemo三个而不是一个,是扫过消费半径后的结论:
SchemaThumbnail在/docs/guide/schema-catalog上渲染整个 catalog,只在组件页包一层 loader 会把索引页留在红面板状态。两个页面都实测过:/docs/layout/page-headerflex flex-col gap-3 pb-4 border-b/docs/guide/schema-catalogflex flex-col gap-3 pb-4 border-bregistrar 是显式调用的,尽管
@object-ui/layout的模块体自己也会调:该包声明了sideEffects: false,纯副作用 import 可以被打包器整体丢掉。这是绕行不是修复,原因写在模块头,并另立了 #3899。模块作用域调用(不是放进 effect)也保证 server render 时注册已完成,demo 留在预渲染 HTML 里。顺带被消灭的:第三份副本 + 两个附带修正
demo 原来手抄了
text-2xl font-bold tracking-tight/text-sm text-muted-foreground/gap-4 pb-4—— 与组件、文档 Styling 小节并列的第三份副本,而且已经漂了(抄的正是 #3786 修掉的gap-4)。换成组件节点后这份副本没有了,同一组数值回到一处。另外两条附带:div节点都在触发The "div" component is deprecated弃用警告,现在没有了。span,整个 demo 一个h1都没有 —— 这一页的 Accessibility 小节却承诺「Semantic HTML (h1for title)」。现在真的渲染出h1: ["Users"]。测试
新增
examples/schema-catalog/test/pageheader-with-actions.test.tsx(4 条)。分两类事实钉:形状(根节点是page-header;JSON 里不再出现只属于PageHeader.tsx的 class 串 —— 有人再手搓就红)与渲染(走真SchemaRenderer,断言h1标题、副标题、两个 children 都到右槽)。第 4 条钉住 #3786 那三条数值的代码侧:gap-3/pb-4/border-b都在,且不含sm|md|lg|xl:pb-断点变体 —— class 一改就红,提示回来同步文档。钉代码侧不是单里推迟的那个「文档改成指向代码」的根治方案,只是普通组件 pin。反向验证(方向事前判定为红):把手搓 div 版 JSON 放回去,4 条全红,且第 4 条是在正向断言上失败而不是空过 —— 这条尤其要看清,因为
page-header根节点不存在时className取到空串,末尾那句not.toMatch本身是会空过的:examples/schema-catalog的 tsconfigexclude了test/(既有两个测试同此),所以仓库门禁不做这个文件的类型检查;另跑了一次定向tsc --noEmit通过。门禁
pnpm exec vitest run examples/schema-catalog packages/layout --maxWorkers=2→ 9 files / 944 tests passedpnpm exec turbo run type-check --concurrency=2→ 78/78 successful(apps/site没有type-checktask,单独跑了pnpm --filter @object-ui/site types:check,通过)pnpm exec eslint(全部改动文件)→ 0 errors(LiveSplitDemo的 2 条set-state-in-effectwarning 在:153-156,既有代码,与本次 import 无关)node scripts/check-doc-links.mjs→ Links are valid across 7 scan rootsnode scripts/check-control-bytes.mjs→ OK;改动文件另做grep -naP控制字节自扫,零命中node scripts/check-changeset-presence.mjs→ No source of a released package changed in this range, so no changeset is owed(改动全部落在content/docs、examples/schema-catalog、apps/site,无 released 包的src/)浏览器实证用仓库自带 Playwright + Next dev,截图与读数见上;完整 demo 外观:图标块 + 加粗
h1标题 + 副标题 + 右对齐 Export / Add User + 底部border-b。越界发现(均已另立单,本 PR 不碰)
sideEffects: falsecontradicts the load-timeregisterLayout()— a side-effect-only import can be tree-shaken away #3899 —packages/layout声明sideEffects: false却把注册放在模块加载副作用里,纯副作用 import 可被 tree-shake 掉(本 PR 显式调 registrar 绕开)page-header注册缺isContainer: true,而PageHeader有意渲染schema.children—— sdui-parser 对文档认可的写法报not-a-container#3900 —page-header注册缺isContainer: true,而组件与文档都认schema.children,sdui-parser 因此对本 PR 的 demo 写法报not-a-containerpage-header.mdx的 Responsive Behavior 仍写「Spacing: Adjusts padding for different screen sizes」—— 与 #3786 修掉的pb-8 on desktop是同一个假断言 #3902 — 同一文档页 Responsive Behavior 的「Spacing: Adjusts padding for different screen sizes」是 docs:page-header.mdx的 Styling/Container 两条数值与 PageHeader.tsx 不符(pb-8 on desktop、gap-4) #3786 那个假断言的第四份副本(在 docs:page-header.mdx的 Styling/Container 两条数值与 PageHeader.tsx 不符(pb-8 on desktop、gap-4) #3786 钉定的面之外)button里,85 个含 button 节点的示例都触发 React 嵌套按钮 hydration 报错 #3903 — Schema Catalog 索引页把缩略图包在button里,85 个含 button 节点的示例都触发嵌套按钮 hydration 报错(先于本 PR 存在)page-header得红色错误面板);transpilePackages还列着两个非依赖包 #3904 — Playground 是第四个渲染宿主、仍未注册 layout;transpilePackages还列着两个非依赖包协调
不碰
PageHeader.tsx本体(两单都是文档/示例面);与在飞 #3852(cli)、#3838(plugin-detail)、#3837(app-shell/ai)零文件相交;#3789(description退役,pm:blocked)未碰。Generated by Claude Code