b1c09aa53f
- ArticleCard: реальные обложки с fallback на детерминированный градиент по id статьи - HeroBackground: 3 анимированных blob'а + dot-grid + плавный fade к контенту - Stats компонент: 4 карточки — статьи / минуты чтения / токены / просмотры - Reveal компонент: IntersectionObserver-based fade-in при скролле, respect prefers-reduced-motion - next.config: rewrites /uploads/* → engine, чтобы картинки работали с относительными путями - На странице статьи — обложка над контентом
71 lines
2.6 KiB
JavaScript
71 lines
2.6 KiB
JavaScript
'use client';
|
|
|
|
export default function HeroBackground() {
|
|
return (
|
|
<div className="absolute inset-0 -z-10 overflow-hidden pointer-events-none">
|
|
{/* Mesh gradient — несколько размытых blob'ов с медленной анимацией */}
|
|
<div className="hero-blob hero-blob-1" />
|
|
<div className="hero-blob hero-blob-2" />
|
|
<div className="hero-blob hero-blob-3" />
|
|
|
|
{/* Сетка точек поверх — тонкий фоновый паттерн */}
|
|
<div className="hero-grid" />
|
|
|
|
{/* Виньетка к низу — плавный переход к контенту */}
|
|
<div className="hero-fade" />
|
|
|
|
<style jsx>{`
|
|
.hero-blob {
|
|
position: absolute;
|
|
border-radius: 50%;
|
|
filter: blur(80px);
|
|
opacity: 0.5;
|
|
}
|
|
.hero-blob-1 {
|
|
width: 520px; height: 520px;
|
|
background: radial-gradient(circle, rgba(16,185,129,0.6) 0%, transparent 70%);
|
|
top: -120px; right: -80px;
|
|
animation: blob1 22s ease-in-out infinite alternate;
|
|
}
|
|
.hero-blob-2 {
|
|
width: 420px; height: 420px;
|
|
background: radial-gradient(circle, rgba(20,184,166,0.5) 0%, transparent 70%);
|
|
top: 50px; left: -60px;
|
|
animation: blob2 28s ease-in-out infinite alternate;
|
|
}
|
|
.hero-blob-3 {
|
|
width: 360px; height: 360px;
|
|
background: radial-gradient(circle, rgba(132,204,22,0.35) 0%, transparent 70%);
|
|
top: 200px; left: 40%;
|
|
animation: blob3 25s ease-in-out infinite alternate;
|
|
}
|
|
@keyframes blob1 {
|
|
0% { transform: translate(0, 0) scale(1); }
|
|
100% { transform: translate(-60px, 80px) scale(1.1); }
|
|
}
|
|
@keyframes blob2 {
|
|
0% { transform: translate(0, 0) scale(1); }
|
|
100% { transform: translate(80px, -40px) scale(0.95); }
|
|
}
|
|
@keyframes blob3 {
|
|
0% { transform: translate(0, 0) scale(1); }
|
|
100% { transform: translate(-40px, -60px) scale(1.08); }
|
|
}
|
|
.hero-grid {
|
|
position: absolute;
|
|
inset: 0;
|
|
background-image: radial-gradient(circle, rgb(var(--ink) / 0.06) 1px, transparent 1px);
|
|
background-size: 24px 24px;
|
|
mask-image: radial-gradient(ellipse at center, black 30%, transparent 70%);
|
|
}
|
|
.hero-fade {
|
|
position: absolute;
|
|
left: 0; right: 0; bottom: 0;
|
|
height: 180px;
|
|
background: linear-gradient(to bottom, transparent, rgb(var(--bg)));
|
|
}
|
|
`}</style>
|
|
</div>
|
|
);
|
|
}
|