From e7839bd550cdedae5e638fb228e16665da6011d5 Mon Sep 17 00:00:00 2001 From: Bangdayeon Date: Tue, 11 Aug 2026 00:32:52 +0900 Subject: [PATCH] Design: modify mobile chat page design (#493) --- src/app/(route)/chat/[id]/ChatPage.tsx | 35 +++++++++++----- src/app/(route)/home/HomePage.tsx | 8 ++-- src/app/layout.tsx | 6 +++ src/components/basics/CardList/CardList.tsx | 5 ++- src/components/basics/Modal/Modal.style.ts | 2 +- src/components/basics/Tab/Tab.style.ts | 3 +- .../basics/Toast/ToastContainer.tsx | 3 +- .../layout/SideNavigation/SideNavigation.tsx | 4 +- .../LinkCardDetailPanel.style.ts | 4 +- .../LinkCardDetailPanel.tsx | 16 ++++++++ src/hooks/util/useKeyboardInset.ts | 40 +++++++++++++++++++ src/styles/globals.css | 25 ++++++++++++ 12 files changed, 129 insertions(+), 22 deletions(-) create mode 100644 src/hooks/util/useKeyboardInset.ts diff --git a/src/app/(route)/chat/[id]/ChatPage.tsx b/src/app/(route)/chat/[id]/ChatPage.tsx index 6fa1cdc8..7af6ed0b 100644 --- a/src/app/(route)/chat/[id]/ChatPage.tsx +++ b/src/app/(route)/chat/[id]/ChatPage.tsx @@ -10,6 +10,7 @@ import CopyButton from '@/components/wrappers/CopyButton'; import LinkCardDetailPanel from '@/components/wrappers/LinkCardDetailPanel/LinkCardDetailPanel'; import ReportModal from '@/components/wrappers/ReportModal/ReportModal'; import { useChatStream } from '@/hooks/server/Chats/useChatStream'; +import useKeyboardInset from '@/hooks/util/useKeyboardInset'; import { trackEvent, trackQueryFeedback } from '@/lib/client/analytics'; import { useModalStore } from '@/stores/modalStore'; import { showToast } from '@/stores/toastStore'; @@ -106,6 +107,8 @@ export default function Chat() { const [historyBootstrapped, setHistoryBootstrapped] = useState(false); const [showResponseBottomGap, setShowResponseBottomGap] = useState(false); const [responseBottomGapHeight, setResponseBottomGapHeight] = useState(0); + // iOS Safari에서 소프트 키보드가 가린 높이. Android는 dvh가 처리하므로 0이다. + const keyboardInset = useKeyboardInset(); const scrollRootRef = useRef(null); const latestUserMessageRef = useRef(null); @@ -456,7 +459,8 @@ export default function Chat() { const nextGapHeight = Math.max(root.clientHeight - latestUserMessage.offsetHeight, 0); setResponseBottomGapHeight(prev => (Math.abs(prev - nextGapHeight) < 1 ? prev : nextGapHeight)); scrollLatestQuestionToTop('auto'); - }, [messages, scrollLatestQuestionToTop, showResponseBottomGap]); + // keyboardInset이 바뀌면 스크롤 영역 높이도 바뀌므로 스페이서를 다시 계산한다. + }, [messages, scrollLatestQuestionToTop, showResponseBottomGap, keyboardInset]); useEffect(() => { const adjust = pendingScrollAdjustRef.current; @@ -654,12 +658,21 @@ export default function Chat() { }, [latestUserMessageIndex, messages]); return ( -
-
+
+
+ {/* 스크롤되는 메시지가 좌상단 고정 메뉴 버튼 뒤로 비치지 않도록 가리는 스크림 */} +