diff --git a/src/shared/ui/ViewTransitionWrapper/index.ts b/src/shared/ui/ViewTransitionWrapper/index.ts
new file mode 100644
index 0000000..548b11f
--- /dev/null
+++ b/src/shared/ui/ViewTransitionWrapper/index.ts
@@ -0,0 +1 @@
+export { ViewTransitionWrapper } from './ui/ViewTransitionWrapper';
diff --git a/src/shared/ui/ViewTransitionWrapper/ui/ViewTransitionWrapper.test.tsx b/src/shared/ui/ViewTransitionWrapper/ui/ViewTransitionWrapper.test.tsx
new file mode 100644
index 0000000..b34b133
--- /dev/null
+++ b/src/shared/ui/ViewTransitionWrapper/ui/ViewTransitionWrapper.test.tsx
@@ -0,0 +1,33 @@
+import { render, screen } from '@testing-library/react';
+import { ViewTransitionWrapper } from './ViewTransitionWrapper';
+
+describe('ViewTransitionWrapper', () => {
+ it('renders children', () => {
+ render(
+
+ Hello
+ ,
+ );
+ expect(screen.getByText('Hello')).toBeInTheDocument();
+ });
+
+ it('renders multiple children', () => {
+ render(
+
+ First
+ Second
+ ,
+ );
+ expect(screen.getByText('First')).toBeInTheDocument();
+ expect(screen.getByText('Second')).toBeInTheDocument();
+ });
+
+ it('does not add an extra wrapper DOM element', () => {
+ const { container } = render(
+
+ Content
+ ,
+ );
+ expect(container.firstChild?.nodeName).toBe('P');
+ });
+});
diff --git a/src/shared/ui/ViewTransitionWrapper/ui/ViewTransitionWrapper.tsx b/src/shared/ui/ViewTransitionWrapper/ui/ViewTransitionWrapper.tsx
new file mode 100644
index 0000000..3aad3d4
--- /dev/null
+++ b/src/shared/ui/ViewTransitionWrapper/ui/ViewTransitionWrapper.tsx
@@ -0,0 +1,26 @@
+import { Fragment, type ReactNode, ViewTransition as VT } from 'react';
+
+/**
+ * VT is undefined in stable react-dom (test env / non-experimental builds).
+ * Fall back to Fragment so children render and the name prop is silently ignored.
+ */
+const Transition = (VT ?? Fragment) as typeof VT;
+
+type Props = {
+ /**
+ * Maps to the view-transition-name CSS property
+ */
+ name: string;
+ /**
+ * Content to animate
+ */
+ children: ReactNode;
+};
+
+/**
+ * Wraps children in React's ViewTransition when available,
+ * falling back to a Fragment in environments where ViewTransition is undefined.
+ */
+export function ViewTransitionWrapper({ name, children }: Props) {
+ return {children};
+}
diff --git a/src/shared/ui/index.ts b/src/shared/ui/index.ts
index 45bda75..6dc448b 100644
--- a/src/shared/ui/index.ts
+++ b/src/shared/ui/index.ts
@@ -10,3 +10,4 @@ export { RichText } from './RichText';
export type { ContainerSize, SectionBackground } from './Section';
export { Container, Section } from './Section';
export { TechStackBrick, TechStackGrid } from './TechStack';
+export { ViewTransitionWrapper } from './ViewTransitionWrapper';
diff --git a/tsconfig.json b/tsconfig.json
index d3c3b5c..de58819 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -18,7 +18,7 @@
"name": "next"
}
],
- "types": ["vitest/globals"],
+ "types": ["vitest/globals", "react/canary"],
"paths": {
"@/*": ["./*"],
"$shared/*": ["./src/shared/*"],