@patternfly/react-core 6.1.0-prerelease.6 → 6.1.0-prerelease.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +10 -0
- package/components/package.json +1 -1
- package/deprecated/package.json +1 -1
- package/dist/dynamic/components/AboutModal/package.json +1 -1
- package/dist/dynamic/components/Accordion/package.json +1 -1
- package/dist/dynamic/components/ActionList/package.json +1 -1
- package/dist/dynamic/components/Alert/package.json +1 -1
- package/dist/dynamic/components/Avatar/package.json +1 -1
- package/dist/dynamic/components/BackToTop/package.json +1 -1
- package/dist/dynamic/components/Backdrop/package.json +1 -1
- package/dist/dynamic/components/BackgroundImage/package.json +1 -1
- package/dist/dynamic/components/Badge/package.json +1 -1
- package/dist/dynamic/components/Banner/package.json +1 -1
- package/dist/dynamic/components/Brand/package.json +1 -1
- package/dist/dynamic/components/Breadcrumb/package.json +1 -1
- package/dist/dynamic/components/Button/package.json +1 -1
- package/dist/dynamic/components/CalendarMonth/package.json +1 -1
- package/dist/dynamic/components/Card/package.json +1 -1
- package/dist/dynamic/components/Checkbox/package.json +1 -1
- package/dist/dynamic/components/ClipboardCopy/package.json +1 -1
- package/dist/dynamic/components/CodeBlock/package.json +1 -1
- package/dist/dynamic/components/Content/package.json +1 -1
- package/dist/dynamic/components/DataList/package.json +1 -1
- package/dist/dynamic/components/DatePicker/package.json +1 -1
- package/dist/dynamic/components/DescriptionList/package.json +1 -1
- package/dist/dynamic/components/Divider/package.json +1 -1
- package/dist/dynamic/components/Drawer/package.json +1 -1
- package/dist/dynamic/components/Dropdown/package.json +1 -1
- package/dist/dynamic/components/DualListSelector/package.json +1 -1
- package/dist/dynamic/components/EmptyState/package.json +1 -1
- package/dist/dynamic/components/ExpandableSection/package.json +1 -1
- package/dist/dynamic/components/FileUpload/package.json +1 -1
- package/dist/dynamic/components/Form/package.json +1 -1
- package/dist/dynamic/components/FormSelect/package.json +1 -1
- package/dist/dynamic/components/HelperText/package.json +1 -1
- package/dist/dynamic/components/Hint/package.json +1 -1
- package/dist/dynamic/components/Icon/package.json +1 -1
- package/dist/dynamic/components/InputGroup/package.json +1 -1
- package/dist/dynamic/components/JumpLinks/package.json +1 -1
- package/dist/dynamic/components/Label/package.json +1 -1
- package/dist/dynamic/components/List/package.json +1 -1
- package/dist/dynamic/components/LoginPage/package.json +1 -1
- package/dist/dynamic/components/Masthead/package.json +1 -1
- package/dist/dynamic/components/Menu/package.json +1 -1
- package/dist/dynamic/components/MenuToggle/package.json +1 -1
- package/dist/dynamic/components/Modal/package.json +1 -1
- package/dist/dynamic/components/MultipleFileUpload/package.json +1 -1
- package/dist/dynamic/components/Nav/package.json +1 -1
- package/dist/dynamic/components/NotificationBadge/package.json +1 -1
- package/dist/dynamic/components/NotificationDrawer/package.json +1 -1
- package/dist/dynamic/components/NumberInput/package.json +1 -1
- package/dist/dynamic/components/OverflowMenu/package.json +1 -1
- package/dist/dynamic/components/Page/package.json +1 -1
- package/dist/dynamic/components/Pagination/package.json +1 -1
- package/dist/dynamic/components/Panel/package.json +1 -1
- package/dist/dynamic/components/Popover/package.json +1 -1
- package/dist/dynamic/components/Progress/package.json +1 -1
- package/dist/dynamic/components/ProgressStepper/package.json +1 -1
- package/dist/dynamic/components/Radio/package.json +1 -1
- package/dist/dynamic/components/SearchInput/package.json +1 -1
- package/dist/dynamic/components/Select/package.json +1 -1
- package/dist/dynamic/components/Sidebar/package.json +1 -1
- package/dist/dynamic/components/SimpleList/package.json +1 -1
- package/dist/dynamic/components/Skeleton/package.json +1 -1
- package/dist/dynamic/components/SkipToContent/package.json +1 -1
- package/dist/dynamic/components/Slider/package.json +1 -1
- package/dist/dynamic/components/Spinner/package.json +1 -1
- package/dist/dynamic/components/Switch/package.json +1 -1
- package/dist/dynamic/components/Tabs/package.json +1 -1
- package/dist/dynamic/components/TextArea/package.json +1 -1
- package/dist/dynamic/components/TextInput/package.json +1 -1
- package/dist/dynamic/components/TextInputGroup/package.json +1 -1
- package/dist/dynamic/components/TimePicker/package.json +1 -1
- package/dist/dynamic/components/Timestamp/package.json +1 -1
- package/dist/dynamic/components/Title/package.json +1 -1
- package/dist/dynamic/components/ToggleGroup/package.json +1 -1
- package/dist/dynamic/components/Toolbar/package.json +1 -1
- package/dist/dynamic/components/Tooltip/package.json +1 -1
- package/dist/dynamic/components/TreeView/package.json +1 -1
- package/dist/dynamic/components/Truncate/package.json +1 -1
- package/dist/dynamic/components/Wizard/hooks/package.json +1 -1
- package/dist/dynamic/components/Wizard/package.json +1 -1
- package/dist/dynamic/deprecated/components/Chip/package.json +1 -1
- package/dist/dynamic/deprecated/components/DragDrop/package.json +1 -1
- package/dist/dynamic/deprecated/components/DualListSelector/package.json +1 -1
- package/dist/dynamic/deprecated/components/Modal/package.json +1 -1
- package/dist/dynamic/deprecated/components/Tile/package.json +1 -1
- package/dist/dynamic/deprecated/components/Wizard/package.json +1 -1
- package/dist/dynamic/deprecated/components/package.json +1 -1
- package/dist/dynamic/helpers/FocusTrap/FocusTrap/package.json +1 -1
- package/dist/dynamic/helpers/GenerateId/GenerateId/package.json +1 -1
- package/dist/dynamic/helpers/KeyboardHandler/package.json +1 -1
- package/dist/dynamic/helpers/OUIA/ouia/package.json +1 -1
- package/dist/dynamic/helpers/Popper/Popper/package.json +1 -1
- package/dist/dynamic/helpers/constants/package.json +1 -1
- package/dist/dynamic/helpers/datetimeUtils/package.json +1 -1
- package/dist/dynamic/helpers/fileUtils/package.json +1 -1
- package/dist/dynamic/helpers/htmlConstants/package.json +1 -1
- package/dist/dynamic/helpers/package.json +1 -1
- package/dist/dynamic/helpers/resizeObserver/package.json +1 -1
- package/dist/dynamic/helpers/typeUtils/package.json +1 -1
- package/dist/dynamic/helpers/useInterval/package.json +1 -1
- package/dist/dynamic/helpers/useIsomorphicLayout/package.json +1 -1
- package/dist/dynamic/helpers/useUnmountEffect/package.json +1 -1
- package/dist/dynamic/helpers/util/package.json +1 -1
- package/dist/dynamic/layouts/Bullseye/package.json +1 -1
- package/dist/dynamic/layouts/Flex/package.json +1 -1
- package/dist/dynamic/layouts/Gallery/package.json +1 -1
- package/dist/dynamic/layouts/Grid/package.json +1 -1
- package/dist/dynamic/layouts/Level/package.json +1 -1
- package/dist/dynamic/layouts/Split/package.json +1 -1
- package/dist/dynamic/layouts/Stack/package.json +1 -1
- package/dist/dynamic/styles/package.json +1 -1
- package/dist/esm/components/Modal/Modal.d.ts +2 -2
- package/dist/esm/components/Modal/Modal.d.ts.map +1 -1
- package/dist/esm/components/Modal/Modal.js +13 -20
- package/dist/esm/components/Modal/Modal.js.map +1 -1
- package/dist/esm/components/Modal/ModalContent.d.ts +2 -0
- package/dist/esm/components/Modal/ModalContent.d.ts.map +1 -1
- package/dist/esm/components/Modal/ModalContent.js +2 -2
- package/dist/esm/components/Modal/ModalContent.js.map +1 -1
- package/dist/esm/deprecated/components/Modal/Modal.d.ts +2 -2
- package/dist/esm/deprecated/components/Modal/Modal.d.ts.map +1 -1
- package/dist/esm/deprecated/components/Modal/Modal.js +13 -20
- package/dist/esm/deprecated/components/Modal/Modal.js.map +1 -1
- package/dist/esm/deprecated/components/Modal/ModalContent.d.ts +2 -0
- package/dist/esm/deprecated/components/Modal/ModalContent.d.ts.map +1 -1
- package/dist/esm/deprecated/components/Modal/ModalContent.js +2 -2
- package/dist/esm/deprecated/components/Modal/ModalContent.js.map +1 -1
- package/dist/js/components/Modal/Modal.d.ts +2 -2
- package/dist/js/components/Modal/Modal.d.ts.map +1 -1
- package/dist/js/components/Modal/Modal.js +13 -20
- package/dist/js/components/Modal/Modal.js.map +1 -1
- package/dist/js/components/Modal/ModalContent.d.ts +2 -0
- package/dist/js/components/Modal/ModalContent.d.ts.map +1 -1
- package/dist/js/components/Modal/ModalContent.js +2 -2
- package/dist/js/components/Modal/ModalContent.js.map +1 -1
- package/dist/js/deprecated/components/Modal/Modal.d.ts +2 -2
- package/dist/js/deprecated/components/Modal/Modal.d.ts.map +1 -1
- package/dist/js/deprecated/components/Modal/Modal.js +13 -20
- package/dist/js/deprecated/components/Modal/Modal.js.map +1 -1
- package/dist/js/deprecated/components/Modal/ModalContent.d.ts +2 -0
- package/dist/js/deprecated/components/Modal/ModalContent.d.ts.map +1 -1
- package/dist/js/deprecated/components/Modal/ModalContent.js +2 -2
- package/dist/js/deprecated/components/Modal/ModalContent.js.map +1 -1
- package/dist/umd/assets/{output-C2gozh3-.css → output-Df7FMwYL.css} +3654 -3647
- package/dist/umd/react-core.min.js +2 -2
- package/helpers/package.json +1 -1
- package/layouts/package.json +1 -1
- package/next/package.json +1 -1
- package/package.json +6 -6
- package/src/components/Modal/Modal.tsx +13 -18
- package/src/components/Modal/ModalContent.tsx +4 -1
- package/src/components/Modal/__tests__/Modal.test.tsx +45 -0
- package/src/deprecated/components/Modal/Modal.tsx +13 -18
- package/src/deprecated/components/Modal/ModalContent.tsx +4 -1
- package/src/deprecated/components/Modal/__tests__/Modal.test.tsx +28 -0
package/helpers/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name":"@patternfly/react-core-helpers","main":"../dist/js/helpers/index.js","module":"../dist/esm/helpers/index.js","typings":"../dist/esm/helpers/index.d.ts","version":"6.1.0-prerelease.
|
|
1
|
+
{"name":"@patternfly/react-core-helpers","main":"../dist/js/helpers/index.js","module":"../dist/esm/helpers/index.js","typings":"../dist/esm/helpers/index.d.ts","version":"6.1.0-prerelease.7","private":true}
|
package/layouts/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name":"@patternfly/react-core-layouts","main":"../dist/js/layouts/index.js","module":"../dist/esm/layouts/index.js","typings":"../dist/esm/layouts/index.d.ts","version":"6.1.0-prerelease.
|
|
1
|
+
{"name":"@patternfly/react-core-layouts","main":"../dist/js/layouts/index.js","module":"../dist/esm/layouts/index.js","typings":"../dist/esm/layouts/index.d.ts","version":"6.1.0-prerelease.7","private":true}
|
package/next/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name":"@patternfly/react-core-next","main":"../dist/js/next/index.js","module":"../dist/esm/next/index.js","typings":"../dist/esm/next/index.d.ts","version":"6.1.0-prerelease.
|
|
1
|
+
{"name":"@patternfly/react-core-next","main":"../dist/js/next/index.js","module":"../dist/esm/next/index.js","typings":"../dist/esm/next/index.d.ts","version":"6.1.0-prerelease.7","private":true}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@patternfly/react-core",
|
|
3
|
-
"version": "6.1.0-prerelease.
|
|
3
|
+
"version": "6.1.0-prerelease.8",
|
|
4
4
|
"description": "This library provides a set of common React components for use with the PatternFly reference implementation.",
|
|
5
5
|
"main": "dist/js/index.js",
|
|
6
6
|
"module": "dist/esm/index.js",
|
|
@@ -46,15 +46,15 @@
|
|
|
46
46
|
"subpaths": "node ../../scripts/exportSubpaths.mjs --config subpaths.config.json"
|
|
47
47
|
},
|
|
48
48
|
"dependencies": {
|
|
49
|
-
"@patternfly/react-icons": "^6.1.0-prerelease.
|
|
50
|
-
"@patternfly/react-styles": "^6.1.0-prerelease.
|
|
51
|
-
"@patternfly/react-tokens": "^6.1.0-prerelease.
|
|
49
|
+
"@patternfly/react-icons": "^6.1.0-prerelease.4",
|
|
50
|
+
"@patternfly/react-styles": "^6.1.0-prerelease.3",
|
|
51
|
+
"@patternfly/react-tokens": "^6.1.0-prerelease.3",
|
|
52
52
|
"focus-trap": "7.6.2",
|
|
53
53
|
"react-dropzone": "^14.2.3",
|
|
54
54
|
"tslib": "^2.8.1"
|
|
55
55
|
},
|
|
56
56
|
"devDependencies": {
|
|
57
|
-
"@patternfly/patternfly": "6.1.0-prerelease.
|
|
57
|
+
"@patternfly/patternfly": "6.1.0-prerelease.5",
|
|
58
58
|
"case-anything": "^2.1.13",
|
|
59
59
|
"css": "^3.0.0",
|
|
60
60
|
"fs-extra": "^11.2.0"
|
|
@@ -63,5 +63,5 @@
|
|
|
63
63
|
"react": "^17 || ^18",
|
|
64
64
|
"react-dom": "^17 || ^18"
|
|
65
65
|
},
|
|
66
|
-
"gitHead": "
|
|
66
|
+
"gitHead": "0f9245023fb9bdf860c9eee91b6fe160b6c261c5"
|
|
67
67
|
}
|
|
@@ -60,7 +60,6 @@ export enum ModalVariant {
|
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
interface ModalState {
|
|
63
|
-
container: HTMLElement;
|
|
64
63
|
ouiaStateId: string;
|
|
65
64
|
}
|
|
66
65
|
|
|
@@ -68,6 +67,7 @@ class Modal extends React.Component<ModalProps, ModalState> {
|
|
|
68
67
|
static displayName = 'Modal';
|
|
69
68
|
static currentId = 0;
|
|
70
69
|
boxId = '';
|
|
70
|
+
backdropId = '';
|
|
71
71
|
|
|
72
72
|
static defaultProps: PickOptional<ModalProps> = {
|
|
73
73
|
isOpen: false,
|
|
@@ -80,10 +80,11 @@ class Modal extends React.Component<ModalProps, ModalState> {
|
|
|
80
80
|
constructor(props: ModalProps) {
|
|
81
81
|
super(props);
|
|
82
82
|
const boxIdNum = Modal.currentId++;
|
|
83
|
+
const backdropId = boxIdNum + 1;
|
|
83
84
|
this.boxId = props.id || `pf-modal-part-${boxIdNum}`;
|
|
85
|
+
this.backdropId = `pf-modal-part-${backdropId}`;
|
|
84
86
|
|
|
85
87
|
this.state = {
|
|
86
|
-
container: undefined,
|
|
87
88
|
ouiaStateId: getDefaultOUIAId(Modal.displayName, props.variant)
|
|
88
89
|
};
|
|
89
90
|
}
|
|
@@ -107,7 +108,7 @@ class Modal extends React.Component<ModalProps, ModalState> {
|
|
|
107
108
|
const target: HTMLElement = this.getElement(appendTo);
|
|
108
109
|
const bodyChildren = target.children;
|
|
109
110
|
for (const child of Array.from(bodyChildren)) {
|
|
110
|
-
if (child !== this.
|
|
111
|
+
if (child.id !== this.backdropId) {
|
|
111
112
|
hide ? child.setAttribute('aria-hidden', '' + hide) : child.removeAttribute('aria-hidden');
|
|
112
113
|
}
|
|
113
114
|
}
|
|
@@ -118,36 +119,31 @@ class Modal extends React.Component<ModalProps, ModalState> {
|
|
|
118
119
|
componentDidMount() {
|
|
119
120
|
const { appendTo } = this.props;
|
|
120
121
|
const target: HTMLElement = this.getElement(appendTo);
|
|
121
|
-
const container = document.createElement('div');
|
|
122
|
-
this.setState({ container });
|
|
123
|
-
target.appendChild(container);
|
|
124
122
|
target.addEventListener('keydown', this.handleEscKeyClick, false);
|
|
125
123
|
|
|
126
124
|
if (this.props.isOpen) {
|
|
127
125
|
target.classList.add(css(styles.backdropOpen));
|
|
128
|
-
|
|
129
|
-
target.classList.remove(css(styles.backdropOpen));
|
|
126
|
+
this.toggleSiblingsFromScreenReaders(true);
|
|
130
127
|
}
|
|
131
128
|
}
|
|
132
129
|
|
|
133
|
-
componentDidUpdate() {
|
|
130
|
+
componentDidUpdate(prevProps: ModalProps) {
|
|
134
131
|
const { appendTo } = this.props;
|
|
135
132
|
const target: HTMLElement = this.getElement(appendTo);
|
|
136
133
|
if (this.props.isOpen) {
|
|
137
134
|
target.classList.add(css(styles.backdropOpen));
|
|
138
135
|
this.toggleSiblingsFromScreenReaders(true);
|
|
139
136
|
} else {
|
|
140
|
-
|
|
141
|
-
|
|
137
|
+
if (prevProps.isOpen !== this.props.isOpen) {
|
|
138
|
+
target.classList.remove(css(styles.backdropOpen));
|
|
139
|
+
this.toggleSiblingsFromScreenReaders(false);
|
|
140
|
+
}
|
|
142
141
|
}
|
|
143
142
|
}
|
|
144
143
|
|
|
145
144
|
componentWillUnmount() {
|
|
146
145
|
const { appendTo } = this.props;
|
|
147
146
|
const target: HTMLElement = this.getElement(appendTo);
|
|
148
|
-
if (this.state.container) {
|
|
149
|
-
target.removeChild(this.state.container);
|
|
150
|
-
}
|
|
151
147
|
target.removeEventListener('keydown', this.handleEscKeyClick, false);
|
|
152
148
|
target.classList.remove(css(styles.backdropOpen));
|
|
153
149
|
this.toggleSiblingsFromScreenReaders(false);
|
|
@@ -155,7 +151,6 @@ class Modal extends React.Component<ModalProps, ModalState> {
|
|
|
155
151
|
|
|
156
152
|
render() {
|
|
157
153
|
const {
|
|
158
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
159
154
|
appendTo,
|
|
160
155
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
161
156
|
onEscapePress,
|
|
@@ -168,15 +163,15 @@ class Modal extends React.Component<ModalProps, ModalState> {
|
|
|
168
163
|
elementToFocus,
|
|
169
164
|
...props
|
|
170
165
|
} = this.props;
|
|
171
|
-
const { container } = this.state;
|
|
172
166
|
|
|
173
|
-
if (!canUseDOM || !
|
|
167
|
+
if (!canUseDOM || !this.getElement(appendTo)) {
|
|
174
168
|
return null;
|
|
175
169
|
}
|
|
176
170
|
|
|
177
171
|
return ReactDOM.createPortal(
|
|
178
172
|
<ModalContent
|
|
179
173
|
boxId={this.boxId}
|
|
174
|
+
backdropId={this.backdropId}
|
|
180
175
|
aria-label={ariaLabel}
|
|
181
176
|
aria-describedby={ariaDescribedby}
|
|
182
177
|
aria-labelledby={ariaLabelledby}
|
|
@@ -187,7 +182,7 @@ class Modal extends React.Component<ModalProps, ModalState> {
|
|
|
187
182
|
backdropClassName={props.backdropClassName}
|
|
188
183
|
{...props}
|
|
189
184
|
/>,
|
|
190
|
-
|
|
185
|
+
this.getElement(appendTo)
|
|
191
186
|
) as React.ReactElement;
|
|
192
187
|
}
|
|
193
188
|
}
|
|
@@ -16,6 +16,8 @@ export interface ModalContentProps extends OUIAProps {
|
|
|
16
16
|
'aria-labelledby'?: string;
|
|
17
17
|
/** Id of the modal box container. */
|
|
18
18
|
boxId: string;
|
|
19
|
+
/** Id of the backdrop. */
|
|
20
|
+
backdropId?: string;
|
|
19
21
|
/** Content rendered inside the modal. */
|
|
20
22
|
children: React.ReactNode;
|
|
21
23
|
/** Additional classes added to the modal box. */
|
|
@@ -63,6 +65,7 @@ export const ModalContent: React.FunctionComponent<ModalContentProps> = ({
|
|
|
63
65
|
width,
|
|
64
66
|
maxWidth,
|
|
65
67
|
boxId,
|
|
68
|
+
backdropId,
|
|
66
69
|
disableFocusTrap = false,
|
|
67
70
|
ouiaId,
|
|
68
71
|
ouiaSafe = true,
|
|
@@ -109,7 +112,7 @@ export const ModalContent: React.FunctionComponent<ModalContentProps> = ({
|
|
|
109
112
|
</ModalBox>
|
|
110
113
|
);
|
|
111
114
|
return (
|
|
112
|
-
<Backdrop className={css(backdropClassName)}>
|
|
115
|
+
<Backdrop className={css(backdropClassName)} id={backdropId}>
|
|
113
116
|
<FocusTrap
|
|
114
117
|
active={!disableFocusTrap}
|
|
115
118
|
focusTrapOptions={{
|
|
@@ -2,6 +2,7 @@ import * as React from 'react';
|
|
|
2
2
|
|
|
3
3
|
import { render, screen } from '@testing-library/react';
|
|
4
4
|
import userEvent from '@testing-library/user-event';
|
|
5
|
+
import '@testing-library/jest-dom';
|
|
5
6
|
|
|
6
7
|
import { css } from '../../../../../react-styles/dist/js';
|
|
7
8
|
import styles from '@patternfly/react-styles/css/components/Backdrop/backdrop';
|
|
@@ -38,6 +39,32 @@ const ModalWithSiblings = () => {
|
|
|
38
39
|
);
|
|
39
40
|
};
|
|
40
41
|
|
|
42
|
+
const ModalWithAdjacentModal = () => {
|
|
43
|
+
const [isOpen, setIsOpen] = React.useState(true);
|
|
44
|
+
const [isModalMounted, setIsModalMounted] = React.useState(true);
|
|
45
|
+
const modalProps = { ...props, isOpen, appendTo: target, onClose: () => setIsOpen(false) };
|
|
46
|
+
|
|
47
|
+
return (
|
|
48
|
+
<>
|
|
49
|
+
<aside>Aside sibling</aside>
|
|
50
|
+
<article>Section sibling</article>
|
|
51
|
+
{isModalMounted && (
|
|
52
|
+
<>
|
|
53
|
+
<Modal {...modalProps}>
|
|
54
|
+
<button onClick={() => setIsModalMounted(false)}>Unmount Modal</button>
|
|
55
|
+
</Modal>
|
|
56
|
+
<Modal isOpen={false} onClose={() => {}}>
|
|
57
|
+
Modal closed for test
|
|
58
|
+
</Modal>
|
|
59
|
+
<Modal isOpen={false} onClose={() => {}}>
|
|
60
|
+
modal closed for test
|
|
61
|
+
</Modal>
|
|
62
|
+
</>
|
|
63
|
+
)}
|
|
64
|
+
</>
|
|
65
|
+
);
|
|
66
|
+
};
|
|
67
|
+
|
|
41
68
|
describe('Modal', () => {
|
|
42
69
|
test('Modal creates a container element once for div', () => {
|
|
43
70
|
render(<Modal {...props} />);
|
|
@@ -128,4 +155,22 @@ describe('Modal', () => {
|
|
|
128
155
|
expect(asideSibling).not.toHaveAttribute('aria-hidden');
|
|
129
156
|
expect(articleSibling).not.toHaveAttribute('aria-hidden');
|
|
130
157
|
});
|
|
158
|
+
|
|
159
|
+
test('modal siblings have the aria-hidden attribute when it has adjacent modals', async () => {
|
|
160
|
+
const user = userEvent.setup();
|
|
161
|
+
|
|
162
|
+
render(<ModalWithAdjacentModal />, { container: document.body.appendChild(target) });
|
|
163
|
+
|
|
164
|
+
const asideSibling = screen.getByRole('complementary', { hidden: true });
|
|
165
|
+
const articleSibling = screen.getByRole('article', { hidden: true });
|
|
166
|
+
const unmountButton = screen.getByRole('button', { name: 'Unmount Modal' });
|
|
167
|
+
|
|
168
|
+
expect(asideSibling).toHaveAttribute('aria-hidden');
|
|
169
|
+
expect(articleSibling).toHaveAttribute('aria-hidden');
|
|
170
|
+
|
|
171
|
+
await user.click(unmountButton);
|
|
172
|
+
|
|
173
|
+
expect(asideSibling).not.toHaveAttribute('aria-hidden');
|
|
174
|
+
expect(articleSibling).not.toHaveAttribute('aria-hidden');
|
|
175
|
+
});
|
|
131
176
|
});
|
|
@@ -92,7 +92,6 @@ export enum ModalVariant {
|
|
|
92
92
|
}
|
|
93
93
|
|
|
94
94
|
interface ModalState {
|
|
95
|
-
container: HTMLElement;
|
|
96
95
|
ouiaStateId: string;
|
|
97
96
|
}
|
|
98
97
|
|
|
@@ -102,6 +101,7 @@ class Modal extends React.Component<ModalProps, ModalState> {
|
|
|
102
101
|
boxId = '';
|
|
103
102
|
labelId = '';
|
|
104
103
|
descriptorId = '';
|
|
104
|
+
backdropId = '';
|
|
105
105
|
|
|
106
106
|
static defaultProps: PickOptional<ModalProps> = {
|
|
107
107
|
className: '',
|
|
@@ -128,12 +128,13 @@ class Modal extends React.Component<ModalProps, ModalState> {
|
|
|
128
128
|
const boxIdNum = Modal.currentId++;
|
|
129
129
|
const labelIdNum = boxIdNum + 1;
|
|
130
130
|
const descriptorIdNum = boxIdNum + 2;
|
|
131
|
+
const backdropIdNum = boxIdNum + 3;
|
|
131
132
|
this.boxId = props.id || `pf-modal-part-${boxIdNum}`;
|
|
132
133
|
this.labelId = `pf-modal-part-${labelIdNum}`;
|
|
133
134
|
this.descriptorId = `pf-modal-part-${descriptorIdNum}`;
|
|
135
|
+
this.backdropId = `pf-modal-part-${backdropIdNum}`;
|
|
134
136
|
|
|
135
137
|
this.state = {
|
|
136
|
-
container: undefined,
|
|
137
138
|
ouiaStateId: getDefaultOUIAId(Modal.displayName, props.variant)
|
|
138
139
|
};
|
|
139
140
|
}
|
|
@@ -157,7 +158,7 @@ class Modal extends React.Component<ModalProps, ModalState> {
|
|
|
157
158
|
const target: HTMLElement = this.getElement(appendTo);
|
|
158
159
|
const bodyChildren = target.children;
|
|
159
160
|
for (const child of Array.from(bodyChildren)) {
|
|
160
|
-
if (child !== this.
|
|
161
|
+
if (child.id !== this.backdropId) {
|
|
161
162
|
hide ? child.setAttribute('aria-hidden', '' + hide) : child.removeAttribute('aria-hidden');
|
|
162
163
|
}
|
|
163
164
|
}
|
|
@@ -175,15 +176,11 @@ class Modal extends React.Component<ModalProps, ModalState> {
|
|
|
175
176
|
header
|
|
176
177
|
} = this.props;
|
|
177
178
|
const target: HTMLElement = this.getElement(appendTo);
|
|
178
|
-
const container = document.createElement('div');
|
|
179
|
-
this.setState({ container });
|
|
180
|
-
target.appendChild(container);
|
|
181
179
|
target.addEventListener('keydown', this.handleEscKeyClick, false);
|
|
182
180
|
|
|
183
181
|
if (this.props.isOpen) {
|
|
184
182
|
target.classList.add(css(styles.backdropOpen));
|
|
185
|
-
|
|
186
|
-
target.classList.remove(css(styles.backdropOpen));
|
|
183
|
+
this.toggleSiblingsFromScreenReaders(true);
|
|
187
184
|
}
|
|
188
185
|
|
|
189
186
|
if (!title && this.isEmpty(ariaLabel) && this.isEmpty(ariaLabelledby)) {
|
|
@@ -199,24 +196,23 @@ class Modal extends React.Component<ModalProps, ModalState> {
|
|
|
199
196
|
}
|
|
200
197
|
}
|
|
201
198
|
|
|
202
|
-
componentDidUpdate() {
|
|
199
|
+
componentDidUpdate(prevProps: ModalProps) {
|
|
203
200
|
const { appendTo } = this.props;
|
|
204
201
|
const target: HTMLElement = this.getElement(appendTo);
|
|
205
202
|
if (this.props.isOpen) {
|
|
206
203
|
target.classList.add(css(styles.backdropOpen));
|
|
207
204
|
this.toggleSiblingsFromScreenReaders(true);
|
|
208
205
|
} else {
|
|
209
|
-
|
|
210
|
-
|
|
206
|
+
if (prevProps.isOpen !== this.props.isOpen) {
|
|
207
|
+
target.classList.remove(css(styles.backdropOpen));
|
|
208
|
+
this.toggleSiblingsFromScreenReaders(false);
|
|
209
|
+
}
|
|
211
210
|
}
|
|
212
211
|
}
|
|
213
212
|
|
|
214
213
|
componentWillUnmount() {
|
|
215
214
|
const { appendTo } = this.props;
|
|
216
215
|
const target: HTMLElement = this.getElement(appendTo);
|
|
217
|
-
if (this.state.container) {
|
|
218
|
-
target.removeChild(this.state.container);
|
|
219
|
-
}
|
|
220
216
|
target.removeEventListener('keydown', this.handleEscKeyClick, false);
|
|
221
217
|
target.classList.remove(css(styles.backdropOpen));
|
|
222
218
|
this.toggleSiblingsFromScreenReaders(false);
|
|
@@ -224,7 +220,6 @@ class Modal extends React.Component<ModalProps, ModalState> {
|
|
|
224
220
|
|
|
225
221
|
render() {
|
|
226
222
|
const {
|
|
227
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
228
223
|
appendTo,
|
|
229
224
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
230
225
|
onEscapePress,
|
|
@@ -242,9 +237,8 @@ class Modal extends React.Component<ModalProps, ModalState> {
|
|
|
242
237
|
elementToFocus,
|
|
243
238
|
...props
|
|
244
239
|
} = this.props;
|
|
245
|
-
const { container } = this.state;
|
|
246
240
|
|
|
247
|
-
if (!canUseDOM || !
|
|
241
|
+
if (!canUseDOM || !this.getElement(appendTo)) {
|
|
248
242
|
return null;
|
|
249
243
|
}
|
|
250
244
|
|
|
@@ -254,6 +248,7 @@ class Modal extends React.Component<ModalProps, ModalState> {
|
|
|
254
248
|
boxId={this.boxId}
|
|
255
249
|
labelId={this.labelId}
|
|
256
250
|
descriptorId={this.descriptorId}
|
|
251
|
+
backdropId={this.backdropId}
|
|
257
252
|
title={title}
|
|
258
253
|
titleIconVariant={titleIconVariant}
|
|
259
254
|
titleLabel={titleLabel}
|
|
@@ -267,7 +262,7 @@ class Modal extends React.Component<ModalProps, ModalState> {
|
|
|
267
262
|
position={position}
|
|
268
263
|
elementToFocus={elementToFocus}
|
|
269
264
|
/>,
|
|
270
|
-
|
|
265
|
+
this.getElement(appendTo)
|
|
271
266
|
) as React.ReactElement;
|
|
272
267
|
}
|
|
273
268
|
}
|
|
@@ -25,6 +25,8 @@ export interface ModalContentProps extends OUIAProps {
|
|
|
25
25
|
'aria-label'?: string;
|
|
26
26
|
/** Id to use for the modal box label. */
|
|
27
27
|
'aria-labelledby'?: string | null;
|
|
28
|
+
/** Id of the backdrop. */
|
|
29
|
+
backdropId?: string;
|
|
28
30
|
/** Accessible label applied to the modal box body. This should be used to communicate
|
|
29
31
|
* important information about the modal box body div element if needed, such as that it
|
|
30
32
|
* is scrollable.
|
|
@@ -117,6 +119,7 @@ export const ModalContent: React.FunctionComponent<ModalContentProps> = ({
|
|
|
117
119
|
maxWidth,
|
|
118
120
|
boxId,
|
|
119
121
|
labelId,
|
|
122
|
+
backdropId,
|
|
120
123
|
descriptorId,
|
|
121
124
|
disableFocusTrap = false,
|
|
122
125
|
hasNoBodyWrapper = false,
|
|
@@ -202,7 +205,7 @@ export const ModalContent: React.FunctionComponent<ModalContentProps> = ({
|
|
|
202
205
|
</ModalBox>
|
|
203
206
|
);
|
|
204
207
|
return (
|
|
205
|
-
<Backdrop>
|
|
208
|
+
<Backdrop id={backdropId}>
|
|
206
209
|
<FocusTrap
|
|
207
210
|
active={!disableFocusTrap}
|
|
208
211
|
focusTrapOptions={{
|
|
@@ -2,6 +2,7 @@ import * as React from 'react';
|
|
|
2
2
|
|
|
3
3
|
import { render, screen } from '@testing-library/react';
|
|
4
4
|
import userEvent from '@testing-library/user-event';
|
|
5
|
+
import '@testing-library/jest-dom';
|
|
5
6
|
|
|
6
7
|
import { css } from '../../../../../../react-styles/dist/js';
|
|
7
8
|
import styles from '@patternfly/react-styles/css/components/Backdrop/backdrop';
|
|
@@ -39,6 +40,32 @@ const ModalWithSiblings = () => {
|
|
|
39
40
|
);
|
|
40
41
|
};
|
|
41
42
|
|
|
43
|
+
const ModalWithAdjacentModal = () => {
|
|
44
|
+
const [isOpen, setIsOpen] = React.useState(true);
|
|
45
|
+
const [isModalMounted, setIsModalMounted] = React.useState(true);
|
|
46
|
+
const modalProps = { ...props, isOpen, appendTo: target, onClose: () => setIsOpen(false) };
|
|
47
|
+
|
|
48
|
+
return (
|
|
49
|
+
<>
|
|
50
|
+
<aside>Aside sibling</aside>
|
|
51
|
+
<article>Section sibling</article>
|
|
52
|
+
{isModalMounted && (
|
|
53
|
+
<>
|
|
54
|
+
<Modal {...modalProps}>
|
|
55
|
+
<button onClick={() => setIsModalMounted(false)}>Unmount Modal</button>
|
|
56
|
+
</Modal>
|
|
57
|
+
<Modal isOpen={false} onClose={() => {}}>
|
|
58
|
+
Modal closed for test
|
|
59
|
+
</Modal>
|
|
60
|
+
<Modal isOpen={false} onClose={() => {}}>
|
|
61
|
+
modal closed for test
|
|
62
|
+
</Modal>
|
|
63
|
+
</>
|
|
64
|
+
)}
|
|
65
|
+
</>
|
|
66
|
+
);
|
|
67
|
+
};
|
|
68
|
+
|
|
42
69
|
describe('Modal', () => {
|
|
43
70
|
test('Modal creates a container element once for div', () => {
|
|
44
71
|
render(<Modal {...props} />);
|
|
@@ -154,6 +181,7 @@ describe('Modal', () => {
|
|
|
154
181
|
expect(asideSibling).not.toHaveAttribute('aria-hidden');
|
|
155
182
|
expect(articleSibling).not.toHaveAttribute('aria-hidden');
|
|
156
183
|
});
|
|
184
|
+
|
|
157
185
|
test('The modalBoxBody has no aria-label when bodyAriaLabel is not passed', () => {
|
|
158
186
|
const props = {
|
|
159
187
|
isOpen: true
|