feat: upgrade Next.js 12 to 15.5.9 and React 17 to 19#9
feat: upgrade Next.js 12 to 15.5.9 and React 17 to 19#9
Conversation
Major version upgrades: - Next.js: ^12.0.8 → ^15.5.9 - React: 17.0.2 → ^19.0.0 - React DOM: 17.0.2 → ^19.0.0 - TypeScript: ^4.9.5 → ^5.0.0 - framer-motion: ^6.2.1 → ^11.0.0 - ESLint: ^8.57.1 → ^9.0.0 Testing library updates for React 19 compatibility: - @testing-library/react: ^12.1.2 → ^16.0.0 - @testing-library/jest-dom: ^5.16.1 → ^6.0.0 - @testing-library/user-event: ^13.5.0 → ^14.0.0 - Removed deprecated @testing-library/react-hooks Breaking changes addressed: - AnimatePresence exitBeforeEnter → mode="wait" - Link component no longer requires <a> child - jest-dom import path change - renderHook moved to @testing-library/react All 139 tests passing.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
framer-motion v11 removed useViewportScroll in favor of useScroll. Updated Parallax.tsx, Compressor.tsx, and test mocks accordingly.
- Update Reveal component to use whileInView instead of manual useAnimation + useInView pattern for better React 19 compatibility - Add threshold option to useReveal hook for better intersection detection - Use next/legacy/image for Overview component (via codemod) The previous approach using useAnimation with react-intersection-observer had compatibility issues with framer-motion v11 and React 19.
- Lower threshold to 0 and add rootMargin for earlier trigger - Add 2-second fallback timer to ensure content is always visible - This fixes issues where IntersectionObserver may not trigger correctly on mobile devices
- Run next-lint-to-eslint-cli codemod - Update eslint.config.mjs to use FlatCompat for next/core-web-vitals - Add ignores for .next, node_modules, and coverage directories - Remove deprecated .eslintrc.json
- Remove useAnimation controls in favor of direct animate prop
- Simplify useReveal to return [ref, inView] instead of [ref, controls]
- Use declarative `animate={inView ? 'animate' : 'initial'}` pattern
- Increase rootMargin to 100px for earlier trigger on mobile
The previous approach using useAnimation().start() with useEffect
was causing issues on mobile devices. The new approach uses
framer-motion's declarative animation props which are more reliable.
Replace useReveal hook with native framer-motion whileInView prop for each feature item. This is more reliable as each item has its own viewport observer instead of sharing one observer for the container.
- Fix typo: text-themetext2 -> text-themeText2 (case sensitivity) - Simplify Reveal to use framer-motion whileInView instead of react-intersection-observer useInView hook - Remove dependency on external IntersectionObserver library for animation triggers The text-themetext2 typo caused feature content to have no text color. The Reveal component now uses the same whileInView pattern as Features for more consistent and reliable animation behavior.
Simplified Reveal and Features components to render content without animations to test if content visibility issue is animation-related.
Replace framer-motion whileInView with CSS transitions and react-intersection-observer for more reliable mobile behavior. Includes 2-second fallback timer to ensure content visibility.
Implement proper scroll-triggered animations using framer-motion's whileInView prop with viewport options per official documentation. Removed fallback timer that was causing premature content reveal.
There was a problem hiding this comment.
Pull request overview
This PR upgrades the application from Next.js 12 to 15.5.9, React 17 to 19, and updates related dependencies including framer-motion (v6 to v11), TypeScript (v4.9 to v5), and ESLint (v8 to v9). The changes address breaking changes in these major version upgrades while maintaining all 139 passing tests.
Key changes:
- Migrated from deprecated framer-motion APIs (
useViewportScroll→useScroll,AnimatePresence exitBeforeEnter→mode="wait") - Updated Next.js Link component to remove deprecated
<a>child pattern - Refactored animation hooks to use modern framer-motion patterns (simplified
useRevealhook andRevealcomponent)
Reviewed changes
Copilot reviewed 21 out of 23 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| package.json | Updated major dependencies including Next.js, React, framer-motion, TypeScript, and testing libraries |
| eslint.config.mjs | New ESLint v9 flat config format replacing legacy .eslintrc.json |
| .eslintrc.json | Removed legacy ESLint configuration file |
| src/hooks/useReveal.tsx | Simplified hook to return inView state instead of animation controls |
| src/components/shared/ux/Reveal.tsx | Refactored to use whileInView instead of manual animation controls |
| src/components/shared/ux/Parallax.tsx | Updated useViewportScroll to useScroll API |
| src/components/shared/ux/Compressor.tsx | Updated useViewportScroll to useScroll API |
| src/components/shared/ThemeToggle/ThemeToggle.tsx | Changed exitBeforeEnter to mode="wait" |
| src/components/NoteList/NoteList.tsx | Changed exitBeforeEnter to mode="wait" |
| src/components/ActionInput/ActionSymbols/ActionSymbols.tsx | Changed exitBeforeEnter to mode="wait" |
| pages/_app.tsx | Changed exitBeforeEnter to mode="wait" |
| src/context/globalContext.tsx | Removed deprecated child from Link components |
| src/components/Sidebar/SidebarHeader/Menu/Menu.tsx | Removed deprecated child from Link component |
| src/components/LoginPage/RegisterModal/RegisterModal.tsx | Removed deprecated child from Link component |
| src/components/LoginPage/LoginModal/LoginModal.tsx | Removed deprecated child from Link component |
| src/components/Layout/Footer/Footer.tsx | Removed deprecated child and moved className to Link |
| src/components/HelloPage/Overview/Overview.tsx | Updated to use next/legacy/image |
| src/components/HelloPage/Features/Features.tsx | Refactored to use new Reveal component pattern with staggered delays |
| src/context/tests/videoContext.test.tsx | Updated renderHook import from @testing-library/react |
| src/context/tests/noteContext.test.tsx | Updated renderHook import and removed waitForNextUpdate |
| src/test/setupTests.tsx | Updated jest-dom import path and useScroll mock |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| <Link href='/hello'> | ||
|
|
||
| <Heading2 className='text-center'>VideoNote</Heading2> |
There was a problem hiding this comment.
Empty line after Link opening tag creates orphaned whitespace. The Heading2 component should be directly nested within Link without line breaks.
| <Heading2 className='text-center'>VideoNote</Heading2> | ||
|
|
||
| </Link> |
There was a problem hiding this comment.
Empty line before Link closing tag creates orphaned whitespace. The closing tag should immediately follow the Heading2 component.
| <Link href='/hello'> | ||
|
|
||
| <Heading2 className='text-center'>VideoNote</Heading2> |
There was a problem hiding this comment.
Empty line after Link opening tag creates orphaned whitespace. The Heading2 component should be directly nested within Link without line breaks.
| <Heading2 className='text-center'>VideoNote</Heading2> | ||
|
|
||
| </Link> |
There was a problem hiding this comment.
Empty line before Link closing tag creates orphaned whitespace. The closing tag should immediately follow the Heading2 component.
Major version upgrades:
Testing library updates for React 19 compatibility:
Breaking changes addressed:
All 139 tests passing.