MCPcopy Index your code
hub / github.com/primer/react / useDialog

Function useDialog

packages/react/src/hooks/useDialog.ts:25–127  ·  view source on GitHub ↗
({
  modalRef,
  overlayRef,
  isOpen,
  onDismiss = noop,
  initialFocusRef,
  closeButtonRef,
}: UseDialogParameters)

Source from the content-addressed store, hash-verified

23}
24
25function useDialog({
26 modalRef,
27 overlayRef,
28 isOpen,
29 onDismiss = noop,
30 initialFocusRef,
31 closeButtonRef,
32}: UseDialogParameters) {
33 const onClickOutside = useCallback(
34 (e: MouseEvent) => {
35 if (
36 modalRef.current &&
37 overlayRef.current &&
38 e.target instanceof Node &&
39 !modalRef.current.contains(e.target) &&
40 overlayRef.current.contains(e.target)
41 ) {
42 onDismiss()
43 }
44 },
45 [onDismiss, modalRef, overlayRef],
46 )
47
48 useEffect(() => {
49 if (isOpen) {
50 document.addEventListener('click', onClickOutside)
51 return () => {
52 document.removeEventListener('click', onClickOutside)
53 }
54 }
55 }, [isOpen, onClickOutside])
56
57 useEffect(() => {
58 if (isOpen) {
59 if (initialFocusRef && initialFocusRef.current) {
60 initialFocusRef.current.focus()
61 } else if (closeButtonRef && closeButtonRef.current) {
62 closeButtonRef.current.focus()
63 }
64 }
65 }, [isOpen, initialFocusRef, closeButtonRef])
66
67 const getFocusableItem = useCallback(
68 (e: React.KeyboardEvent, movement: number) => {
69 if (modalRef.current) {
70 const items = Array.from(modalRef.current.querySelectorAll('*')).filter(focusable)
71 if (items.length === 0) return
72 e.preventDefault()
73 const focusedElement = document.activeElement
74 if (!focusedElement) {
75 return
76 }
77
78 const index = items.indexOf(focusedElement)
79 const offsetIndex = index + movement
80 const fallbackIndex = movement === 1 ? 0 : items.length - 1
81 const focusableItem = items[offsetIndex] || items[fallbackIndex]
82 return focusableItem as HTMLElement

Callers 1

Dialog.tsxFile · 0.85

Calls 1

useOnEscapePressFunction · 0.90

Tested by

no test coverage detected