@@ -19,7 +19,7 @@ interface Dashboard {
1919interface SideMenuProps {
2020 teamId : string ;
2121 dashboardList : Dashboard [ ] ;
22- onCreateDashboard ?: ( dashboard : Dashboard ) => void ; // ✅ 부모 상태 갱신용 콜백
22+ onCreateDashboard ?: ( dashboard : Dashboard ) => void ;
2323}
2424
2525export default function SideMenu ( {
@@ -31,9 +31,10 @@ export default function SideMenu({
3131 const boardId = parseInt ( boardid as string ) ;
3232
3333 const [ currentPage , setCurrentPage ] = useState ( 1 ) ;
34+ const [ isCollapsed , setIsCollapsed ] = useState ( false ) ;
3435 const [ isModalOpen , setIsModalOpen ] = useState ( false ) ;
3536
36- const itemsPerPage = 18 ;
37+ const itemsPerPage = 15 ;
3738 const totalPages = Math . ceil ( dashboardList . length / itemsPerPage ) ;
3839 const startIndex = ( currentPage - 1 ) * itemsPerPage ;
3940 const endIndex = startIndex + itemsPerPage ;
@@ -48,12 +49,22 @@ export default function SideMenu({
4849 } ;
4950
5051 return (
51- < aside className = "h-screen overflow-y-auto border-r border-[var(--color-gray3)] px-3 py-5 lg:w-[300px] md:w-[160px] sm:w-[67px] transition-all duration-200 flex flex-col" >
52- { /* 로고 */ }
53- < div className = "mb-14 px-3 sm:mb-9 sm:px-0" >
52+ < aside
53+ className = { clsx (
54+ "h-screen overflow-y-auto border-r border-[var(--color-gray3)] px-3 py-5 transition-all duration-200 flex flex-col" ,
55+ isCollapsed
56+ ? "w-[67px]"
57+ : "w-[67px] sm:w-[67px] md:w-[160px] lg:w-[300px]"
58+ ) }
59+ >
60+ { /* 로고 + 접기버튼 */ }
61+ < div className = "mb-14 px-3 sm:mb-9 sm:px-0 relative" >
5462 < Link
55- href = { "/mydashboard" }
56- className = "flex lg:justify-start md:justify-start sm:justify-center"
63+ href = "/mydashboard"
64+ className = { clsx (
65+ "flex" ,
66+ isCollapsed ? "justify-center" : "justify-start"
67+ ) }
5768 >
5869 < Image
5970 src = "/svgs/logo_taskify.svg"
@@ -74,41 +85,94 @@ export default function SideMenu({
7485 unoptimized
7586 />
7687 </ Link >
88+
89+ { /* 접기/펼치기 버튼 (✅ md 이상에서만 보이게 수정) */ }
90+ < div
91+ className = { clsx (
92+ "md:flex hidden" ,
93+ isCollapsed ? "mt-3 justify-center" : "absolute right-0 top-0"
94+ ) }
95+ >
96+ < button
97+ onClick = { ( ) => setIsCollapsed ( ! isCollapsed ) }
98+ className = "w-6 h-6 bg-gray-100 hover:bg-gray-200 border rounded flex items-center justify-center"
99+ title = { isCollapsed ? "펼치기" : "접기" }
100+ >
101+ { isCollapsed ? (
102+ < svg
103+ className = "w-2.5 h-2.5 text-gray-600"
104+ fill = "none"
105+ stroke = "currentColor"
106+ viewBox = "0 0 24 24"
107+ >
108+ < path
109+ strokeLinecap = "round"
110+ strokeLinejoin = "round"
111+ strokeWidth = { 2 }
112+ d = "M9 5l7 7-7 7"
113+ />
114+ </ svg >
115+ ) : (
116+ < svg
117+ className = "w-2.5 h-2.5 text-gray-600"
118+ fill = "none"
119+ stroke = "currentColor"
120+ viewBox = "0 0 24 24"
121+ >
122+ < path
123+ strokeLinecap = "round"
124+ strokeLinejoin = "round"
125+ strokeWidth = { 2 }
126+ d = "M15 19l-7-7 7-7"
127+ />
128+ </ svg >
129+ ) }
130+ </ button >
131+ </ div >
77132 </ div >
78133
79134 { /* 메뉴 전체 */ }
80135 < nav className = "flex flex-col flex-1 justify-between" >
81136 < div >
82137 { /* 대시보드 타이틀 */ }
83- < div className = "mb-4 flex items-center justify-between px-3 md:px-2" >
84- < span className = "hidden md:block font-12sb text-[var(--color-black)]" >
85- Dash Boards
86- </ span >
87- < button className = "ml-auto" onClick = { ( ) => setIsModalOpen ( true ) } >
88- < Image
89- src = "/svgs/icon-add-box.svg"
90- width = { 20 }
91- height = { 20 }
92- alt = "추가 아이콘"
93- unoptimized
94- />
95- </ button >
96- </ div >
138+ { ! isCollapsed && (
139+ < div className = "mb-4 flex items-center justify-between px-3 md:px-2" >
140+ < span className = "hidden md:block font-12sb text-[var(--color-black)]" >
141+ Dash Boards
142+ </ span >
143+ < button className = "ml-auto" onClick = { ( ) => setIsModalOpen ( true ) } >
144+ < Image
145+ src = "/svgs/icon-add-box.svg"
146+ width = { 20 }
147+ height = { 20 }
148+ alt = "추가 아이콘"
149+ unoptimized
150+ />
151+ </ button >
152+ </ div >
153+ ) }
97154
98155 { /* 대시보드 목록 */ }
99- < ul className = "flex flex-col lg:items-start md:items-start sm:items-center sm:w-full" >
156+ < ul
157+ className = { clsx (
158+ "flex flex-col" ,
159+ isCollapsed
160+ ? "items-center"
161+ : "items-start md:items-start sm:items-center w-full"
162+ ) }
163+ >
100164 { paginatedDashboards . map ( ( dashboard ) => (
101165 < li
102166 key = { dashboard . id }
103167 className = { clsx (
104- "w-full flex justify-center sm:justify-center lg:justify-start md:justify-start p-3 font-18m text-[var(--color-black)] transition-colors duration-200" ,
168+ "w-full flex justify-center md:justify-start p-3 font-18m text-[var(--color-black)] transition-colors duration-200" ,
105169 dashboard . id === boardId &&
106170 "bg-[var(--primary)] text-white rounded-lg"
107171 ) }
108172 >
109173 < Link
110174 href = { `/dashboard/${ dashboard . id } ` }
111- className = "flex items-center gap-3 sm:gap- 2"
175+ className = "flex items-center gap-2"
112176 >
113177 < svg
114178 xmlns = "http://www.w3.org/2000/svg"
@@ -120,29 +184,31 @@ export default function SideMenu({
120184 >
121185 < circle cx = "4" cy = "4" r = "4" />
122186 </ svg >
123- < div className = "hidden md:flex items-center gap-2" >
124- < span className = "truncate font-18m md:text-base" >
125- { dashboard . title }
126- </ span >
127- { dashboard . createdByMe && (
128- < Image
129- src = "/svgs/crown.svg"
130- width = { 18 }
131- height = { 14 }
132- alt = "크라운 아이콘"
133- unoptimized
134- priority
135- />
136- ) }
137- </ div >
187+ { ! isCollapsed && (
188+ < div className = "hidden md:flex items-center gap-2" >
189+ < span className = "truncate md:text-base" >
190+ { dashboard . title }
191+ </ span >
192+ { dashboard . createdByMe && (
193+ < Image
194+ src = "/svgs/crown.svg"
195+ width = { 18 }
196+ height = { 14 }
197+ alt = "크라운 아이콘"
198+ unoptimized
199+ priority
200+ />
201+ ) }
202+ </ div >
203+ ) }
138204 </ Link >
139205 </ li >
140206 ) ) }
141207 </ ul >
142208 </ div >
143209
144- { /* 페이지네이션 버튼 */ }
145- { dashboardList . length > itemsPerPage && (
210+ { /* 페이지네이션 */ }
211+ { ! isCollapsed && dashboardList . length > itemsPerPage && (
146212 < div className = "flex justify-start mt-4 px-3" >
147213 < PaginationButton
148214 direction = "left"
@@ -156,18 +222,16 @@ export default function SideMenu({
156222 />
157223 </ div >
158224 ) }
225+ { isModalOpen && (
226+ < NewDashboard
227+ onClose = { ( ) => setIsModalOpen ( false ) }
228+ onCreate = { ( newDashboard ) => {
229+ onCreateDashboard ?.( newDashboard ) ;
230+ setIsModalOpen ( false ) ;
231+ } }
232+ />
233+ ) }
159234 </ nav >
160-
161- { /* 대시보드 생성 모달 */ }
162- { isModalOpen && (
163- < NewDashboard
164- onClose = { ( ) => setIsModalOpen ( false ) }
165- onCreate = { ( newDashboard ) => {
166- onCreateDashboard ?.( newDashboard ) ;
167- setIsModalOpen ( false ) ;
168- } }
169- />
170- ) }
171235 </ aside >
172236 ) ;
173237}
0 commit comments