Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(WarningModal): Add warning modal component #62

Merged
merged 2 commits into from
Oct 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
---
# Sidenav top-level section
# should be the same for all markdown files
section: extensions
subsection: Component groups
# Sidenav secondary level section
# should be the same for all markdown files
id: Warning modal
# Tab (react | react-demos | html | html-demos | design-guidelines | accessibility)
source: react
# If you use typescript, the name of the interface to display props for
# These are found through the sourceProps function provided in patternfly-docs.source.js
propComponents: ['WarningModal']
---

import WarningModal from '@patternfly/react-component-groups/dist/dynamic/WarningModal';

A **warning modal** component displays a modal asking user to confirm his intention to perform a risky action.

## Examples

### Basic warning modal

A basic warning modal component provides users with a basic layout to which only specific texts need to be passed.
Action buttons callbacks can be customized using `onConfirm` and `onClose`.

```js file="./WarningModalExample.tsx"

```
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import React from 'react';
import WarningModal from '@patternfly/react-component-groups/dist/dynamic/WarningModal';
import { Button } from '@patternfly/react-core';

export const BasicExample: React.FunctionComponent = () => {
const [ isOpen, setIsOpen ] = React.useState(false);
return <>
<Button onClick={() => setIsOpen(true)}>Open modal</Button>
<WarningModal
isOpen={isOpen}
title='Unsaved changes'
onClose={() => setIsOpen(false)}
onConfirm={() => setIsOpen(false)}>
Your page contains unsaved changes. Do you want to leave?
</WarningModal>
</>
};
16 changes: 16 additions & 0 deletions packages/module/src/WarningModal/WarningModal.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import React from 'react';
import { render } from '@testing-library/react';
import WarningModal from './WarningModal';

describe('WarningModal component', () => {
const initialProps = {
title: 'Unsaved changes',
onClose: () => null,
onConfirm: () => null,
};

it('should render', () => {
const container = render(<WarningModal isOpen={true} {...initialProps}>Warning modal content</WarningModal>);
expect(container).toMatchSnapshot();
});
});
55 changes: 55 additions & 0 deletions packages/module/src/WarningModal/WarningModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import React from 'react';
import { Button, ModalProps, Modal, ModalVariant, ButtonVariant } from '@patternfly/react-core';

export interface WarningModalProps extends Omit<ModalProps, 'ref'> {
/** Callback for the confirm action button. */
onConfirm?: () => void;
/** Custom label for the confirm action button */
confirmButtonLabel? : string;
/** Custom label for the cancel action button */
cancelButtonLabel? : string;
}

const WarningModal: React.FunctionComponent<WarningModalProps> = ({
isOpen,
onConfirm,
onClose,
children,
confirmButtonLabel = 'Confirm',
cancelButtonLabel = 'Cancel',
variant = ModalVariant.small,
titleIconVariant = 'warning',
...props
}: WarningModalProps) => (
<Modal
variant={variant}
isOpen={isOpen}
onClose={onClose}
onEscapePress={onClose}
titleIconVariant={titleIconVariant}
actions={[
<Button
ouiaId="primary-confirm-button"
key="confirm"
variant={ButtonVariant.primary}
onClick={onConfirm}
>
{confirmButtonLabel}
</Button>,
<Button
ouiaId="secondary-cancel-button"
key="cancel"
variant={ButtonVariant.link}
onClick={onClose}
>
{cancelButtonLabel}
</Button>,
]}
{...props}
>
{children}
</Modal>
);


export default WarningModal;
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`WarningModal component should render 1`] = `
{
"asFragment": [Function],
"baseElement": <body
class="pf-v5-c-backdrop__open"
>
<div
aria-hidden="true"
/>
<div>
<div
class="pf-v5-c-backdrop"
>
<div
class="pf-v5-l-bullseye"
>
<div
aria-describedby="pf-modal-part-2"
aria-labelledby="pf-modal-part-1"
aria-modal="true"
class="pf-v5-c-modal-box pf-m-warning pf-m-sm"
data-ouia-component-id="OUIA-Generated-Modal-small-1"
data-ouia-component-type="PF5/ModalContent"
data-ouia-safe="true"
id="pf-modal-part-0"
role="dialog"
>
<div
class="pf-v5-c-modal-box__close"
>
<button
aria-disabled="false"
aria-label="Close"
class="pf-v5-c-button pf-m-plain"
data-ouia-component-id="OUIA-Generated-Modal-small-1-ModalBoxCloseButton"
data-ouia-component-type="PF5/Button"
data-ouia-safe="true"
type="button"
>
<svg
aria-hidden="true"
class="pf-v5-svg"
fill="currentColor"
height="1em"
role="img"
viewBox="0 0 352 512"
width="1em"
>
<path
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"
/>
</svg>
</button>
</div>
<header
class="pf-v5-c-modal-box__header"
>
<h1
class="pf-v5-c-modal-box__title pf-m-icon"
id="pf-modal-part-1"
>
<span
class="pf-v5-c-modal-box__title-icon"
>
<svg
aria-hidden="true"
class="pf-v5-svg"
fill="currentColor"
height="1em"
role="img"
viewBox="0 0 576 512"
width="1em"
>
<path
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"
/>
</svg>
</span>
<span
class="pf-v5-u-screen-reader"
>
Warning alert:
</span>
<span
class="pf-v5-c-modal-box__title-text"
>
Unsaved changes
</span>
</h1>
</header>
<div
class="pf-v5-c-modal-box__body"
id="pf-modal-part-2"
>
Warning modal content
</div>
<footer
class="pf-v5-c-modal-box__footer"
>
<button
aria-disabled="false"
class="pf-v5-c-button pf-m-primary"
data-ouia-component-id="primary-confirm-button"
data-ouia-component-type="PF5/Button"
data-ouia-safe="true"
type="button"
>
Confirm
</button>
<button
aria-disabled="false"
class="pf-v5-c-button pf-m-link"
data-ouia-component-id="secondary-cancel-button"
data-ouia-component-type="PF5/Button"
data-ouia-safe="true"
type="button"
>
Cancel
</button>
</footer>
</div>
</div>
</div>
</div>
</body>,
"container": <div
aria-hidden="true"
/>,
"debug": [Function],
"findAllByAltText": [Function],
"findAllByDisplayValue": [Function],
"findAllByLabelText": [Function],
"findAllByPlaceholderText": [Function],
"findAllByRole": [Function],
"findAllByTestId": [Function],
"findAllByText": [Function],
"findAllByTitle": [Function],
"findByAltText": [Function],
"findByDisplayValue": [Function],
"findByLabelText": [Function],
"findByPlaceholderText": [Function],
"findByRole": [Function],
"findByTestId": [Function],
"findByText": [Function],
"findByTitle": [Function],
"getAllByAltText": [Function],
"getAllByDisplayValue": [Function],
"getAllByLabelText": [Function],
"getAllByPlaceholderText": [Function],
"getAllByRole": [Function],
"getAllByTestId": [Function],
"getAllByText": [Function],
"getAllByTitle": [Function],
"getByAltText": [Function],
"getByDisplayValue": [Function],
"getByLabelText": [Function],
"getByPlaceholderText": [Function],
"getByRole": [Function],
"getByTestId": [Function],
"getByText": [Function],
"getByTitle": [Function],
"queryAllByAltText": [Function],
"queryAllByDisplayValue": [Function],
"queryAllByLabelText": [Function],
"queryAllByPlaceholderText": [Function],
"queryAllByRole": [Function],
"queryAllByTestId": [Function],
"queryAllByText": [Function],
"queryAllByTitle": [Function],
"queryByAltText": [Function],
"queryByDisplayValue": [Function],
"queryByLabelText": [Function],
"queryByPlaceholderText": [Function],
"queryByRole": [Function],
"queryByTestId": [Function],
"queryByText": [Function],
"queryByTitle": [Function],
"rerender": [Function],
"unmount": [Function],
}
`;
2 changes: 2 additions & 0 deletions packages/module/src/WarningModal/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { default } from './WarningModal';
export * from './WarningModal';
3 changes: 3 additions & 0 deletions packages/module/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,6 @@ export * from './TagCount';

export { default as UnavailableContent } from './UnavailableContent';
export * from './UnavailableContent';

export { default as WarningModal } from './WarningModal';
export * from './WarningModal';
Loading