-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
(#16) Modal & Drawer Component
- Loading branch information
Showing
21 changed files
with
707 additions
and
165 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
import { Meta } from "@storybook/react"; | ||
import { useState } from "react"; | ||
|
||
import Drawer from "./index"; | ||
import { DrawerProps } from "./types"; | ||
|
||
const meta = { | ||
title: "core/Drawer", | ||
component: Drawer, | ||
parameters: { | ||
layout: "fullscreen", | ||
}, | ||
argTypes: { | ||
target: { | ||
control: "text", | ||
defaultValue: "modal", | ||
description: "Modal Render Position Element id", | ||
}, | ||
title: { | ||
control: "text", | ||
description: "Drawer Title", | ||
}, | ||
titleSub: { | ||
control: "text", | ||
description: "Drawer Title Sub", | ||
}, | ||
isOpen: { | ||
control: "boolean", | ||
defaultValue: false, | ||
description: "Open Modal", | ||
}, | ||
onClose: { | ||
action: "clicked", | ||
description: "Drawer Close Function", | ||
}, | ||
}, | ||
} satisfies Meta<typeof Drawer>; | ||
|
||
export default meta; | ||
|
||
export const Default = (props: DrawerProps) => { | ||
const [ isOpen, setIsOpen ] = useState(false); | ||
|
||
const onToggle = () => setIsOpen(v => !v); | ||
|
||
return ( | ||
<> | ||
<header className = "h-14 bg-gray-01">Header</header> | ||
<div className = "flex h-[calc(100vh-4rem)]"> | ||
<nav className = "w-[15rem] border-r border-gray-01">SideBar</nav> | ||
<main className = "relative flex-1"> | ||
<div id = {props.target ?? "bar"} /> | ||
<Drawer | ||
title = {props.title ?? "알림"} | ||
titleSub = {props.titleSub} | ||
target = {props.target ?? "bar"} | ||
isOpen = {props.isOpen || isOpen} | ||
onClose = {onToggle} | ||
> | ||
Drawer | ||
</Drawer> | ||
<button onClick = {onToggle}> | ||
Drawer Open!! | ||
</button> | ||
</main> | ||
</div> | ||
</> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
import clsx from "clsx"; | ||
import { PropsWithChildren, forwardRef } from "react"; | ||
|
||
import ModalBase from "../Modal/ModalBase"; | ||
import Section from "../Section"; | ||
import Typography from "../Typography"; | ||
import { DrawerProps } from "./types"; | ||
|
||
const Drawer = forwardRef(( | ||
{ | ||
title, | ||
titleSub, | ||
onClose, | ||
children, | ||
...props | ||
}: PropsWithChildren<DrawerProps>, | ||
ref: React.Ref<HTMLDialogElement>, | ||
) => { | ||
const { className, ...rest } = props; | ||
const CloseIcon = | ||
<svg xmlns = "http://www.w3.org/2000/svg" width = "32" height = "32" viewBox = "0 0 32 32" fill = "none" focusable = "false"> | ||
<path d = "M25.7076 24.2926C25.8005 24.3855 25.8742 24.4958 25.9245 24.6172C25.9747 24.7386 26.0006 24.8687 26.0006 25.0001C26.0006 25.1315 25.9747 25.2616 25.9245 25.383C25.8742 25.5044 25.8005 25.6147 25.7076 25.7076C25.6147 25.8005 25.5044 25.8742 25.383 25.9245C25.2616 25.9747 25.1315 26.0006 25.0001 26.0006C24.8687 26.0006 24.7386 25.9747 24.6172 25.9245C24.4958 25.8742 24.3855 25.8005 24.2926 25.7076L16.0001 17.4138L7.70757 25.7076C7.51993 25.8952 7.26543 26.0006 7.00007 26.0006C6.7347 26.0006 6.48021 25.8952 6.29257 25.7076C6.10493 25.5199 5.99951 25.2654 5.99951 25.0001C5.99951 24.7347 6.10493 24.4802 6.29257 24.2926L14.5863 16.0001L6.29257 7.70757C6.10493 7.51993 5.99951 7.26543 5.99951 7.00007C5.99951 6.7347 6.10493 6.48021 6.29257 6.29257C6.48021 6.10493 6.7347 5.99951 7.00007 5.99951C7.26543 5.99951 7.51993 6.10493 7.70757 6.29257L16.0001 14.5863L24.2926 6.29257C24.4802 6.10493 24.7347 5.99951 25.0001 5.99951C25.2654 5.99951 25.5199 6.10493 25.7076 6.29257C25.8952 6.48021 26.0006 6.7347 26.0006 7.00007C26.0006 7.26543 25.8952 7.51993 25.7076 7.70757L17.4138 16.0001L25.7076 24.2926Z" fill = "#343330"/> | ||
</svg>; | ||
|
||
return ( | ||
<ModalBase | ||
ref = {ref} | ||
variants = {"drawer"} | ||
onClose = {onClose} | ||
{...rest} | ||
> | ||
<Section | ||
element = "div" | ||
className = {clsx("w-[29.1875rem] h-full animate-drawer", className)} | ||
hasRounded = {false} | ||
hasShadow | ||
> | ||
<header className = "flex-v-stack gap-y-6 pt-6 pl-6 pr-4 after:content-[''] after:h-[0.0625rem] after:bg-gray-02"> | ||
<div className = "flex items-center justify-between"> | ||
<div className = {clsx(titleSub && "flex items-center gap-x-2")}> | ||
<Typography element = "strong" theme = "head-01-bold" className = "text-[#000]" text = {title} /> | ||
{titleSub && <Typography theme = "body-02-regular" color = "gray-06" text = {titleSub} />} | ||
</div> | ||
<button onClick = {onClose} aria-label = "창 닫기"> | ||
{CloseIcon} | ||
</button> | ||
</div> | ||
</header> | ||
{children} | ||
</Section> | ||
</ModalBase> | ||
); | ||
}); | ||
|
||
export default Drawer; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import { HTMLAttributes } from "react"; | ||
|
||
import { ModalBaseProps } from "../../Modal/ModalBase/types"; | ||
import { TypographyProps } from "../../Typography"; | ||
|
||
export interface DrawerProps extends Pick<ModalBaseProps, "target" | "isOpen">, HTMLAttributes<HTMLElement> { | ||
title: TypographyProps<"strong">["text"]; | ||
titleSub?: TypographyProps<"span">["text"]; | ||
onClose: ModalBaseProps["onClose"]; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
import { Meta } from "@storybook/react"; | ||
import clsx from "clsx"; | ||
import { useState } from "react"; | ||
|
||
import Section from "../../Section"; | ||
import ModalBase from "./index"; | ||
import { ModalBaseProps } from "./types"; | ||
|
||
const meta = { | ||
title: "core/Modal/ModalBase", | ||
component: ModalBase, | ||
parameters: { | ||
layout: "fullscreen", | ||
}, | ||
argTypes: { | ||
target: { | ||
control: "text", | ||
defaultValue: "modal", | ||
description: "Modal Render Position Element id", | ||
}, | ||
variants: { | ||
control: "select", | ||
options: [ "modal", "drawer" ], | ||
description: "Modal Variants", | ||
}, | ||
isOpen: { | ||
control: "boolean", | ||
defaultValue: false, | ||
description: "Open Modal", | ||
}, | ||
dimmed: { | ||
control: "boolean", | ||
defaultValue: true, | ||
description: "use Modal Component with dimmed", | ||
}, | ||
onClose: { | ||
action: "clicked", | ||
description: "Modal Close Function", | ||
}, | ||
}, | ||
} satisfies Meta<typeof ModalBase>; | ||
|
||
export default meta; | ||
|
||
export const Default = (props: ModalBaseProps) => { | ||
const [ isOpen, setIsOpen ] = useState(false); | ||
|
||
return ( | ||
<> | ||
<div id = {props.target ?? "modal"} /> | ||
<ModalBase | ||
variants = {props.variants ?? "modal"} | ||
isOpen = {props.isOpen || isOpen} | ||
target = {props.target} | ||
dimmed = {props.dimmed} | ||
> | ||
<Section | ||
element = {"div"} | ||
className = {clsx("w-[20rem] h-[20rem]", | ||
props.variants === "modal" ? "animate-popup" : "animate-drawer", | ||
)} | ||
/> | ||
</ModalBase> | ||
<button onClick = {() => setIsOpen(true)}> | ||
Modal Open!! | ||
</button> | ||
</> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import { VariantsType } from "../types"; | ||
|
||
export const VARIANTS = { | ||
MODAL: "modal", | ||
DRAWER: "drawer", | ||
} as const; | ||
|
||
export const MODAL_CONTENT_POSITION: Record<VariantsType, string> = { | ||
[VARIANTS.MODAL]: "flex items-center justify-center", | ||
[VARIANTS.DRAWER]: "flex justify-end", | ||
} as const; | ||
|
||
export const MODAL_DIMMED_COLOR: Record<VariantsType, string> = { | ||
[VARIANTS.MODAL]: "bg-[#1018284d]", | ||
[VARIANTS.DRAWER]: "bg-[#f8faffcc]", | ||
} as const; | ||
|
||
export const MODAL_CONTENT_SIZE: Record<VariantsType, string> = { | ||
[VARIANTS.MODAL]: "h-auto", | ||
[VARIANTS.DRAWER]: "h-full", | ||
} as const; | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
import clsx from "clsx"; | ||
import { PropsWithChildren, forwardRef } from "react"; | ||
|
||
import useClickOutside from "@/hooks/useClickOutSide"; | ||
import ModalPortal from "../ModalPortal"; | ||
import { MODAL_CONTENT_POSITION, MODAL_CONTENT_SIZE, MODAL_DIMMED_COLOR } from "./constants"; | ||
import { ModalBaseProps } from "./types"; | ||
|
||
const ModalBase = forwardRef(( | ||
{ | ||
target, | ||
variants, | ||
isOpen, | ||
dimmed = true, | ||
onClose, | ||
children, | ||
...props | ||
}: PropsWithChildren<ModalBaseProps>, | ||
ref: React.Ref<HTMLDialogElement>, | ||
) => { | ||
const { contentRef } = useClickOutside<HTMLDivElement>(onClose); | ||
const { className, ...rest } = props; | ||
|
||
if (!isOpen) return null; | ||
|
||
return ( | ||
<ModalPortal target = {target}> | ||
<dialog | ||
ref = {ref} | ||
className = {clsx( | ||
"w-full h-full open:animate-fade-in", | ||
MODAL_CONTENT_POSITION[variants], | ||
dimmed && MODAL_DIMMED_COLOR[variants], | ||
className, | ||
)} | ||
open = {isOpen} | ||
{...rest} | ||
> | ||
<div | ||
ref = {contentRef} | ||
className = {MODAL_CONTENT_SIZE[variants]} | ||
> | ||
{children} | ||
</div> | ||
</dialog> | ||
</ModalPortal> | ||
); | ||
}); | ||
|
||
export default ModalBase; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import { DialogHTMLAttributes } from "react"; | ||
|
||
import { ModalPortalProps } from "../../ModalPortal"; | ||
import { VARIANTS } from "../constants"; | ||
|
||
export type VariantsType = typeof VARIANTS[keyof typeof VARIANTS]; | ||
|
||
export interface ModalBaseProps extends DialogHTMLAttributes<HTMLDialogElement>, ModalPortalProps { | ||
variants: VariantsType; | ||
isOpen: boolean; | ||
dimmed?: boolean; | ||
onClose?: () => void; | ||
} |
80 changes: 80 additions & 0 deletions
80
src/core/components/Modal/ModalPopUp/ModalPopUp.stories.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
import { Meta } from "@storybook/react"; | ||
import { useState } from "react"; | ||
|
||
import ModalPopUp from "./index"; | ||
import { ModalPopUpProps } from "./types"; | ||
|
||
const meta = { | ||
title: "core/Modal/ModalPopUp", | ||
component: ModalPopUp, | ||
parameters: { | ||
layout: "fullscreen", | ||
}, | ||
argTypes: { | ||
target: { | ||
control: "text", | ||
defaultValue: "modal", | ||
description: "Modal Render Position Element id", | ||
}, | ||
isOpen: { | ||
control: "boolean", | ||
defaultValue: false, | ||
description: "Open Modal", | ||
}, | ||
onClose: { | ||
action: "clicked", | ||
description: "Modal Close Function", | ||
}, | ||
}, | ||
} satisfies Meta<typeof ModalPopUp>; | ||
|
||
export default meta; | ||
|
||
export const Default = (props: ModalPopUpProps) => { | ||
const [ isOpen, setIsOpen ] = useState(false); | ||
|
||
const onToggle = () => setIsOpen(v => !v); | ||
|
||
return ( | ||
<> | ||
<div id = {props.target ?? "modal"} /> | ||
<ModalPopUp | ||
target = {props.target} | ||
isOpen = {props.isOpen || isOpen} | ||
className = "flex-v-stack gap-y-5 w-[20rem] h-[20rem] p-4" | ||
> | ||
<button className = "ml-auto" onClick = {onToggle}> | ||
닫기 | ||
</button> | ||
ModalPopUp | ||
</ModalPopUp> | ||
<button onClick = {onToggle}> | ||
ModalPopUp Open!! | ||
</button> | ||
</> | ||
); | ||
}; | ||
|
||
export const ModalPopUpUseBlur = (props: ModalPopUpProps) => { | ||
const [ isOpen, setIsOpen ] = useState(false); | ||
|
||
const onToggle = () => setIsOpen(v => !v); | ||
|
||
return ( | ||
<> | ||
<div id = {props.target ?? "foo"} /> | ||
<ModalPopUp | ||
target = {props.target ?? "foo"} | ||
isOpen = {props.isOpen || isOpen} | ||
onClose = {onToggle} | ||
className = "w-[20rem] h-[20rem] p-4" | ||
> | ||
ModalPopUp | ||
</ModalPopUp> | ||
<button onClick = {onToggle}> | ||
ModalPopUp Open!! | ||
</button> | ||
</> | ||
); | ||
}; | ||
|
Oops, something went wrong.