The portfolio is a single-page application where every screen is a discrete route rendered by React Router v7. Navigation happens through the Persona 3-style menu UI as well as the keyboard, and Framer Motion’sDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/blairxu13/persona3-website/llms.txt
Use this file to discover all available pages before exploring further.
AnimatePresence listens for route changes so it can play cinematic transition animations between pages without any visible flicker or unmounted-component artifacts.
Provider hierarchy
BrowserRouter is mounted once in main.jsx, wrapping the entire React tree so that every component in the app can call hooks like useLocation and useNavigate freely.
App renders <AnimatedRoutes />, which is the only place that reads the current location and maps it to page components.
AnimatedRoutes and AnimatePresence
AnimatedRoutes uses useLocation() to capture the live location object and passes it down to both <Routes> and <AnimatePresence> as a stable key.
The
key={location.pathname} prop on <Routes> is essential. Without it, React treats the same component tree as a simple update rather than an unmount-remount cycle, so AnimatePresence never fires the exit animations. Changing the key whenever the pathname changes forces React to unmount the old route tree and mount the new one — which is exactly what AnimatePresence needs to detect in order to orchestrate enter and exit sequences.Route table
Each route is wrapped in a<PageTransition> that receives an optional variant prop controlling the cinematic wipe style. Routes that omit variant fall back to the default three-panel sweep.
| Path | Page component | PageTransition variant |
|---|---|---|
/ | MenuScreen | "default" |
/about | AboutMe | "about" |
/resume | ResumePage | "default" |
/socials | Socials | "socials" |
Programmatic navigation
The root menu screen renders<P3Menu> and passes it an onNavigate callback. When the user selects an item — either by pressing Enter on the keyboard or clicking a menu row — the callback fires useNavigate to push the target path onto the history stack.
P3Menu exposes onNavigate as a prop so the component itself stays decoupled from routing — it only knows about abstract page identifiers like "about" or "socials", not full URL paths.
Keyboard navigation per page
Every page registers its ownkeydown handler via useEffect so that the interactive elements feel like a real JRPG menu system. Handlers are cleaned up when the component unmounts.
| Page | Key | Action |
|---|---|---|
Menu (/) | ↑ / ↓ | Move selection up or down through menu items |
Menu (/) | Enter | Navigate to the selected page |
About Me (/about) | ↑ / ↓ | Move selection between character cards |
About Me (/about) | Enter or → | Reveal the detail panel for the active card |
About Me (/about) | ← | Collapse the detail panel (or go back if already collapsed) |
About Me (/about) | Escape / Backspace | Navigate back (navigate(-1)) |
Resume (/resume) | ↑ / ↓ | Move selection between resume sections |
Resume (/resume) | ← or Escape / Backspace | Navigate back |
Socials (/socials) — left panel | ↑ / ↓ | Move between social platform items |
Socials (/socials) — left panel | Enter | Open the platform link in a new tab |
Socials (/socials) — left panel | → | Switch focus to the right info-bar panel |
Socials (/socials) — left panel | ← | Navigate back (navigate(-1)) |
Socials (/socials) — right panel | ↑ / ↓ | Move between content bars |
Socials (/socials) — right panel | Enter | Open the selected bar’s link in a new tab |
Socials (/socials) — right panel | ← | Switch focus back to the left panel |
Socials (/socials) — any | Escape / Backspace | Navigate back |
"left" / "right" string so the same key events produce different actions depending on which panel is currently active.