Skip to content

bug(components): action:menu's execute payload is narrower than action:button's — an overflow action loses its dialog title, description, Undo and record-id field #4192

Description

@yinlianghui

Measured while implementing #4162 (making action:menu consume autoTrigger). Filed separately: it affects every overflow action on an ordinary CLICK, not only auto-triggered ones, and predates that card.

Fact

Both renderers hand the runner an explicit key whitelist rather than the action itself. The two whitelists have drifted. Measured on this tree with the real renderers and the real runner, one identical type: 'api' action driven through each path:

PROBE-BTN-KEYS:        ["actionParams","description","endpoint","label","locations","method","name","recordIdField","type","undoable"]
PROBE-MENU-KEYS:       ["endpoint","locations","method","name","params","type"]
PROBE-MISSING-IN-MENU: ["actionParams","description","label","recordIdField","undoable"]
PROBE-MENU-PARAMS-SHAPE: array-as-params

(Keys with an undefined value filtered out on both sides, so this is what the runner actually receives.)

Four consequences, each already argued at the action:button call site that forwards the key:

  • label / descriptionaction-button.tsx forwards them so a param-collection dialog titles itself as the action ("Create Environment") instead of a generic "Action parameters" prompt. An overflow action's dialog gets the generic title.
  • undoable / recordIdField — forwarded by the button so an update action can offer an Undo affordance; the runner never builds the undo operation without them. Clicking the same action from the "More" menu silently loses Undo.
  • params shape — the button routes an ActionParamDef[] to actionParams and a values object to params; the menu always passes params: action.params. This one does NOT break: ActionRunner accepts an array params as the collection definition (ActionRunner.ts:816), which is why the dialog still opens. It is a latent divergence rather than a live defect, and it is the reason the first bullet is only a wrong title rather than a missing dialog.

Which renderer a given action gets is decided by action:bar's maxVisible split (3 desktop, 1 mobile) and by systemActions, which are ALWAYS in the menu. So the same declared action behaves differently depending on the viewport — the same class of viewport-dependent divergence as #4162 and objectui#4075, on a different key set.

Why it may matter

Reachable today with no metadata change: any undoable update action that sits past maxVisible (or on mobile, past the first action) is offered without Undo, and any action with declared params in the same position gets an unlabelled dialog. No error is raised on either path — the payload is simply thinner, so both failures look like the feature was never declared.

The narrow fix is to bring the menu's forward list up to the button's. The wider question, which is why this is filed rather than patched inside #4162's scope: two hand-maintained whitelists over the same ActionSchema will drift again — bodyExtra (objectstack#6837), bodyShape (objectstack#6938) and resultDialog were each added to both lists one incident at a time. A single shared "action to ActionDef" projection, or a parity test over the two whitelists, is what stops the next one.

action:icon and action:group compose their own payloads too and are not measured here; a fix should check all four rather than just these two.

Related


Generated by Claude Code

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingpm:queue

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions