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

Modal 컴포넌트 (공통) #20

Merged
merged 4 commits into from
Apr 2, 2024
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
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