diff --git a/app/contribute/contribute-view.tsx b/app/contribute/contribute-view.tsx index 43351be6..aac09d50 100644 --- a/app/contribute/contribute-view.tsx +++ b/app/contribute/contribute-view.tsx @@ -5,6 +5,7 @@ import { ContributeHero } from "@/components/contribute/contribute-hero"; import { ContributionCard } from "@/components/contribute/contribution-card"; import { ContributionEmptyState } from "@/components/contribute/contribution-empty-state"; import { ContributionHint } from "@/components/contribute/contribution-hint"; +import { useReducedMotion } from "@/hooks/use-reduced-motion"; const containerVariants = { hidden: { opacity: 0 }, @@ -27,6 +28,8 @@ export interface ContributionCardData { } export default function ContributeView({ cards }: { cards: ContributionCardData[] }) { + const prefersReducedMotion = useReducedMotion(); + return (
{/* Background decoration */} @@ -40,10 +43,10 @@ export default function ContributeView({ cards }: { cards: ContributionCardData[
{cards.length > 0 ? ( {cards.map((card, index) => ( {/* Tilted Content */} -
+
{/* Inner blur container */} -
+
{/* Auto-scrolling animation container */} -
+
{/* Duplicate content for seamless loop */} @@ -290,6 +290,11 @@ export default function EternalCombatPage() { .animate-scroll-y:hover { animation-play-state: paused; } + @media (prefers-reduced-motion: reduce) { + .animate-scroll-y { + animation: none; + } + } `}
diff --git a/app/projects/eternalcore/eternal-showcase.tsx b/app/projects/eternalcore/eternal-showcase.tsx index ba7f57cc..2ff9fc51 100644 --- a/app/projects/eternalcore/eternal-showcase.tsx +++ b/app/projects/eternalcore/eternal-showcase.tsx @@ -6,6 +6,7 @@ import Image from "next/image"; import { useEffect, useState } from "react"; import { createPortal } from "react-dom"; import { FadeIn } from "@/components/ui/motion/motion-components"; +import { useReducedMotion } from "@/hooks/use-reduced-motion"; const marqueeItems = [ // Row 1: Essentials & Chat @@ -124,30 +125,41 @@ const InfiniteMarquee = ({ speed?: number; onItemClick: (item: (typeof marqueeItems)[0]) => void; }) => { + const prefersReducedMotion = useReducedMotion(); + let marqueeX: "0%" | ["0%", "-50%"] | ["-50%", "0%"]; + + if (prefersReducedMotion) { + marqueeX = "0%"; + } else if (direction === "left") { + marqueeX = ["0%", "-50%"]; + } else { + marqueeX = ["-50%", "0%"]; + } + return (
{[...items, ...items].map((item, i) => ( onItemClick(item)} - whileHover={{ scale: 1.02 }} - whileTap={{ scale: 0.98 }} + whileHover={prefersReducedMotion ? undefined : { scale: 1.02 }} + whileTap={prefersReducedMotion ? undefined : { scale: 0.98 }} > {item.id} {/* Gradient Overlay & Content - Always visible on hover */} -
+
diff --git a/app/projects/eternalcore/page.tsx b/app/projects/eternalcore/page.tsx index fef6b8fd..ccc11bff 100644 --- a/app/projects/eternalcore/page.tsx +++ b/app/projects/eternalcore/page.tsx @@ -8,6 +8,7 @@ import { Button } from "@/components/ui/button"; import { Card } from "@/components/ui/card"; import { FacadePattern } from "@/components/ui/facade-pattern"; import { FadeIn, MotionSection, ScaleIn, SlideIn } from "@/components/ui/motion/motion-components"; +import { useReducedMotion } from "@/hooks/use-reduced-motion"; import { slideUp } from "@/lib/animations/variants"; import { ConfigPreview } from "./config-preview"; @@ -15,6 +16,7 @@ import { EternalShowcase } from "./eternal-showcase"; export default function EternalCorePage() { const targetRef = useRef(null); + const prefersReducedMotion = useReducedMotion(); const { scrollYProgress } = useScroll({ target: targetRef, offset: ["start start", "end start"], @@ -160,8 +162,12 @@ export default function EternalCorePage() { gradient: "from-blue-500/20 to-cyan-500/20", }, ].map((feature) => ( - - + +
@@ -242,9 +248,9 @@ export default function EternalCorePage() { {/* Content Container (Standard, non-tilted) */}
{/* Inner blur container */} -
+
{/* Auto-scrolling animation container */} -
+
{/* Duplicate content for seamless loop */} @@ -267,6 +273,11 @@ export default function EternalCorePage() { .animate-scroll-y:hover { animation-play-state: paused; } + @media (prefers-reduced-motion: reduce) { + .animate-scroll-y { + animation: none; + } + } `}
diff --git a/components/builds/build-table.tsx b/components/builds/build-table.tsx index 0a969e49..6b7659ff 100644 --- a/components/builds/build-table.tsx +++ b/components/builds/build-table.tsx @@ -26,7 +26,9 @@ export function BuildTable({ className="flex flex-col items-center justify-center gap-4 py-32 text-gray-400" > -

Fetching builds for {project.name}…

+

+ Fetching builds for {project.name}… +

) : (
diff --git a/components/contribute/contribution-card.tsx b/components/contribute/contribution-card.tsx index ca1d4198..8cd26e29 100644 --- a/components/contribute/contribution-card.tsx +++ b/components/contribute/contribution-card.tsx @@ -4,6 +4,7 @@ import { m } from "framer-motion"; import { LucideIcon } from "@/components/lucide-icon"; import { Button } from "@/components/ui/button"; import { Card } from "@/components/ui/card"; +import { useReducedMotion } from "@/hooks/use-reduced-motion"; const itemVariants = { hidden: { y: 20, opacity: 0 }, @@ -35,9 +36,10 @@ export function ContributionCard({ color, }: ContributionCardProps) { const external = href.startsWith("http"); + const prefersReducedMotion = useReducedMotion(); return ( - +
diff --git a/components/docs/content/docs-header.tsx b/components/docs/content/docs-header.tsx index 5d8dc661..9c90a963 100644 --- a/components/docs/content/docs-header.tsx +++ b/components/docs/content/docs-header.tsx @@ -33,7 +33,7 @@ export function DocsHeader({ category, title, description, icon, actions }: DocH transition={{ delay: prefersReducedMotion ? 0 : 0.1 }} > - + {category} diff --git a/components/docs/content/docs-navigation.tsx b/components/docs/content/docs-navigation.tsx index ef68cabd..9ddd186b 100644 --- a/components/docs/content/docs-navigation.tsx +++ b/components/docs/content/docs-navigation.tsx @@ -28,7 +28,7 @@ export function DocsNavigation({ prev, next }: DocsNavigationProps) { crypto.randomUUID()); export function LoadingFallback() { return (
(