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

react-ui-org / react-ui / 12711508427

10 Jan 2025 02:35PM UTC coverage: 91.979% (-0.1%) from 92.074%
12711508427

Pull #582

github

web-flow
Merge 275469d60 into d3264dd94
Pull Request #582: Add controlled popover

813 of 891 branches covered (91.25%)

Branch coverage included in aggregate %.

1 of 1 new or added line in 1 file covered. (100.0%)

735 of 792 relevant lines covered (92.8%)

72.49 hits per line

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

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

3
export const useModalFocus = (
4✔
4
  autoFocus,
5
  childrenWrapperRef,
6
  primaryButtonRef,
7
  closeButtonRef,
8
) => {
9
  useEffect(
62✔
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, childrenWrapperElement
16
      // (Modal itself) is focused.
17

18
      const childrenWrapperElement = childrenWrapperRef.current;
62✔
19

20
      if (childrenWrapperElement == null) {
62!
21
        return () => {};
×
22
      }
23

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

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

31
      const resolveFocusBeforeListener = () => {
62✔
32
        if (!autoFocus || childrenFocusableElements.length === 0) {
62✔
33
          childrenWrapperElement.tabIndex = -1;
28✔
34
          childrenWrapperElement.focus();
28✔
35
          return;
28✔
36
        }
37

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

42
        if (firstFormFieldEl) {
34✔
43
          firstFormFieldEl.focus();
10✔
44
          return;
10✔
45
        }
46

47
        if (primaryButtonRef?.current != null) {
24✔
48
          primaryButtonRef.current.focus();
6✔
49
          return;
6✔
50
        }
51

52
        firstFocusableElement.focus();
18✔
53
      };
54

55
      const keyPressHandler = (e) => {
62✔
56
        if (e.key === 'Escape' && closeButtonRef?.current != null) {
20✔
57
          closeButtonRef.current.click();
8✔
58
          return;
8✔
59
        }
60

61
        if (
12✔
62
          e.key === 'Enter'
11✔
63
          && e.target.nodeName !== 'BUTTON'
64
          && e.target.nodeName !== 'TEXTAREA'
65
          && e.target.nodeName !== 'A'
66
          && primaryButtonRef?.current != null
67
        ) {
68
          primaryButtonRef.current.click();
2✔
69
          return;
2✔
70
        }
71

72
        // Following code traps focus inside Modal
73

74
        if (e.key !== 'Tab') {
10✔
75
          return;
4✔
76
        }
77

78
        if (childrenFocusableElements.length === 0) {
6!
79
          childrenWrapperElement.focus();
×
80
          e.preventDefault();
×
81
          return;
×
82
        }
83

84
        if (
6!
85
          ![
86
            ...childrenFocusableElements,
87
            childrenWrapperElement,
88
          ]
89
            .includes(window.document.activeElement)
90
        ) {
91
          firstFocusableElement.focus();
×
92
          e.preventDefault();
×
93
          return;
×
94
        }
95

96
        if (!e.shiftKey && window.document.activeElement === lastFocusableElement) {
6✔
97
          firstFocusableElement.focus();
2✔
98
          e.preventDefault();
2✔
99
          return;
2✔
100
        }
101

102
        if (e.shiftKey
4!
103
          && (
104
            window.document.activeElement === firstFocusableElement
105
            || window.document.activeElement === childrenWrapperElement
106
          )
107
        ) {
108
          lastFocusableElement.focus();
2✔
109
          e.preventDefault();
2✔
110
        }
111
      };
112

113
      resolveFocusBeforeListener();
62✔
114

115
      window.document.addEventListener('keydown', keyPressHandler, false);
62✔
116

117
      return () => window.document.removeEventListener('keydown', keyPressHandler, false);
62✔
118
    },
119
    [
120
      autoFocus,
121
      childrenWrapperRef,
122
      primaryButtonRef,
123
      closeButtonRef,
124
    ],
125
  );
126
};
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

© 2025 Coveralls, Inc