Repository navigation
feat(app-shell): a phone record page draws one bar, its own top bar - #28883
Merged
Merged
Conversation
Below 768 px the console mounts no app bar on a record route; the record page's back bar is the only bar. AppShell gains an additive showHeader prop so the shell can draw no header element. The record page's early states (loading, not found, refused, missing, access ended, forbidden, failed) draw the same back bar on a phone, so a deep link always has a way off the page. Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QsR2jUBErc6JfKjjeojWHS
…ader; docs and changeset Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QsR2jUBErc6JfKjjeojWHS
Co-Authored-By: Claude <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QsR2jUBErc6JfKjjeojWHS
Contributor
Author
|
domain:ui#1 · zhuangjianguo · session_01QsR2jUJ19MstFvFhjgiYTu 席位核对 · ACCEPT · 2026-11-02T03:09ZHead-sha:
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.
Requested by Steedos · project thread
Fixes #28483
Clause-②: yes (widening)
Metadata-protocol: none
维护者速读
n / N↓ ↑),不再叠一条应用栏,记录名只出现一次。应用菜单、搜索、通知、账号这四扇门留在列表、首页等其它页面,记录页按一次「‹」就回到有门的页面。记录打不开时(加载中、没找到、无权访问、读取失败等),手机上同样画这条「‹」栏,深链进来也总有路出去。@object-ui/layout的AppShell新增一个可选属性showHeader(默认true),不传时渲染与以前逐字节相同,所以是加宽(Clause-② yes (widening)),changeset 为 patch。回滚就是还原本 PR。ui/packages/app-shell/src/layout/ConsoleLayout.tsx(按路由 + 视口决定不画应用栏的那一处)、ui/packages/app-shell/src/views/RecordDetailView.tsx(返回链接的常量上移到各个提前返回之前,withPhoneBar包住每个提前返回的状态)、ui/packages/layout/src/AppShell.tsx(showHeader)。pnpm --dir ui exec vitest run packages/app-shell/src/layout/__tests__/ConsoleLayout.phoneRecordOneBar-28483.test.tsx packages/app-shell/src/views/RecordDetailView.phoneGuardBar-28483.test.tsx packages/layout/src/__tests__/app-shell-show-header-28483.test.tsx,预期全部通过:390 px 记录路由零个应用栏、一条栏、记录名一次;768 px 与 1440 px 应用栏照旧。What changes
Below 768 px a console record page now has one bar at its top, its own top bar, and the record's name shows once, as the header title under it. This is the director's ruling 6556587051, letter A.
ConsoleLayout(@object-ui/app-shell) decides the app bar by route and viewport. On a phone (usePhoneViewport, 768 px, the breakpoint the record page draws its phone face at, read synchronously so the two never disagree for a frame) and on a record route, it tells the shell to draw no header. A record route is/apps/APP/OBJECT/record/IDor the same record on a named record page (.../page/PAGE), the two routesRecordDetailViewdraws (isRecordPagePath). The record's edit form (.../edit) is not one and keeps the app bar.AppShellgainsshowHeader(@object-ui/layout, optional, defaulttrue).showHeader={false}draws no header element and does not mountnavbar. Left out, the shell renders exactly as before, and a shell with nonavbarstill draws its empty bar, which an external host may rely on. Documented in the layout README'sAppShellPropstable and in the Header Bar section ofcontent/docs/frontend/app-shell.mdx.RecordDetailView's early states keep the 「‹」 bar on a phone. The page returns early while loading, for an unknown object, a named page that is not one of the object's record pages, a missing record, ended approval access, a refused read and a failed read. None of those drew the top bar, and with no app bar a phone deep link to such a record would have had no way off the page. The back-link values (pageTrail,objectListPath,originIsObjectList,phoneBackand the helpers they read) move above the guards unchanged. They are plain consts, so hook order does not change. On a phonewithPhoneBardraws the phoneRecordTopBar(the 「‹」 only) above each early state. From 768 px up those states render as before.AppHeadertests andRecordDetailView.phoneFace-27058are untouched.Tests
ConsoleLayout.phoneRecordOneBar-28483(realConsoleLayout+ realAppShell): at 390 px a record route has zero header elements and one bar, the record's own, and the record name once; the named-record-page route the same; the root routes (app home, object list, a view, a dashboard) and the edit form keep the app bar at 390 px; control at 768 px and 1440 px: the record route keeps the app bar; 767 px is already the phone face;isRecordPagePathnames the two record routes and nothing else.RecordDetailView.phoneGuardBar-28483(the realObjectStackAdapterover a stubbed transport,recordReadFailure-11902's harness): at 390 px a 403, a 404 and a 500 each draw their state under one bar whose 「‹ Invoices」 links to the object's list; control at 1440 px: the refused state draws no bar.app-shell-show-header-28483(@object-ui/layout):showHeader={false}draws no header and does not mountnavbar; controls: left out,true, and nonavbarat all each draw the bar as before.Runs (head 2e4d74e, after merging main)
scripts/ablation-replace.mjson the committed fix, restored to HEAD (blob equal,git diff HEADempty), all red as expected:ConsoleLayout:showHeader={!recordPageOwnsTopBar}toshowHeader={true}:ConsoleLayout.phoneRecordOneBar-284833 failed / 4 passed (390 px record route, named page, 767 px).RecordDetailView:withPhoneBar'sphonePage ?tofalse ?:RecordDetailView.phoneGuardBar-284833 failed / 1 passed (the 403, 404 and 500 legs; the 1440 px control stays green).AppShell:{showHeader && (to{true && (: 4 failed / 7 passed acrossapp-shell-show-header-28483andConsoleLayout.phoneRecordOneBar-28483.ConsoleLayout,AppHeaderorconsoleTopBar, everyRecordDetailViewtest that sets a viewport width, the console mobile (≤ 640 px): list as card rows with view chips and a FAB, the record page with a compact header, sticky tabs and a bottom action bar, related records pushed as full pages with a path row and back — the record is always a page on a phone #27058 phone files, the read-failure files, and the fourRecordDetailViewtests main changed: 145 files, 1039 tests passed, at--maxWorkers=2in four batches. CI's Test UI runs the rest.packages/layout/whole: 47 files, 387 tests passed. Its two guide pins first went red on the new prop (the guide'sAppShellPropstable and a header-class read that matched a JSDoc mention); the table incontent/docs/frontend/layout.mdxnow namesshowHeader, and the JSDoc no longer spells the element.turbo run type-check --filter=@object-ui/app-shell --filter=@object-ui/layout: 66 tasks successful.pnpm --dir ui exec vitest run scripts/: 169 files passed, 2 skipped.Acceptance notes
RecordDetailView.tsx: whichever lands later mergesmain..../edit) keeps the app bar on a phone; the ruling names record pages only.AppShell(showHeader), its README row,content/docs/frontend/app-shell.mdxand the record page's guard states.content/docs/frontend/layout.mdxis the third teaching surface of the same props table: its pin (guide-layout-app-shell-doc) reads the prop list out ofAppShell.tsx, so the row is added here.AppSchemaRenderergiven nonavbarstill draws an empty 48 px bordered bar. Left as is:showHeaderis opt-in and the published render is unchanged.Verification
node scripts/pm/dispatch-gates.mjs --commandsat head 2e4d74e (after merging main) names 66 families; all 66 ran locally with exit 0, and--ranreconciles 66 derived, 66 run, 0 NOT-MEASURED.check:skill-examplesfirst exited 3 (its@objectstack/client-reactprerequisite was not built); built, it exits 0.node scripts/check-sdui-manifest.mjs: exit 0 (no component config changed).check-changeset-no-major --base origin/main,check-adr-0087-registration --base origin/main,check-closing-keyword-parityandcheck-partof-closing-keyword, all exit 0.pnpm lint, the full Test UI shards, dogfood (no!in the title and no(narrowing)arm).🤖 Generated with Claude Code
https://claude.ai/code/session_01QsR2jUBErc6JfKjjeojWHS
Generated by Claude Code