[AGILE-348] Show the card ActionMenu as a context menu - #24464
Open
myabc wants to merge 3 commits into
Open
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
Adds a reusable, framework-agnostic “contextual action menu” implementation and wires it into Backlogs work package cards so the existing Primer ActionMenu can be opened via right-click (pointer) and Shift+F10 / Context Menu key (keyboard), while preserving native context menus for interactive descendants and touch long-press.
Changes:
- Introduces
ContextualActionMenupresenter (shared, framework-agnostic) and a Stimulus controller to invoke it contextually (pointer + keyboard), including cleanup across morph/turbo-stream updates. - Wires Backlogs work package cards to opt into the new controller and exposes page-object helpers for Selenium feature coverage.
- Adds comprehensive frontend unit tests (Vitest) and Backlogs Selenium feature specs to cover focus/anchoring/gesture edge cases.
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| modules/backlogs/spec/support/pages/backlog.rb | Adds page-object helpers/selectors for contextual menu interaction and assertions; refactors overlay selector reuse. |
| modules/backlogs/spec/features/work_packages/card_context_menu_spec.rb | New Selenium feature spec verifying contextual open, focus behavior, keyboard invocation, and anchor restoration. |
| modules/backlogs/spec/components/backlogs/work_package_card_list_item_component_spec.rb | Extends component specs to assert the new controller wiring and updated aria-keyshortcuts. |
| modules/backlogs/app/components/backlogs/work_package_card_list_item_component.rb | Wires contextual-action-menu Stimulus controller onto Backlogs cards and updates ARIA key shortcuts. |
| frontend/tsconfig.json | Adds core-common/* path alias for shared, framework-agnostic modules under src/common/. |
| frontend/src/stimulus/controllers/dynamic/contextual-action-menu.controller.ts | New Stimulus controller handling pointer + keyboard invocation, native-menu fallthrough rules, and morph-safe presenter lifecycle. |
| frontend/src/stimulus/controllers/dynamic/contextual-action-menu.controller.spec.ts | New unit tests covering ordering differences (macOS vs Windows/Linux), echo suppression, cancellation, morph swaps, and disconnect cleanup. |
| frontend/src/common/contextual-action-menu.ts | New presenter that re-anchors Primer ActionMenu overlays contextually, restores overlay state, and returns focus appropriately. |
| frontend/src/common/contextual-action-menu.spec.ts | Unit tests for presenter anchoring, state restoration, focus restoration, and destroy cleanup. |
| frontend/AGENTS.md | Documents src/common/ as the home for framework-agnostic modules (core-common alias). |
Deploying openproject with ⚡ PullPreview
|
myabc
force-pushed
the
implementation/AGILE-348-card-context-menu
branch
from
July 28, 2026 22:02
6f0ec5f to
70245cf
Compare
myabc
marked this pull request as ready for review
July 28, 2026 22:03
|
Caution The provided work package version does not match the core version Details:
Please make sure that:
|
myabc
commented
Jul 28, 2026
Comment on lines
+33
to
+47
| // Mirrors the members of Primer's `AnchoredPositionElement` that the presenter | ||
| // drives — including the quirk that gives this spec its teeth: `anchorOffset` | ||
| // reads its attribute as an enum (only `spacious`/`8` mean 8), so an arbitrary | ||
| // pixel offset can only reach `getAnchoredPosition` as a property. | ||
| // | ||
| // The accessors deliberately live on a prototype. The presenter carries the | ||
| // vertical offset as an *own* property shadowing `anchorOffset`, and a fake | ||
| // that defined its accessors per instance would be overwritten rather than | ||
| // shadowed, leaving the restore with nothing to undo and nothing to prove. | ||
| // | ||
| // `update()` runs the real `getAnchoredPosition`, with the element itself as | ||
| // the settings object, exactly as the production element does. The offsets | ||
| // this spec asserts on are therefore read the way Primer reads them, rather | ||
| // than the way this spec wishes they were read. | ||
| class FakeAnchoredPositionElement extends HTMLElement { |
Contributor
Author
There was a problem hiding this comment.
Perhaps we should just import the real AnchoredPositionElement? Not sure how "unit"-ey frontend specs should be.
Primer's ActionMenu opens at its trigger button; presenting one at a pointer position means re-anchoring the overlay and restoring it after. It lands in `src/common/` because the Angular card lists will want the same behaviour. https://community.openproject.org/wp/AGILE-348
Attaches contextual entry points — right-click, Shift+F10, the Context Menu key — to any element that already owns an action menu, without touching that element's own behaviour. Its cancelable `beforeOpen` event is the seam a later batch-selection slice needs. https://community.openproject.org/wp/AGILE-348
Right-clicking a backlog card is the gesture people reach for, and the card already carries the menu its More button opens. Non-movable cards opt in too: their one action is still worth reaching contextually. https://community.openproject.org/wp/AGILE-348
myabc
force-pushed
the
implementation/AGILE-348-card-context-menu
branch
from
July 28, 2026 22:36
70245cf to
007f09f
Compare
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.
Ticket
https://community.openproject.org/wp/AGILE-348
What are you trying to accomplish?
Right-clicking a Backlogs work-package card now opens that card's own ActionMenu at the pointer, instead of the browser's native context menu. The same menu is reachable from the keyboard with
Shift+F10or the Context Menu key, and the card advertises this viaaria-keyshortcuts="Enter Shift+F10".Screenshots
...button)Shift+F10)What approach did you choose and why?
Three layers, so nothing Backlogs-specific leaks into the generic pieces:
frontend/src/common/contextual-action-menu.ts) — framework-agnostic; opens a PrimerActionMenuoverlay at a point or at its invoker, borrows and restores the overlay's anchoring state, and restores focus on close.contextual-action-menu.controller.ts) — wirescontextmenu/ keyboard entry points onto any element, and emits a cancelablecontextual-action-menu:beforeOpenso hosts can opt out.Merge checklist