
본 컴포넌트는 단일 파일 구조 내에서 **"사용자 인터랙션"**과 **"레이어 관리"**라는 역할을 유연하게 수행하도록 설계하였다.
| 파일명 | 유형 | 주요 역할 |
|---|---|---|
Drawer.tsx |
Client | Portal을 통해 DOM 최상단에 렌더링되며, 바닥에서 올라오는 서랍 형태의 UI를 제공하는 공통 컴포넌트 |
createPortal을 사용하여 부모 요소의 z-index나 overflow 스타일의 간섭 없이 body 최상단에 독립적으로 렌더링된다.body)의 스크롤을 자동으로 방지했다.ESC 키보드 인터랙션을 기본 지원한다.모든 표준 HTML 레이아웃 속성을 고려하며, 아래의 커스텀 속성을 추가로 가진다.
| Props | 설명 |
|---|---|
isOpen: boolean |
(필수) Drawer의 표시 여부를 결정. |
onClose: () => void |
(필수) Drawer를 닫는 로직을 수행하는 함수입니다. 배경 클릭이나 ESC 입력 시 호출한다. |
title?: string |
Drawer 상단에 표시될 제목입니다. 주입 시 자동으로 상단 여백과 텍스트 스타일이 적용된다. |
className?: string |
className?: string: |
children: React.ReactNode |
Drawer 내부에 렌더링될 실제 컨텐츠 요소. |
부모 컴포넌트에서 boolean 상태를 관리하여 필요에 따라 서랍을 호출한다.
"use client";
import { useState } from "react";
import { Drawer } from "@/shared/ui/drawer";
export default function MobileMenu() {
const [isOpen, setIsOpen] = useState(false);
return (
<>
<button onClick={() => setIsOpen(true)}>메뉴 열기</button>
<Drawer
isOpen={isOpen}
onClose={() => setIsOpen(false)}
title="환경 설정"
>
<div className="flex flex-col gap-4 py-2">
<p className="text-sm text-slate-500">앱의 주요 설정을 변경할 수 있습니다.</p>
<button className="w-full rounded-md bg-slate-900 py-2 text-white">
프로필 수정
</button>
</div>
</Drawer>
</>
);
}
className을 사용하여 특정 너비나 패딩 값을 조정할 수 있으며, 제목 없이 컨텐츠만 배치할 수도 있다.
"use client";
import { Drawer } from "@/shared/ui/drawer";
export default function FullHeightDrawer({ isOpen, onClose }) {
return (
<Drawer
isOpen={isOpen}
onClose={onClose}
className="max-w-2xl bg-slate-50" // 추가 스타일 주입
>
<div className="flex flex-col items-center py-10">
<h3 className="text-xl font-bold">제목 없는 전체 화면 공지</h3>
<p className="mt-4">자유로운 컨텐츠 구성이 가능합니다.</p>
</div>
</Drawer>
);
}