mirror of
https://github.com/R0m1k3/PleinR.git
synced 2026-10-11 17:27:54 +02:00
Accueil: etoiles flottantes + animations forcees
- Retire le kill-switch prefers-reduced-motion (* { animation:none }) qui
coupait toutes les animations : etoiles, flottement du logo, apparitions
au defilement ne bougeaient pas. Animations desormais toujours actives.
- Nouveau StarField : champ d'etoiles qui scintillent ET derivent
(keyframe plr-drift via propriete translate, cumulee au scintillement),
place dans le hero. Contenu du hero passe au-dessus (z-index).
- Carrousel : fondu force (n'est plus desactive sous reduced-motion).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
1 parent
a4f03a21aa
commit
c15213c131
4 files changed
+86
-25
No files matched your search
+26
-13
@@ -88,9 +88,18 @@ button {
|
|||||||
transform: translateY(-14px) rotate(0.6deg);
|
transform: translateY(-14px) rotate(0.6deg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@media (prefers-reduced-motion: reduce) {
|
/* Dérive lente des étoiles. Utilise la propriété `translate` (indépendante de
|
||||||
* {
|
`transform`) pour se cumuler avec le scintillement `plr-twinkle`. */
|
||||||
animation: none !important;
|
@keyframes plr-drift {
|
||||||
|
0%,
|
||||||
|
100% {
|
||||||
|
translate: 0 0;
|
||||||
|
}
|
||||||
|
33% {
|
||||||
|
translate: 12px -18px;
|
||||||
|
}
|
||||||
|
66% {
|
||||||
|
translate: -10px 10px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -98,6 +107,20 @@ button {
|
|||||||
clip-path: polygon(50% 0, 60% 40%, 100% 50%, 60% 60%, 50% 100%, 40% 60%, 0 50%, 40% 40%);
|
clip-path: polygon(50% 0, 60% 40%, 100% 50%, 60% 60%, 50% 100%, 40% 60%, 0 50%, 40% 40%);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ---- Champ d'étoiles flottantes ---- */
|
||||||
|
.starfield {
|
||||||
|
position: absolute;
|
||||||
|
inset: 0;
|
||||||
|
overflow: hidden;
|
||||||
|
pointer-events: none;
|
||||||
|
z-index: 0;
|
||||||
|
}
|
||||||
|
.starfield .star {
|
||||||
|
position: absolute;
|
||||||
|
animation: plr-twinkle var(--tw, 3.2s) ease-in-out infinite,
|
||||||
|
plr-drift var(--dr, 9s) ease-in-out infinite;
|
||||||
|
}
|
||||||
|
|
||||||
/* ---- Scroll-reveal entrance animations ---- */
|
/* ---- Scroll-reveal entrance animations ---- */
|
||||||
@keyframes plr-fade-up {
|
@keyframes plr-fade-up {
|
||||||
from {
|
from {
|
||||||
@@ -134,16 +157,6 @@ button {
|
|||||||
.reveal-stagger.is-visible > *:nth-child(8) { animation-delay: 0.46s; }
|
.reveal-stagger.is-visible > *:nth-child(8) { animation-delay: 0.46s; }
|
||||||
.reveal-stagger.is-visible > *:nth-child(n + 9) { animation-delay: 0.52s; }
|
.reveal-stagger.is-visible > *:nth-child(n + 9) { animation-delay: 0.52s; }
|
||||||
|
|
||||||
@media (prefers-reduced-motion: reduce) {
|
|
||||||
.reveal,
|
|
||||||
.reveal-stagger > * {
|
|
||||||
opacity: 1 !important;
|
|
||||||
}
|
|
||||||
.reveal.is-visible,
|
|
||||||
.reveal-stagger.is-visible > * {
|
|
||||||
animation: none !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.twinkle {
|
.twinkle {
|
||||||
animation: plr-twinkle 3.2s ease-in-out infinite;
|
animation: plr-twinkle 3.2s ease-in-out infinite;
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-6
@@ -5,6 +5,7 @@ import { SiteHeader } from "@/components/SiteHeader";
|
|||||||
import { SiteFooter } from "@/components/SiteFooter";
|
import { SiteFooter } from "@/components/SiteFooter";
|
||||||
import { MembershipModalButton } from "@/components/MembershipModalButton";
|
import { MembershipModalButton } from "@/components/MembershipModalButton";
|
||||||
import { MembersCarousel } from "@/components/MembersCarousel";
|
import { MembersCarousel } from "@/components/MembersCarousel";
|
||||||
|
import { StarField } from "@/components/StarField";
|
||||||
import { getLivePromotions, getRotatingActiveMembers } from "@/lib/queries";
|
import { getLivePromotions, getRotatingActiveMembers } from "@/lib/queries";
|
||||||
|
|
||||||
export const dynamic = "force-dynamic";
|
export const dynamic = "force-dynamic";
|
||||||
@@ -40,12 +41,9 @@ export default async function AccueilPage() {
|
|||||||
className="grid hero-grid"
|
className="grid hero-grid"
|
||||||
style={{ position: "relative", padding: "30px 0 50px", overflow: "hidden", alignItems: "center" }}
|
style={{ position: "relative", padding: "30px 0 50px", overflow: "hidden", alignItems: "center" }}
|
||||||
>
|
>
|
||||||
<Sparkle color="#E0A63C" size={22} style={{ top: 30, left: 20 }} duration={3.2} />
|
<StarField />
|
||||||
<Sparkle color="#6FB0C6" size={15} style={{ bottom: 64, left: 120 }} duration={2.6} delay={0.4} />
|
|
||||||
<Sparkle color="#9a6638" size={18} style={{ top: 40, right: 90 }} duration={3.8} delay={0.9} />
|
|
||||||
<Sparkle color="#2C6FB3" size={24} style={{ bottom: 80, right: 180 }} duration={3} delay={1.3} />
|
|
||||||
|
|
||||||
<div style={{ display: "flex", justifyContent: "center", alignItems: "center" }}>
|
<div style={{ position: "relative", zIndex: 1, display: "flex", justifyContent: "center", alignItems: "center" }}>
|
||||||
{/* eslint-disable-next-line @next/next/no-img-element */}
|
{/* eslint-disable-next-line @next/next/no-img-element */}
|
||||||
<img
|
<img
|
||||||
src="/assets/logo.png"
|
src="/assets/logo.png"
|
||||||
@@ -61,7 +59,7 @@ export default async function AccueilPage() {
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Reveal className="reveal">
|
<Reveal className="reveal" style={{ position: "relative", zIndex: 1 }}>
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
display: "inline-flex",
|
display: "inline-flex",
|
||||||
|
|||||||
@@ -89,14 +89,8 @@ export function MembersCarousel({ members }: { members: CarouselMember[] }) {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!canRotate) return;
|
if (!canRotate) return;
|
||||||
// Respecte la préférence de réduction d'animation.
|
|
||||||
const reduce = window.matchMedia?.("(prefers-reduced-motion: reduce)").matches;
|
|
||||||
|
|
||||||
const tick = setInterval(() => {
|
const tick = setInterval(() => {
|
||||||
if (reduce) {
|
|
||||||
setStart((s) => (s + VISIBLE) % total);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Disparition une à une, puis changement, puis réapparition une à une.
|
// Disparition une à une, puis changement, puis réapparition une à une.
|
||||||
setVisible(false);
|
setVisible(false);
|
||||||
const outMs = FADE_MS + STAGGER_MS * (VISIBLE - 1);
|
const outMs = FADE_MS + STAGGER_MS * (VISIBLE - 1);
|
||||||
|
|||||||
@@ -0,0 +1,56 @@
|
|||||||
|
import type { CSSProperties } from "react";
|
||||||
|
|
||||||
|
type Star = {
|
||||||
|
top: string;
|
||||||
|
left: string;
|
||||||
|
size: number;
|
||||||
|
color: string;
|
||||||
|
tw: number; // durée scintillement (s)
|
||||||
|
dr: number; // durée dérive (s)
|
||||||
|
delay: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Positions fixes (déterministes) pour éviter tout décalage d'hydratation.
|
||||||
|
const STARS: Star[] = [
|
||||||
|
{ top: "8%", left: "6%", size: 16, color: "#E0A63C", tw: 3.1, dr: 9, delay: 0 },
|
||||||
|
{ top: "18%", left: "22%", size: 10, color: "#6FB0C6", tw: 2.6, dr: 11, delay: 0.6 },
|
||||||
|
{ top: "12%", left: "44%", size: 13, color: "#9a6638", tw: 3.6, dr: 8, delay: 1.1 },
|
||||||
|
{ top: "26%", left: "63%", size: 11, color: "#2C6FB3", tw: 2.9, dr: 12, delay: 0.3 },
|
||||||
|
{ top: "9%", left: "82%", size: 18, color: "#E0A63C", tw: 3.3, dr: 10, delay: 0.9 },
|
||||||
|
{ top: "40%", left: "12%", size: 12, color: "#2C6FB3", tw: 3.0, dr: 13, delay: 1.4 },
|
||||||
|
{ top: "52%", left: "33%", size: 9, color: "#E0A63C", tw: 2.7, dr: 9.5, delay: 0.2 },
|
||||||
|
{ top: "46%", left: "72%", size: 14, color: "#6FB0C6", tw: 3.4, dr: 11.5, delay: 1.7 },
|
||||||
|
{ top: "62%", left: "52%", size: 10, color: "#9a6638", tw: 2.8, dr: 10.5, delay: 0.5 },
|
||||||
|
{ top: "70%", left: "18%", size: 13, color: "#E0A63C", tw: 3.2, dr: 12.5, delay: 1.0 },
|
||||||
|
{ top: "76%", left: "88%", size: 11, color: "#2C6FB3", tw: 3.5, dr: 8.5, delay: 0.7 },
|
||||||
|
{ top: "84%", left: "40%", size: 15, color: "#6FB0C6", tw: 3.0, dr: 11, delay: 1.3 },
|
||||||
|
{ top: "33%", left: "90%", size: 9, color: "#9a6638", tw: 2.5, dr: 9, delay: 0.4 },
|
||||||
|
{ top: "88%", left: "67%", size: 12, color: "#E0A63C", tw: 3.3, dr: 10, delay: 1.6 },
|
||||||
|
];
|
||||||
|
|
||||||
|
export function StarField({ density = 1, style }: { density?: number; style?: CSSProperties }) {
|
||||||
|
const stars = STARS.slice(0, Math.max(4, Math.round(STARS.length * density)));
|
||||||
|
return (
|
||||||
|
<div className="starfield" aria-hidden style={style}>
|
||||||
|
{stars.map((s, i) => (
|
||||||
|
<span
|
||||||
|
key={i}
|
||||||
|
className="sparkle star"
|
||||||
|
style={
|
||||||
|
{
|
||||||
|
top: s.top,
|
||||||
|
left: s.left,
|
||||||
|
width: s.size,
|
||||||
|
height: s.size,
|
||||||
|
background: s.color,
|
||||||
|
opacity: 0.7,
|
||||||
|
"--tw": `${s.tw}s`,
|
||||||
|
"--dr": `${s.dr}s`,
|
||||||
|
animationDelay: `${s.delay}s, ${s.delay}s`,
|
||||||
|
} as CSSProperties
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
Reference in new issue
Block a user