+++ app/(protected)/(basic)/_components/admin-shell.module.scss
... | ... | @@ -0,0 +1,59 @@ |
| 1 | +// Basic 레이아웃 셸 — 헤더·사이드바·본문·풋터의 배치만 책임진다. | |
| 2 | +// | |
| 3 | +// @fox에 넣지 않고 레이아웃 전용으로 둔다(사용자 확정) — 로고·프로필처럼 이 앱에만 있는 | |
| 4 | +// 구성을 전제로 한 배치라 포터블 디자인시스템에 들어갈 성격이 아니다. 대신 여백·색·서체는 | |
| 5 | +// 전부 @fox 토큰을 거치므로 없는 이름을 쓰면 빌드가 실패한다. | |
| 6 | +// | |
| 7 | +// **뷰포트를 채우고 그 안에서만 스크롤한다.** 헤더는 항상 보이고 사이드바와 본문이 각자 | |
| 8 | +// 스크롤한다 — 사이드바가 `overflow-y: auto`를 전제로 만들어져 있어(시안 높이 1251px이 | |
| 9 | +// 뷰포트보다 크다) 행 높이가 뷰포트에 묶여 있어야 그 스크롤이 동작한다. | |
| 10 | +// globals.scss가 `html, body { block-size: 100% }`와 `body { display: flex }`를 깔아 두므로 | |
| 11 | +// 이 셸은 그 flex 자식으로서 남은 높이를 그대로 받는다. | |
| 12 | + | |
| 13 | +@use "@fox/styles/abstracts" as fox; | |
| 14 | + | |
| 15 | +.shell { | |
| 16 | + display: flex; | |
| 17 | + flex: 1; | |
| 18 | + flex-direction: column; | |
| 19 | + // 자식이 넘칠 때 셸이 늘어나지 않게 한다 — 늘어나면 안쪽 스크롤 대신 페이지가 스크롤된다. | |
| 20 | + min-block-size: 0; | |
| 21 | +} | |
| 22 | + | |
| 23 | +.body { | |
| 24 | + display: flex; | |
| 25 | + flex: 1; | |
| 26 | + min-block-size: 0; | |
| 27 | +} | |
| 28 | + | |
| 29 | +.content { | |
| 30 | + display: flex; | |
| 31 | + flex: 1; | |
| 32 | + flex-direction: column; | |
| 33 | + // flex 자식의 기본 min-inline-size는 auto라, 넓은 표가 들어오면 줄어들지 않고 사이드바를 | |
| 34 | + // 밀어낸다. 0으로 낮춰야 표 쪽이 스크롤된다. | |
| 35 | + min-inline-size: 0; | |
| 36 | + background: fox.color(background-default); | |
| 37 | + overflow-y: auto; | |
| 38 | +} | |
| 39 | + | |
| 40 | +.main { | |
| 41 | + display: flex; | |
| 42 | + flex: 1; | |
| 43 | + flex-direction: column; | |
| 44 | + // 헤더의 좌우 여백과 같은 값이라 세로 기준선이 맞는다. | |
| 45 | + padding: fox.padding(8); | |
| 46 | +} | |
| 47 | + | |
| 48 | +.footer { | |
| 49 | + flex-shrink: 0; | |
| 50 | + padding-block: fox.padding(6); | |
| 51 | + padding-inline: fox.padding(8); | |
| 52 | + border-block-start: fox.border(1) solid fox.color(border-neutral-subtler); | |
| 53 | + color: fox.color(font-neutral-subtler); | |
| 54 | + font-family: fox.font-family(body); | |
| 55 | + font-size: fox.font-size(label-sm); | |
| 56 | + line-height: 1.5; | |
| 57 | + letter-spacing: -0.025em; | |
| 58 | + text-align: center; | |
| 59 | +} |
--- app/(protected)/(basic)/_components/admin-shell.tsx
+++ app/(protected)/(basic)/_components/admin-shell.tsx
... | ... | @@ -2,6 +2,7 @@ |
| 2 | 2 |
|
| 3 | 3 |
import type { SidebarMenu } from '@/lib/domain/sidebar-menu';
|
| 4 | 4 |
import { AdminFooter } from './admin-footer';
|
| 5 |
+import styles from './admin-shell.module.scss'; |
|
| 5 | 6 |
import { AdminHeader } from './admin-header';
|
| 6 | 7 |
import { AdminSidebar } from './admin-sidebar';
|
| 7 | 8 |
|
... | ... | @@ -24,13 +25,13 @@ |
| 24 | 25 |
*/ |
| 25 | 26 |
export function AdminShell({ children, adminName, menu }: AdminShellProps) {
|
| 26 | 27 |
return ( |
| 27 |
- <div className="flex min-h-screen flex-col"> |
|
| 28 |
+ <div className={styles.shell}>
|
|
| 28 | 29 |
<AdminHeader adminName={adminName} />
|
| 29 |
- <div className="flex flex-1"> |
|
| 30 |
+ <div className={styles.body}>
|
|
| 30 | 31 |
<AdminSidebar menu={menu} />
|
| 31 |
- <div className="flex flex-1 flex-col"> |
|
| 32 |
- <main className="flex flex-1 flex-col">{children}</main>
|
|
| 33 |
- <AdminFooter /> |
|
| 32 |
+ <div className={styles.content}>
|
|
| 33 |
+ <main className={styles.main}>{children}</main>
|
|
| 34 |
+ <AdminFooter className={styles.footer} />
|
|
| 34 | 35 |
</div> |
| 35 | 36 |
</div> |
| 36 | 37 |
</div> |
Add a comment
Delete comment
Once you delete this comment, you won't be able to recover it. Are you sure you want to delete this comment?