Anime la page d'accueil : apparitions au défilement + étoiles en mouvement

- Composant Reveal (IntersectionObserver) + keyframes CSS : sections et grilles
  apparaissent en fondu/glissement, cartes en cascade (stagger). Respecte
  prefers-reduced-motion + repli no-JS.
- Étoiles (sparkles) : l'animation twinkle inclut désormais une dérive
  (translation) pour un mouvement nettement visible.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XwfhYHzC9hQWPDnQ2p53GL
This commit is contained in:
Claude committed 2026-06-26 22:09:43 +00:00
1 parent 9c4bdbe09d
commit e2cf03c9f3
4 files changed
+150 -34

No files matched your search

+51
View File
@@ -0,0 +1,51 @@
"use client";
import { useEffect, useRef, useState, type CSSProperties, type ReactNode } from "react";
/**
* Wraps content and reveals it (via the `is-visible` class) when it scrolls into
* view. Pair with the `.reveal` or `.reveal-stagger` CSS classes. Respects
* prefers-reduced-motion (CSS forces content visible there).
*/
export function Reveal({
children,
className = "",
style,
id,
}: {
children: ReactNode;
className?: string;
style?: CSSProperties;
id?: string;
}) {
const ref = useRef<HTMLDivElement>(null);
const [visible, setVisible] = useState(false);
useEffect(() => {
const el = ref.current;
if (!el) return;
if (typeof IntersectionObserver === "undefined") {
setVisible(true);
return;
}
const obs = new IntersectionObserver(
(entries) => {
entries.forEach((e) => {
if (e.isIntersecting) {
setVisible(true);
obs.disconnect();
}
});
},
{ threshold: 0.12, rootMargin: "0px 0px -8% 0px" }
);
obs.observe(el);
return () => obs.disconnect();
}, []);
return (
<div ref={ref} id={id} className={`${className}${visible ? " is-visible" : ""}`} style={style}>
{children}
</div>
);
}