fix(Modal): allow Escape to close ContextualMenu before closing Modal#1339
Open
koushik717 wants to merge 1 commit intocanonical:mainfrom
Open
fix(Modal): allow Escape to close ContextualMenu before closing Modal#1339koushik717 wants to merge 1 commit intocanonical:mainfrom
koushik717 wants to merge 1 commit intocanonical:mainfrom
Conversation
When a ContextualMenu is rendered inside a Modal, pressing Escape failed to close the menu because Modal's handleEscKey called stopImmediatePropagation() unconditionally. Since ContextualMenu renders via a Portal (a DOM sibling), its document-level keydown listener was silenced before it could run. Fix by checking for an open contextual menu dropdown (.p-contextual-menu__dropdown[aria-hidden="false"]) before stopping propagation. If one exists, the Escape event is allowed to continue so the menu's own handler can close it first. A subsequent Escape press will then close the Modal as expected. Fixes canonical#1305
|
koushik717 is not a collaborator of the repo |
koushik717
added a commit
to koushik717/cloud-init-builder
that referenced
this pull request
Apr 3, 2026
- Schema-driven forms for 8 cloud-init modules (users, packages, runcmd, write_files, ssh, hostname, timezone, ntp) - Real-time YAML output with Monaco Editor starting with #cloud-config - Client-side validation with Ajv against official cloud-init JSON schema - Server-side validation via FastAPI backend - 5 built-in templates: Ubuntu Server, Docker Host, Kubernetes Node, Web Server, Developer Workstation - Shareable config links via lz-string URL encoding - Full keyboard navigation and ARIA accessibility - axe-core accessibility tests in CI - Built with @canonical/react-components (Vanilla Framework) - Motivated by canonical/cloud-init#6796 and canonical/react-components#1339
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.
Problem
Fixes #1305
When a
ContextualMenuis open inside aModal, pressing Escape closesthe Modal immediately rather than closing the menu first. This breaks the
expected layered-dismiss UX and is an accessibility issue — screen reader
users expect Escape to close the topmost layer only.
Root cause
Modal.tsxcallsstopImmediatePropagation()unconditionally on everyEscape keydown event. Because
ContextualMenurenders its dropdown via aPortal (a DOM sibling of Modal, outside the React tree), its own keydown
handler never receives the event — Modal has already stopped propagation.
Fix
Added a guard in
Modal.tsx: before stopping propagation, check whetheran open contextual menu dropdown exists in the DOM
(
.p-contextual-menu__dropdown[aria-hidden="false"]). If one is found,allow the event to propagate so the ContextualMenu can handle it and close.
A subsequent Escape keydown (with no open dropdown) then closes the Modal
as normal.
This produces the correct two-step dismiss behaviour:
Changes
src/components/Modal/Modal.tsx— guard logic beforestopImmediatePropagationsrc/components/Modal/Modal.test.tsx— regression test for the two-step dismissTesting
All 832 existing tests pass. New regression test added specifically for
Escape behaviour when a ContextualMenu is open inside a Modal.