Repository navigation
Record header: one primary action, the rest secondary; a declared record_header action (Convert Lead) is missing from the header and the ⋯ menu #12617
Description
Source
Walked on objectui main 8415d9f11 with HotCRM 63db83e2, the lead record /apps/app.objectstack.hotcrm/crm_lead/record/lZxZJxDxLzE08lyU and the opportunity record /crm_opportunity/record/maC9HZ_MynW5tj40 at 1024 px.
- The lead header renders three filled primary buttons "Log a Call · Log a Meeting · Schedule a Meeting" (the package's activity actions), then Edit as an icon button, ⋯ and Refresh; the opportunity header renders "Generate Quote · Clone Opportunity · Log a Call" the same way. Every header action is drawn with the primary style, so nothing is primary. The spec says otherwise:
packages/spec/src/ui/action.zod.tsgives actionsvariant: 'primary' | 'secondary' | 'danger' | 'ghost' | 'link'andorder, and documents that "inrecord_headerthe first visible action becomes the primary button" and that renderers may prefervariant: 'primary'. - HotCRM declares
convert_lead("Convert Lead",locations: ['record_header', 'list_item'],src/sales/actions/lead.actions.ts) andschedule_followupwith the same locations. Neither is in the lead header nor in its ⋯ menu, which holds only Edit · Add to favorites · Share · Delete. The lead's most important action is unreachable from the record page; the list row's ⋯ was not checked.
Target
- The header draws one filled primary button: the first visible
record_headeraction byorder(or the one withvariant: 'primary'); the next two as outline buttons; the rest in the ⋯ menu above Share / Delete. Edit stays a labelled outline button, never only an icon, since it is the record's base action. - Every action declared for
record_headerwhosevisibleWhen/ permission passes is rendered somewhere in the header group; the card finds whyconvert_leadis dropped (registration, condition, capability or a cap on the count) and fixes that path, with a test that a declared action with a passing condition is present. - The list row's ⋯ menu renders
list_itemactions the same way; the card verifies it on the lead list.
File surface
packages/plugin-detail/src/DetailView.tsx (header actions), the record-header action resolver in packages/app-shell/src/ (where declared actions are read and filtered), packages/plugin-list row menu, tests beside each.
Acceptance
- Tests: three
record_headeractions render as one primary + two outline; a fourth goes to ⋯; a declared action with a true condition is present;variant: 'primary'wins over order. - Screenshots of the lead and opportunity headers at 1280 px, light and dark.
pnpm --filter @object-ui/plugin-detail test,pnpm --filter @object-ui/app-shell testgreen.
Constraints
- objectui#12303: a disabled or hidden-by-condition action explains itself through the tooltip wrapper when it is drawn disabled; one that fails its condition is absent.
- No change to HotCRM's declarations; if the drop is caused by the app's
visibleWhen, the card says so and files the app card on objectstack-ai/hotcrm.
Evidence
Screenshots on the temporary branch claude/console-home-login-design-20261016 of objectstack-ai/objectui (commit b72c97985, never merged): hotcrm-lead-record-header-and-stage.jpg · hotcrm-lead-more-menu-no-convert.jpg · hotcrm-opportunity-record.jpg.
Filed by the epic PM session session_cdb7a717-def7-4e71-9988-f089fbaa18ff from the 2026-10-16 walk of HotCRM's core pages as a user: objectui main 8415d9f11, HotCRM 63db83e2, the vite console on :5180 against objectstack serve --dev on :4001, the maintainer's browser pane at 1024 × 768 (en). The maintainer asked for the findings to be filed on the repository each belongs to, verbatim: 「相关问题也在对应的项目上创建任务」.
Activity
objectstack-fleet commentedon Oct 16, 2026
Claim: PM loop round 2
Session:
session_01XVp19E1MYUTFM3dnkwz8gBAccount:
baozhoutao(the seat's linked user asGET /useranswers it; the card's assignee)Branch:
claude/issue-12617-record-header-actionsWorktree:
objectui-issue-12617Domain:
domain:uiSeat:
domain:ui#2File surface:
packages/plugin-detail/src/DetailView.tsx(header actions); the record-header action resolver inpackages/app-shell/src/(where declared actions are read and filtered); thepage:headeraction banding inpackages/components/src/renderers/layout/containers.tsxonly if the record header draws through it; theplugin-listrow menu for target 3; the tests beside each; and one.changeset/12617-*.md(stop on breach; explain in the report). ⛔ No change to HotCRM's declarations.Container & model:
M,mode:subagent,model: opus(default tier;dispatch-gates --tier --repo objectstack-ai/objectuireads no path-derived mandate)Clause-②: no
Responsibility:
objectui: the record header draws every action with the primary style and drops a declared record_header action (convert_lead) | the spec's action variant and order, and the documented first-visible-is-primary rule | every console user on a record page whose app declares record_header actions; measured on the HotCRM lead and opportunity recordsThread-read: none
Serial constraints cleared: no open PR touches
DetailView.tsx, the action resolver orcontainers.tsx. The PR #12545 (objectui#12529) header bands landed earlier and are the base this card builds on.Claimed at: 2026-10-16T06:15Z
objectstack-fleet commentedon Oct 16, 2026
Landed ·
domain:uiseat 2 ·session_01XVp19E1MYUTFM3dnkwz8gB· 2026-10-16T10:02ZPR #12635 merged through the merge queue as
ef71a09, which is onmain. Verified by content:origin/mainare blob-identical to the accepted heada4c0fcf.containers.tsx, also carries objectui#12627'sshowStarretirement (PR feat(components): page:header stops reading showStar; the host toggle is the one star switch #12644), which landed first. The queue merge applied this PR's own patch to it line for line.What landed:
variant: 'primary'if an action declares it, else the first byorder. The other inline actions are outline buttons, and the overflow goes to the ⋯.Convert Lead: its absence on the walk came from HotCRM's own
visiblepredicate, evaluated against the record the header held. objectui drops nothing. If it recurs with a loadedis_converted: falselead, reopen this card.Owed by the maintainer: the browser reading at 1280 px, light and dark.
pm:dispatchedleaves with this note, and the card closedcompletedon merge.Generated by Claude Code