Skip to content

Commit 61dc864

Browse files
committed
Add basic modal support
1 parent bb3486f commit 61dc864

File tree

4 files changed

+85
-7
lines changed

4 files changed

+85
-7
lines changed
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import React, { useEffect, useState } from 'react';
2+
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
3+
import { faTimes } from '@fortawesome/free-solid-svg-icons/faTimes';
4+
import { CSSTransition } from 'react-transition-group';
5+
6+
interface Props {
7+
visible: boolean;
8+
onDismissed: () => void;
9+
dismissable?: boolean;
10+
closeOnEscape?: boolean;
11+
closeOnBackground?: boolean;
12+
children: React.ReactChild;
13+
}
14+
15+
export default (props: Props) => {
16+
const [render, setRender] = useState(props.visible);
17+
18+
const handleEscapeEvent = (e: KeyboardEvent) => {
19+
if (props.dismissable !== false && props.closeOnEscape !== false && e.key === 'Escape') {
20+
setRender(false);
21+
}
22+
};
23+
24+
useEffect(() => setRender(props.visible), [props.visible]);
25+
26+
useEffect(() => {
27+
window.addEventListener('keydown', handleEscapeEvent);
28+
29+
return () => window.removeEventListener('keydown', handleEscapeEvent);
30+
}, [render]);
31+
32+
return (
33+
<CSSTransition
34+
timeout={250}
35+
classNames={'fade'}
36+
in={render}
37+
unmountOnExit={true}
38+
onExited={() => props.onDismissed()}
39+
>
40+
<div className={'modal-mask'} onClick={e => {
41+
if (props.dismissable !== false && props.closeOnBackground !== false) {
42+
e.stopPropagation();
43+
if (e.target === e.currentTarget) {
44+
setRender(false);
45+
}
46+
}
47+
}}>
48+
<div className={'modal-container top'}>
49+
{props.dismissable !== false &&
50+
<div className={'modal-close-icon'} onClick={() => setRender(false)}>
51+
<FontAwesomeIcon icon={faTimes}/>
52+
</div>
53+
}
54+
<div className={'modal-content p-6'}>
55+
{props.children}
56+
</div>
57+
</div>
58+
</div>
59+
</CSSTransition>
60+
);
61+
};
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import React, { useState } from 'react';
2+
import { ServerDatabase } from '@/api/server/getServerDatabases';
3+
import Modal from '@/components/elements/Modal';
4+
5+
export default ({ onCreated }: { onCreated: (database: ServerDatabase) => void }) => {
6+
const [ visible, setVisible ] = useState(false);
7+
8+
return (
9+
<React.Fragment>
10+
<Modal visible={visible} onDismissed={() => setVisible(false)}>
11+
<p>Testing</p>
12+
</Modal>
13+
<button className={'btn btn-primary btn-lg'} onClick={() => setVisible(true)}>
14+
Create Database
15+
</button>
16+
</React.Fragment>
17+
);
18+
};

resources/scripts/components/server/databases/DatabasesContainer.tsx

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import FlashMessageRender from '@/components/FlashMessageRender';
88
import DatabaseRow from '@/components/server/databases/DatabaseRow';
99
import Spinner from '@/components/elements/Spinner';
1010
import { CSSTransition } from 'react-transition-group';
11+
import CreateDatabaseButton from '@/components/server/databases/CreateDatabaseButton';
1112

1213
export default () => {
1314
const [ loading, setLoading ] = useState(true);
@@ -45,10 +46,8 @@ export default () => {
4546
It looks like you have no databases. Click the button below to create one now.
4647
</p>
4748
}
48-
<div className={'mt-6 text-right'}>
49-
<button className={'btn btn-primary btn-lg'}>
50-
Create Database
51-
</button>
49+
<div className={'mt-6 flex justify-end'}>
50+
<CreateDatabaseButton onCreated={database => setDatabases(s => [...s, database])}/>
5251
</div>
5352
</React.Fragment>
5453
</CSSTransition>

resources/styles/components/modal.css

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,13 @@
77
@apply .relative .w-full .max-w-md .m-auto .flex-col .flex;
88

99
&.top {
10-
margin-top: 15%;
10+
margin-top: 10%;
1111
}
1212

1313
& > .modal-close-icon {
1414
@apply .absolute .pin-r .p-2 .text-white .cursor-pointer .opacity-50;
1515
transition: opacity 150ms linear, transform 150ms ease-in;
16-
top: -2.5rem;
16+
top: -2rem;
1717

1818
&:hover {
1919
@apply .opacity-100;
@@ -22,7 +22,7 @@
2222
}
2323

2424
& > .modal-content {
25-
@apply .bg-white .rounded .shadow-md;
25+
@apply .bg-neutral-900 .rounded .shadow-md;
2626
transition: all 250ms ease;
2727
}
2828

0 commit comments

Comments
 (0)