diff --git a/src/common/component/BottomSheet/BottomSheet.tsx b/src/common/component/BottomSheet/BottomSheet.tsx index 292fb11d..ebf181eb 100644 --- a/src/common/component/BottomSheet/BottomSheet.tsx +++ b/src/common/component/BottomSheet/BottomSheet.tsx @@ -8,7 +8,11 @@ interface BottomSheetPropTypes { } //화면 전체를 차지하는 바텀시트 틀 (children 필요) -const BottomSheet = ({ isOpen, children, handleOpen }: BottomSheetPropTypes) => { +const BottomSheet = ({ + isOpen, + children, + handleOpen, +}: BottomSheetPropTypes) => { if (!isOpen) return; const handleClose = () => { @@ -20,12 +24,19 @@ const BottomSheet = ({ isOpen, children, handleOpen }: BottomSheetPropTypes) => }; return ( - <div className={styles.overlay} onClick={handleClose} onKeyDown={handleClose}> + <div + className={styles.overlay} + onClick={handleClose} + onKeyDown={handleClose} + > <div className={styles.bottomSheet} onClick={handleBottomSheetClick}> <div className={styles.bottomTabBar}> - <div className={styles.bar} onClick={handleClose} onKeyDown={handleClose} /> + <div + className={styles.bar} + onClick={handleClose} + onKeyDown={handleClose} + /> </div> - {children} </div> </div> diff --git a/src/page/community/[postId]/Post.ts b/src/page/community/[postId]/Post.ts new file mode 100644 index 00000000..11d9e549 --- /dev/null +++ b/src/page/community/[postId]/Post.ts @@ -0,0 +1,2 @@ +import { style } from "@vanilla-extract/css"; +import { color } from "@style/styles.css.ts"; diff --git a/src/page/community/[postId]/Post.tsx b/src/page/community/[postId]/Post.tsx index 20f5b177..92167169 100644 --- a/src/page/community/[postId]/Post.tsx +++ b/src/page/community/[postId]/Post.tsx @@ -1,5 +1,25 @@ +import MoreModal from "@shared/component/MoreModal/MoreModal.tsx"; +import useMoreModal from "@shared/hook/useMoreModal"; + const PostDetail = () => { - return <div>Postid</div>; + const { isOpen, openModal, closeModal, toggleModal } = useMoreModal(); + + const handleDelete = () => { + alert("삭제되었습니다!"); + toggleModal(); + }; + + return ( + <div> + <MoreModal + isOpen={isOpen} + onToggleModal={toggleModal} + onDelete={handleDelete} + iconSize={2} + onEdit={() => alert("수정하기")} + /> + </div> + ); }; export default PostDetail; diff --git a/src/shared/component/MoreModal/MoreModal.css.ts b/src/shared/component/MoreModal/MoreModal.css.ts new file mode 100644 index 00000000..9ce500b1 --- /dev/null +++ b/src/shared/component/MoreModal/MoreModal.css.ts @@ -0,0 +1,92 @@ +import { createVar, style } from "@vanilla-extract/css"; +import { recipe, RecipeVariants } from "@vanilla-extract/recipes"; +import { button } from "@common/component/Button/styles.css.ts"; +import { color, font } from "@style/styles.css.ts"; + +export const iconSizeVar = createVar(); + +export const container = style({ + position: "relative", + width: iconSizeVar, + height: iconSizeVar, +}); + +export const moreIcon = style({ + width: iconSizeVar, + height: iconSizeVar, +}); + +export const moreModal = recipe({ + base: { + position: "absolute", + top: "calc(100% + 0.8rem)", + left: "-16rem", + display: "flex", + flexDirection: "column", + borderRadius: "1.2rem", + backgroundColor: "white", + boxShadow: "0px 2px 10px 0px rgba(0, 0, 0, 0.15)", + width: "18.4rem", + zIndex: 10, + }, + variants: { + onEdit: { + true: { + // 수정하기가 있을 때 + height: "11.2rem", + }, + false: { + // 수정하기가 없을 때 + height: "5.6rem", + }, + }, + }, + defaultVariants: { + onEdit: false, // 기본값 + }, +}); + +export const moreModalItem = recipe({ + base: [ + font.body01, + { + background: "none", + border: "none", + textAlign: "left", + width: "100%", + padding: "1.8rem 3.2rem", + color: color.red.warning_red200, + ":hover": { + backgroundColor: color.gray.gray300, + }, + ":active": { + backgroundColor: color.gray.gray300, + }, + }, + ], + variants: { + position: { + first: { + // 수정하기가 들어간 경우의 삭제하기 border + borderRadius: "1.2rem 1.2rem 0 0", + }, + last: { + // 수정하기가 들어간 경우의 수정하기 border + borderRadius: "0 0 1.2rem 1.2rem", + }, + default: { + // 수정하기가 없는 경우의 border + borderRadius: "1.2rem", + }, + }, + }, + defaultVariants: { + position: "default", + }, +}); + +export const moreModalDivider = style({ + height: "1px", + backgroundColor: color.gray.gray300, + margin: "0", +}); diff --git a/src/shared/component/MoreModal/MoreModal.tsx b/src/shared/component/MoreModal/MoreModal.tsx new file mode 100644 index 00000000..8514cacf --- /dev/null +++ b/src/shared/component/MoreModal/MoreModal.tsx @@ -0,0 +1,67 @@ +import React from "react"; +import { IcEllipses } from "@asset/svg"; +import { + container, + iconSizeVar, + moreIcon, + moreModal, + moreModalDivider, + moreModalItem, +} from "@shared/component/MoreModal/MoreModal.css.ts"; +import { assignInlineVars } from "@vanilla-extract/dynamic"; + +interface MoreModalParams { + isOpen: boolean; + onToggleModal: () => void; + onDelete: () => void; + iconSize: number; + onEdit?: () => void; +} + +const MoreModal = ({ + isOpen, + onToggleModal, + onDelete, + iconSize, + onEdit, +}: MoreModalParams) => { + return ( + <div + className={container} + style={assignInlineVars({ [iconSizeVar]: `${iconSize}rem` })} + > + <IcEllipses + className={moreIcon} + style={assignInlineVars({ [iconSizeVar]: `${iconSize}rem` })} + onClick={onToggleModal} + /> + {isOpen && ( + <div className={moreModal({ onEdit: !!onEdit })}> + <button + className={moreModalItem({ + position: !!onEdit ? "first" : "default", + })} + onClick={onDelete} + > + 삭제하기 + </button> + {onEdit && ( + <> + <div className={moreModalDivider} /> + <button + className={moreModalItem({ + position: !!onEdit ? "last" : "default", + })} + onClick={onEdit} + > + 수정하기 + </button> + </> + )} + </div> + )} + </div> + ); +}; + +export default MoreModal; diff --git a/src/shared/constant/.gitkeep b/src/shared/constant/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/src/shared/hook/.gitkeep b/src/shared/hook/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/src/shared/hook/useMoreModal.ts b/src/shared/hook/useMoreModal.ts new file mode 100644 index 00000000..8048be16 --- /dev/null +++ b/src/shared/hook/useMoreModal.ts @@ -0,0 +1,13 @@ +import { useState } from "react"; + +const useMoreModal = () => { + const [isOpen, setIsOpen] = useState(false); + + const openModal = () => setIsOpen(true); + const closeModal = () => setIsOpen(false); + const toggleModal = () => setIsOpen((prev) => !prev); + + return { isOpen, openModal, closeModal, toggleModal }; +}; + +export default useMoreModal;