AppLayout
Dark Mode앱 전체 페이지를 감싸는 레이아웃 컴포넌트입니다. Sidebar(좌측 고정) + Header(상단 고정) + SubHeader(선택) + Content(스크롤) 구조로, 사이드바 확장/축소에 따라 콘텐츠 영역이 자동 조정됩니다.
import { AppLayout } from "@/shared/ui/common"구조
┌──────────────────────────────────────────────────┐ │ AppLayout (h-screen, flex) │ ├────────────┬─────────────────────────────────────┤ │ │ header (MainHeader, 84px, 고정) │ │ sidebar ├─────────────────────────────────────┤ │ (Sidebar) │ subHeader? (TabBar 등, 고정) │ │ 212/80px ├─────────────────────────────────────┤ │ 고정 │ main (children, 스크롤) │ │ │ px-7 py-8 기본 패딩 │ │ │ │ └────────────┴─────────────────────────────────────┘
사이드바 토글 연동
토글 버튼 위치: 사이드바 접기/펼치기 버튼은MainHeader에 위치합니다. Sidebar 컴포넌트에는 버튼이 없습니다.
상태 소유권: collapsed 상태는 AppLayout을 사용하는 page 컴포넌트가 소유합니다. AppLayout 자체는 sidebar / header를 ReactNode 슬롯으로 받는 구조라 내부에서 상태를 직접 중계하지 않습니다.
연결 방법: page에서 하나의 collapsed state를 만들고,Sidebar에는 collapsed를,MainHeader에는 collapsed + onToggleCollapse를 각각 전달합니다.
인터랙티브 데모
디캠프 주식회사투자 담당자
콘텐츠 블록 A
이 영역만 스크롤됩니다. 사이드바와 헤더는 고정됩니다.
콘텐츠 블록 B
콘텐츠 블록 C
tsx
// collapsed 상태를 page에서 소유하고 Sidebar/MainHeader 양쪽에 주입합니다.
// AppLayout은 ReactNode 슬롯 구조이므로 상태를 직접 중계하지 않습니다.
const [collapsed, setCollapsed] = useState(false);
<AppLayout
sidebar={
<Sidebar
items={navItems}
collapsed={collapsed}
user={{ userName: "홍길동", spaceName: "디캠프 주식회사" }}
/>
}
header={
<MainHeader
title="대시보드"
backHref="/dashboard"
collapsed={collapsed}
onToggleCollapse={() => setCollapsed((p) => !p)}
actions={
<>
<MainHeaderIconButton icon={Search} label="검색" />
<MainHeaderIconButton icon={Settings} label="설정" />
</>
}
profile={profile}
/>
}
>
{/* 콘텐츠 — 이 영역만 스크롤됩니다 */}
<PageContent />
</AppLayout>사이드바 확장 vs 축소
사이드바 확장 시 212px, 축소 시 80px. 콘텐츠 영역은 flex-1로 나머지 공간을 자동으로 채웁니다.
SubHeader 슬롯
헤더 아래에 TabBar 등의 서브 네비게이션을 고정 배치할 수 있습니다. subHeader는 콘텐츠와 함께 스크롤되지 않습니다.
tsx
// subHeader 슬롯에 TabBar 등을 배치하면 헤더 아래에 고정됩니다
<AppLayout
sidebar={<Sidebar items={navItems} collapsed={false} />}
header={<MainHeader title="펀드 상세" backHref="#" />}
subHeader={
<TabBar
items={tabItems}
value={tabValue}
onChange={setTabValue}
/>
}
>
<PageContent />
</AppLayout>Props
AppLayout
| Prop | Type | Required | Default | 설명 |
|---|---|---|---|---|
sidebar | ReactNode | ✓ | — | 좌측 사이드바 영역. Sidebar 컴포넌트를 전달합니다. |
header | ReactNode | ✓ | — | 상단 헤더 영역. MainHeader 컴포넌트를 전달합니다. |
subHeader | ReactNode | — | — | 헤더 바로 아래 고정되는 서브헤더 영역. TabBar 등에 사용합니다. |
children | ReactNode | ✓ | — | 메인 콘텐츠 영역. 이 영역만 스크롤됩니다. |
contentClassName | string | — | — | 콘텐츠 래퍼에 적용할 추가 클래스. 기본 패딩(px-7 py-8)을 커스터마이즈할 때 사용합니다. |
className | string | — | — | 루트 요소에 적용할 추가 클래스. |