Skip to content

Commit

Permalink
Merge pull request #20 from EUM-kmu/feature/14
Browse files Browse the repository at this point in the history
Modal 컴포넌트 (공통)
  • Loading branch information
Honghyeonji authored Apr 2, 2024
2 parents 040198a + 94991eb commit 7c66c1b
Show file tree
Hide file tree
Showing 7 changed files with 172 additions and 23 deletions.
19 changes: 19 additions & 0 deletions src/assets/icons/close.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion src/components/common/activity-box.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ const Member = styled.span`
}
`;

const PostDetail = styled.p`
const PostDetail = styled.div`
display: flex;
flex-direction: column;
gap: 20px;
Expand Down
25 changes: 16 additions & 9 deletions src/components/common/bottom-fixed.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,27 +7,34 @@ type ButtonProps = {
} & Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, "type">;

type BottomFixedProps = {
align?: "row" | "column";
alignDirection?: "row" | "column";
children: React.ReactNode;
};

const Button = ({ isRounded = true, ...props }: ButtonProps) => {
return (
<StyledButton isRounded={isRounded} {...props}>
<StyledButton $isRounded={isRounded} {...props}>
{props.children}
</StyledButton>
);
};

export const BottomFixed = ({ align = "row", children }: BottomFixedProps) => {
return <BottomFixedContainer align={align}>{children}</BottomFixedContainer>;
export const BottomFixed = ({
alignDirection = "row",
children,
}: BottomFixedProps) => {
return (
<BottomFixedContainer $alignDirection={alignDirection}>
{children}
</BottomFixedContainer>
);
};

BottomFixed.Button = Button;

const BottomFixedContainer = styled.div<{ align: string }>`
const BottomFixedContainer = styled.div<{ $alignDirection: string }>`
display: flex;
flex-direction: ${({ align }) => align};
flex-direction: ${({ $alignDirection }) => $alignDirection};
gap: 11px;
width: 100%;
margin: auto;
Expand All @@ -37,13 +44,13 @@ const BottomFixedContainer = styled.div<{ align: string }>`
left: 0;
`;

const StyledButton = styled.button<{ isRounded: boolean }>`
const StyledButton = styled.button<{ $isRounded: boolean }>`
width: 100%;
padding: 12px;
background-color: black;
${({ isRounded }) =>
isRounded ? "border-radius: 50px;" : "background-color: #aaaaaa"};
${({ $isRounded }) =>
$isRounded ? "border-radius: 50px;" : "background-color: #aaaaaa"};
border: 0;
color: white;
font-size: 24px;
Expand Down
22 changes: 11 additions & 11 deletions src/components/common/button.tsx
Original file line number Diff line number Diff line change
@@ -1,42 +1,42 @@
import React from "react";
import { css, styled } from "styled-components";
import React, { ButtonHTMLAttributes } from "react";
import { styled } from "styled-components";

type ButtonProps = {
isSmall?: boolean;
primary?: boolean;
children: React.ReactNode;
} & Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, "type">;
} & ButtonHTMLAttributes<HTMLButtonElement>;

export const Button = ({
isSmall = false,
primary = false,
...props
}: ButtonProps) => {
return (
<StyledButton primary={primary} isSmall={isSmall} {...props}>
<StyledButton $primary={primary} $isSmall={isSmall} {...props}>
{props.children}
</StyledButton>
);
};

const StyledButton = styled.button<{ primary: boolean; isSmall: boolean }>`
const StyledButton = styled.button<{ $primary: boolean; $isSmall: boolean }>`
width: fit-content;
padding: 15px 30px;
border-radius: 21px;
border: 0;
background-color: black;
color: white;
font-size: 16px;
${({ primary }) =>
!primary &&
css`
${({ $primary }) =>
!$primary &&
`
background-color: white;
box-shadow: 0 0 1px rgba(0, 0, 0, 0);
color: black;
`}
${({ isSmall }) =>
isSmall &&
css`
${({ $isSmall }) =>
$isSmall &&
`
font-size: 18px;
border-radius: 40px;
`}
Expand Down
115 changes: 115 additions & 0 deletions src/components/common/modal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
import { ButtonHTMLAttributes, MouseEventHandler, ReactNode } from "react";
import { createPortal } from "react-dom";
import { styled } from "styled-components";

import { ReactComponent as CloseSVG } from "@/assets/icons/close.svg";

type CloseButtonType = {
onClick: MouseEventHandler<HTMLDivElement>;
};

type TitleType = {
text: string;
};

type ButtonType = Omit<ButtonHTMLAttributes<HTMLButtonElement>, "type">;

type ModalType = {
onClose: MouseEventHandler<HTMLDivElement>;
children: ReactNode;
};

const CloseButton = ({ onClick }: CloseButtonType) => (
<CloseButtonWrapper className="modal-close-button" onClick={onClick}>
<CloseSVG />
</CloseButtonWrapper>
);

const Title = ({ text }: TitleType) => {
return (
<TitleWrapper>
{text.split("\\n").map((t) => (
<span key={t}>{t}</span>
))}
</TitleWrapper>
);
};

const Button = ({ children, ...props }: ButtonType) => {
return <ButtonWrapper {...props}>{children}</ButtonWrapper>;
};

export const Modal = ({ onClose, children }: ModalType) => {
return (
<>
{createPortal(
<ModalBackground>
<Content>
<CloseButton onClick={onClose} />
{children}
</Content>
</ModalBackground>,
document.body,
)}
</>
);
};

Modal.Button = Button;
Modal.Title = Title;

const CloseButtonWrapper = styled.div`
width: 64px;
height: 64px;
position: absolute;
background-color: transparent;
top: -15px;
right: -10px;
`;

const TitleWrapper = styled.div`
display: flex;
flex-direction: column;
gap: 10px;
word-wrap: break-word;
`;

const ButtonWrapper = styled.button`
padding-top: 20px;
padding-bottom: 20px;
background-color: #f17547;
border: 0;
border-radius: 30px;
color: white;
font-size: 30px;
font-weight: 600;
`;

const ModalBackground = styled.div`
position: absolute;
top: 0;
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 100%;
background-color: rgba(217, 217, 217, 0.7);
`;

const Content = styled.div`
position: relative;
display: flex;
max-width: 90%;
max-height: 90%;
padding: 40px 34px;
background-color: #f5f5f5;
border-radius: 35px;
box-shadow: 0px 4px 30px 0px rgba(0, 0, 0, 0.25);
font-size: 25px;
flex-direction: column;
text-align: center;
gap: 30px;
& > * {
flex: 1;
}
`;
2 changes: 1 addition & 1 deletion src/pages/mypost/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export const MyPostPage = () => {
<Button primary>수정하기</Button>
</JustifyWrapper>
<ActivityBox {...activityData} />
<BottomFixed align="column">
<BottomFixed alignDirection="column">
<BottomFixed.Button
onClick={() => console.log("참여관리 페이지로 이동")}
>
Expand Down
10 changes: 9 additions & 1 deletion src/pages/post/post-detail.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { styled } from "styled-components";
import { ActivityBox } from "@/components/common/activity-box";
import { BottomFixed } from "@/components/common/bottom-fixed";
import { Button } from "@/components/common/button";
import { Modal } from "@/components/common/modal";
import { DefaultLayout } from "@/components/layout/default-layout";
import activityData from "@/data/activity-data.json";

Expand All @@ -14,14 +15,21 @@ export const PostDetailPage = () => {

// TODO: 자신이 신청한 게시글인지 확인하는 로직
const [apply, setApply] = useState<boolean>(false);
const [reportModal, setReportModal] = useState<boolean>(false);

return (
<DefaultLayout>
<ActivityBox {...activityData} />
<ButtonWrapper>
<Button primary isSmall onClick={() => console.log("신고합니다")}>
<Button primary isSmall onClick={() => setReportModal(true)}>
신고
</Button>
{reportModal && (
<Modal onClose={() => setReportModal(false)}>
<Modal.Title text="신청을\n취소하시겠습니까?" />
<Modal.Button>취소하기</Modal.Button>
</Modal>
)}
</ButtonWrapper>
<BottomFixed>
<BottomFixed.Button
Expand Down

0 comments on commit 7c66c1b

Please sign in to comment.