Merge version_7_1776693037983 into main #6

Merged
bender merged 4 commits from version_7_1776693037983 into main 2026-04-20 13:56:18 +00:00
5 changed files with 164 additions and 43 deletions

View File

@@ -5,7 +5,7 @@ import FeaturesLabeledList from '@/components/sections/features/FeaturesLabeledL
import FooterSimpleCard from '@/components/sections/footer/FooterSimpleCard';
import HeroBrand from '@/components/sections/hero/HeroBrand';
import MetricsMinimalCards from '@/components/sections/metrics/MetricsMinimalCards';
import NavbarCentered from '@/components/ui/NavbarCentered';
import FloatingNav from '@/components/ui/FloatingNav';
import PricingLayeredCards from '@/components/sections/pricing/PricingLayeredCards';
import SocialProofMarquee from '@/components/sections/social-proof/SocialProofMarquee';
import TestimonialRatingCards from '@/components/sections/testimonial/TestimonialRatingCards';
@@ -14,33 +14,32 @@ import HeroTrustedBy from '@/components/ui/HeroTrustedBy';
export default function App() {
return (
<>
<div id="nav" data-section="nav">
<NavbarCentered
logo="TOKYO-MARKETING"
navItems={[
{
name: "About",
href: "#about",
},
{
name: "Services",
href: "#services",
},
{
name: "Pricing",
href: "#pricing",
},
{
name: "Contact",
href: "#contact",
},
]}
ctaButton={{
text: "Get Started",
href: "#contact",
}}
/>
</div>
<FloatingNav
logo="TOKYO-MARKETING"
navItems={[
{
name: 'About',
href: '#about',
},
{
name: 'Services',
href: '#services',
},
{
name: 'Pricing',
href: '#pricing',
},
{
name: 'Contact',
href: '#contact',
},
]}
ctaButton={{
text: 'Get Started',
href: '#contact',
}}
/>
<div id="hero" data-section="hero">
<HeroBrand

View File

@@ -0,0 +1,85 @@
import { useState, useEffect } from 'react';
import { useButtonClick } from '@/hooks/useButtonClick';
import { motion, AnimatePresence } from 'framer-motion';
type NavItem = {
name: string;
href: string;
};
type CtaButton = {
text: string;
href: string;
};
type FloatingNavProps = {
logo: string;
navItems: NavItem[];
ctaButton: CtaButton;
};
const NavLink = ({ name, href }: { name: string; href: string }) => {
const handleClick = useButtonClick(href);
return (
<button
onClick={handleClick}
className="text-sm font-medium text-foreground/80 hover:text-foreground transition-colors"
>
{name}
</button>
);
};
export default function FloatingNav({ logo, navItems, ctaButton }: FloatingNavProps) {
const [visible, setVisible] = useState(true);
const [lastScrollY, setLastScrollY] = useState(0);
const controlNavbar = () => {
if (typeof window !== 'undefined') {
if (window.scrollY > lastScrollY && window.scrollY > 100) {
setVisible(false);
} else {
setVisible(true);
}
setLastScrollY(window.scrollY);
}
};
useEffect(() => {
window.addEventListener('scroll', controlNavbar);
return () => {
window.removeEventListener('scroll', controlNavbar);
};
}, [lastScrollY]);
const CtaButtonHandler = useButtonClick(ctaButton.href);
return (
<AnimatePresence>
{visible && (
<motion.nav
initial={{ y: -100, opacity: 0 }}
animate={{ y: 0, opacity: 1 }}
exit={{ y: -100, opacity: 0 }}
transition={{ duration: 0.3, ease: 'easeInOut' }}
className="fixed top-6 left-1/2 -translate-x-1/2 z-50"
>
<div className="flex items-center justify-between gap-8 px-4 py-2 border rounded-full border-accent bg-card/80 backdrop-blur-lg">
<span className="text-lg font-bold text-foreground">{logo}</span>
<div className="hidden md:flex items-center gap-6">
{navItems.map((item) => (
<NavLink key={item.name} name={item.name} href={item.href} />
))}
</div>
<button
onClick={CtaButtonHandler}
className="primary-button px-4 py-2 text-sm font-medium rounded-full text-primary-cta-text"
>
{ctaButton.text}
</button>
</div>
</motion.nav>
)}
</AnimatePresence>
);
}

View File

@@ -1,23 +1,27 @@
const avatars = [
const avatarUrls = [
"https://webuild-dev.s3.eu-north-1.amazonaws.com/users/user_3AM9hp4M6eDzEwMxDU5gYArbELf/professional-headshot-of-a-japanese-male-1776690846328-d57aee35.png",
"https://webuild-dev.s3.eu-north-1.amazonaws.com/users/user_3AM9hp4M6eDzEwMxDU5gYArbELf/professional-headshot-of-a-female-busine-1776690854791-b9f5ea1f.png",
"https://webuild-dev.s3.eu-north-1.amazonaws.com/users/user_3AM9hp4M6eDzEwMxDU5gYArbELf/professional-headshot-of-a-young-japanes-1776690864881-b5f3321c.png",
"https://webuild-dev.s3.eu-north-1.amazonaws.com/users/user_3AM9hp4M6eDzEwMxDU5gYArbELf/professional-headshot-of-a-japanese-fema-1776690873867-edc6ebaa.png",
"https://webuild-dev.s3.eu-north-1.amazonaws.com/users/user_3AM9hp4M6eDzEwMxDU5gYArbELf/professional-headshot-of-a-middle-aged-m-1776690883590-fe8d0a50.png",
];
const HeroTrustedBy = () => {
return (
<div className="glassmorphic-tag">
<div className="hero-trusted-by">
<div className="avatar-stack">
{avatars.map((src, index) => (
{avatarUrls.map((url, index) => (
<img
key={index}
src={src}
src={url}
alt={`Trusted by user ${index + 1}`}
className="avatar"
/>
))}
</div>
<span>Trusted by over 2000 agencies</span>
<span className="text-sm">
Trusted by over 2000 agencies
</span>
</div>
);
};

View File

@@ -16,7 +16,7 @@
--background-accent: #222222;
/* @layout/border-radius/rounded */
--radius: 0.25rem;
--radius: 0.2rem;
/* @layout/content-width/medium */
--width-content-width: clamp(40rem, 80vw, 100rem);
@@ -141,15 +141,6 @@ body {
min-height: 100vh;
overscroll-behavior: none;
overscroll-behavior-y: none;
padding-top: 5rem;
}
#nav {
position: fixed;
top: 0;
width: 100%;
z-index: 1000;
background-color: var(--background);
}
h1,
@@ -188,6 +179,8 @@ h6 {
.primary-button,
.secondary-button {
position: relative;
overflow: hidden;
transition: transform 0.3s ease-out, box-shadow 0.3s ease-out;
}
@@ -208,6 +201,18 @@ h6 {
0 0 8px var(--secondary-cta-text);
}
.hero-trusted-by {
display: inline-flex;
align-items: center;
gap: 0.75rem;
padding: 0.5rem 1rem 0.5rem 0.5rem;
background-color: rgba(255, 255, 255, 0.1);
border: 1px solid rgba(255, 255, 255, 0.2);
border-radius: 9999px;
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
}
.glassmorphic-tag {
display: inline-flex;
align-items: center;

View File

@@ -200,3 +200,31 @@
transform: translateY(-2px) scale(1.02);
}
}
@keyframes shimmer-effect {
from {
transform: translateX(-100%) skewX(-25deg);
}
to {
transform: translateX(200%) skewX(-25deg);
}
}
.btn-hover-shimmer::after,
.primary-button::after,
.secondary-button::after {
content: "";
position: absolute;
top: 0;
left: 0;
width: 50%;
height: 100%;
background: linear-gradient(to right, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0) 100%);
transform: translateX(-100%);
}
.btn-hover-shimmer:hover::after,
.primary-button:hover::after,
.secondary-button:hover::after {
animation: shimmer-effect 0.8s ease-in-out;
}