3 Commits

2 changed files with 84 additions and 12 deletions

View File

@@ -28,27 +28,27 @@ export default function LandingPage() {
<div id="nav" data-section="nav">
<NavbarStyleFullscreen
navItems={[
{ name: "Home", id: "hero" },
{ name: "About", id: "about" },
{ name: "Products", id: "products" },
{ name: "Contact", id: "contact" },
{ name: "Order", id: "order" }
{ name: "Головна", id: "hero" },
{ name: "Про нас", id: "about" },
{ name: "Продукти", id: "products" },
{ name: "Контакти", id: "contact" },
{ name: "Замовити", id: "order" }
]}
brandName="Пекарня"
bottomLeftText="Authentic Ukrainian Bakery"
bottomLeftText="Автентична українська пекарня"
bottomRightText="hello@ukrainianbakery.local"
/>
</div>
<div id="hero" data-section="hero">
<HeroBillboard
title="Freshly Baked Ukrainian Traditions"
description="Discover authentic Ukrainian breads and pastries made daily with traditional recipes passed down through generations. Every loaf tells a story of heritage and craftsmanship."
title="Свіжовипечені українські традиції"
description="Відкрийте для себе автентичний український хліб та випічку, виготовлені щодня за традиційними рецептами, переданими з покоління в покоління. Кожна булка розповідає історію спадщини та майстерності."
background={{ variant: "plain" }}
tag="Est. 2005"
tag="Заснована 2005"
tagIcon={Sparkles}
buttons={[
{ text: "Order Now", href: "#order" },
{ text: "Замовити зараз", href: "#order" },
{ text: "Learn More", href: "#about" }
]}
imageSrc="https://img.b2bpic.net/free-photo/various-type-rustic-breads-box_23-2147975199.jpg"

View File

@@ -100,7 +100,7 @@ const HeroBillboard = ({
buttonClassName = "",
buttonTextClassName = "",
mediaWrapperClassName = "",
imageClassName = "",
imageClassName = "",
marqueeClassName = "",
marqueeItemClassName = "",
marqueeCardClassName = "",
@@ -110,6 +110,78 @@ const HeroBillboard = ({
}: HeroBillboardProps) => {
const { containerRef: mediaContainerRef } = useButtonAnimation({ animationType: mediaAnimation });
const handleButtonClick = (e: React.MouseEvent<HTMLButtonElement>, callback?: () => void) => {
const button = e.currentTarget;
const rect = button.getBoundingClientRect();
const x = rect.left + rect.width / 2;
const y = rect.top + rect.height / 2;
// Create particle explosion effect
for (let i = 0; i < 12; i++) {
const particle = document.createElement("div");
const angle = (i / 12) * Math.PI * 2;
const velocity = 5 + Math.random() * 5;
const vx = Math.cos(angle) * velocity;
const vy = Math.sin(angle) * velocity;
particle.style.position = "fixed";
particle.style.left = x + "px";
particle.style.top = y + "px";
particle.style.width = "8px";
particle.style.height = "8px";
particle.style.borderRadius = "50%";
particle.style.backgroundColor = getComputedStyle(button).backgroundColor || "#3b82f6";
particle.style.pointerEvents = "none";
particle.style.zIndex = "9999";
particle.style.boxShadow = "0 0 10px currentColor";
document.body.appendChild(particle);
let px = x;
let py = y;
let pvx = vx;
let pvy = vy;
const gravity = 0.2;
const friction = 0.98;
let life = 1;
const animate = () => {
pvx *= friction;
pvy *= friction;
pvy += gravity;
px += pvx;
py += pvy;
life -= 0.02;
particle.style.left = px + "px";
particle.style.top = py + "px";
particle.style.opacity = String(Math.max(0, life));
if (life > 0) {
requestAnimationFrame(animate);
} else {
particle.remove();
}
};
animate();
}
// Execute button action after animation starts
if (callback) {
setTimeout(callback, 100);
}
};
const enhancedButtons = buttons?.map((button) => ({
...button,
onClick: (e: React.MouseEvent<HTMLButtonElement> | null) => {
if (e && e.currentTarget) {
handleButtonClick(e, button.onClick as (() => void) | undefined);
}
},
}));
return (
<section
aria-label={ariaLabel}
@@ -123,7 +195,7 @@ const HeroBillboard = ({
tag={tag}
tagIcon={tagIcon}
tagAnimation={tagAnimation}
buttons={buttons}
buttons={enhancedButtons}
buttonAnimation={buttonAnimation}
avatars={avatars}
avatarText={avatarText}