첫 커밋
This commit is contained in:
82
src/shared/ui/bottom-sheets/bottom-sheet.tsx
Normal file
82
src/shared/ui/bottom-sheets/bottom-sheet.tsx
Normal file
@@ -0,0 +1,82 @@
|
||||
/* eslint-disable react-hooks/exhaustive-deps */
|
||||
import clsx from 'clsx';
|
||||
import { useBlocker } from 'react-router';
|
||||
import {
|
||||
JSX,
|
||||
Fragment,
|
||||
ReactNode,
|
||||
useCallback
|
||||
} from 'react';
|
||||
import {
|
||||
Dialog,
|
||||
Transition,
|
||||
DialogPanel,
|
||||
DialogTitle,
|
||||
TransitionChild
|
||||
} from '@headlessui/react';
|
||||
|
||||
export interface BottomSheetProps {
|
||||
open: boolean;
|
||||
onClose: () => void;
|
||||
afterLeave?: () => void;
|
||||
children: ReactNode;
|
||||
title?: string | JSX.Element;
|
||||
description?: string | JSX.Element;
|
||||
centeredTitle?: boolean;
|
||||
}
|
||||
|
||||
const BottomSheet = ({ open, onClose, afterLeave, children, title, centeredTitle, description }: BottomSheetProps) => {
|
||||
const whenToBlock = useCallback(() => open, [open]);
|
||||
const blocker = useBlocker(whenToBlock);
|
||||
const handleClose = useCallback(() => {
|
||||
blocker?.reset?.();
|
||||
onClose();
|
||||
}, []);
|
||||
return (
|
||||
<Transition show={open} as={Fragment} afterLeave={afterLeave}>
|
||||
<Dialog onClose={handleClose}>
|
||||
<TransitionChild
|
||||
as={Fragment}
|
||||
enter="ease-out duration-300"
|
||||
enterFrom="opacity-0"
|
||||
enterTo="opacity-100"
|
||||
leave="ease-in duration-200"
|
||||
leaveFrom="opacity-100"
|
||||
leaveTo="opacity-0"
|
||||
>
|
||||
<div className="fixed inset-0 bg-black/30" aria-hidden="true" />
|
||||
</TransitionChild>
|
||||
<TransitionChild
|
||||
as={Fragment}
|
||||
enter="transition-transform duration-400"
|
||||
enterFrom="translate-y-full"
|
||||
enterTo="translate-y-0"
|
||||
leave="transition-transform duration-200"
|
||||
leaveFrom=" translate-y-0"
|
||||
leaveTo="translate-y-full"
|
||||
>
|
||||
<DialogPanel className="fixed bottom-0 w-full rounded-t-[30px] bg-white">
|
||||
<DialogTitle className="relative flex px-[30px] pt-[30px]">
|
||||
<div>
|
||||
<h2
|
||||
className={clsx('grow text-lg font-bold', {
|
||||
'text-center': centeredTitle,
|
||||
})}
|
||||
>
|
||||
{title}
|
||||
</h2>
|
||||
{description && <p className="mt-[8px] text-[14px] text-[#888888]">{description}</p>}
|
||||
</div>
|
||||
<button onClick={handleClose} className="btn close-btn absolute right-[30px] top-[27px]">
|
||||
<span>닫기</span>
|
||||
</button>
|
||||
</DialogTitle>
|
||||
{ children }
|
||||
</DialogPanel>
|
||||
</TransitionChild>
|
||||
</Dialog>
|
||||
</Transition>
|
||||
);
|
||||
};
|
||||
|
||||
export { BottomSheet };
|
||||
Reference in New Issue
Block a user