Mirror: React hooks for accessible, common web interactions. UI super powers without the UI.

Add useDialogDismiss hook

+1
src/index.ts
···
export * from './useModalFocus';
export * from './useDialogFocus';
export * from './useMenuFocus';
+
export * from './useDialogDismiss';
+36
src/useDialogDismiss.ts
···
+
import { useLayoutEffect } from './utils/react';
+
import { contains } from './utils/element';
+
import { makePriorityHook } from './usePriority';
+
import { Ref } from './types';
+
+
const usePriority = makePriorityHook();
+
+
export function useDialogDismiss<T extends HTMLElement>(ref: Ref<T>, onDismiss: () => void) {
+
const hasPriority = usePriority(ref);
+
+
useLayoutEffect(() => {
+
if (!hasPriority) return;
+
+
function onKey(event: KeyboardEvent) {
+
if (event.isComposing || event.defaultPrevented || event.code !== 'Escape') return;
+
event.preventDefault();
+
onDismiss();
+
};
+
+
function onClick(event: MouseEvent | TouchEvent) {
+
if (!ref.current || contains(ref.current, event.target) || event.defaultPrevented) return;
+
event.preventDefault();
+
onDismiss();
+
}
+
+
document.addEventListener('mousedown', onClick);
+
document.addEventListener('touchstart', onClick);
+
document.addEventListener('keydown', onKey);
+
+
return () => {
+
document.removeEventListener('mousedown', onClick);
+
document.removeEventListener('touchstart', onClick);
+
document.removeEventListener('keydown', onKey);
+
};
+
}, [ref, hasPriority, onDismiss]);
+
}
+1 -1
src/useDialogFocus.ts
···
}
function onKey(event: KeyboardEvent) {
-
if (!ref.current || event.defaultPrevented) return;
+
if (!ref.current || event.defaultPrevented || event.isComposing) return;
// Mark whether focus is moving forward for the `onFocus` handler
if (event.code === 'Tab') {
+1 -1
src/useMenuFocus.ts
···
}
function onKey(event: KeyboardEvent) {
-
if (!ref.current || event.defaultPrevented) return;
+
if (!ref.current || event.defaultPrevented || event.isComposing) return;
const owner = (ownerRef && ownerRef.current) || selection && selection.element;
const active = document.activeElement as HTMLElement;