fix: Keyboard shortcuts for ? key and ESC modal closing

- Fix ? shortcut: removed incorrect !e.shiftKey condition
- ESC now closes all modal types (overlay, settings, advanced search)
- Replace toast-based help with proper styled modal
- ESC also blurs focused inputs before canceling edit mode

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-23 22:04:39 -05:00
parent 11a593a7dd
commit ee317d6662

View File

@@ -4,18 +4,60 @@
document.addEventListener('DOMContentLoaded', function() { document.addEventListener('DOMContentLoaded', function() {
document.addEventListener('keydown', function(e) { document.addEventListener('keydown', function(e) {
// Skip if user is typing in an input/textarea // ESC: Close modals, cancel edit mode, blur inputs
if (e.target.tagName === 'INPUT' || if (e.key === 'Escape') {
e.target.tagName === 'TEXTAREA' || // Close any open modals first
e.target.isContentEditable) { const openModals = document.querySelectorAll('.modal-overlay');
// Allow ESC to exit edit mode even when in input let closedModal = false;
if (e.key === 'Escape') { openModals.forEach(modal => {
e.target.blur(); if (modal.style.display !== 'none' && modal.offsetParent !== null) {
const editButton = document.getElementById('editButton'); modal.remove();
if (editButton && editButton.classList.contains('active')) { document.body.classList.remove('modal-open');
editButton.click(); closedModal = true;
} }
});
// Close settings modal if open
const settingsModal = document.getElementById('settingsModal');
if (settingsModal && settingsModal.style.display !== 'none') {
settingsModal.style.display = 'none';
document.body.classList.remove('modal-open');
closedModal = true;
} }
// Close advanced search modal if open
const searchModal = document.getElementById('advancedSearchModal');
if (searchModal && searchModal.style.display !== 'none') {
searchModal.style.display = 'none';
document.body.classList.remove('modal-open');
closedModal = true;
}
// If we closed a modal, stop here
if (closedModal) {
e.preventDefault();
return;
}
// Blur any focused input
if (e.target.tagName === 'INPUT' ||
e.target.tagName === 'TEXTAREA' ||
e.target.isContentEditable) {
e.target.blur();
}
// Cancel edit mode on ticket pages
const editButton = document.getElementById('editButton');
if (editButton && editButton.classList.contains('active')) {
window.location.reload();
}
return;
}
// Skip other shortcuts if user is typing in an input/textarea
if (e.target.tagName === 'INPUT' ||
e.target.tagName === 'TEXTAREA' ||
e.target.isContentEditable) {
return; return;
} }
@@ -39,15 +81,6 @@ document.addEventListener('DOMContentLoaded', function() {
} }
} }
// ESC: Cancel edit mode
if (e.key === 'Escape') {
const editButton = document.getElementById('editButton');
if (editButton && editButton.classList.contains('active')) {
// Reset without saving
window.location.reload();
}
}
// Ctrl/Cmd + K: Focus search (on dashboard) // Ctrl/Cmd + K: Focus search (on dashboard)
if ((e.ctrlKey || e.metaKey) && e.key === 'k') { if ((e.ctrlKey || e.metaKey) && e.key === 'k') {
e.preventDefault(); e.preventDefault();
@@ -58,24 +91,43 @@ document.addEventListener('DOMContentLoaded', function() {
} }
} }
// ? : Show keyboard shortcuts help // ? : Show keyboard shortcuts help (requires Shift on most keyboards)
if (e.key === '?' && !e.shiftKey) { if (e.key === '?') {
e.preventDefault();
showKeyboardHelp(); showKeyboardHelp();
} }
}); });
}); });
function showKeyboardHelp() { function showKeyboardHelp() {
const helpText = ` // Check if help is already showing
╔════════════════════════════════════════╗ if (document.getElementById('keyboardHelpModal')) {
KEYBOARD SHORTCUTS ║ return;
╠════════════════════════════════════════╣ }
║ Ctrl/Cmd + E : Toggle Edit Mode ║
║ Ctrl/Cmd + S : Save Changes ║ const modal = document.createElement('div');
║ Ctrl/Cmd + K : Focus Search ║ modal.id = 'keyboardHelpModal';
║ ESC : Cancel Edit/Close ║ modal.className = 'modal-overlay';
║ ? : Show This Help ║ modal.innerHTML = `
╚════════════════════════════════════════╝ <div class="modal-content ascii-frame-outer" style="max-width: 400px;">
<div class="ascii-frame">
<div class="ascii-content">
<h3 style="margin: 0 0 1rem 0; color: var(--terminal-green);">KEYBOARD SHORTCUTS</h3>
<div class="modal-body" style="padding: 0;">
<table style="width: 100%; border-collapse: collapse;">
<tr><td style="padding: 0.5rem; border-bottom: 1px solid var(--border-color);"><kbd>Ctrl/Cmd + E</kbd></td><td style="padding: 0.5rem; border-bottom: 1px solid var(--border-color);">Toggle Edit Mode</td></tr>
<tr><td style="padding: 0.5rem; border-bottom: 1px solid var(--border-color);"><kbd>Ctrl/Cmd + S</kbd></td><td style="padding: 0.5rem; border-bottom: 1px solid var(--border-color);">Save Changes</td></tr>
<tr><td style="padding: 0.5rem; border-bottom: 1px solid var(--border-color);"><kbd>Ctrl/Cmd + K</kbd></td><td style="padding: 0.5rem; border-bottom: 1px solid var(--border-color);">Focus Search</td></tr>
<tr><td style="padding: 0.5rem; border-bottom: 1px solid var(--border-color);"><kbd>ESC</kbd></td><td style="padding: 0.5rem; border-bottom: 1px solid var(--border-color);">Close Modal / Cancel</td></tr>
<tr><td style="padding: 0.5rem;"><kbd>?</kbd></td><td style="padding: 0.5rem;">Show This Help</td></tr>
</table>
</div>
<div class="modal-footer" style="margin-top: 1rem;">
<button class="btn btn-secondary" onclick="this.closest('.modal-overlay').remove()">Close</button>
</div>
</div>
</div>
</div>
`; `;
toast.info(helpText, 5000); document.body.appendChild(modal);
} }