Skip to content

Commit

Permalink
Merge pull request #526 from woowacourse-teams/feat/510-modal-component
Browse files Browse the repository at this point in the history
Modal 컴포넌트 완성
  • Loading branch information
Hain-tain authored Aug 21, 2024
2 parents c930791 + a2c5d9c commit cfb9462
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 38 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useState } from 'react';

import { Heading, Text, Modal, Input, Flex, Button } from '@/components';
import { Text, Modal, Input, Flex, Button } from '@/components';
import { useCategoryNameValidation } from '@/hooks/category';
import { useCategoryDeleteMutation, useCategoryEditMutation, useCategoryUploadMutation } from '@/queries/category';
import type { Category, CustomError } from '@/types';
Expand Down Expand Up @@ -116,9 +116,7 @@ const CategoryEditModal = ({ isOpen, toggleModal, categories, handleCancelEdit }

return (
<Modal isOpen={isOpen} toggleModal={handleCancelEditWithReset} size='small'>
<Modal.Header>
<Heading.XSmall color={theme.color.light.secondary_900}>카테고리 편집</Heading.XSmall>
</Modal.Header>
<Modal.Header>{'카테고리 편집'}</Modal.Header>
<Modal.Body>
<S.EditCategoryItemList>
<CategoryItems
Expand Down
37 changes: 20 additions & 17 deletions frontend/src/components/Modal/Modal.style.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import styled from '@emotion/styled';

import { ModalSize } from './Modal';

export const Container = styled.div`
export const Base = styled.div`
position: fixed;
z-index: 200;
top: 0;
Expand Down Expand Up @@ -33,37 +33,45 @@ export const Backdrop = styled.div`
background-color: rgba(0, 0, 0, 0.3);
`;

export const Header = styled.div`
margin-bottom: 1rem;
font-size: 1.25rem;
font-weight: bold;
export const HeaderWrapper = styled.div`
display: flex;
flex-shrink: 0;
align-items: center;
padding-bottom: 1rem;
`;

export const Body = styled.div`
margin-bottom: 1.5rem;
export const BodyContainer = styled.div`
overflow-y: auto;
flex-grow: 1;
font-size: 1rem;
`;

export const Footer = styled.div`
export const FooterContainer = styled.div`
display: flex;
flex-shrink: 0;
gap: 1rem;
justify-content: space-between;
padding-top: 1rem;
`;

export const Base = styled.div<{ size: ModalSize }>`
export const ModalContainer = styled.div<{ size: ModalSize }>`
position: relative;
z-index: 202;
display: flex;
flex-direction: column;
gap: 1rem;
max-height: 90vh;
padding: 1.5rem;
background-color: white;
border-radius: 24px;
@media (min-width: 48rem) {
position: fixed;
padding: 1.5rem;
background-color: white;
width: 90%;
${({ size }) => size && sizes[size]};
}
Expand All @@ -74,30 +82,25 @@ export const Base = styled.div<{ size: ModalSize }>`
overflow-y: auto;
width: 100%;
max-height: 90vh;
border-radius: 1.5rem 1.5rem 0 0;
}
`;

const sizes = {
xsmall: css`
width: 90%;
max-width: 17.5rem;
min-height: 11.25rem;
`,
small: css`
width: 90%;
max-width: 25rem;
min-height: 18.75rem;
`,
medium: css`
width: 90%;
max-width: 37.5rem;
min-height: 28.125rem;
`,
large: css`
width: 90%;
max-width: 50rem;
min-height: 37.5rem;
`,
Expand Down
35 changes: 18 additions & 17 deletions frontend/src/components/Modal/Modal.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { HTMLAttributes, PropsWithChildren } from 'react';
import { HTMLAttributes, PropsWithChildren, ReactNode } from 'react';
import { createPortal } from 'react-dom';

import { theme } from '../../style/theme';
import Heading from '../Heading/Heading';
import * as S from './Modal.style';

export type ModalSize = 'xsmall' | 'small' | 'medium' | 'large';
Expand All @@ -11,39 +13,38 @@ export interface BaseProps extends HTMLAttributes<HTMLDivElement> {
size?: ModalSize;
}

const Base = ({
isOpen,
toggleModal,
size = 'small',

children,
...rests
}: PropsWithChildren<BaseProps>) => {
const Base = ({ isOpen, toggleModal, size = 'small', children, ...props }: PropsWithChildren<BaseProps>) => {
if (!isOpen) {
return null;
}

return createPortal(
<S.Container>
<S.Base>
<S.Backdrop onClick={toggleModal} />
<S.Base size={size} {...rests}>
<S.ModalContainer size={size} {...props}>
{children}
</S.Base>
</S.Container>,
</S.ModalContainer>
</S.Base>,
document.body,
);
};

const Header = ({ children, ...props }: PropsWithChildren<HTMLAttributes<HTMLDivElement>>) => (
<S.Header {...props}>{children}</S.Header>
const Header = ({ children }: { children: ReactNode }) => (
<S.HeaderWrapper>
{typeof children === 'string' ? (
<Heading.XSmall color={theme.color.light.secondary_900}>{children}</Heading.XSmall>
) : (
children
)}
</S.HeaderWrapper>
);

const Body = ({ children, ...props }: PropsWithChildren<HTMLAttributes<HTMLDivElement>>) => (
<S.Body {...props}>{children}</S.Body>
<S.BodyContainer {...props}>{children}</S.BodyContainer>
);

const Footer = ({ children, ...props }: PropsWithChildren<HTMLAttributes<HTMLDivElement>>) => (
<S.Footer {...props}>{children}</S.Footer>
<S.FooterContainer {...props}>{children}</S.FooterContainer>
);

const Modal = Object.assign(Base, {
Expand Down

0 comments on commit cfb9462

Please sign in to comment.