• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

react-ui-org / react-ui / 12744940249

13 Jan 2025 10:09AM UTC coverage: 80.471% (-11.5%) from 91.979%
12744940249

Pull #544

github

web-flow
Merge ec8d690d5 into 684d5abff
Pull Request #544: Re-implement `Modal` component using HTMLDialogElement (#461)

743 of 923 branches covered (80.5%)

Branch coverage included in aggregate %.

4 of 43 new or added lines in 7 files covered. (9.3%)

65 existing lines in 5 files now uncovered.

658 of 818 relevant lines covered (80.44%)

61.83 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

1.1
/src/components/Modal/_hooks/useModalFocus.js
1
import { useEffect } from 'react';
2

3
export const useModalFocus = (
4✔
4
  allowPrimaryActionOnEnterKey,
5
  autoFocus,
6
  dialogRef,
7
  primaryButtonRef,
8
) => {
UNCOV
9
  useEffect(
×
10
    () => {
11
      // Following code finds all focusable elements and among them first not disabled form
12
      // field element (input, textarea or select) or primary button and focuses it. This is
13
      // necessary to have focus on one of those elements to be able to submit the form
14
      // by pressing Enter key. If there are neither, it tries to focus any other focusable
15
      // elements. In case there are none or `autoFocus` is disabled, dialogElement
16
      // (Modal itself) is focused.
17

NEW
18
      const dialogElement = dialogRef.current;
×
19

NEW
20
      if (dialogElement == null) {
×
21
        return () => {};
×
22
      }
23

UNCOV
24
      const childrenFocusableElements = Array.from(
×
25
        dialogElement.querySelectorAll('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])'),
26
      );
27

UNCOV
28
      const firstFocusableElement = childrenFocusableElements[0];
×
UNCOV
29
      const lastFocusableElement = childrenFocusableElements[childrenFocusableElements.length - 1];
×
30

UNCOV
31
      const resolveFocusBeforeListener = () => {
×
UNCOV
32
        if (!autoFocus || childrenFocusableElements.length === 0) {
×
NEW
33
          dialogElement.tabIndex = -1;
×
NEW
34
          dialogElement.focus();
×
UNCOV
35
          return;
×
36
        }
37

UNCOV
38
        const firstFormFieldEl = childrenFocusableElements.find(
×
UNCOV
39
          (element) => ['INPUT', 'TEXTAREA', 'SELECT'].includes(element.nodeName) && !element.disabled,
×
40
        );
41

UNCOV
42
        if (firstFormFieldEl) {
×
UNCOV
43
          firstFormFieldEl.focus();
×
UNCOV
44
          return;
×
45
        }
46

NEW
47
        if (primaryButtonRef?.current != null && primaryButtonRef?.current?.disabled === false) {
×
UNCOV
48
          primaryButtonRef.current.focus();
×
UNCOV
49
          return;
×
50
        }
51

UNCOV
52
        firstFocusableElement.focus();
×
53
      };
54

UNCOV
55
      const keyPressHandler = (e) => {
×
UNCOV
56
        if (
×
57
          allowPrimaryActionOnEnterKey
×
58
          && e.key === 'Enter'
59
          && e.target.nodeName !== 'BUTTON'
60
          && e.target.nodeName !== 'TEXTAREA'
61
          && e.target.nodeName !== 'A'
62
          && primaryButtonRef?.current != null
63
          && primaryButtonRef?.current?.disabled === false
64
        ) {
UNCOV
65
          primaryButtonRef.current.click();
×
UNCOV
66
          return;
×
67
        }
68

69
        // Following code traps focus inside Modal
70

UNCOV
71
        if (e.key !== 'Tab') {
×
UNCOV
72
          return;
×
73
        }
74

UNCOV
75
        if (childrenFocusableElements.length === 0) {
×
NEW
76
          dialogElement.focus();
×
77
          e.preventDefault();
×
78
          return;
×
79
        }
80

UNCOV
81
        if (
×
82
          ![
83
            ...childrenFocusableElements,
84
            dialogElement,
85
          ]
86
            .includes(window.document.activeElement)
87
        ) {
88
          firstFocusableElement.focus();
×
89
          e.preventDefault();
×
90
          return;
×
91
        }
92

UNCOV
93
        if (!e.shiftKey && window.document.activeElement === lastFocusableElement) {
×
UNCOV
94
          firstFocusableElement.focus();
×
UNCOV
95
          e.preventDefault();
×
UNCOV
96
          return;
×
97
        }
98

UNCOV
99
        if (e.shiftKey
×
100
          && (
101
            window.document.activeElement === firstFocusableElement
102
            || window.document.activeElement === dialogElement
103
          )
104
        ) {
UNCOV
105
          lastFocusableElement.focus();
×
UNCOV
106
          e.preventDefault();
×
107
        }
108
      };
109

UNCOV
110
      resolveFocusBeforeListener();
×
111

UNCOV
112
      window.document.addEventListener('keydown', keyPressHandler, false);
×
113

UNCOV
114
      return () => window.document.removeEventListener('keydown', keyPressHandler, false);
×
115
    },
116
    [
117
      allowPrimaryActionOnEnterKey,
118
      autoFocus,
119
      dialogRef,
120
      primaryButtonRef,
121
    ],
122
  );
123
};
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc