From 75152df43a8fd3df14fd8e03401c3f92d0952151 Mon Sep 17 00:00:00 2001 From: Andy Hong Date: Thu, 12 Feb 2026 20:26:02 +0900 Subject: [PATCH 1/4] =?UTF-8?q?feat:=20=EB=AA=A8=EB=B0=94=EC=9D=BC=20?= =?UTF-8?q?=ED=97=A4=EB=8D=94=20=EC=88=98=EC=A0=95=20(#216)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/common/layout/HeaderButton.tsx | 14 ++++++++++++-- src/components/common/layout/LoginButton.tsx | 10 +++++++--- src/components/common/layout/ShareButton.tsx | 4 +++- 3 files changed, 22 insertions(+), 6 deletions(-) diff --git a/src/components/common/layout/HeaderButton.tsx b/src/components/common/layout/HeaderButton.tsx index 690d6da4..aa095a63 100644 --- a/src/components/common/layout/HeaderButton.tsx +++ b/src/components/common/layout/HeaderButton.tsx @@ -11,22 +11,32 @@ interface HeaderButtonProps { icon?: ReactNode; onClick: () => void; className?: string; + iconOnlyOnMobile?: boolean; } /** * @description 헤더 우측 슬롯에서 공통으로 사용되는 아이콘+텍스트 버튼 컴포넌트 */ -export function HeaderButton({ text, icon, onClick, className }: HeaderButtonProps) { +export function HeaderButton({ + text, + icon, + onClick, + className, + iconOnlyOnMobile = false, +}: HeaderButtonProps) { + const shouldHideTextOnMobile = iconOnlyOnMobile && !!icon; + return ( ); diff --git a/src/components/common/layout/LoginButton.tsx b/src/components/common/layout/LoginButton.tsx index bc57a88a..60c46472 100644 --- a/src/components/common/layout/LoginButton.tsx +++ b/src/components/common/layout/LoginButton.tsx @@ -50,7 +50,9 @@ export function LoginButton() { }; // 로그인 전 (게스트) if (isGuest) { - return } onClick={openLoginModal} />; + return ( + } onClick={openLoginModal} iconOnlyOnMobile /> + ); } // 익명 사용자 @@ -60,7 +62,9 @@ export function LoginButton() { // 소셜이 아닌데 여기까지 왔다면(비정상 상태) 방어 if (!isSocial) { - return } onClick={openLoginModal} />; + return ( + } onClick={openLoginModal} iconOnlyOnMobile /> + ); } const handleWithdraw = async () => { @@ -91,7 +95,7 @@ export function LoginButton() { type="button" className="flex cursor-pointer items-center gap-2 text-body-s-bold text-gray-800 transition-colors hover:text-gray-600" > - {displayName} + {displayName} } diff --git a/src/components/common/layout/ShareButton.tsx b/src/components/common/layout/ShareButton.tsx index e1a1873a..be25fb35 100644 --- a/src/components/common/layout/ShareButton.tsx +++ b/src/components/common/layout/ShareButton.tsx @@ -10,5 +10,7 @@ import { HeaderButton } from './HeaderButton'; export function ShareButton() { const openShareModal = useShareStore((s) => s.openShareModal); - return } onClick={openShareModal} />; + return ( + } onClick={openShareModal} iconOnlyOnMobile /> + ); } From 719b8c7ba23c7fdefeefa2d6f1cb314477d8a92e Mon Sep 17 00:00:00 2001 From: Andy Hong Date: Thu, 12 Feb 2026 20:30:47 +0900 Subject: [PATCH 2/4] =?UTF-8?q?feat:=20=EB=AA=A8=EB=B0=94=EC=9D=BC=20?= =?UTF-8?q?=EB=B7=B0=20=EA=B5=AC=ED=98=84=20(#216)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/SlidePage.tsx | 63 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 62 insertions(+), 1 deletion(-) diff --git a/src/pages/SlidePage.tsx b/src/pages/SlidePage.tsx index 1d4bac58..79cd810d 100644 --- a/src/pages/SlidePage.tsx +++ b/src/pages/SlidePage.tsx @@ -14,6 +14,11 @@ export default function SlidePage() { const slideIdParam = searchParams.get('slideId'); const currentSlide = slides?.find((s) => s.slideId === slideIdParam) ?? slides?.[0]; + const currentIndex = currentSlide + ? (slides?.findIndex((s) => s.slideId === currentSlide.slideId) ?? -1) + : -1; + const hasPrev = currentIndex > 0; + const hasNext = !!slides && currentIndex >= 0 && currentIndex < slides.length - 1; /** * 슬라이드 로드 에러 처리 @@ -49,15 +54,71 @@ export default function SlidePage() { } }, [projectId, currentSlide?.slideId]); + const goPrev = () => { + if (!slides || !hasPrev) return; + setSearchParams({ slideId: slides[currentIndex - 1].slideId }, { replace: true }); + }; + + const goNext = () => { + if (!slides || !hasNext) return; + setSearchParams({ slideId: slides[currentIndex + 1].slideId }, { replace: true }); + }; + return (
-
+
+ +
+
+ + + {slides && currentIndex >= 0 ? `${currentIndex + 1} / ${slides.length}` : '- / -'} + + +
+ +
+ +
+
); } From 8fa44a57acc6598cc8e4a6f6424eac76068aca5f Mon Sep 17 00:00:00 2001 From: Andy Hong Date: Thu, 12 Feb 2026 20:34:19 +0900 Subject: [PATCH 3/4] =?UTF-8?q?feat:=20=EB=AA=A8=EB=B0=94=EC=9D=BC=20?= =?UTF-8?q?=EB=B7=B0=20=EA=B5=AC=ED=98=84=20(#216)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/common/TitleEditorPopover.tsx | 12 ++++++++++-- src/components/slide/script/SlideTitle.tsx | 1 + 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/components/common/TitleEditorPopover.tsx b/src/components/common/TitleEditorPopover.tsx index 3e8e11c5..745eca41 100644 --- a/src/components/common/TitleEditorPopover.tsx +++ b/src/components/common/TitleEditorPopover.tsx @@ -23,6 +23,7 @@ interface TitleEditorPopoverProps { ariaLabel: string; isPending?: boolean; titleClassName?: string; + showOnMobile?: boolean; } export function TitleEditorPopover({ @@ -33,6 +34,7 @@ export function TitleEditorPopover({ ariaLabel, isPending = false, titleClassName = 'max-w-60 truncate', + showOnMobile = false, }: TitleEditorPopoverProps) { const [editTitle, setEditTitle] = useState(title); @@ -47,7 +49,10 @@ export function TitleEditorPopover({ );