75 lines
2.0 KiB
TypeScript
75 lines
2.0 KiB
TypeScript
import { type ReactNode } from 'react'
|
|
import { Logo } from '@/components'
|
|
import { cn } from '@/lib'
|
|
|
|
// 좌측 폭: list=반응형 비율 / chat=고정 350px
|
|
const SIDEBAR_WIDTH = {
|
|
list:
|
|
'w-[20%] max-w-[320px] ' +
|
|
'max-[1520px]:w-[23%] max-[1410px]:w-[25%] ' +
|
|
'max-[1180px]:w-[27%] max-[1024px]:w-[29%] max-[960px]:w-[33%]',
|
|
chat: 'w-[350px]',
|
|
} as const
|
|
|
|
const styles = {
|
|
root: 'flex w-full min-h-screen max-h-screen bg-background',
|
|
scrollX: 'flex w-full min-h-screen max-h-screen overflow-x-auto overflow-y-hidden',
|
|
scrollXInner: 'flex w-full min-h-screen max-h-screen min-w-[1350px] bg-background',
|
|
sidebar: 'flex flex-col h-screen pt-2 bg-background',
|
|
logoHeader:
|
|
'flex w-full h-[56px] pl-[32px] pr-[24px] py-[8px] items-center justify-between shrink-0',
|
|
main: 'flex flex-1 flex-col h-screen overflow-hidden pt-2 pr-2 pb-2 pl-0',
|
|
// 다크 헤더와 합쳐져 카드 형태
|
|
content: 'flex flex-1 flex-col min-h-0 w-full overflow-hidden rounded-b-[8px] bg-surface',
|
|
} as const
|
|
|
|
export type SidebarWidth = keyof typeof SIDEBAR_WIDTH
|
|
|
|
export interface MainLayoutProps {
|
|
sidebarWidth?: SidebarWidth
|
|
/** 루트 가로 스크롤 + 최소폭 (chat 전용) */
|
|
scrollX?: boolean
|
|
logoAction?: ReactNode
|
|
sidebar: ReactNode
|
|
header: ReactNode
|
|
children?: ReactNode
|
|
}
|
|
|
|
export function MainLayout({
|
|
sidebarWidth = 'list',
|
|
scrollX = false,
|
|
logoAction,
|
|
sidebar,
|
|
header,
|
|
children,
|
|
}: MainLayoutProps) {
|
|
const panes = (
|
|
<>
|
|
<aside className={cn(styles.sidebar, SIDEBAR_WIDTH[sidebarWidth])}>
|
|
<div className={styles.logoHeader}>
|
|
<Logo size="sm" />
|
|
{logoAction}
|
|
</div>
|
|
{sidebar}
|
|
</aside>
|
|
|
|
<main className={styles.main}>
|
|
{header}
|
|
<div className={styles.content}>{children}</div>
|
|
</main>
|
|
</>
|
|
)
|
|
|
|
if (!scrollX) {
|
|
return <div className={styles.root}>{panes}</div>
|
|
}
|
|
|
|
return (
|
|
<div className={styles.scrollX}>
|
|
<div className={styles.scrollXInner}>{panes}</div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
export default MainLayout
|