diff --git a/admin/src/app/hotkeys.ts b/admin/src/app/hotkeys.ts index a4e5ee58..59769ace 100644 --- a/admin/src/app/hotkeys.ts +++ b/admin/src/app/hotkeys.ts @@ -23,6 +23,13 @@ // dismissable layer (dialog, popover, dropdown, select, link popover) is // open: those close on Esc themselves without calling preventDefault, so the // DOM is checked for their data-dismissable-layer attribute instead. +// +// A focused custom element (a tag name with "-") inside a form counts as an +// editable control, because a closed shadow root hides whether it holds an +// input. The trade-off: a focusable widget that is not an input (a type: +// widget chart or button strip) also mutes Esc, / and ? while it has focus; +// they work again once focus leaves it. Narrowing the rule to plugin field +// types would let Esc leave the form from a widget with an input inside. import { readonly, ref } from 'vue' import { t } from './i18n' @@ -100,7 +107,8 @@ export function comboOf(event: KeyboardEvent): HotkeyCombo | null { * True when the target is inside an input, textarea, select or contenteditable * element, or is a custom element (a tag name with "-") inside a form: a * plugin field type whose closed shadow root hides the real input, where - * composedPath() stops at the host. + * composedPath() stops at the host. Any such element counts, a focusable + * non-input widget included (see the header comment). */ export function isEditableTarget(target: EventTarget | null): boolean { if (!target || typeof (target as Element).closest !== 'function') {