Repository navigation
feat(fields): every record reference shows a hover card with the target's declared highlights - #27912
Conversation
…clared highlights Lookup links and the record page's compact related rows show, after a 400 ms hover or Space, a floating card with the target object's icon and label, the record's name as a link, and its declared highlightFields (name excluded, at most six) drawn by the lookup's own cell renderers. One findOne per shown card, cached per record and dropped on the data bus; nothing is read on row render. Claude-Session: https://claude.ai/code/session_01Utp6Ca4Vk1969xZxELoSFG Co-authored-by: Claude <noreply@anthropic.com>
…d rows Covers declared highlights minus the name for three objects, the no-highlights and unreadable faces, one read per shown card, Space and Esc, one card at a time, the host's unchanged markup, the title's open path and the viewer's field policy. Adds the changeset. Claude-Session: https://claude.ai/code/session_01Utp6Ca4Vk1969xZxELoSFG Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Utp6Ca4Vk1969xZxELoSFG Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Utp6Ca4Vk1969xZxELoSFG Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Utp6Ca4Vk1969xZxELoSFG Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Utp6Ca4Vk1969xZxELoSFG Co-authored-by: Claude <noreply@anthropic.com>
|
domain:ui#4 · os-bill · session_01Utp6CbDAucNyQ4UtzCJKyh |
|
domain:ui#4 · os-bill · session_01Utp6CbDAucNyQ4UtzCJKyh Contract reviewServed-tier: Face: declaration only. The PR body, the changeset and claim 6513000523 (file surface amended 2026-10-30T01:57Z) each say ① Derived judgments
② Semver level
③ Boundary flags
Implemented-by: VERDICT: PASS Generated by Claude Code |
|
domain:ui#4 · os-bill · session_01Utp6CbDAucNyQ4UtzCJKyh 史诗席位预览核对请求 · epic:#26676#1To the epic seat ( State on head What to look at
Deviations to confirm or reject
Evidence (never-merged branch
|
|
domain:ui#4 · os-bill · session_01Utp6CbDAucNyQ4UtzCJKyh 席位核对ACCEPT · head
Generated by Claude Code |
|
domain:ui#4 · os-bill · session_01Utp6Ca4Vk1969xZxELoSFG Preview review (proxy for epic:#26676#1) · 1831836 · PASS Run under ruling 6520722066 on #26676, after the merge. One context-free reviewer was given only the card's Acceptance section, the v4 boards (a782549), the "What to look at" list of 6514502858, and the console. It drove the console with Playwright on Stand-ins for HotCRM's objects: Account declares 1. Hover or Space shows the card on every surface: PASS.
2. What the card draws: PASS.
3. Requests: PASS.
Notes, not REWORK.
Review taken 2026-10-30T11:44Z. Generated by Claude Code |
Requested by Bill · project thread
维护者速读
ui/packages/fields/src/RecordHoverCard.tsx(读取缓存、highlightFields 取舍、空格/Esc);ui/packages/fields/src/index.tsx的ReferencedRecordLink;ui/packages/plugin-detail/src/RelatedList.tsx紧凑行。pnpm --dir ui exec vitest run packages/fields/src/__tests__/RecordHoverCard-27604.test.tsx packages/plugin-detail/src/__tests__/RelatedList.compactHoverCard-27604.test.tsx,预期 14 条全部通过。RecordHoverCard,Clause-② yes (widening),席位按车道规则安排合同审查)。Fixes #27604
Clause-②: yes (widening)
Metadata-protocol: none
What changes
RecordHoverCardin@object-ui/fields(ui/packages/fields/src/RecordHoverCard.tsx), exported withRecordHoverCardPropsandRecordHoverCardObjectDef. It wraps the element that names a record and, after a 400 ms hover or Space on the focused reference, shows a card portalled todocument.body: the target object's icon (LazyIcon) and label (useObjectLabel), the record's name as a link (the host'srecordHref; a plain click goes to the host's open path, or the caller'sonOpen), and the object's declaredhighlightFieldsdrawn throughgetCellRenderer. Focus alone does not open it; Esc, pointer-out and blur close it; one card is open at a time; a reference inside a card gets no card of its own.highlightFieldsonly, filtered to names the object defines, minus the name field (resolveNameField) and minus fields the viewer may not read (checkField(..., 'read')), then capped at six. Nothing is derived: an object that declares none shows the name and the object label. Empty values are not drawn, as on the record header strip.findOne(object, id)with$expandnaming only the readable reference fields among the highlights. Answers are cached per record in the module (at most 200), and anotifyDataChangedfor the record drops its entry; an open card re-reads in place. The cache is local to the component; the data-layer dedupe of the sibling performance card is not duplicated.ReferencedRecordLink(the anchorLookupCellRendererdraws for every linkable lookup / master-detail value), which covers a relation column in a list, a related list's table and its enlarged view, and a lookup in the details column. The cell hands over the target definition it already reads (refSchema) and its display name.RelatedList's compact face), with the list's own data source and object definition; the card's title opens the row through the samehandleRowClickas the name.@object-ui/fieldsand@object-ui/plugin-detail, patch, with both declaration lines.Tests
ui/packages/fields/src/__tests__/RecordHoverCard-27604.test.tsx(11), throughLookupCellRendererunder a realSchemaRendererProviderandRelatedRecordActionsProvider: a lead (eight declared, name first: six shown, name dropped, option label and currency drawn), a contact with no status field (exactly its four, one read with$expand: ['account'], the inner lookup has no card of its own), a product, an object declaring nohighlightFields(name + object label, no list), an unreadable record (reference name + object label), 200 rows drawn with zero reads then one read per shown record and a cache hit on re-hover, the hover delay, focus alone shows nothing while Space shows and Esc hides, one card at a time, the host's markup unchanged apart from Radix's state attributes, and the title opening through the host with no click reaching the row.ui/packages/fields/src/__tests__/RecordHoverCard.fieldAccess-27604.test.tsx(1): a highlight the viewer may not read is neither drawn nor expanded.ui/packages/plugin-detail/src/__tests__/RelatedList.compactHoverCard-27604.test.tsx(3): hovering a compact row's name shows the row's declared highlights with no read on row render and the row's markup unchanged; Space shows the card without opening the row and Esc hides it; the card title opens the row throughonRowClick.Readings at heads e57402a, 49504eb and 090db13
At e57402a (the implementation, before any merge of
main):LookupCellRenderer, a hostrecordHreforRelatedListCompactContextinfields,plugin-detail,plugin-gridandplugin-list(git grep -lover their*.test.tsx). VERDICT command-exit 0, Test Files 37 passed (37), Tests 283 passed (283).pnpm --filter @object-ui/fields run type-checkandpnpm --filter @object-ui/plugin-detail run type-check(each the src and the test tsconfig): VERDICT command-exit 0.eslintover the six changed ui files: 0 errors.node scripts/ablation-replace.mjs --file ui/packages/fields/src/RecordHoverCard.tsx --anchor 'name !== nameField &&' --delete -- pnpm --dir ui exec vitest run packages/fields/src/__tests__/RecordHoverCard-27604.test.tsx: anchor 1 -> 0 on disk, blob d67867f8 -> d9717101; exit 1, Tests 1 failed / 10 passed: the lead case went red withexpected [ 'name', 'company', 'status', ... ] to deeply equal [ 'company', 'status', 'rating', ... ]. Restored by the tool: blob == HEAD,git diff HEADempty.At 49504eb (
mainmerged in; it had movedindex.tsxandRelatedList.tsx, merged without conflict, nopackages/spec/**or lockfile change), one run under os-verify-lock: the@object-ui/plugin-detailclosure rebuilt, both package type-checks, then the same 37 test files. VERDICT command-exit 0, Test Files 37 passed (37), Tests 283 passed (283).At 090db13 (
mainmerged in again: six commits, all outsideui/): the three new test files under os-verify-lock, VERDICT command-exit 0, Test Files 3 passed (3), Tests 15 passed (15).Acceptance notes
ReferencedRecordLinklive in@object-ui/fields, and@object-ui/fieldsdepends on@object-ui/components, not the reverse. A card that draws the target's values withgetCellRenderertherefore lives infields; nothing underui/packages/components/src/ui/**changed. The seat amended the claim's file surface to match.LookupCellRendereris the rendererDetailSection,RelatedList's table andObjectGrid's lookup columns all resolve through.plugin-listandplugin-gridneeded no change.referenceViapointer cells. Those can takeRecordHoverCardlater the same way the compact row does.RelatedList.tsx's docblock region touched by the in-flight fix(console): a declared same-origintype: 'api'click goes through the action door #27793 is not edited; this PR changes only the compact face's row.claude/issue-27604-evidence(a8b2da2), folderevidence/27604/: a relation cell in the Projects list, a lookup chip in a record's details column, and a compact related row whose object declares nohighlightFields(name and object label only), with the two Playwright scripts and a README. HotCRM is a separate repository this session cannot reach, so they are taken onexamples/app-showcaseat 49504eb, whoseshowcase_accountdeclareshighlightFields: ['status', 'industry', 'annual_revenue']./data/showcase_account/<id>) after one hover on an Account cell; on the compact row, Space on the focused name showed one card without navigating and Esc left none.Verification
Derived gates at heads e57402a and 49504eb
node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack: 35 commands, each run and recorded ascommand :: exit codebefore any pipe; all 35 exit 0, includingnode scripts/check-sdui-manifest.mjs,pnpm check:type-check-coverageandpnpm check:type-check-debt.pnpm check:changeset-fixed(roster under.changeset/, flagged by the derivation) also exit 0. Reconciliation with--ran: 35 derived, 35 run, 0 NOT-MEASURED, 0 UNRUN. The same 36 commands ran again at 49504eb after the merge ofmain: all exit 0, reconciliation again 35 derived, 35 run, 0 NOT-MEASURED, 0 UNRUN. The later merge to 090db13 brought only files outsideui/.pnpm check:new-line-citations(underui/): 0 new citations. Every other family is left to this PR's CI check-runs.🤖 Generated with Claude Code
https://claude.ai/code/session_01Utp6Ca4Vk1969xZxELoSFG
Generated by Claude Code