Layout.tsx 1.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354
  1. 'use client';
  2. import { useState, useCallback } from 'react';
  3. import Styles from '../styles/layout.module.scss';
  4. import Header from './Header';
  5. import Footer from './Footer'
  6. import ChannelSidebar from '@/app/component/channel/ChannelSidebar';
  7. import { ChannelListItem } from '@/types/channel';
  8. import { FEATURE_CHANNEL } from '@/constants/features';
  9. type Props = {
  10. children: React.ReactNode;
  11. initialChannels?: ChannelListItem[];
  12. };
  13. export default function Layout({ children, initialChannels }: Props) {
  14. const [sidebarOpen, setSidebarOpen] = useState(false);
  15. const toggleSidebar = useCallback(() => {
  16. setSidebarOpen((prev) => !prev);
  17. }, []);
  18. const closeOverlay = useCallback(() => {
  19. setSidebarOpen(false);
  20. }, []);
  21. return (
  22. <>
  23. <div id='container' className={`${Styles.container}${sidebarOpen ? ` ${Styles.sidebarOpen}` : ''}${FEATURE_CHANNEL ? '' : ` ${Styles.noAside}`}`}>
  24. <Header sidebarOpen={sidebarOpen} onToggle={toggleSidebar} />
  25. {/* 모바일 오버레이 */}
  26. <div className={Styles.overlay} onClick={closeOverlay} />
  27. {/* 좌측 채널 사이드바 — 채널 기능 OFF 시 미노출 */}
  28. {FEATURE_CHANNEL && (
  29. <aside id='aside' className={Styles.aside}>
  30. <ChannelSidebar initialChannels={initialChannels} />
  31. </aside>
  32. )}
  33. {/* 메인 내용 */}
  34. <main id='main' className={`${Styles.main} relative`}>
  35. {children}
  36. </main>
  37. {/* 하단 */}
  38. <Footer />
  39. </div>
  40. </>
  41. );
  42. }