Skip to content

Commit

Permalink
feat(ui): modal 컴포넌트 개발 (#104)
Browse files Browse the repository at this point in the history
* chore(ui): 라이브러리 버전 업데이트

* chore(ui): portal isopen prop 추가

* feat(ui): modal 컴포넌트 개발

* feat(ui): modal storybook 작성

* fix(ui): portal 버그 수정

* chore(ui): height 수정
  • Loading branch information
SEOKKAMONI authored Dec 26, 2023
1 parent 514a448 commit 9f80045
Show file tree
Hide file tree
Showing 10 changed files with 1,695 additions and 1,938 deletions.
8 changes: 4 additions & 4 deletions apps/admin/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,16 @@
"@tanstack/react-query-devtools": "^5.7.2",
"framer-motion": "^10.16.4",
"next": "14.0.2",
"react": "^18",
"react-dom": "^18",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-hook-form": "^7.48.2"
},
"devDependencies": {
"@sickgyun/tsconfig":"workspace:*",
"@sickgyun/eslint-config": "workspace:*",
"@types/node": "^20",
"@types/react": "^18",
"@types/react-dom": "^18",
"@types/react": "^18.2.0",
"@types/react-dom": "^18.2.0",
"eslint": "^8",
"eslint-config-next": "14.0.2",
"typescript": "^5"
Expand Down
8 changes: 4 additions & 4 deletions apps/client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@
"framer-motion": "^10.16.4",
"jotai": "^2.6.0",
"next": "14.0.2",
"react": "^18",
"react-dom": "^18",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-hook-form": "^7.48.2",
"recoil": "^0.7.7"
},
Expand All @@ -39,8 +39,8 @@
"@testing-library/react": "^14.1.2",
"@types/jest": "^29.5.10",
"@types/node": "^20",
"@types/react": "^18",
"@types/react-dom": "^18",
"@types/react": "^18.2.0",
"@types/react-dom": "^18.2.0",
"eslint": "^8.52.0",
"eslint-config-next": "14.0.1",
"jest": "^29.7.0",
Expand Down
4 changes: 2 additions & 2 deletions packages/design-token/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@
"devDependencies": {
"@sickgyun/eslint-config": "workspace:*",
"@sickgyun/tsconfig": "workspace:*",
"@types/react": "^18.2.45"
"@types/react": "^18.2.0"
},
"dependencies": {
"@emotion/react": "^11.11.1",
"react": "^18"
"react": "^18.2.0"
}
}
6 changes: 3 additions & 3 deletions packages/ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@
"@storybook/react": "^7.6.6",
"@storybook/react-vite": "^7.6.6",
"@storybook/test": "^7.6.6",
"@types/react": "^18.2.45",
"@types/react-dom": "^18",
"@types/react": "^18.2.0",
"@types/react-dom": "^18.2.0",
"eslint-plugin-storybook": "^0.6.15",
"storybook": "^7.6.6",
"typescript": "^5"
Expand All @@ -30,7 +30,7 @@
"@emotion/react": "^11.11.1",
"@emotion/styled": "^11.11.0",
"@sickgyun/design-token": "workspace:*",
"react": "^18",
"react": "^18.2.0",
"react-dom": "^18.2.0"
}
}
45 changes: 45 additions & 0 deletions packages/ui/src/Modal/Modal.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import type { Meta, StoryObj } from '@storybook/react';
import { useState } from 'react';
import { Modal as ModalComponent } from '.';

type Modal = typeof ModalComponent;

const meta: Meta<Modal> = {
component: ModalComponent,
title: 'Components/Modal',
};

export default meta;

export const Default: StoryObj<Modal> = {
args: {
isOpen: false,
},
render: (args) => {
// eslint-disable-next-line react-hooks/rules-of-hooks
const [isOpen, setIsOpen] = useState(false);

return (
<>
<ModalComponent {...args} isOpen={isOpen}>
<button
type="button"
onClick={() => {
setIsOpen(false);
}}
>
Close!
</button>
</ModalComponent>
<button
type="button"
onClick={() => {
setIsOpen(true);
}}
>
Open!
</button>
</>
);
},
};
49 changes: 49 additions & 0 deletions packages/ui/src/Modal/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import styled from '@emotion/styled';
import type { ForwardedRef, ReactNode } from 'react';
import { forwardRef } from 'react';
import Portal from '../Portal';

type ModalProps = {
isOpen: boolean;
width?: string;
height?: string;
children: ReactNode;
};

export const Modal = forwardRef(function Modal(
{ isOpen, width = '600px', height = 'auto', children, ...props }: ModalProps,
ref: ForwardedRef<HTMLDivElement>
) {
return (
<Portal isOpen={isOpen}>
<StyledDIM>
<StyledModal ref={ref} width={width} height={height} {...props}>
{children}
</StyledModal>
</StyledDIM>
</Portal>
);
});

const StyledDIM = styled.div`
position: fixed;
z-index: 1;
top: 0;
left: 0;
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
background-color: #d8e3ff99;
backdrop-filter: blur(12.5px);
`;

const StyledModal = styled.div<{ width: string; height: string }>`
width: ${({ width }) => width};
height: ${({ height }) => height};
min-height: 350px;
background-color: ${({ theme }) => theme.colors.white};
padding: 36px;
border-radius: 16px;
`;
8 changes: 4 additions & 4 deletions packages/ui/src/Portal/index.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { type PropsWithChildren, useState } from 'react';
import { createPortal } from 'react-dom';
import useDidMount from './useDidMount';
import { useDidMount } from './useDidMount';

type PortalProps = PropsWithChildren;
type PortalProps = PropsWithChildren<{ isOpen: boolean }>;

export const Portal = ({ children }: PortalProps) => {
export const Portal = ({ isOpen, children }: PortalProps) => {
const [container, setContainer] = useState<Element | null>(null);

useDidMount(() => {
Expand All @@ -15,7 +15,7 @@ export const Portal = ({ children }: PortalProps) => {

if (!container) return null;

return createPortal(children, container);
return createPortal(isOpen && children, container);
};

export default Portal;
4 changes: 1 addition & 3 deletions packages/ui/src/Portal/useDidMount.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { type EffectCallback, useEffect, useRef } from 'react';

const useDidMount = (callback: EffectCallback) => {
export const useDidMount = (callback: EffectCallback) => {
const didMountRef = useRef(false);

useEffect(() => {
Expand All @@ -10,5 +10,3 @@ const useDidMount = (callback: EffectCallback) => {
callback();
}, []);

Check warning on line 11 in packages/ui/src/Portal/useDidMount.ts

View workflow job for this annotation

GitHub Actions / Check quality (lint)

React Hook useEffect has a missing dependency: 'callback'. Either include it or remove the dependency array. If 'callback' changes too often, find the parent component that defines it and wrap that definition in useCallback
};

export default useDidMount;
1 change: 0 additions & 1 deletion packages/ui/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
export * from './Text';
export * from './Flex';
export * from './Button';
export * from './Portal';
export * from './Stack';
Loading

0 comments on commit 9f80045

Please sign in to comment.