Repository navigation
Commit 273137d
fix(plugin-detail,app-shell,components): record page round 2 — related OFF draws no column or rail, one segmented panel control in the header row, three columns in a 1440 window with the sidebar (#27473)
Fixes #27055
Fixes #27241
Clause-②: no
Metadata-protocol: none
Round 2 of the record page v3 (epic #26676), on `main` after #27310: the
three rulings of #27241, the #27069 fence half of #27055, and a standing
「恢复默认顺序」 entry. Maintainer, 2026-10-28, verbatim: 「是:三栏阈值改成 1440
窗口(含侧栏)即三栏;开关改进头部动作行,关联 OFF 就没有栏」.
## What changes
**A1 — the related switch decides whether the column exists.**
`recordPageArrangementFor` sets `relatedRail` to `switches.related &&
!columns.includes('related')`, and `RecordPageColumns` draws the related
column only when the arrangement places it. Related OFF: no related
column and no rail toggle, in both column tiers. Related ON with no room
(two-column tier): the rail toggle, which opens the column. With both
switches off the page is the details column alone.
**A2 — one segmented control at the end of the header's action row.**
`PanelToggles` (`@object-ui/components`) is now one segmented control,
an icon and a label per segment (Timeline with the activity glyph,
Related column with the right-panel glyph). The console's record view
hands it to `page:header` through a new host slot,
`PageHeaderTrailingContext`. `PageHeaderActions` draws it as the last
segment of its `role=toolbar` row, after `⋯`, behind a vertical
hairline. It is drawn in both column tiers, and not in the tabbed tier
or in the drawer. The toolbar gained `max-w-full`, so on a narrow header
the segment wraps onto its own line, right-aligned, instead of running
past the page (measured at a 1024 px window; see screenshot 08). The
crumb row keeps only the ways back (origin link, 「Collapse to drawer」)
and has no child without one, so `empty:hidden` removes it. Tooltip
keycaps and `aria-keyshortcuts` are unchanged. The chord matcher accepts
`code` `Period` / `Comma`, or `key` `.` / `>` and `,` / `<`.
**A3 — thresholds.** Measured on the console from this branch (HotCRM
contact, sidebar expanded): the sidebar is 255 px plus its 1 px border,
and `[data-record-page-root]` is 1184 px in a 1440 window, 1024 px in
1280 and 768 px in 1024. The constants are `1440 − 256 − 64 = 1120` and
`1024 − 256 − 8 = 760`, with the derivation in their docblock. The
#26758 tier pins move to 1120 / 760, plus a pin on the three windows the
thresholds serve. `e2e/live/record-history-display.spec.ts` opens the
tab strip, so its viewport moves from 1200 to 1000, which keeps the
record view under the new two-column floor.
**B — the #27069 fence half.**
- *Default order.* The premise was half stale. `deriveRelatedLists`
already orders by the object's `relatedLists`
(`resolveRelatedListOrder`, landed with #27215/#27303), and `synthParts`
keeps that order. Only the fence comment said otherwise. The comment is
replaced, and a mounted pin (`RecordDetailView.relatedListsOrder-27241`)
holds the card order with and without `relatedLists`.
- *Body-table placement.* `bodyTablePlacement` reads the field groups. A
body table whose relationship a group's `relatedList` names (child
object name, or `object.field`) is drawn at that group's position among
`fieldGroups`. Other body tables keep the "after the first section"
rule. The one reading of an entry, `relatedListEntryNames`, moved from
app-shell into `@object-ui/plugin-detail` (app-shell re-exports it), so
the order and the placement cannot read an entry two ways.
**C — standing 「恢复默认顺序」.** `resolveRelatedArrangement` now reports
`rearranged`: the shown order differs from the default, or a card is
hidden. The column foot, which is the same line as 「已隐藏 N 张 · 显示」 and
appears in both the related column and the tabbed tier's Related tab,
then offers 「Restore default order」 (new key
`detail.relatedRestoreDefaultOrder`, ten packs). It writes the new edit
`restore-default-arrangement`: `order: []`, `hidden: []`, `basedOn` set
to the current default's hash, `seen: {}`. Collapsed state is kept. The
stored shape `{v,order,collapsed,hidden,basedOn,seen}` is unchanged.
`RelatedDefaultChangedHint` is unchanged.
Not touched: `packages/spec/**`, `navigation-overlay.tsx`,
`recordDrawerStack.tsx`.
## Screenshots
HotCRM contact record page. The console runs on vite from this branch;
the backend is `objectstack dev --fresh --seed-admin` from hotcrm
1f3f8880; headless Chromium. The images are on the never-merged branch
`claude/issue-27055-evidence-20261029`.
1. [1440 window, sidebar expanded: three columns, the segmented control
in the header
row](https://github.com/objectstack-ai/objectstack/blob/f6062d78b65b8cd830fbed665d60b8c0ea9441a7/evidence/27241/01-1440-three-columns-both-on.png?raw=true)
· [header row close
up](https://github.com/objectstack-ai/objectstack/blob/f6062d78b65b8cd830fbed665d60b8c0ea9441a7/evidence/27241/02-1440-header-row-segmented.png?raw=true)
2. [Related OFF: details and timeline, no rail
toggle](https://github.com/objectstack-ai/objectstack/blob/f6062d78b65b8cd830fbed665d60b8c0ea9441a7/evidence/27241/03-1440-related-off.png?raw=true)
3. [Timeline OFF: details and related, the timeline folded at the
related column's
foot](https://github.com/objectstack-ai/objectstack/blob/f6062d78b65b8cd830fbed665d60b8c0ea9441a7/evidence/27241/04-1440-timeline-off.png?raw=true)
4. [A card moved: Restore default order at the column
foot](https://github.com/objectstack-ai/objectstack/blob/f6062d78b65b8cd830fbed665d60b8c0ea9441a7/evidence/27241/05-1440-moved-restore-default-order.png?raw=true)
· [foot line close
up](https://github.com/objectstack-ai/objectstack/blob/f6062d78b65b8cd830fbed665d60b8c0ea9441a7/evidence/27241/06-1440-related-foot-line.png?raw=true).
Clicking it put the default order back; stored value
`{"order":[],"collapsed":[],"hidden":[],"basedOn":"e40133ac","v":1}`.
5. [1024 window, sidebar expanded: two columns, related ON, the rail
toggle](https://github.com/objectstack-ai/objectstack/blob/f6062d78b65b8cd830fbed665d60b8c0ea9441a7/evidence/27241/07-1024-two-columns-related-on-rail.png?raw=true)
· [related OFF: no rail toggle; the segmented control
wraps](https://github.com/objectstack-ai/objectstack/blob/f6062d78b65b8cd830fbed665d60b8c0ea9441a7/evidence/27241/08-1024-two-columns-related-off-no-rail.png?raw=true)
6. [Dark theme header row, timeline off and related
on](https://github.com/objectstack-ai/objectstack/blob/f6062d78b65b8cd830fbed665d60b8c0ea9441a7/evidence/27241/09-1440-dark-header-row-timeline-off.png?raw=true)
## Tests
Head \`9c82d929a8\`. The build and type-check closure was rebuilt first
(\`pnpm --workspace-concurrency=2 --filter '@object-ui/console^...'
build\`, VERDICT command-exit 0, 72 of 127 projects, then
\`@object-ui/i18n\`, \`components\` and \`plugin-detail\` again after
the edits). Every run went through \`scripts/pm/os-verify-lock.sh\`,
UNLOCKED (declared below).
- \`@object-ui/plugin-detail\` whole package: \`Test Files 334 passed |
1 skipped (335)\`, \`Tests 3058 passed | 18 skipped\`.
- \`@object-ui/components\` whole package, on the final head: \`Test
Files 449 passed | 1 skipped (450)\`, \`Tests 4338 passed | 24
skipped\`.
- \`@object-ui/i18n\` whole package: \`Test Files 89 passed (89)\`,
\`Tests 1373 passed | 13 skipped\`.
- \`@object-ui/app-shell\` \`src/views/\`: \`Test Files 1262 passed
(1262)\`, \`Tests 11874 passed | 1 skipped\`. This includes
\`panelToggles-27052\`, \`recordPageTiers-26678\` and the new
\`relatedListsOrder-27241\`.
- The changed and new files were re-run on the final head after the last
edits: 7 files / 65 tests in app-shell, and 3 files / 11 tests in the
components header suite.
- Type-check, each script echoed (\`tsc --noEmit && tsc -p
tsconfig.test.json\`), exit 0 with 0 \`error TS\`: components,
plugin-detail, app-shell, i18n.
- eslint on the changed files of the four packages: 0 errors.
- ui \`check:new-line-citations\` reported 0 new citations, and ui
\`check:spec-symbols\` exited 0.
- \`ui/e2e/record-header-title-width.spec.ts\` ran locally under a
throwaway config with no webServer (the spec uses \`page.setContent\`),
with the installed \`chromium_headless_shell-1234\` given as
\`executablePath\`: \`14 passed (1.8s)\`. The config was deleted after
the run.
## Reverse verification
Each new pin was run against its mutation through \`node
scripts/ablation-replace.mjs\`. The tool's own verdict was \`ok mutation
landed\` (anchor 1 → 0, blob moved), and it restored with \`git diff
HEAD empty\` and the HEAD blob matching. All runs were vitest on the
aliased \`src\`, so no dist step applies.
1. Related OFF keeps the rail (\`relatedRail:
!columns.includes('related')\`): 7 failed (arrangement,
\`RecordPageColumns\` and app-shell pins).
2. The header row drops the trailing segment: 10 failed (the components
slot pin and the app-shell toggles file). The first attempt was refused
by the tool as a no-op, because the replacement text already existed in
the file. It was re-run with a distinct replacement.
3. The chord matcher reads \`code\` only: 1 failed (the code-less event
pin).
4. Three-column floor back to 1280: 2 failed. The first run failed at
import, with \`@objectstack/spec/data\` not found while the gate battery
was running beside it. That run is not counted as a measurement, and the
re-run is the reading.
5. Two-column floor back to 1024: 3 failed.
6. \`deriveRelatedLists\` drops \`relatedLists\`: 1 failed (the mounted
order pin).
7. \`bodyTablePlacement\` places nothing: 5 failed.
8. The foot line never offers the restore: 2 failed.
9. \`restore-default-arrangement\` keeps \`hidden\`: 2 failed.
10. The pressed tint back to \`bg-muted\`: 1 failed.
\`git diff HEAD\` was empty after the ten runs.
## Gates
Derived with \`node scripts/pm/dispatch-gates.mjs --commands --repo
objectstack-ai/objectstack\` at \`9c82d929a8\`. The change set is 38
paths against merge base \`3bfb357aa3\`, which derives 34 commands. Each
command's exit code was written before any pipe. \`--ran\` reports \`Run
reconciliation — 34 derived, 34 run, 0 NOT-MEASURED, 0 UNRUN\`.
33 commands exited 0. \`pnpm --dir ui exec vitest run scripts/\` exited
1, with \`Test Files 2 failed | 167 passed | 2 skipped (171)\` and
\`Tests 3 failed | 4898 passed\`. All three failures are known host gaps
on this macOS box, the same three as in rounds 0 and 1 of #27310. Two
are the bash 3.2 \`mapfile: command not found\` in
\`select-affected-tests-wiring.test.ts\`. The third is the
\`check-i18n-dead-keys\` 「on the real tree」 case, which times out. These
three are NOT MEASURED locally, and CI reads them.
**Declared narrowing — verification ran UNLOCKED.**
`scripts/pm/os-verify-lock.sh`
could not take the shared verify lock on this host: no usable `flock`.
The shared
verify lock is declared Linux-only (`flock` is util-linux, and a stock
macOS does
not ship it), so every build and test command in this PR was run
directly, without the lock —
a declared narrowing, not a silent one. No serialization guarantee held
for these
runs, nor for any sibling agent in this container while they ran.
## Acceptance notes
- **`text-accent` vs `text-accent-foreground`.** The ruling names
`bg-accent` + `text-accent` and describes the result as 「accent 浅底深字」.
In both console themes, `text-accent` is the same pale HSL as
`bg-accent` (light: `--accent` 240 18% 94%, measured on the page). The
literal pair would draw invisible text. The on segment is therefore
`bg-accent` + `text-accent-foreground`, which is the light-tint,
dark-text pair the ruling describes. An off segment is
`text-muted-foreground`. This is flagged for the seat in the report.
- **Wrapping on a narrow header.** At a 1024 px window (768 px record
page) the header's actions plus the segmented control are wider than the
header. The toolbar now wraps inside the header (`max-w-full`), and the
segment ends its own line. Before this, the toolbar overflowed and a
click scrolled the page sideways.
`e2e/record-header-title-width.spec.ts` ran locally: 14 passed.
- **A group naming a side card.** Per the ruling, `bodyTablePlacement`
places body tables only. A field group whose `relatedList` names a
relationship that is not a body table (not `'primary'`, not an
inline-edited `master_detail`) places nothing, and the card stays in the
related column. Before this, such a group drew nothing either.
- `main` gained 7 commits since the base `3bfb357aa3`, none touching a
changed path. GitHub reports no conflict, and no merge was made.
---
_Generated by [Claude
Code](https://claude.ai/code/session_cdb7a717def74e719988f089fbaa18ff)_
---------
Co-authored-by: Jack Zhuang <50353452+hotlong@users.noreply.github.com>
Co-authored-by: Claude <noreply@anthropic.com>1 parent 7614f8f commit 273137d
38 files changed
Lines changed: 958 additions & 159 deletions
File tree
- .changeset
- ui
- e2e/live
- packages
- app-shell/src
- utils
- views
- components/src
- __tests__
- custom
- renderers/layout
- i18n/src/locales
- plugin-detail/src
- __tests__
- renderers
- synth
- __tests__
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
40 | 40 | | |
41 | 41 | | |
42 | 42 | | |
43 | | - | |
44 | | - | |
45 | | - | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
46 | 47 | | |
47 | | - | |
| 48 | + | |
48 | 49 | | |
49 | 50 | | |
50 | 51 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
71 | 71 | | |
72 | 72 | | |
73 | 73 | | |
| 74 | + | |
74 | 75 | | |
75 | 76 | | |
76 | 77 | | |
| |||
286 | 287 | | |
287 | 288 | | |
288 | 289 | | |
289 | | - | |
290 | | - | |
291 | | - | |
| 290 | + | |
| 291 | + | |
| 292 | + | |
| 293 | + | |
292 | 294 | | |
293 | | - | |
294 | | - | |
295 | | - | |
296 | | - | |
297 | | - | |
298 | | - | |
299 | | - | |
300 | | - | |
| 295 | + | |
301 | 296 | | |
302 | 297 | | |
303 | 298 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
22 | 22 | | |
23 | 23 | | |
24 | 24 | | |
25 | | - | |
26 | | - | |
27 | | - | |
28 | | - | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
29 | 35 | | |
30 | 36 | | |
31 | 37 | | |
| |||
203 | 209 | | |
204 | 210 | | |
205 | 211 | | |
206 | | - | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
| 219 | + | |
| 220 | + | |
| 221 | + | |
207 | 222 | | |
208 | 223 | | |
209 | 224 | | |
| |||
280 | 295 | | |
281 | 296 | | |
282 | 297 | | |
| 298 | + | |
| 299 | + | |
| 300 | + | |
| 301 | + | |
| 302 | + | |
| 303 | + | |
| 304 | + | |
| 305 | + | |
| 306 | + | |
| 307 | + | |
| 308 | + | |
| 309 | + | |
| 310 | + | |
| 311 | + | |
| 312 | + | |
| 313 | + | |
| 314 | + | |
| 315 | + | |
| 316 | + | |
| 317 | + | |
| 318 | + | |
| 319 | + | |
| 320 | + | |
| 321 | + | |
| 322 | + | |
| 323 | + | |
| 324 | + | |
| 325 | + | |
| 326 | + | |
283 | 327 | | |
284 | 328 | | |
285 | 329 | | |
| |||
288 | 332 | | |
289 | 333 | | |
290 | 334 | | |
291 | | - | |
| 335 | + | |
292 | 336 | | |
293 | 337 | | |
294 | 338 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
19 | 19 | | |
20 | 20 | | |
21 | 21 | | |
22 | | - | |
| 22 | + | |
| 23 | + | |
23 | 24 | | |
24 | 25 | | |
25 | 26 | | |
| |||
218 | 219 | | |
219 | 220 | | |
220 | 221 | | |
221 | | - | |
222 | | - | |
| 222 | + | |
| 223 | + | |
223 | 224 | | |
224 | 225 | | |
225 | 226 | | |
| |||
234 | 235 | | |
235 | 236 | | |
236 | 237 | | |
237 | | - | |
| 238 | + | |
238 | 239 | | |
239 | 240 | | |
240 | 241 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
0 commit comments