Skip to content

Commit ccd6bb8

Browse files
committed
feat(dialog): implement Dialog, AlertDialog and ConfirmationDialog
1 parent 4a29306 commit ccd6bb8

12 files changed

+430
-19
lines changed

demo/DialogExamples.jsx

+120
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
import React from 'react';
2+
3+
import { Dialog, Form, FormGroupInput } from '../dist/main';
4+
import { ConfirmationDialog, AlertDialog } from '../src/dialog';
5+
6+
export function DialogExamples() {
7+
return (
8+
<div className="row">
9+
<div className="col-6">
10+
<h1 className="h4">Simple Dialog</h1>
11+
<Dialog
12+
title="Simple dialog"
13+
body={
14+
<div>
15+
Lorem ipsum dolor, sit amet consectetur adipisicing elit. Quibusdam sequi vero sapiente delectus error
16+
sunt, a eveniet nobis est ex magni nesciunt magnam. Eaque eius hic eligendi dolorum ut quas?
17+
</div>
18+
}
19+
>
20+
<a href="" className="btn btn-primary">
21+
Simple Dialog
22+
</a>
23+
</Dialog>
24+
</div>
25+
<div className="col-6">
26+
<h1 className="h4 mt-3">Scrolling long content Dialog</h1>
27+
<Dialog
28+
title="Long content dialog"
29+
body="Lorem ipsum dolor sit amet consectetur adipisicing elit. Consequuntur optio sequi dicta quia quaerat natus quisquam minus molestiae ipsa accusantium, hic amet quis aliquam dolor. Odit, error placeat! Magni, voluptatum!
30+
Ut esse iusto quae quod in quas minus aliquid cum veniam, eius, ipsa corrupti dolorem quaerat, recusandae voluptatibus necessitatibus ea unde exercitationem? Est quod in corrupti porro nam necessitatibus suscipit!
31+
Optio voluptate, pariatur officia voluptates perferendis, consectetur saepe iste nobis ea accusamus, et quia eum eligendi earum expedita possimus vero! Optio adipisci minus debitis nostrum asperiores alias fugit tempora dicta.
32+
Doloremque facilis rerum suscipit accusantium eveniet in nesciunt debitis. Iste placeat voluptatum quisquam architecto quidem, eos fugit impedit accusamus soluta et harum ipsa ad perspiciatis, odit nesciunt sit possimus sed.
33+
Nam in vitae, ipsum beatae eveniet, odit itaque sit aliquid delectus veritatis reprehenderit libero enim quibusdam ipsa incidunt est alias eligendi omnis sed similique nemo quisquam. Reiciendis similique placeat quia.
34+
Nemo explicabo maiores minus debitis eligendi soluta qui quam suscipit dolores possimus velit temporibus, adipisci inventore recusandae dignissimos dicta vitae modi. Autem perspiciatis doloremque corrupti quas deleniti ex sapiente iure.
35+
Quae quas odit libero accusamus nostrum architecto nihil optio eaque sequi iste aut, aperiam illum blanditiis perferendis distinctio earum pariatur? Earum provident minus ullam cupiditate nihil perferendis error corporis alias?
36+
Repudiandae dignissimos maiores expedita sunt, debitis optio nobis ad iure harum quasi exercitationem esse odit, numquam fugiat reiciendis quas ratione voluptatem nisi atque explicabo ducimus ea itaque. Quibusdam, sequi! Dignissimos.
37+
Ducimus, ullam natus reiciendis maxime ipsam magni repellendus, distinctio consequuntur nostrum ipsum odio numquam rerum perferendis quod quo excepturi, voluptatibus sunt veritatis beatae hic animi. Provident accusamus voluptates illo maiores?
38+
Iste ex similique enim ipsum perferendis repellat sunt nam velit eum quas excepturi consequatur quibusdam numquam rerum, dolore optio eligendi, consequuntur tempore? Fugiat reprehenderit, veritatis aspernatur perspiciatis nobis sint rerum."
39+
scrollable={true}
40+
>
41+
<button className="btn btn-primary">Long content</button>
42+
</Dialog>
43+
</div>
44+
<div className="col-6">
45+
<h1 className="h4 mt-3">Close dialog from body/footer</h1>
46+
<Dialog
47+
title="Custom footer dialog"
48+
body={({ close }) => (
49+
<>
50+
<strong>
51+
Lorem ipsum dolor sit amet consectetur adipisicing elit. Quibusdam amet rerum ducimus maiores deleniti
52+
ullam necessitatibus, minus dolore maxime repellat provident perspiciatis veritatis eum sunt? Nam quo
53+
vel quia qui.
54+
</strong>
55+
<button type="button" className="btn btn-primary" onClick={close}>
56+
Close from body
57+
</button>
58+
</>
59+
)}
60+
footer={({ close }) => (
61+
<button type="button" className="btn btn-primary" onClick={close}>
62+
Close from footer
63+
</button>
64+
)}
65+
>
66+
<a href="">&amp;</a>
67+
</Dialog>
68+
</div>
69+
<div className="col-6">
70+
<h1 className="h4 mt-3">Confirmation dialog</h1>
71+
<ConfirmationDialog
72+
title="Atention!"
73+
message="Are you sure you want to proceed?"
74+
onProceed={() => console.info('onProceed')}
75+
onCancel={() => console.warn('onCancel')}
76+
>
77+
<button type="button" className="btn btn-info">
78+
Do something
79+
</button>
80+
</ConfirmationDialog>
81+
</div>
82+
<div className="col-6">
83+
<h1 className="h4 mt-3">Alert dialog</h1>
84+
<AlertDialog
85+
message="Checking new updates"
86+
onClose={() => Promise.resolve().then(() => console.warn('onClose'))}
87+
>
88+
<button type="button" className="btn btn-info">
89+
Check
90+
</button>
91+
</AlertDialog>
92+
</div>
93+
<div className="col-6">
94+
<h1 className="h4 mt-3">Form dialog</h1>
95+
<Dialog
96+
title="Edit item"
97+
body={({ close }) => (
98+
<Form
99+
initialValues={{}}
100+
onSubmit={(data) => {
101+
console.info('submit', data);
102+
close();
103+
}}
104+
onCancel={() => {
105+
console.warn('cancel');
106+
close();
107+
}}
108+
>
109+
<FormGroupInput name="test" label="Test" />
110+
</Form>
111+
)}
112+
>
113+
<button type="button" className="btn btn-primary">
114+
Add item
115+
</button>
116+
</Dialog>
117+
</div>
118+
</div>
119+
);
120+
}

demo/demo.jsx

+29-16
Original file line numberDiff line numberDiff line change
@@ -5,25 +5,38 @@ import { StatefulTabs, Pagination } from '../dist/main';
55
import { FormExamples } from './FormExamples';
66
import { TableExamples } from './TableExamples';
77
import { TabsExamples } from './TabsExamples';
8+
import { DialogExamples } from './DialogExamples';
89

910
ReactDOM.render(
1011
<div className="mt-3">
11-
<StatefulTabs
12-
vertical={true}
13-
initialTab={3}
14-
tabs={[
15-
{
16-
title: 'Forms',
17-
content: <FormExamples />,
18-
},
19-
{
20-
title: 'Tables',
21-
content: <TableExamples />,
22-
},
23-
{ title: 'Tabs', content: <TabsExamples /> },
24-
{ title: 'Pagination', content: <PaginationExamples /> },
25-
]}
26-
/>
12+
<React.StrictMode>
13+
<StatefulTabs
14+
vertical={true}
15+
initialTab={0}
16+
tabs={[
17+
{
18+
title: 'Dialog',
19+
content: <DialogExamples />,
20+
},
21+
{
22+
title: 'Forms',
23+
content: <FormExamples />,
24+
},
25+
{
26+
title: 'Pagination',
27+
content: <PaginationExamples />,
28+
},
29+
{
30+
title: 'Tables',
31+
content: <TableExamples />,
32+
},
33+
{
34+
title: 'Tabs',
35+
content: <TabsExamples />,
36+
},
37+
]}
38+
/>
39+
</React.StrictMode>
2740
</div>,
2841
document.getElementById('root')
2942
);

package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
},
4242
"dependencies": {
4343
"react": "^16.13.0",
44-
"react-dom": "^16.13.0"
44+
"react-dom": "^16.13.0",
45+
"react-modal": "^3.11.2"
4546
}
4647
}

rollup.config.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,5 @@ export default {
1515
exclude: 'node_modules/**', // only transpile our source code
1616
}),
1717
],
18-
external: ['react', 'prop-types'],
18+
external: ['react', 'prop-types', 'react-modal', 'react-dom'],
1919
};

src/dialog/AlertDialog.jsx

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import React from 'react';
2+
import PropTypes from 'prop-types';
3+
import { Dialog } from './Dialog';
4+
import { handleClick } from './modal-helpers';
5+
6+
export function AlertDialog({ title, message, children, onClose, closeLabel }) {
7+
return (
8+
<Dialog
9+
title={title}
10+
body={message}
11+
footer={({ close }) => (
12+
<button type="button" className="btn btn-primary" onClick={handleClick(onClose, close)}>
13+
{closeLabel}
14+
</button>
15+
)}
16+
>
17+
{children}
18+
</Dialog>
19+
);
20+
}
21+
22+
AlertDialog.defaultProps = {
23+
onClose: () => {},
24+
title: 'Atention required',
25+
closeLabel: 'Close',
26+
};
27+
28+
AlertDialog.propTypes = {
29+
children: PropTypes.oneOfType([PropTypes.string, PropTypes.element]),
30+
message: PropTypes.oneOfType([PropTypes.string, PropTypes.element]),
31+
onClose: PropTypes.func,
32+
title: PropTypes.oneOfType([PropTypes.string, PropTypes.element]),
33+
closeLabel: PropTypes.oneOfType([PropTypes.string, PropTypes.element]),
34+
};

src/dialog/ConfirmationDialog.jsx

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import React from 'react';
2+
import PropTypes from 'prop-types';
3+
import { Dialog } from './Dialog';
4+
import { handleClick } from './modal-helpers';
5+
6+
export function ConfirmationDialog({ title, message, children, onProceed, onCancel, cancelLabel, proceedLabel }) {
7+
return (
8+
<Dialog
9+
title={title}
10+
body={message}
11+
footer={({ close }) => (
12+
<>
13+
<button type="button" className="btn btn-secondary" onClick={handleClick(onCancel, close)}>
14+
{cancelLabel}
15+
</button>
16+
<button type="button" className="btn btn-primary" onClick={handleClick(onProceed, close)}>
17+
{proceedLabel}
18+
</button>
19+
</>
20+
)}
21+
>
22+
{children}
23+
</Dialog>
24+
);
25+
}
26+
27+
ConfirmationDialog.defaultProps = {
28+
onProceed: () => {},
29+
onCancel: () => {},
30+
title: 'Atention required',
31+
cancelLabel: 'Cancel',
32+
proceedLabel: 'Proceed',
33+
};
34+
35+
ConfirmationDialog.propTypes = {
36+
children: PropTypes.oneOfType([PropTypes.string, PropTypes.element]),
37+
message: PropTypes.oneOfType([PropTypes.string, PropTypes.element]),
38+
onCancel: PropTypes.func,
39+
onProceed: PropTypes.func,
40+
title: PropTypes.oneOfType([PropTypes.string, PropTypes.element]),
41+
cancelLabel: PropTypes.oneOfType([PropTypes.string, PropTypes.element]),
42+
proceedLabel: PropTypes.oneOfType([PropTypes.string, PropTypes.element]),
43+
};

src/dialog/Dialog.jsx

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import React from 'react';
2+
import PropTypes from 'prop-types';
3+
import { ModalPortal } from './ModalPortal';
4+
import { Modal } from './Modal';
5+
import { useModal } from './modal-helpers';
6+
7+
export function Dialog({ children, ...props }) {
8+
const { isOpen, open, close } = useModal();
9+
10+
return (
11+
<React.Fragment>
12+
<DialogTrigger open={open}>{children}</DialogTrigger>
13+
14+
<ModalPortal isOpen={isOpen()}>
15+
<Modal {...props} onClose={close} isOpen={isOpen()} />
16+
</ModalPortal>
17+
</React.Fragment>
18+
);
19+
}
20+
21+
Dialog.propTypes = {
22+
content: PropTypes.any,
23+
children: PropTypes.any,
24+
};
25+
26+
function DialogTrigger({ children, open }) {
27+
return React.cloneElement(children, {
28+
onClick(e) {
29+
e.stopPropagation();
30+
e.preventDefault();
31+
open();
32+
},
33+
});
34+
}

0 commit comments

Comments
 (0)