Skip to content

Commit

Permalink
Merge pull request #23 from turkey-kim/feat/timer
Browse files Browse the repository at this point in the history
Feat/timer: 타이머 모달 팝업 구현 (인터페이스 분리)
  • Loading branch information
JitHoon authored Sep 14, 2023
2 parents 8508e97 + 450b001 commit 61d8381
Show file tree
Hide file tree
Showing 7 changed files with 247 additions and 1 deletion.
10 changes: 9 additions & 1 deletion src/components/Header/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,13 @@ import React from "react";
import {Link} from "react-router-dom";
import Clock from "../../utils/clock";
import "../../styles/Header.css";
import Modal from "../Modal/Modal";
import TimerModal from "../Timer/TimerModal";
import useModal from "../../hooks/useModal";

function Header() {
const {isOpen, toggle} = useModal();

return (
<div className="Main">
<header className="HeaderMain">
Expand All @@ -27,7 +32,7 @@ function Header() {
</Link>
</li>
<li>
<button type="button" className="Timer">
<button type="button" className="Timer" onClick={toggle}>
Timer
</button>
</li>
Expand All @@ -40,6 +45,9 @@ function Header() {
</ul>
</nav>
</header>
<Modal isOpen={isOpen} onClose={toggle}>
<TimerModal onClose={toggle} />
</Modal>
</div>
);
}
Expand Down
31 changes: 31 additions & 0 deletions src/components/Modal/Modal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import React from "react";
import "../../styles/Modal.css";
import {ModalType} from "../../types/Modal";

export default function Modal({isOpen, onClose, children}: ModalType) {
const handleKeyDown = (event: React.KeyboardEvent) => {
if (event.key === "Enter" || event.key === " ") {
onClose();
}
};

return isOpen ? (
<div
className="ModalBackdrop"
onClick={onClose}
onKeyDown={handleKeyDown}
role="button"
tabIndex={0}
>
<div
onClick={e => e.stopPropagation()}
className="ModalContent"
role="presentation"
>
{children}
</div>
</div>
) : null;
}

export {};
26 changes: 26 additions & 0 deletions src/components/Timer/TimerModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import React from "react";
import "../../styles/Modal.css";
import "../../styles/TimerModal.css";

interface TimerModalProps {
onClose: () => void;
}

export default function TimerModal({onClose}: TimerModalProps) {
return (
<div className="ModalBackdrop">
<div className="TimerModalContent">
<button type="button" className="CloseButton" onClick={onClose}>
Close
</button>
<p>모달 창 내용</p>
<button type="button" className="CancelButton" onClick={onClose}>
Cancel
</button>
<button type="button" className="OKButton" onClick={onClose}>
OK
</button>
</div>
</div>
);
}
14 changes: 14 additions & 0 deletions src/hooks/useModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import {useState} from "react";

export default function useModal() {
const [isOpen, setIsOpen] = useState(false);

const toggle = () => {
setIsOpen(!isOpen);
};

return {
isOpen,
toggle,
};
}
150 changes: 150 additions & 0 deletions src/styles/Modal.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
.ModalBackdrop {
display: flex;

position: fixed;
top: 0;
left: 0;
z-index: 1000;

width: 100%;
height: 100%;

padding-top: 8%;

background-color: rgba(0, 0, 0, 0.5);

justify-content: center;
align-items: flex-start;
}

.ModalContent {
position: relative;
z-index: 1001;

width: 500px;
height: 300px;

padding: 20px;

background-color: white;
border-radius: 8px;
}

.CloseButton {
position: absolute;
top: 10px;
right: 10px;
overflow: hidden;

width: 2em;
height: 2em;

padding: 0;

border: none;
background: transparent;
border-radius: 50%;

color: rgba(255, 55, 115, 0.8);
font: inherit;
text-indent: 100%;

cursor: pointer;

&:focus {
outline: solid 0 transparent;
box-shadow: 0 0 0 2px rgba(255, 55, 115, 0.8);
}

&:hover {
background: rgba(231, 122, 222, 0.1);
}

&:before,
&:after {
position: absolute;
top: 15%;
left: calc(50% - 0.0625em);

width: 0.125em;
height: 70%;

border-radius: 0.125em;
background: currentcolor;
content: "";
transform: rotate(45deg);
}

&:after {
transform: rotate(-45deg);
}
}

.CancelButton {
position: absolute;
right: 120px;
bottom: 10px;

width: 40px;
min-width: 100px;
height: 36px;

padding: 8px;

border: 2.5px solid #e0e1e4;
background-color: white;
border-radius: 5px;
box-shadow: 0px 0px 20px -20px;

color: #7a7575;
font-weight: bold;

cursor: pointer;

transition: all 0.2s ease-in-out 0ms;
user-select: none;
}

.CancelButton:hover {
background-color: #f2f2f2;
box-shadow: 0px 0px 20px -18px;
}

.CancelButton:active {
transform: scale(0.95);
}

.OKButton {
position: absolute;
right: 10px;
bottom: 10px;

width: 40px;
min-width: 100px;
height: 36px;

padding: 8px;

border: 2.5px solid rgba(247, 123, 160, 0.8);
background-color: rgba(255, 55, 115, 0.8);
border-radius: 5px;
box-shadow: 0px 0px 20px -20px;

color: #f2f2f2;
font-weight: bold;

cursor: pointer;

transition: all 0.2s ease-in-out 0ms;
user-select: none;
}

.OKButton:hover {
background-color: #d83f93;
box-shadow: 0px 0px 20px -18px;
border: 2.5px solid #d83f93;
}

.OKButton:active {
transform: scale(0.95);
}
12 changes: 12 additions & 0 deletions src/styles/TimerModal.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
.TimerModalContent {
position: relative;
z-index: 1001;

width: 500px;
height: 300px;

padding: 20px;

background-color: white;
border-radius: 8px;
}
5 changes: 5 additions & 0 deletions src/types/Modal.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export interface ModalType {
children: React.ReactNode;
isOpen: boolean;
onClose: () => void;
}

0 comments on commit 61d8381

Please sign in to comment.