Skip to content

Commit d4984bd

Browse files
authored
Merge pull request #62 from fhlavac/warningModal
feat(WarningModal): Add warning modal component
2 parents dc22fb3 + 329ce6c commit d4984bd

7 files changed

Lines changed: 305 additions & 0 deletions

File tree

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
---
2+
# Sidenav top-level section
3+
# should be the same for all markdown files
4+
section: extensions
5+
subsection: Component groups
6+
# Sidenav secondary level section
7+
# should be the same for all markdown files
8+
id: Warning modal
9+
# Tab (react | react-demos | html | html-demos | design-guidelines | accessibility)
10+
source: react
11+
# If you use typescript, the name of the interface to display props for
12+
# These are found through the sourceProps function provided in patternfly-docs.source.js
13+
propComponents: ['WarningModal']
14+
---
15+
16+
import WarningModal from '@patternfly/react-component-groups/dist/dynamic/WarningModal';
17+
18+
A **warning modal** component displays a modal asking user to confirm his intention to perform a risky action.
19+
20+
## Examples
21+
22+
### Basic warning modal
23+
24+
A basic warning modal component provides users with a basic layout to which only specific texts need to be passed.
25+
Action buttons callbacks can be customized using `onConfirm` and `onClose`.
26+
27+
```js file="./WarningModalExample.tsx"
28+
29+
```
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import React from 'react';
2+
import WarningModal from '@patternfly/react-component-groups/dist/dynamic/WarningModal';
3+
import { Button } from '@patternfly/react-core';
4+
5+
export const BasicExample: React.FunctionComponent = () => {
6+
const [ isOpen, setIsOpen ] = React.useState(false);
7+
return <>
8+
<Button onClick={() => setIsOpen(true)}>Open modal</Button>
9+
<WarningModal
10+
isOpen={isOpen}
11+
title='Unsaved changes'
12+
onClose={() => setIsOpen(false)}
13+
onConfirm={() => setIsOpen(false)}>
14+
Your page contains unsaved changes. Do you want to leave?
15+
</WarningModal>
16+
</>
17+
};
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import React from 'react';
2+
import { render } from '@testing-library/react';
3+
import WarningModal from './WarningModal';
4+
5+
describe('WarningModal component', () => {
6+
const initialProps = {
7+
title: 'Unsaved changes',
8+
onClose: () => null,
9+
onConfirm: () => null,
10+
};
11+
12+
it('should render', () => {
13+
const container = render(<WarningModal isOpen={true} {...initialProps}>Warning modal content</WarningModal>);
14+
expect(container).toMatchSnapshot();
15+
});
16+
});
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import React from 'react';
2+
import { Button, ModalProps, Modal, ModalVariant, ButtonVariant } from '@patternfly/react-core';
3+
4+
export interface WarningModalProps extends Omit<ModalProps, 'ref'> {
5+
/** Callback for the confirm action button. */
6+
onConfirm?: () => void;
7+
/** Custom label for the confirm action button */
8+
confirmButtonLabel? : string;
9+
/** Custom label for the cancel action button */
10+
cancelButtonLabel? : string;
11+
}
12+
13+
const WarningModal: React.FunctionComponent<WarningModalProps> = ({
14+
isOpen,
15+
onConfirm,
16+
onClose,
17+
children,
18+
confirmButtonLabel = 'Confirm',
19+
cancelButtonLabel = 'Cancel',
20+
variant = ModalVariant.small,
21+
titleIconVariant = 'warning',
22+
...props
23+
}: WarningModalProps) => (
24+
<Modal
25+
variant={variant}
26+
isOpen={isOpen}
27+
onClose={onClose}
28+
onEscapePress={onClose}
29+
titleIconVariant={titleIconVariant}
30+
actions={[
31+
<Button
32+
ouiaId="primary-confirm-button"
33+
key="confirm"
34+
variant={ButtonVariant.primary}
35+
onClick={onConfirm}
36+
>
37+
{confirmButtonLabel}
38+
</Button>,
39+
<Button
40+
ouiaId="secondary-cancel-button"
41+
key="cancel"
42+
variant={ButtonVariant.link}
43+
onClick={onClose}
44+
>
45+
{cancelButtonLabel}
46+
</Button>,
47+
]}
48+
{...props}
49+
>
50+
{children}
51+
</Modal>
52+
);
53+
54+
55+
export default WarningModal;
Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`WarningModal component should render 1`] = `
4+
{
5+
"asFragment": [Function],
6+
"baseElement": <body
7+
class="pf-v5-c-backdrop__open"
8+
>
9+
<div
10+
aria-hidden="true"
11+
/>
12+
<div>
13+
<div
14+
class="pf-v5-c-backdrop"
15+
>
16+
<div
17+
class="pf-v5-l-bullseye"
18+
>
19+
<div
20+
aria-describedby="pf-modal-part-2"
21+
aria-labelledby="pf-modal-part-1"
22+
aria-modal="true"
23+
class="pf-v5-c-modal-box pf-m-warning pf-m-sm"
24+
data-ouia-component-id="OUIA-Generated-Modal-small-1"
25+
data-ouia-component-type="PF5/ModalContent"
26+
data-ouia-safe="true"
27+
id="pf-modal-part-0"
28+
role="dialog"
29+
>
30+
<div
31+
class="pf-v5-c-modal-box__close"
32+
>
33+
<button
34+
aria-disabled="false"
35+
aria-label="Close"
36+
class="pf-v5-c-button pf-m-plain"
37+
data-ouia-component-id="OUIA-Generated-Modal-small-1-ModalBoxCloseButton"
38+
data-ouia-component-type="PF5/Button"
39+
data-ouia-safe="true"
40+
type="button"
41+
>
42+
<svg
43+
aria-hidden="true"
44+
class="pf-v5-svg"
45+
fill="currentColor"
46+
height="1em"
47+
role="img"
48+
viewBox="0 0 352 512"
49+
width="1em"
50+
>
51+
<path
52+
d="M242.72 256l100.07-100.07c12.28-12.28 12.28-32.19 0-44.48l-22.24-22.24c-12.28-12.28-32.19-12.28-44.48 0L176 189.28 75.93 89.21c-12.28-12.28-32.19-12.28-44.48 0L9.21 111.45c-12.28 12.28-12.28 32.19 0 44.48L109.28 256 9.21 356.07c-12.28 12.28-12.28 32.19 0 44.48l22.24 22.24c12.28 12.28 32.2 12.28 44.48 0L176 322.72l100.07 100.07c12.28 12.28 32.2 12.28 44.48 0l22.24-22.24c12.28-12.28 12.28-32.19 0-44.48L242.72 256z"
53+
/>
54+
</svg>
55+
</button>
56+
</div>
57+
<header
58+
class="pf-v5-c-modal-box__header"
59+
>
60+
<h1
61+
class="pf-v5-c-modal-box__title pf-m-icon"
62+
id="pf-modal-part-1"
63+
>
64+
<span
65+
class="pf-v5-c-modal-box__title-icon"
66+
>
67+
<svg
68+
aria-hidden="true"
69+
class="pf-v5-svg"
70+
fill="currentColor"
71+
height="1em"
72+
role="img"
73+
viewBox="0 0 576 512"
74+
width="1em"
75+
>
76+
<path
77+
d="M569.517 440.013C587.975 472.007 564.806 512 527.94 512H48.054c-36.937 0-59.999-40.055-41.577-71.987L246.423 23.985c18.467-32.009 64.72-31.951 83.154 0l239.94 416.028zM288 354c-25.405 0-46 20.595-46 46s20.595 46 46 46 46-20.595 46-46-20.595-46-46-46zm-43.673-165.346l7.418 136c.347 6.364 5.609 11.346 11.982 11.346h48.546c6.373 0 11.635-4.982 11.982-11.346l7.418-136c.375-6.874-5.098-12.654-11.982-12.654h-63.383c-6.884 0-12.356 5.78-11.981 12.654z"
78+
/>
79+
</svg>
80+
</span>
81+
<span
82+
class="pf-v5-u-screen-reader"
83+
>
84+
Warning alert:
85+
</span>
86+
<span
87+
class="pf-v5-c-modal-box__title-text"
88+
>
89+
Unsaved changes
90+
</span>
91+
</h1>
92+
</header>
93+
<div
94+
class="pf-v5-c-modal-box__body"
95+
id="pf-modal-part-2"
96+
>
97+
Warning modal content
98+
</div>
99+
<footer
100+
class="pf-v5-c-modal-box__footer"
101+
>
102+
<button
103+
aria-disabled="false"
104+
class="pf-v5-c-button pf-m-primary"
105+
data-ouia-component-id="primary-confirm-button"
106+
data-ouia-component-type="PF5/Button"
107+
data-ouia-safe="true"
108+
type="button"
109+
>
110+
Confirm
111+
</button>
112+
<button
113+
aria-disabled="false"
114+
class="pf-v5-c-button pf-m-link"
115+
data-ouia-component-id="secondary-cancel-button"
116+
data-ouia-component-type="PF5/Button"
117+
data-ouia-safe="true"
118+
type="button"
119+
>
120+
Cancel
121+
</button>
122+
</footer>
123+
</div>
124+
</div>
125+
</div>
126+
</div>
127+
</body>,
128+
"container": <div
129+
aria-hidden="true"
130+
/>,
131+
"debug": [Function],
132+
"findAllByAltText": [Function],
133+
"findAllByDisplayValue": [Function],
134+
"findAllByLabelText": [Function],
135+
"findAllByPlaceholderText": [Function],
136+
"findAllByRole": [Function],
137+
"findAllByTestId": [Function],
138+
"findAllByText": [Function],
139+
"findAllByTitle": [Function],
140+
"findByAltText": [Function],
141+
"findByDisplayValue": [Function],
142+
"findByLabelText": [Function],
143+
"findByPlaceholderText": [Function],
144+
"findByRole": [Function],
145+
"findByTestId": [Function],
146+
"findByText": [Function],
147+
"findByTitle": [Function],
148+
"getAllByAltText": [Function],
149+
"getAllByDisplayValue": [Function],
150+
"getAllByLabelText": [Function],
151+
"getAllByPlaceholderText": [Function],
152+
"getAllByRole": [Function],
153+
"getAllByTestId": [Function],
154+
"getAllByText": [Function],
155+
"getAllByTitle": [Function],
156+
"getByAltText": [Function],
157+
"getByDisplayValue": [Function],
158+
"getByLabelText": [Function],
159+
"getByPlaceholderText": [Function],
160+
"getByRole": [Function],
161+
"getByTestId": [Function],
162+
"getByText": [Function],
163+
"getByTitle": [Function],
164+
"queryAllByAltText": [Function],
165+
"queryAllByDisplayValue": [Function],
166+
"queryAllByLabelText": [Function],
167+
"queryAllByPlaceholderText": [Function],
168+
"queryAllByRole": [Function],
169+
"queryAllByTestId": [Function],
170+
"queryAllByText": [Function],
171+
"queryAllByTitle": [Function],
172+
"queryByAltText": [Function],
173+
"queryByDisplayValue": [Function],
174+
"queryByLabelText": [Function],
175+
"queryByPlaceholderText": [Function],
176+
"queryByRole": [Function],
177+
"queryByTestId": [Function],
178+
"queryByText": [Function],
179+
"queryByTitle": [Function],
180+
"rerender": [Function],
181+
"unmount": [Function],
182+
}
183+
`;
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export { default } from './WarningModal';
2+
export * from './WarningModal';

packages/module/src/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,3 +35,6 @@ export * from './TagCount';
3535

3636
export { default as UnavailableContent } from './UnavailableContent';
3737
export * from './UnavailableContent';
38+
39+
export { default as WarningModal } from './WarningModal';
40+
export * from './WarningModal';

0 commit comments

Comments
 (0)