Skip to content

Commit 54e6b8d

Browse files
authored
Merge pull request #13 from solutionchallenge/setting/motion
add: frame-motion library
2 parents e509c6d + 35b3e43 commit 54e6b8d

File tree

10 files changed

+114
-20
lines changed

10 files changed

+114
-20
lines changed

package-lock.json

Lines changed: 41 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
"preview": "vite preview"
1111
},
1212
"dependencies": {
13+
"framer-motion": "^12.6.2",
1314
"react": "^19.0.0",
1415
"react-dom": "^19.0.0",
1516
"react-router-dom": "^7.4.1",

src/App.tsx

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { BrowserRouter, Route, Routes } from "react-router-dom";
1+
import { Route, Routes, useLocation } from "react-router-dom";
22
import OnboardingConcernPage from "./services/onboarding/additional/concern";
33
import OnboardingEmotionPage from "./services/onboarding/additional/emotion";
44
import OnboardingCompletePage from "./services/onboarding/additional/complete";
@@ -7,12 +7,17 @@ import NotFoundPage from "./services/error/404";
77
import OnboardingBasicPage from "./services/onboarding/basic";
88
import LoginPage from "./services/auth/login";
99
import Layout from "./layout.tsx";
10+
import { AnimatePresence } from "framer-motion";
11+
import { useNavigationDirection } from "./hooks/animation/useNavigationDirection.ts";
1012

1113
function App() {
14+
const location = useLocation();
15+
const direction = useNavigationDirection();
16+
1217
return (
13-
<BrowserRouter>
14-
<Routes>
15-
<Route element={<Layout />}>
18+
<AnimatePresence mode="wait">
19+
<Routes location={location} key={location.pathname}>
20+
<Route element={<Layout direction={direction} />}>
1621
<Route index element={<HomePage />} />
1722
<Route path="onboarding">
1823
<Route index path="*" element={<NotFoundPage />} />
@@ -28,7 +33,7 @@ function App() {
2833
</Route>
2934
<Route path="/login" element={<LoginPage />} />
3035
</Routes>
31-
</BrowserRouter>
36+
</AnimatePresence>
3237
);
3338
}
3439

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { useEffect, useRef, useState } from "react";
2+
import { useLocation } from "react-router-dom";
3+
4+
export function useNavigationDirection() {
5+
const location = useLocation();
6+
const [direction, setDirection] = useState<"forward" | "backward">("forward");
7+
const historyStack = useRef<string[]>([]);
8+
9+
useEffect(() => {
10+
const currentKey = location.key;
11+
12+
const currentIndex = historyStack.current.indexOf(currentKey);
13+
14+
if (currentIndex === -1) {
15+
// 새 페이지 → 앞으로 이동
16+
historyStack.current.push(currentKey);
17+
setDirection("forward");
18+
} else {
19+
// 기존 페이지 → 뒤로 이동
20+
historyStack.current = historyStack.current.slice(0, currentIndex + 1);
21+
setDirection("backward");
22+
}
23+
}, [location.key]);
24+
25+
return direction;
26+
}

src/hooks/onboarding/useOnboardingAdditional.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { useNavigate } from "react-router-dom";
22

3-
function useOnboardingAdditional() {
3+
export function useOnboardingAdditional() {
44
const navigate = useNavigate();
55

66
const goEmotionPage = () => {
@@ -14,11 +14,10 @@ function useOnboardingAdditional() {
1414
const goBackPage = () => {
1515
navigate(-1);
1616
};
17-
const goHome = () => {
17+
const goHomePage = () => {
1818
// Todo api 성공 이후 보내기
19-
navigate("/onboarding/additional/complete");
19+
navigate("/");
2020
};
2121

22-
return { goEmotionPage, goCompletePage, goHome, goBackPage };
22+
return { goEmotionPage, goCompletePage, goHomePage, goBackPage };
2323
}
24-
export default useOnboardingAdditional;

src/layout.tsx

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,40 @@ import GlobalNavigation from "./commons/navigation/GlobalNavigation";
22
import BottomNavigation from "./commons/navigation/BottomNavigation";
33
import { Navigate, Outlet, useLocation } from "react-router-dom";
44
import { useAuthStore } from "./store/auth";
5+
import { motion } from "framer-motion";
56

6-
function Layout() {
7+
function Layout({ direction }: { direction: "forward" | "backward" }) {
78
const { isLoggedIn } = useAuthStore();
89
const location = useLocation();
910

1011
if (!isLoggedIn) {
1112
return <Navigate to="/login" state={{ from: location }} replace />;
1213
}
1314

15+
const variants = {
16+
forward: {
17+
initial: { x: 100, opacity: 0 },
18+
animate: { x: 0, opacity: 1 },
19+
exit: { x: -100, opacity: 0 },
20+
},
21+
backward: {
22+
initial: { x: -100, opacity: 0 },
23+
animate: { x: 0, opacity: 1 },
24+
exit: { x: 100, opacity: 0 },
25+
},
26+
};
27+
1428
return (
1529
<>
1630
<GlobalNavigation />
17-
<Outlet />
31+
<motion.div
32+
initial={variants[direction].initial}
33+
animate={variants[direction].animate}
34+
exit={variants[direction].exit}
35+
transition={{ duration: 0.3 }}
36+
>
37+
<Outlet />
38+
</motion.div>
1839
<BottomNavigation />
1940
</>
2041
);

src/main.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { Profiler, StrictMode } from "react";
22
import { createRoot } from "react-dom/client";
33
import "./styles/reset.css";
44
import App from "./App.tsx";
5+
import { BrowserRouter } from "react-router-dom";
56

67
createRoot(document.getElementById("root")!).render(
78
<StrictMode>
@@ -25,7 +26,9 @@ createRoot(document.getElementById("root")!).render(
2526
);
2627
}}
2728
>
28-
<App />
29+
<BrowserRouter>
30+
<App />
31+
</BrowserRouter>
2932
</Profiler>
3033
</StrictMode>
3134
);

src/services/onboarding/additional/complete/index.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import OnboardingAdditionalLayout from "../layout.tsx";
22
import { useAuthStore } from "../../../../store/auth";
3-
import useOnboardingAdditional from "../../../../hooks/onboarding/useOnboardingAdditional.ts";
3+
import { useOnboardingAdditional } from "../../../../hooks/onboarding/useOnboardingAdditional.ts";
44

55
function OnboardingCompletePage() {
66
const { user } = useAuthStore();
7-
const { goHome } = useOnboardingAdditional();
7+
const { goHomePage } = useOnboardingAdditional();
88

99
return (
1010
<OnboardingAdditionalLayout
@@ -22,7 +22,7 @@ function OnboardingCompletePage() {
2222
}
2323
button={{
2424
name: "Start",
25-
onPress: goHome,
25+
onPress: goHomePage,
2626
}}
2727
>
2828
image

src/services/onboarding/additional/concern/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import {
55
CONCERN,
66
useOnboardingConcernStore,
77
} from "../../../../store/onboarding";
8-
import useOnboardingAdditional from "../../../../hooks/onboarding/useOnboardingAdditional.ts";
8+
import { useOnboardingAdditional } from "../../../../hooks/onboarding/useOnboardingAdditional.ts";
99

1010
function OnboardingConcernPage() {
1111
const { user } = useAuthStore();

src/services/onboarding/additional/emotion/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import OnboardingAdditionalLayout from "../layout.tsx";
22
import { useAuthStore } from "../../../../store/auth";
33
import { useOnboardingEmotionStore } from "../../../../store/onboarding";
4-
import useOnboardingAdditional from "../../../../hooks/onboarding/useOnboardingAdditional.ts";
4+
import { useOnboardingAdditional } from "../../../../hooks/onboarding/useOnboardingAdditional.ts";
55

66
function OnboardingEmotionPage() {
77
const { emotion } = useOnboardingEmotionStore();

0 commit comments

Comments
 (0)