Files
blackheart-website/src/components/ui/FloatingHearts.tsx
diana.dolgolyova d5afaf92ba refactor: centralize gold tokens, extract sub-components, clean up unused code
- Replace hardcoded hex colors with gold/gold-light/gold-dark Tailwind tokens
- Extract Schedule into DayCard, ScheduleFilters, MobileSchedule sub-components
- Extract Team into TeamCarousel, TeamMemberInfo sub-components
- Add UI_CONFIG for centralized magic numbers (timings, thresholds)
- Add reusable IconBadge component, simplify Contact section
- Convert Pricing clickable divs to semantic buttons for a11y
- Remove unused SocialLinks, btn-outline, btn-ghost, nav-link CSS classes
- Fix React setState-during-render error in TeamCarousel (deferred update pattern)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 14:57:39 +03:00

52 lines
1.2 KiB
TypeScript

"use client";
import { useEffect, useState } from "react";
import { UI_CONFIG } from "@/lib/config";
interface Heart {
id: number;
left: number;
size: number;
delay: number;
duration: number;
opacity: number;
}
export function FloatingHearts() {
const [hearts, setHearts] = useState<Heart[]>([]);
useEffect(() => {
const generated: Heart[] = Array.from({ length: UI_CONFIG.team.floatingHeartsCount }, (_, i) => ({
id: i,
left: Math.random() * 100,
size: 8 + Math.random() * 16,
delay: Math.random() * 10,
duration: 10 + Math.random() * 15,
opacity: 0.03 + Math.random() * 0.08,
}));
setHearts(generated);
}, []);
if (hearts.length === 0) return null;
return (
<div className="pointer-events-none absolute inset-0 overflow-hidden">
{hearts.map((heart) => (
<div
key={heart.id}
className="absolute text-gold"
style={{
left: `${heart.left}%`,
bottom: "-20px",
fontSize: `${heart.size}px`,
opacity: heart.opacity,
animation: `heart-float ${heart.duration}s ease-in ${heart.delay}s infinite`,
}}
>
&#9829;
</div>
))}
</div>
);
}