diff --git a/packages/react/src/hooks/useKeyPress.ts b/packages/react/src/hooks/useKeyPress.ts index b2928baa..9dda2aff 100644 --- a/packages/react/src/hooks/useKeyPress.ts +++ b/packages/react/src/hooks/useKeyPress.ts @@ -8,6 +8,7 @@ type KeyOrCode = 'key' | 'code'; export type UseKeyPressOptions = { target?: Window | Document | HTMLElement | ShadowRoot | null; actInsideInputWithModifier?: boolean; + preventDefault?: boolean; }; const defaultDoc = typeof document !== 'undefined' ? document : null; @@ -88,7 +89,7 @@ export function useKeyPress( if (keyCode !== null) { const downHandler = (event: KeyboardEvent) => { - modifierPressed.current = event.ctrlKey || event.metaKey || event.shiftKey; + modifierPressed.current = event.ctrlKey || event.metaKey || event.shiftKey || event.altKey; const preventAction = (!modifierPressed.current || (modifierPressed.current && !options.actInsideInputWithModifier)) && isInputDOMNode(event); @@ -100,7 +101,16 @@ export function useKeyPress( pressedKeys.current.add(event[keyOrCode]); if (isMatchingKey(keyCodes, pressedKeys.current, false)) { - event.preventDefault(); + const target = (event.composedPath?.()?.[0] || event.target) as Element | null; + const isInteractiveElement = target?.nodeName === 'BUTTON' || target?.nodeName === 'A'; + + if ( + (options.preventDefault || typeof options.preventDefault === 'undefined') && + (modifierPressed.current || !isInteractiveElement) + ) { + event.preventDefault(); + } + setKeyPressed(true); } }; diff --git a/packages/system/src/utils/dom.ts b/packages/system/src/utils/dom.ts index 4195ea3a..2311153f 100644 --- a/packages/system/src/utils/dom.ts +++ b/packages/system/src/utils/dom.ts @@ -35,7 +35,7 @@ export const getDimensions = (node: HTMLDivElement): Dimensions => ({ export const getHostForElement = (element: HTMLElement | EventTarget | null): Document | ShadowRoot => ((element as Partial | null)?.getRootNode?.() as Document | ShadowRoot) || window?.document; -const inputTags = ['INPUT', 'SELECT', 'TEXTAREA', 'BUTTON']; +const inputTags = ['INPUT', 'SELECT', 'TEXTAREA']; export function isInputDOMNode(event: KeyboardEvent): boolean { // using composed path for handling shadow dom