@patternfly/react-core 5.4.8 → 5.4.10
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 +13 -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/Chip/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/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/DragDrop/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/Text/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/Tile/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/ApplicationLauncher/package.json +1 -1
- package/dist/dynamic/deprecated/components/ContextSelector/package.json +1 -1
- package/dist/dynamic/deprecated/components/Dropdown/package.json +1 -1
- package/dist/dynamic/deprecated/components/OptionsMenu/package.json +1 -1
- package/dist/dynamic/deprecated/components/PageHeader/package.json +1 -1
- package/dist/dynamic/deprecated/components/Select/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/favorites/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/next/components/DualListSelector/package.json +1 -1
- package/dist/dynamic/next/components/Modal/package.json +1 -1
- package/dist/dynamic/next/components/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/components/Toolbar/ToolbarFilter.d.ts.map +1 -1
- package/dist/esm/components/Toolbar/ToolbarFilter.js +4 -2
- package/dist/esm/components/Toolbar/ToolbarFilter.js.map +1 -1
- package/dist/esm/next/components/Modal/Modal.d.ts +2 -2
- package/dist/esm/next/components/Modal/Modal.d.ts.map +1 -1
- package/dist/esm/next/components/Modal/Modal.js +13 -20
- package/dist/esm/next/components/Modal/Modal.js.map +1 -1
- package/dist/esm/next/components/Modal/ModalContent.d.ts +2 -0
- package/dist/esm/next/components/Modal/ModalContent.d.ts.map +1 -1
- package/dist/esm/next/components/Modal/ModalContent.js +2 -2
- package/dist/esm/next/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/components/Toolbar/ToolbarFilter.d.ts.map +1 -1
- package/dist/js/components/Toolbar/ToolbarFilter.js +4 -2
- package/dist/js/components/Toolbar/ToolbarFilter.js.map +1 -1
- package/dist/js/next/components/Modal/Modal.d.ts +2 -2
- package/dist/js/next/components/Modal/Modal.d.ts.map +1 -1
- package/dist/js/next/components/Modal/Modal.js +13 -20
- package/dist/js/next/components/Modal/Modal.js.map +1 -1
- package/dist/js/next/components/Modal/ModalContent.d.ts +2 -0
- package/dist/js/next/components/Modal/ModalContent.d.ts.map +1 -1
- package/dist/js/next/components/Modal/ModalContent.js +2 -2
- package/dist/js/next/components/Modal/ModalContent.js.map +1 -1
- package/dist/umd/assets/{output-DNh7MEud.css → output-DxbNpZVR.css} +9097 -9097
- 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 +3 -3
- package/src/components/Modal/Modal.tsx +14 -18
- package/src/components/Modal/ModalContent.tsx +4 -1
- package/src/components/Modal/__tests__/Modal.test.tsx +30 -7
- package/src/components/Toolbar/ToolbarFilter.tsx +2 -1
- package/src/next/components/Modal/Modal.tsx +13 -18
- package/src/next/components/Modal/ModalContent.tsx +4 -1
- package/src/next/components/Modal/__tests__/Modal.test.tsx +45 -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":"5.4.
|
|
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":"5.4.9","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":"5.4.
|
|
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":"5.4.9","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":"5.4.
|
|
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":"5.4.9","private":true}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@patternfly/react-core",
|
|
3
|
-
"version": "5.4.
|
|
3
|
+
"version": "5.4.10",
|
|
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",
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
"@patternfly/react-icons": "^5.4.2",
|
|
50
50
|
"@patternfly/react-styles": "^5.4.1",
|
|
51
51
|
"@patternfly/react-tokens": "^5.4.1",
|
|
52
|
-
"focus-trap": "7.6.
|
|
52
|
+
"focus-trap": "7.6.2",
|
|
53
53
|
"react-dropzone": "^14.2.3",
|
|
54
54
|
"tslib": "^2.7.0"
|
|
55
55
|
},
|
|
@@ -62,5 +62,5 @@
|
|
|
62
62
|
"react": "^17 || ^18",
|
|
63
63
|
"react-dom": "^17 || ^18"
|
|
64
64
|
},
|
|
65
|
-
"gitHead": "
|
|
65
|
+
"gitHead": "0f3ece1d04a0f27f48f6369ab81eddf93c078846"
|
|
66
66
|
}
|
|
@@ -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,24 @@ 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
|
-
|
|
218
|
-
target.removeChild(this.state.container);
|
|
219
|
-
}
|
|
216
|
+
|
|
220
217
|
target.removeEventListener('keydown', this.handleEscKeyClick, false);
|
|
221
218
|
target.classList.remove(css(styles.backdropOpen));
|
|
222
219
|
this.toggleSiblingsFromScreenReaders(false);
|
|
@@ -224,7 +221,6 @@ class Modal extends React.Component<ModalProps, ModalState> {
|
|
|
224
221
|
|
|
225
222
|
render() {
|
|
226
223
|
const {
|
|
227
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
228
224
|
appendTo,
|
|
229
225
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
230
226
|
onEscapePress,
|
|
@@ -242,9 +238,8 @@ class Modal extends React.Component<ModalProps, ModalState> {
|
|
|
242
238
|
elementToFocus,
|
|
243
239
|
...props
|
|
244
240
|
} = this.props;
|
|
245
|
-
const { container } = this.state;
|
|
246
241
|
|
|
247
|
-
if (!canUseDOM || !
|
|
242
|
+
if (!canUseDOM || !this.getElement(appendTo)) {
|
|
248
243
|
return null;
|
|
249
244
|
}
|
|
250
245
|
|
|
@@ -254,6 +249,7 @@ class Modal extends React.Component<ModalProps, ModalState> {
|
|
|
254
249
|
boxId={this.boxId}
|
|
255
250
|
labelId={this.labelId}
|
|
256
251
|
descriptorId={this.descriptorId}
|
|
252
|
+
backdropId={this.backdropId}
|
|
257
253
|
title={title}
|
|
258
254
|
titleIconVariant={titleIconVariant}
|
|
259
255
|
titleLabel={titleLabel}
|
|
@@ -267,7 +263,7 @@ class Modal extends React.Component<ModalProps, ModalState> {
|
|
|
267
263
|
position={position}
|
|
268
264
|
elementToFocus={elementToFocus}
|
|
269
265
|
/>,
|
|
270
|
-
|
|
266
|
+
this.getElement(appendTo)
|
|
271
267
|
) as React.ReactElement;
|
|
272
268
|
}
|
|
273
269
|
}
|
|
@@ -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,12 +40,33 @@ const ModalWithSiblings = () => {
|
|
|
39
40
|
);
|
|
40
41
|
};
|
|
41
42
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
});
|
|
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
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
|
+
|
|
69
|
+
describe('Modal', () => {
|
|
48
70
|
test('modal closes with escape', async () => {
|
|
49
71
|
const user = userEvent.setup();
|
|
50
72
|
|
|
@@ -137,10 +159,10 @@ describe('Modal', () => {
|
|
|
137
159
|
expect(asideSibling).not.toHaveAttribute('aria-hidden');
|
|
138
160
|
});
|
|
139
161
|
|
|
140
|
-
test('modal
|
|
162
|
+
test('modal siblings have the aria-hidden attribute when it has adjacent modals', async () => {
|
|
141
163
|
const user = userEvent.setup();
|
|
142
164
|
|
|
143
|
-
render(<
|
|
165
|
+
render(<ModalWithAdjacentModal />, { container: document.body.appendChild(target) });
|
|
144
166
|
|
|
145
167
|
const asideSibling = screen.getByRole('complementary', { hidden: true });
|
|
146
168
|
const articleSibling = screen.getByRole('article', { hidden: true });
|
|
@@ -154,6 +176,7 @@ describe('Modal', () => {
|
|
|
154
176
|
expect(asideSibling).not.toHaveAttribute('aria-hidden');
|
|
155
177
|
expect(articleSibling).not.toHaveAttribute('aria-hidden');
|
|
156
178
|
});
|
|
179
|
+
|
|
157
180
|
test('The modalBoxBody has no aria-label when bodyAriaLabel is not passed', () => {
|
|
158
181
|
const props = {
|
|
159
182
|
isOpen: true
|
|
@@ -134,7 +134,8 @@ class ToolbarFilter extends React.Component<ToolbarFilterProps, ToolbarFilterSta
|
|
|
134
134
|
return (
|
|
135
135
|
<React.Fragment>
|
|
136
136
|
{showToolbarItem && <ToolbarItem {...props}>{children}</ToolbarItem>}
|
|
137
|
-
{
|
|
137
|
+
{chipGroupContentRef?.current?.firstElementChild &&
|
|
138
|
+
ReactDOM.createPortal(chipGroup, chipGroupContentRef.current.firstElementChild)}
|
|
138
139
|
</React.Fragment>
|
|
139
140
|
);
|
|
140
141
|
}
|
|
@@ -58,7 +58,6 @@ export enum ModalVariant {
|
|
|
58
58
|
}
|
|
59
59
|
|
|
60
60
|
interface ModalState {
|
|
61
|
-
container: HTMLElement;
|
|
62
61
|
ouiaStateId: string;
|
|
63
62
|
}
|
|
64
63
|
|
|
@@ -66,6 +65,7 @@ class Modal extends React.Component<ModalProps, ModalState> {
|
|
|
66
65
|
static displayName = 'Modal';
|
|
67
66
|
static currentId = 0;
|
|
68
67
|
boxId = '';
|
|
68
|
+
backdropId = '';
|
|
69
69
|
|
|
70
70
|
static defaultProps: PickOptional<ModalProps> = {
|
|
71
71
|
isOpen: false,
|
|
@@ -78,10 +78,11 @@ class Modal extends React.Component<ModalProps, ModalState> {
|
|
|
78
78
|
constructor(props: ModalProps) {
|
|
79
79
|
super(props);
|
|
80
80
|
const boxIdNum = Modal.currentId++;
|
|
81
|
+
const backdropId = boxIdNum + 1;
|
|
81
82
|
this.boxId = props.id || `pf-modal-part-${boxIdNum}`;
|
|
83
|
+
this.backdropId = `pf-modal-part-${backdropId}`;
|
|
82
84
|
|
|
83
85
|
this.state = {
|
|
84
|
-
container: undefined,
|
|
85
86
|
ouiaStateId: getDefaultOUIAId(Modal.displayName, props.variant)
|
|
86
87
|
};
|
|
87
88
|
}
|
|
@@ -105,7 +106,7 @@ class Modal extends React.Component<ModalProps, ModalState> {
|
|
|
105
106
|
const target: HTMLElement = this.getElement(appendTo);
|
|
106
107
|
const bodyChildren = target.children;
|
|
107
108
|
for (const child of Array.from(bodyChildren)) {
|
|
108
|
-
if (child !== this.
|
|
109
|
+
if (child.id !== this.backdropId) {
|
|
109
110
|
hide ? child.setAttribute('aria-hidden', '' + hide) : child.removeAttribute('aria-hidden');
|
|
110
111
|
}
|
|
111
112
|
}
|
|
@@ -116,36 +117,31 @@ class Modal extends React.Component<ModalProps, ModalState> {
|
|
|
116
117
|
componentDidMount() {
|
|
117
118
|
const { appendTo } = this.props;
|
|
118
119
|
const target: HTMLElement = this.getElement(appendTo);
|
|
119
|
-
const container = document.createElement('div');
|
|
120
|
-
this.setState({ container });
|
|
121
|
-
target.appendChild(container);
|
|
122
120
|
target.addEventListener('keydown', this.handleEscKeyClick, false);
|
|
123
121
|
|
|
124
122
|
if (this.props.isOpen) {
|
|
125
123
|
target.classList.add(css(styles.backdropOpen));
|
|
126
|
-
|
|
127
|
-
target.classList.remove(css(styles.backdropOpen));
|
|
124
|
+
this.toggleSiblingsFromScreenReaders(true);
|
|
128
125
|
}
|
|
129
126
|
}
|
|
130
127
|
|
|
131
|
-
componentDidUpdate() {
|
|
128
|
+
componentDidUpdate(prevProps: ModalProps) {
|
|
132
129
|
const { appendTo } = this.props;
|
|
133
130
|
const target: HTMLElement = this.getElement(appendTo);
|
|
134
131
|
if (this.props.isOpen) {
|
|
135
132
|
target.classList.add(css(styles.backdropOpen));
|
|
136
133
|
this.toggleSiblingsFromScreenReaders(true);
|
|
137
134
|
} else {
|
|
138
|
-
|
|
139
|
-
|
|
135
|
+
if (prevProps.isOpen !== this.props.isOpen) {
|
|
136
|
+
target.classList.remove(css(styles.backdropOpen));
|
|
137
|
+
this.toggleSiblingsFromScreenReaders(false);
|
|
138
|
+
}
|
|
140
139
|
}
|
|
141
140
|
}
|
|
142
141
|
|
|
143
142
|
componentWillUnmount() {
|
|
144
143
|
const { appendTo } = this.props;
|
|
145
144
|
const target: HTMLElement = this.getElement(appendTo);
|
|
146
|
-
if (this.state.container) {
|
|
147
|
-
target.removeChild(this.state.container);
|
|
148
|
-
}
|
|
149
145
|
target.removeEventListener('keydown', this.handleEscKeyClick, false);
|
|
150
146
|
target.classList.remove(css(styles.backdropOpen));
|
|
151
147
|
this.toggleSiblingsFromScreenReaders(false);
|
|
@@ -153,7 +149,6 @@ class Modal extends React.Component<ModalProps, ModalState> {
|
|
|
153
149
|
|
|
154
150
|
render() {
|
|
155
151
|
const {
|
|
156
|
-
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
157
152
|
appendTo,
|
|
158
153
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
159
154
|
onEscapePress,
|
|
@@ -166,15 +161,15 @@ class Modal extends React.Component<ModalProps, ModalState> {
|
|
|
166
161
|
elementToFocus,
|
|
167
162
|
...props
|
|
168
163
|
} = this.props;
|
|
169
|
-
const { container } = this.state;
|
|
170
164
|
|
|
171
|
-
if (!canUseDOM || !
|
|
165
|
+
if (!canUseDOM || !this.getElement(appendTo)) {
|
|
172
166
|
return null;
|
|
173
167
|
}
|
|
174
168
|
|
|
175
169
|
return ReactDOM.createPortal(
|
|
176
170
|
<ModalContent
|
|
177
171
|
boxId={this.boxId}
|
|
172
|
+
backdropId={this.backdropId}
|
|
178
173
|
aria-label={ariaLabel}
|
|
179
174
|
aria-describedby={ariaDescribedby}
|
|
180
175
|
aria-labelledby={ariaLabelledby}
|
|
@@ -184,7 +179,7 @@ class Modal extends React.Component<ModalProps, ModalState> {
|
|
|
184
179
|
elementToFocus={elementToFocus}
|
|
185
180
|
{...props}
|
|
186
181
|
/>,
|
|
187
|
-
|
|
182
|
+
this.getElement(appendTo)
|
|
188
183
|
) as React.ReactElement;
|
|
189
184
|
}
|
|
190
185
|
}
|
|
@@ -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. */
|
|
@@ -60,6 +62,7 @@ export const ModalContent: React.FunctionComponent<ModalContentProps> = ({
|
|
|
60
62
|
width,
|
|
61
63
|
maxWidth,
|
|
62
64
|
boxId,
|
|
65
|
+
backdropId,
|
|
63
66
|
disableFocusTrap = false,
|
|
64
67
|
ouiaId,
|
|
65
68
|
ouiaSafe = true,
|
|
@@ -106,7 +109,7 @@ export const ModalContent: React.FunctionComponent<ModalContentProps> = ({
|
|
|
106
109
|
</ModalBox>
|
|
107
110
|
);
|
|
108
111
|
return (
|
|
109
|
-
<Backdrop>
|
|
112
|
+
<Backdrop id={backdropId}>
|
|
110
113
|
<FocusTrap
|
|
111
114
|
active={!disableFocusTrap}
|
|
112
115
|
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
|
});
|