From 533574a8c6cab12742735a96d3fd08c7b2c0e981 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=A4=80=EC=98=81?= Date: Fri, 27 Mar 2026 21:16:39 +0900 Subject: [PATCH 1/3] =?UTF-8?q?refactor:=20=EC=B1=84=ED=8C=85=20viewport?= =?UTF-8?q?=20=ED=9B=85=20=EB=84=A4=EC=9D=B4=EB=B0=8D=20=EC=A0=95=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/Chat/ChatRoom.tsx | 4 +-- src/utils/hooks/useKeyboardHeight.ts | 42 ------------------------ src/utils/hooks/useViewportHeight.ts | 39 ---------------------- src/utils/hooks/useViewportHeightLock.ts | 20 +++++++++++ 4 files changed, 22 insertions(+), 83 deletions(-) delete mode 100644 src/utils/hooks/useKeyboardHeight.ts delete mode 100644 src/utils/hooks/useViewportHeight.ts create mode 100644 src/utils/hooks/useViewportHeightLock.ts diff --git a/src/pages/Chat/ChatRoom.tsx b/src/pages/Chat/ChatRoom.tsx index 48f008dd..61f539cd 100644 --- a/src/pages/Chat/ChatRoom.tsx +++ b/src/pages/Chat/ChatRoom.tsx @@ -3,7 +3,7 @@ import { useParams } from 'react-router-dom'; import type { ChatMessage } from '@/apis/chat/entity'; import SendArrowIcon from '@/assets/svg/chat-send-arrow.svg'; import LinkifiedText from '@/components/common/LinkifiedText'; -import useKeyboardHeight from '@/utils/hooks/useViewportHeight'; +import useViewportHeightLock from '@/utils/hooks/useViewportHeightLock'; import { cn } from '@/utils/ts/cn'; import useChat from './hooks/useChat'; import useChatRoomScroll from './hooks/useChatRoomScroll'; @@ -84,7 +84,7 @@ function ChatRoom() { useChat(Number(chatRoomId)); const [value, setValue] = useState(''); - useKeyboardHeight(); + useViewportHeightLock(); const textareaRef = useRef(null); const baseTextareaHeightRef = useRef(0); diff --git a/src/utils/hooks/useKeyboardHeight.ts b/src/utils/hooks/useKeyboardHeight.ts deleted file mode 100644 index 94910d2c..00000000 --- a/src/utils/hooks/useKeyboardHeight.ts +++ /dev/null @@ -1,42 +0,0 @@ -import { useEffect } from 'react'; - -function useKeyboardHeight() { - useEffect(() => { - const visualViewport = window.visualViewport; - const root = document.documentElement; - const body = document.body; - const prevBodyOverflow = body.style.overflow; - const prevBodyHeight = body.style.height; - const prevRootHeight = root.style.height; - - const setViewportHeight = () => { - const height = visualViewport?.height ?? window.innerHeight; - const offset = Math.max(0, visualViewport?.offsetTop ?? 0); - document.documentElement.style.setProperty('--viewport-height', `${height}px`); - document.documentElement.style.setProperty('--viewport-offset', `${offset}px`); - }; - - setViewportHeight(); - - body.style.overflow = 'hidden'; - body.style.height = 'var(--viewport-height)'; - root.style.height = 'var(--viewport-height)'; - - const options = { passive: true } as const; - - visualViewport?.addEventListener('resize', setViewportHeight, options); - visualViewport?.addEventListener('scroll', setViewportHeight, options); - window.addEventListener('resize', setViewportHeight, options); - - return () => { - visualViewport?.removeEventListener('resize', setViewportHeight); - visualViewport?.removeEventListener('scroll', setViewportHeight); - window.removeEventListener('resize', setViewportHeight); - body.style.overflow = prevBodyOverflow; - body.style.height = prevBodyHeight; - root.style.height = prevRootHeight; - }; - }, []); -} - -export default useKeyboardHeight; diff --git a/src/utils/hooks/useViewportHeight.ts b/src/utils/hooks/useViewportHeight.ts deleted file mode 100644 index 85e33af5..00000000 --- a/src/utils/hooks/useViewportHeight.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { useEffect } from 'react'; - -function useKeyboardHeight() { - useEffect(() => { - const visualViewport = window.visualViewport; - const root = document.documentElement; - const body = document.body; - const prevBodyOverflow = body.style.overflow; - const prevBodyHeight = body.style.height; - const prevRootHeight = root.style.height; - - const setViewportHeight = () => { - const height = visualViewport?.height ?? window.innerHeight; - const offset = Math.max(0, visualViewport?.offsetTop ?? 0); - document.documentElement.style.setProperty('--viewport-height', `${height}px`); - document.documentElement.style.setProperty('--viewport-offset', `${offset}px`); - }; - - setViewportHeight(); - - body.style.height = 'var(--viewport-height)'; - root.style.height = 'var(--viewport-height)'; - - visualViewport?.addEventListener('resize', setViewportHeight); - visualViewport?.addEventListener('scroll', setViewportHeight); - window.addEventListener('resize', setViewportHeight); - - return () => { - visualViewport?.removeEventListener('resize', setViewportHeight); - visualViewport?.removeEventListener('scroll', setViewportHeight); - window.removeEventListener('resize', setViewportHeight); - body.style.overflow = prevBodyOverflow; - body.style.height = prevBodyHeight; - root.style.height = prevRootHeight; - }; - }, []); -} - -export default useKeyboardHeight; diff --git a/src/utils/hooks/useViewportHeightLock.ts b/src/utils/hooks/useViewportHeightLock.ts new file mode 100644 index 00000000..4a9f40ed --- /dev/null +++ b/src/utils/hooks/useViewportHeightLock.ts @@ -0,0 +1,20 @@ +import { useEffect } from 'react'; + +function useViewportHeightLock() { + useEffect(() => { + const root = document.documentElement; + const body = document.body; + const prevBodyHeight = body.style.height; + const prevRootHeight = root.style.height; + + body.style.height = 'var(--viewport-height)'; + root.style.height = 'var(--viewport-height)'; + + return () => { + body.style.height = prevBodyHeight; + root.style.height = prevRootHeight; + }; + }, []); +} + +export default useViewportHeightLock; From 92a14c66b7dc9213408df20c8f8fdfbdc1f72b9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=A4=80=EC=98=81?= Date: Fri, 27 Mar 2026 21:29:29 +0900 Subject: [PATCH 2/3] =?UTF-8?q?refactor:=20viewport=20=EB=86=92=EC=9D=B4?= =?UTF-8?q?=20=EC=9E=A0=EA=B8=88=20=ED=9B=85=20=EC=A0=81=EC=9A=A9=20?= =?UTF-8?q?=EC=8B=9C=EC=A0=90=20=EC=A1=B0=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/utils/hooks/useViewportHeightLock.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/utils/hooks/useViewportHeightLock.ts b/src/utils/hooks/useViewportHeightLock.ts index 4a9f40ed..0bb8ebfc 100644 --- a/src/utils/hooks/useViewportHeightLock.ts +++ b/src/utils/hooks/useViewportHeightLock.ts @@ -1,7 +1,7 @@ -import { useEffect } from 'react'; +import { useLayoutEffect } from 'react'; function useViewportHeightLock() { - useEffect(() => { + useLayoutEffect(() => { const root = document.documentElement; const body = document.body; const prevBodyHeight = body.style.height; From e06e5b3582eed61f536eeffaf58e1323ec9b759c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EC=A4=80=EC=98=81?= Date: Fri, 27 Mar 2026 21:43:12 +0900 Subject: [PATCH 3/3] =?UTF-8?q?fix:=20=EC=B1=84=ED=8C=85=20=ED=99=94?= =?UTF-8?q?=EB=A9=B4=20=EC=8A=A4=ED=81=AC=EB=A1=A4=20=EC=9E=A0=EA=B8=88?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=ED=82=A4=EB=B3=B4=EB=93=9C=20=ED=9D=94?= =?UTF-8?q?=EB=93=A4=EB=A6=BC=20=EC=99=84=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/utils/hooks/useViewportHeightLock.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/utils/hooks/useViewportHeightLock.ts b/src/utils/hooks/useViewportHeightLock.ts index 0bb8ebfc..4e3c4828 100644 --- a/src/utils/hooks/useViewportHeightLock.ts +++ b/src/utils/hooks/useViewportHeightLock.ts @@ -4,13 +4,16 @@ function useViewportHeightLock() { useLayoutEffect(() => { const root = document.documentElement; const body = document.body; + const prevBodyOverflow = body.style.overflow; const prevBodyHeight = body.style.height; const prevRootHeight = root.style.height; + body.style.overflow = 'hidden'; body.style.height = 'var(--viewport-height)'; root.style.height = 'var(--viewport-height)'; return () => { + body.style.overflow = prevBodyOverflow; body.style.height = prevBodyHeight; root.style.height = prevRootHeight; };