From d28343e22c6d47a13a229af65bae4cb4f7ad9568 Mon Sep 17 00:00:00 2001 From: Ilia Mashkov Date: Tue, 12 May 2026 16:10:50 +0300 Subject: [PATCH] feat: section open/close animations via ViewTransition and @starting-style Enable experimental.viewTransition in Next.js config. Wrap active section in ViewTransitionWrapper so the browser cross-fades between sections on navigation. Replace animate-fadeIn keyframe with @starting-style + CSS transition for the initial render enter animation. --- next.config.ts | 3 ++ .../SectionAccordion.test.tsx | 4 +- .../ui/SectionAccordion/SectionAccordion.tsx | 23 +++++----- src/shared/styles/theme.css | 44 ++++++++++++++++--- 4 files changed, 56 insertions(+), 18 deletions(-) diff --git a/next.config.ts b/next.config.ts index 9bbdb8d..da54b25 100644 --- a/next.config.ts +++ b/next.config.ts @@ -8,6 +8,9 @@ const isExport = process.env.STATIC_EXPORT === 'true'; const nextConfig: NextConfig = { ...(isExport ? { output: 'export' } : {}), images: { unoptimized: true }, + experimental: { + viewTransition: true, + }, }; export default nextConfig; diff --git a/src/entities/Section/ui/SectionAccordion/SectionAccordion.test.tsx b/src/entities/Section/ui/SectionAccordion/SectionAccordion.test.tsx index aa978cf..a5714b4 100644 --- a/src/entities/Section/ui/SectionAccordion/SectionAccordion.test.tsx +++ b/src/entities/Section/ui/SectionAccordion/SectionAccordion.test.tsx @@ -56,9 +56,9 @@ describe('SectionAccordion', () => { expect(screen.queryByRole('link')).not.toBeInTheDocument(); }); - it('content wrapper has animate-fadeIn class', () => { + it('content wrapper has section-content class', () => { const { container } = render(); - expect(container.querySelector('.animate-fadeIn')).toBeInTheDocument(); + expect(container.querySelector('.section-content')).toBeInTheDocument(); }); }); }); diff --git a/src/entities/Section/ui/SectionAccordion/SectionAccordion.tsx b/src/entities/Section/ui/SectionAccordion/SectionAccordion.tsx index 0d66504..4d06ff0 100644 --- a/src/entities/Section/ui/SectionAccordion/SectionAccordion.tsx +++ b/src/entities/Section/ui/SectionAccordion/SectionAccordion.tsx @@ -1,5 +1,6 @@ import Link from 'next/link'; import type { ReactNode } from 'react'; +import { ViewTransitionWrapper } from '$shared/ui'; interface SectionAccordionProps { /** @@ -35,17 +36,19 @@ export function SectionAccordion({ number, title, id, isActive, href, children } return (
{isActive ? ( -
-
-

- {number}. {title} -

+ +
+
+

+ {number}. {title} +

+
+
{children}
-
{children}
-
+ ) : (