diff --git a/client/src/App.tsx b/client/src/App.tsx index 710d79c..d39ae37 100644 --- a/client/src/App.tsx +++ b/client/src/App.tsx @@ -4,6 +4,7 @@ import { WorkSpace } from "@features/workSpace/WorkSpace"; import { useErrorStore } from "@stores/useErrorStore"; import { useUserInfo } from "@stores/useUserStore"; import { useSocketStore } from "./stores/useSocketStore"; +import { BackgroundImage } from "./components/backgroundImage/BackgroundImage"; const App = () => { // TODO 라우터, react query 설정 @@ -25,6 +26,7 @@ const App = () => { return ( <> + {isErrorModalOpen && } diff --git a/client/src/components/backgroundImage/BackgroundImage.tsx b/client/src/components/backgroundImage/BackgroundImage.tsx new file mode 100644 index 0000000..6b80770 --- /dev/null +++ b/client/src/components/backgroundImage/BackgroundImage.tsx @@ -0,0 +1,28 @@ +import backgroundPNG from "@assets/images/background.png"; +import backgroundWEBP from "@assets/images/background.webp"; +import backgroundAVIF from "@assets/images/background.avif"; + +export const BackgroundImage = () => ( + + + + background + +); diff --git a/client/src/components/sidebar/components/menuButton/MenuButton.tsx b/client/src/components/sidebar/components/menuButton/MenuButton.tsx index 5601b70..7b38834 100644 --- a/client/src/components/sidebar/components/menuButton/MenuButton.tsx +++ b/client/src/components/sidebar/components/menuButton/MenuButton.tsx @@ -111,7 +111,7 @@ export const MenuButton = () => { onClick={handleMenuClick} data-onboarding="menu-button" > - + { diff --git a/client/src/features/workSpace/hooks/usePagesManage.ts b/client/src/features/workSpace/hooks/usePagesManage.ts index 07e1f28..9977da5 100644 --- a/client/src/features/workSpace/hooks/usePagesManage.ts +++ b/client/src/features/workSpace/hooks/usePagesManage.ts @@ -10,6 +10,7 @@ import { useEffect, useState, useRef, useCallback } from "react"; import { useSocketStore } from "@src/stores/useSocketStore"; import { useToastStore } from "@src/stores/useToastStore"; import { Page } from "@src/types/page"; +import { PAGE, SIDE_BAR } from "@src/constants/size"; const PAGE_OFFSET = 60; @@ -86,6 +87,42 @@ export const usePagesManage = (workspace: WorkSpace | null, clientId: number | n return Math.max(0, ...pages.map((page) => page.zIndex)) + 1; }; + const adjustPagePosition = (page: Page) => { + const PADDING = 20; + const maxWidth = window.innerWidth - SIDE_BAR.WIDTH - PADDING * 2; + const maxHeight = window.innerHeight - PADDING * 2; + + // 페이지가 최소 크기보다 작아지지 않도록 보장 + const width = PAGE.WIDTH; + const height = PAGE.HEIGHT; + + // 새로운 위치 계산 + let newX = page.x; + let newY = page.y; + + // 오른쪽 경계를 벗어나는 경우 + if (newX + width > maxWidth) { + newX = Math.max(0, maxWidth - width); + } + + // 왼쪽 경계를 벗어나는 경우 + if (newX < 0) { + newX = 0; + } + + // 아래쪽 경계를 벗어나는 경우 + if (newY + height > maxHeight) { + newY = Math.max(0, maxHeight - height); + } + + // 위쪽 경계를 벗어나는 경우 + if (newY < 0) { + newY = 0; + } + + return { x: newX, y: newY }; + }; + const fetchPage = () => { const operation = { type: "pageCreate", @@ -170,11 +207,25 @@ export const usePagesManage = (workspace: WorkSpace | null, clientId: number | n // 페이지를 활성화하고 표시 setPages((prevPages) => - prevPages.map((p) => - p.id === pageId - ? { ...p, isActive: true, isVisible: true, zIndex: getZIndex() } - : { ...p, isActive: false }, - ), + prevPages.map((p) => { + if (p.id === pageId) { + // isLoaded가 false일 때만 위치 재조정 + if (!p.isLoaded) { + const adjustedPosition = adjustPagePosition(p); + return { + ...p, + isActive: true, + isVisible: true, + zIndex: getZIndex(), + x: adjustedPosition.x, + y: adjustedPosition.y, + }; + } + // 이미 로드된 페이지는 위치 유지 + return { ...p, isActive: true, isVisible: true, zIndex: getZIndex() }; + } + return { ...p, isActive: false }; + }), ); setTimeout(() => { diff --git a/client/src/styles/global.ts b/client/src/styles/global.ts index 07d3397..69bed68 100644 --- a/client/src/styles/global.ts +++ b/client/src/styles/global.ts @@ -9,17 +9,6 @@ export const globalStyles = defineGlobalStyles({ }, "html, body": { - // 기본 이미지 - backgroundImage: 'url("./assets/images/background.jpg")', - // WebP 지원 - "@supports (background-image: url('./assets/images/background.webp'))": { - backgroundImage: 'url("./assets/images/background.webp")', - }, - // AVIF 지원 - "@supports (background-image: url('./assets/images/background.avif'))": { - backgroundImage: 'url("./assets/images/background.avif")', - }, - backgroundSize: "cover", fontFamily: "Pretendard, sans-serif", boxSizing: "border-box", },