Skip to content

Commit bde6c32

Browse files
committed
Merge pull request #22: dismiss popups and menus with Escape
# Conflicts: # media/webview.css
2 parents d9cdbbe + 0cd7399 commit bde6c32

3 files changed

Lines changed: 48 additions & 1 deletion

File tree

media/webview.css

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1283,4 +1283,12 @@ body.vscode-high-contrast #grid-container.cm-on {
12831283
background-color: rgba(209,134,22,0.32) !important;
12841284
color: var(--vscode-charts-orange, #d18616) !important;
12851285
font-weight: 700 !important;
1286-
}
1286+
}
1287+
/* Override AG Grid's default Alpine popup styles to match the extension's popovers. */
1288+
:is(.ag-theme-alpine-dark, .ag-theme-alpine) .ag-popup .ag-menu,
1289+
:is(.ag-theme-alpine-dark, .ag-theme-alpine) .ag-popup .ag-filter {
1290+
background: var(--vscode-menu-background, #252526);
1291+
border: 1px solid var(--vscode-menu-border, #454545);
1292+
border-radius: 4px;
1293+
box-shadow: 0 4px 12px rgba(0, 0, 0, .45);
1294+
}

src/webview/features/popups.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { state } from '../state';
2+
13
// ── Central popup coordinator (issue #15) ─────────────────────────────────────
24
// The grid has several transient popups: the column and row context menus, the
35
// Export and Delimiter dropdowns, the column-chooser and go-to-row popovers and
@@ -28,3 +30,38 @@ export function closeAllPopups(except?: string): void {
2830
document.getElementById(id)?.classList.add('hidden');
2931
}
3032
}
33+
34+
// Checks if any coordinated popup is currently visible.
35+
// This ensures the global Esc handler only consumes the keystroke when
36+
// there is actually a popup to dismiss, leaving Esc free for standard
37+
// tasks (like canceling a cell edit).
38+
export function isAnyPopupOpen(): boolean {
39+
return POPUP_IDS.some(id => {
40+
const el = document.getElementById(id);
41+
return el != null && !el.classList.contains('hidden');
42+
});
43+
}
44+
45+
// Sets up a global Esc key listener to dismiss all popups (wired once at startup).
46+
// - Uses the capture phase (true) to intercept the event before AG Grid consumes it.
47+
// - Does NOT call stopPropagation to allow input-focused popups (rename, go-to-row)
48+
// to run their own focus-bound Escape handlers and state cleanup.
49+
// Other popups (context menus, dropdowns) are simply hidden by closeAllPopups().
50+
export function setupPopups(): void {
51+
document.addEventListener('keydown', (e) => {
52+
if (e.key !== 'Escape') return;
53+
54+
// AG Grid's filter panel lives outside POPUP_IDS (it has no fixed id).
55+
// Detect it in the DOM and let AG Grid close it.
56+
const agOpen = document.querySelector('.ag-popup .ag-menu, .ag-popup .ag-filter');
57+
if (agOpen) {
58+
(state.gridApi as any)?.hidePopupMenu?.();
59+
e.preventDefault();
60+
return;
61+
}
62+
63+
if (!isAnyPopupOpen()) return;
64+
closeAllPopups();
65+
e.preventDefault();
66+
}, true);
67+
}

src/webview/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import { setupColumnChooser } from './features/column-chooser';
1818
import { setupColorMode } from './features/color-mode';
1919
import { setupKeyboard } from './keyboard';
2020
import { setupMessaging } from './messaging';
21+
import { setupPopups } from './features/popups';
2122

2223
setupTheme();
2324
setupUndoRedo();
@@ -39,5 +40,6 @@ setupColumnChooser();
3940
setupColorMode();
4041
setupKeyboard();
4142
setupMessaging();
43+
setupPopups();
4244

4345
vscodeApi.postMessage({ type: 'ready' });

0 commit comments

Comments
 (0)