-
Notifications
You must be signed in to change notification settings - Fork 8.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
#10099 adds keyboard handling to close confirm_modal on ESC #10455
Changes from 1 commit
4333032
dccafec
e1b31c6
6761493
13366a5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -182,5 +182,48 @@ describe('ui/modals/confirm_modal', function () { | |
expect(confirmCallback.called).to.be(false); | ||
expect(cancelCallback.called).to.be(true); | ||
}); | ||
|
||
it('onKeyDown detects ESC and calls onCancel', function () { | ||
resetSpyCounts(); | ||
const confirmModalOptions = { | ||
confirmButtonText: 'bye', | ||
onConfirm: confirmCallback, | ||
onCancel: cancelCallback, | ||
onClose: closeCallback, | ||
title: 'hi', | ||
showClose: false | ||
}; | ||
|
||
confirmModal('hi', confirmModalOptions); | ||
|
||
const e = angular.element.Event('keydown'); // eslint-disable-line new-cap | ||
e.keyCode = 27; | ||
angular.element(document.body).trigger(e); | ||
|
||
expect(cancelCallback.called).to.be(true); | ||
}); | ||
|
||
it('onKeyDown ignores keys other than ESC', function () { | ||
resetSpyCounts(); | ||
const confirmModalOptions = { | ||
confirmButtonText: 'bye', | ||
onConfirm: confirmCallback, | ||
onCancel: cancelCallback, | ||
onClose: closeCallback, | ||
title: 'hi', | ||
showClose: false | ||
}; | ||
|
||
confirmModal('hi', confirmModalOptions); | ||
|
||
const e = angular.element.Event('keydown'); // eslint-disable-line new-cap | ||
e.keyCode = 27; | ||
while(e.keyCode === 27) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think you need to worry about the random value here. Just set the keyCode to a value other than 27. Probably good to avoid 9 (tab) and 13 (enter) too. You could play it safe and just pick a letter, so any value between 48 and 90 is fine. |
||
e.keyCode = Math.floor((Math.random() * 100) + 1); | ||
} | ||
angular.element(document.body).trigger(e); | ||
|
||
expect(cancelCallback.called).to.be(false); | ||
}); | ||
}); | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
<div class="kuiModalOverlay"></div> | ||
<div class="kuiModalOverlay" ng-keydown="onKeyDown($event)"></div> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since you're listening for the keypress event on |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,16 +5,25 @@ import modalOverlayTemplate from './modal_overlay.html'; | |
* Appends the modal to the dom on instantiation, and removes it when destroy is called. | ||
*/ | ||
export class ModalOverlay { | ||
constructor(modalElement) { | ||
constructor(modalElement, scope) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I feel like this functionality belongs in confirm_modal.js, and I think we should only bind ESC key functionality if showClose is true in confirm_modal. My concern is, we don't always show the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I disagree. Keyboard navigation is key, and ESC means "no" on a confirmation dialog. If we're going to replace native functionality, we need to provide the same interactions in our replacement.
We are. They can't do anything else until they deal with the confirm dialog. "no" is a valid response, and ESC allows the user to respond that way with from the keyboard, just like they could always do before. The functionality we're trying to replicate here is that of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I also agree that ESC traditionally maps to "Cancel" in basically any dialog that I can think of. It would be very confusing/annoying to me as a user if I was used to navigating using a keyboard, then opened a dialog with "showClose=false" and suddenly my normal means of navigation doesn't work anymore. @stacey-gammon The reason I put this in the ModalOverlay rather than the ConfirmDialog itself was so that the functionality could be re-used for other dialog types when they are created. I figured that ESC->Cancel is universal enough that it would be re-used for any other dialog. If that's not desired then it is easy enough to move that code to the dialog itself. |
||
this.overlayElement = angular.element(modalOverlayTemplate); | ||
this.overlayElement.append(modalElement); | ||
|
||
const onKeyDown = (event) => { | ||
if(event.keyCode === 27) { | ||
scope.onCancel(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should be
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. But if there is no X, then And this is why I've been advocating for a new dialog type for when you want the X/close button. They're different things ;) But this isn't really a concern for @dpenny52 to worry about. I think this PR should be handled with the intention of working with the "confirm" modal, and we can break out the "close" functionality and make a new modal later. To my knowledge, we don't use the yes/no/close interaction anywhere right now, so it's safe to pretend it doesn't exist yet. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Related: #10104 (comment) - your comment which advocates removing the Close option (and thus There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fair enough. Actually the whole reason for the onClose functionality may be going away, so we could rip that out (though I'd prefer to wait till after #10585 gets checked in just to be sure). My modified feedback, in that case, is that I still think this logic should either go in confirm_modal, or be passed in as a function. No need for the modal overlay to have scope knowledge, and this could easily break if we change the name of the function inside confirm_modal. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If you both agree on that point I'd be happy to move that code down to the dialog level. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, I think I'm on board with that part. I think that, while you're right @dpenny52 about the ESC being a universal modal interaction, we probably want to handle it differently in each case (as outlined in the whole onClose/onCancel conversation here). For now, let's move it into the confirm modal, and we can worry about pushing that logic back up when we add other modal types. |
||
} | ||
}; | ||
|
||
angular.element(document.body).bind('keydown', onKeyDown); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please use |
||
angular.element(document.body).append(this.overlayElement); | ||
} | ||
|
||
/** | ||
* Removes the overlay and modal from the dom. | ||
*/ | ||
destroy() { | ||
angular.element(document.body).off('keydown'); | ||
this.overlayElement.remove(); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can remove the
onClose
lines in your tests, as well as theshowClose
setting. They aren't actually used in these tests anyway.