Merge version_2 into main #7
@@ -16,8 +16,7 @@ export const metadata: Metadata = {
|
||||
openGraph: {
|
||||
title: "Computer Club - Tech Community & Innovation Hub", description: "Join a vibrant community of tech enthusiasts. Access coding workshops, hackathons, networking events, and mentorship programs.", type: "website", siteName: "Computer Club", images: [
|
||||
{
|
||||
url: "http://img.b2bpic.net/free-photo/gradient-illuminated-neon-gaming-desk-setup-with-keyboard_23-2149529414.jpg", alt: "Computer Club Community"
|
||||
},
|
||||
url: "http://img.b2bpic.net/free-photo/gradient-illuminated-neon-gaming-desk-setup-with-keyboard_23-2149529414.jpg", alt: "Computer Club Community"},
|
||||
],
|
||||
},
|
||||
twitter: {
|
||||
@@ -33,9 +32,7 @@ export default function RootLayout({
|
||||
return (
|
||||
<html lang="en" suppressHydrationWarning>
|
||||
<ServiceWrapper>
|
||||
<body
|
||||
className={`${karla.variable} antialiased`}
|
||||
>
|
||||
<body className={`${karla.variable} antialiased`}>
|
||||
<Tag />
|
||||
{children}
|
||||
|
||||
|
||||
161
src/app/page.tsx
161
src/app/page.tsx
@@ -7,12 +7,53 @@ import MetricSplitMediaAbout from '@/components/sections/about/MetricSplitMediaA
|
||||
import FeatureBorderGlow from '@/components/sections/feature/featureBorderGlow/FeatureBorderGlow';
|
||||
import ProductCardFour from '@/components/sections/product/ProductCardFour';
|
||||
import TestimonialCardTwelve from '@/components/sections/testimonial/TestimonialCardTwelve';
|
||||
import TeamCardFiveFlip from '@/components/sections/team/TeamCardFiveFlip';
|
||||
import TeamCardFive from '@/components/sections/team/TeamCardFive';
|
||||
import FaqBase from '@/components/sections/faq/FaqBase';
|
||||
import FooterLogoEmphasis from '@/components/sections/footer/FooterLogoEmphasis';
|
||||
import { BookOpen, Calendar, Code, Info, Lightbulb, Rocket, Star, Trophy, Users, Zap, Github, Linkedin, Twitter } from "lucide-react";
|
||||
import { BookOpen, Calendar, Code, Info, Lightbulb, Rocket, Star, Trophy, Users, Zap } from "lucide-react";
|
||||
import React, { useState } from "react";
|
||||
|
||||
export default function ComputerClubPage() {
|
||||
const [flippedCards, setFlippedCards] = useState<{ [key: string]: boolean }>({});
|
||||
|
||||
const toggleFlip = (memberId: string) => {
|
||||
setFlippedCards((prev) => ({
|
||||
...prev,
|
||||
[memberId]: !prev[memberId],
|
||||
}));
|
||||
};
|
||||
|
||||
const teamMembers = [
|
||||
{
|
||||
id: "1", name: "Alex Johnson", role: "Founder & President", imageSrc: "http://img.b2bpic.net/free-photo/black-businessman-happy-expression_1194-2533.jpg", imageAlt: "Alex Johnson", social: [
|
||||
{ platform: "linkedin", url: "https://linkedin.com/in/alexjohnson" },
|
||||
{ platform: "twitter", url: "https://twitter.com/alexjohnson" },
|
||||
{ platform: "github", url: "https://github.com/alexjohnson" },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "2", name: "Jessica Lee", role: "Vice President", imageSrc: "http://img.b2bpic.net/free-photo/smiling-beautiful-middle-aged-business-woman_1262-3085.jpg?_wi=1", imageAlt: "Jessica Lee", social: [
|
||||
{ platform: "linkedin", url: "https://linkedin.com/in/jessicalee" },
|
||||
{ platform: "twitter", url: "https://twitter.com/jessicalee" },
|
||||
{ platform: "github", url: "https://github.com/jessicalee" },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "3", name: "David Kumar", role: "Technical Director", imageSrc: "http://img.b2bpic.net/free-photo/smiling-beautiful-middle-aged-business-woman_1262-3085.jpg?_wi=2", imageAlt: "David Kumar", social: [
|
||||
{ platform: "linkedin", url: "https://linkedin.com/in/davidkumar" },
|
||||
{ platform: "twitter", url: "https://twitter.com/davidkumar" },
|
||||
{ platform: "github", url: "https://github.com/davidkumar" },
|
||||
],
|
||||
},
|
||||
{
|
||||
id: "4", name: "Rachel Martinez", role: "Event Coordinator", imageSrc: "http://img.b2bpic.net/free-photo/smiling-beautiful-middle-aged-business-woman_1262-3085.jpg?_wi=3", imageAlt: "Rachel Martinez", social: [
|
||||
{ platform: "linkedin", url: "https://linkedin.com/in/rachelmartinez" },
|
||||
{ platform: "twitter", url: "https://twitter.com/rachelmartinez" },
|
||||
{ platform: "github", url: "https://github.com/rachelmartinez" },
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<ThemeProvider
|
||||
defaultButtonVariant="shift-hover"
|
||||
@@ -161,45 +202,83 @@ export default function ComputerClubPage() {
|
||||
</div>
|
||||
|
||||
<div id="team" data-section="team">
|
||||
<TeamCardFiveFlip
|
||||
title="Meet Our Leadership"
|
||||
description="Dedicated professionals driving innovation and community growth"
|
||||
tag="Leadership"
|
||||
tagIcon={Users}
|
||||
textboxLayout="default"
|
||||
animationType="slide-up"
|
||||
useInvertedBackground={false}
|
||||
team={[
|
||||
{
|
||||
id: "1", name: "Alex Johnson", role: "Founder & President", imageSrc: "http://img.b2bpic.net/free-photo/black-businessman-happy-expression_1194-2533.jpg", imageAlt: "Alex Johnson", socialLinks: [
|
||||
{ icon: Github, url: "https://github.com" },
|
||||
{ icon: Linkedin, url: "https://linkedin.com" },
|
||||
{ icon: Twitter, url: "https://twitter.com" }
|
||||
]
|
||||
},
|
||||
{
|
||||
id: "2", name: "Jessica Lee", role: "Vice President", imageSrc: "http://img.b2bpic.net/free-photo/smiling-beautiful-middle-aged-business-woman_1262-3085.jpg?_wi=1", imageAlt: "Jessica Lee", socialLinks: [
|
||||
{ icon: Github, url: "https://github.com" },
|
||||
{ icon: Linkedin, url: "https://linkedin.com" },
|
||||
{ icon: Twitter, url: "https://twitter.com" }
|
||||
]
|
||||
},
|
||||
{
|
||||
id: "3", name: "David Kumar", role: "Technical Director", imageSrc: "http://img.b2bpic.net/free-photo/smiling-beautiful-middle-aged-business-woman_1262-3085.jpg?_wi=2", imageAlt: "David Kumar", socialLinks: [
|
||||
{ icon: Github, url: "https://github.com" },
|
||||
{ icon: Linkedin, url: "https://linkedin.com" },
|
||||
{ icon: Twitter, url: "https://twitter.com" }
|
||||
]
|
||||
},
|
||||
{
|
||||
id: "4", name: "Rachel Martinez", role: "Event Coordinator", imageSrc: "http://img.b2bpic.net/free-photo/smiling-beautiful-middle-aged-business-woman_1262-3085.jpg?_wi=3", imageAlt: "Rachel Martinez", socialLinks: [
|
||||
{ icon: Github, url: "https://github.com" },
|
||||
{ icon: Linkedin, url: "https://linkedin.com" },
|
||||
{ icon: Twitter, url: "https://twitter.com" }
|
||||
]
|
||||
}
|
||||
]}
|
||||
/>
|
||||
<div className="py-20 md:py-28">
|
||||
<div className="w-content-width mx-auto">
|
||||
<div className="mb-16 md:mb-20">
|
||||
<div className="mb-6">
|
||||
<span className="inline-flex items-center gap-2 px-4 py-2 rounded-theme-capped bg-primary-cta/10 text-primary-cta text-sm font-medium">
|
||||
<Users className="w-4 h-4" />
|
||||
Leadership
|
||||
</span>
|
||||
</div>
|
||||
<h2 className="text-5xl md:text-7xl font-bold mb-6 text-foreground">Meet Our Leadership</h2>
|
||||
<p className="text-lg md:text-xl text-foreground/80">Dedicated professionals driving innovation and community growth</p>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 md:gap-8">
|
||||
{teamMembers.map((member) => {
|
||||
const isFlipped = flippedCards[member.id];
|
||||
return (
|
||||
<div
|
||||
key={member.id}
|
||||
className="h-96 cursor-pointer perspective"
|
||||
onClick={() => toggleFlip(member.id)}
|
||||
>
|
||||
<div
|
||||
className="relative w-full h-full transition-transform duration-500 transform-gpu"
|
||||
style={{
|
||||
transformStyle: 'preserve-3d',
|
||||
transform: isFlipped ? 'rotateY(180deg)' : 'rotateY(0deg)',
|
||||
}}
|
||||
>
|
||||
{/* Front of card */}
|
||||
<div
|
||||
className="absolute w-full h-full rounded-theme-capped overflow-hidden"
|
||||
style={{
|
||||
backfaceVisibility: 'hidden',
|
||||
}}
|
||||
>
|
||||
<img
|
||||
src={member.imageSrc}
|
||||
alt={member.imageAlt}
|
||||
className="w-full h-full object-cover"
|
||||
/>
|
||||
<div className="absolute inset-0 bg-gradient-to-t from-black/80 via-transparent to-transparent flex flex-col justify-end p-6">
|
||||
<h3 className="text-2xl font-bold text-white mb-1">{member.name}</h3>
|
||||
<p className="text-sm text-white/90">{member.role}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Back of card */}
|
||||
<div
|
||||
className="absolute w-full h-full rounded-theme-capped overflow-hidden bg-gradient-to-br from-primary-cta to-primary-cta/80 flex flex-col items-center justify-center p-6"
|
||||
style={{
|
||||
backfaceVisibility: 'hidden',
|
||||
transform: 'rotateY(180deg)',
|
||||
}}
|
||||
>
|
||||
<h3 className="text-white font-bold mb-6 text-center">{member.name}</h3>
|
||||
<div className="flex flex-col gap-4 w-full">
|
||||
{member.social.map((link) => (
|
||||
<a
|
||||
key={link.platform}
|
||||
href={link.url}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="w-full py-3 px-4 rounded-lg bg-white/20 hover:bg-white/30 text-white text-sm font-medium text-center transition-colors duration-200"
|
||||
>
|
||||
{link.platform.charAt(0).toUpperCase() + link.platform.slice(1)}
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="faq" data-section="faq">
|
||||
|
||||
@@ -8,7 +8,7 @@ interface ServiceWrapperProps {
|
||||
|
||||
export function ServiceWrapper({ children }: ServiceWrapperProps) {
|
||||
return (
|
||||
<div className="min-h-screen w-full bg-white">
|
||||
<div className="w-full min-h-screen bg-white">
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -38,7 +38,7 @@ export default function NavbarStyleApple({
|
||||
</div>
|
||||
|
||||
{/* Desktop Navigation */}
|
||||
<div className="hidden md:flex items-center space-x-8">
|
||||
<div className="hidden md:flex space-x-8">
|
||||
{navItems.map((item) => (
|
||||
<button
|
||||
key={item.id}
|
||||
@@ -54,7 +54,7 @@ export default function NavbarStyleApple({
|
||||
<div className="md:hidden">
|
||||
<button
|
||||
onClick={() => setIsOpen(!isOpen)}
|
||||
className="inline-flex items-center justify-center p-2 rounded-md text-gray-700 hover:text-blue-600 hover:bg-gray-100 focus:outline-none transition-colors duration-200"
|
||||
className="inline-flex items-center justify-center p-2 rounded-md text-gray-700 hover:text-blue-600 focus:outline-none"
|
||||
>
|
||||
<svg
|
||||
className="h-6 w-6"
|
||||
@@ -75,16 +75,18 @@ export default function NavbarStyleApple({
|
||||
|
||||
{/* Mobile Navigation */}
|
||||
{isOpen && (
|
||||
<div className="md:hidden pb-4 space-y-2">
|
||||
{navItems.map((item) => (
|
||||
<button
|
||||
key={item.id}
|
||||
onClick={() => handleNavClick(item.id)}
|
||||
className="block w-full text-left px-4 py-2 text-gray-700 hover:text-blue-600 hover:bg-gray-100 rounded-md font-medium transition-colors duration-200"
|
||||
>
|
||||
{item.name}
|
||||
</button>
|
||||
))}
|
||||
<div className="md:hidden pb-4">
|
||||
<div className="space-y-2">
|
||||
{navItems.map((item) => (
|
||||
<button
|
||||
key={item.id}
|
||||
onClick={() => handleNavClick(item.id)}
|
||||
className="block w-full text-left px-3 py-2 rounded-md text-gray-700 hover:bg-blue-50 hover:text-blue-600 font-medium transition-colors duration-200"
|
||||
>
|
||||
{item.name}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
"use client";
|
||||
|
||||
import React from "react";
|
||||
import Image from "next/image";
|
||||
import { LucideIcon } from "lucide-react";
|
||||
|
||||
interface Metric {
|
||||
@@ -8,7 +9,7 @@ interface Metric {
|
||||
title: string;
|
||||
}
|
||||
|
||||
interface Props {
|
||||
interface MetricSplitMediaAboutProps {
|
||||
tag: string;
|
||||
tagIcon: LucideIcon;
|
||||
title: string;
|
||||
@@ -32,7 +33,7 @@ export default function MetricSplitMediaAbout({
|
||||
useInvertedBackground = false,
|
||||
mediaAnimation = "slide-up",
|
||||
metricsAnimation = "slide-up",
|
||||
}: Props) {
|
||||
}: MetricSplitMediaAboutProps) {
|
||||
const bgClass = useInvertedBackground ? "bg-slate-900" : "bg-white";
|
||||
const textClass = useInvertedBackground ? "text-white" : "text-slate-900";
|
||||
const descriptionClass = useInvertedBackground
|
||||
@@ -42,20 +43,47 @@ export default function MetricSplitMediaAbout({
|
||||
const getAnimationClass = (animation: string) => {
|
||||
switch (animation) {
|
||||
case "slide-up":
|
||||
return "animate-in fade-in slide-in-from-bottom-4 duration-700";
|
||||
case "fade":
|
||||
return "animate-in fade-in duration-700";
|
||||
return "animate-slide-up";
|
||||
case "fade-in":
|
||||
return "animate-fade-in";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<section className={`${bgClass} py-16 md:py-24 transition-colors duration-300`}>
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<section className={`${bgClass} py-16 md:py-24 lg:py-32 transition-colors duration-300`}>
|
||||
<style>{`
|
||||
@keyframes slideUp {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(30px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
@keyframes fadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
.animate-slide-up {
|
||||
animation: slideUp 0.6s ease-out forwards;
|
||||
}
|
||||
.animate-fade-in {
|
||||
animation: fadeIn 0.6s ease-out forwards;
|
||||
}
|
||||
`}</style>
|
||||
|
||||
<div className="container mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div className="grid grid-cols-1 lg:grid-cols-2 gap-12 lg:gap-16 items-center">
|
||||
{/* Left Content */}
|
||||
<div className={`${getAnimationClass(mediaAnimation)}`}>
|
||||
<div className={`${getAnimationClass(metricsAnimation)}`}>
|
||||
{/* Tag */}
|
||||
<div className="flex items-center gap-2 mb-6">
|
||||
<TagIcon className="w-5 h-5 text-blue-600" />
|
||||
@@ -65,29 +93,23 @@ export default function MetricSplitMediaAbout({
|
||||
</div>
|
||||
|
||||
{/* Title */}
|
||||
<h2
|
||||
className={`text-4xl md:text-5xl font-bold ${textClass} mb-6 leading-tight`}
|
||||
>
|
||||
<h2 className={`${textClass} text-3xl md:text-4xl lg:text-5xl font-bold mb-6 leading-tight`}>
|
||||
{title}
|
||||
</h2>
|
||||
|
||||
{/* Description */}
|
||||
<p className={`${descriptionClass} text-lg leading-relaxed mb-8`}>
|
||||
<p className={`${descriptionClass} text-base md:text-lg mb-10 leading-relaxed`}>
|
||||
{description}
|
||||
</p>
|
||||
|
||||
{/* Metrics */}
|
||||
<div
|
||||
className={`grid grid-cols-2 gap-6 ${getAnimationClass(metricsAnimation)}`}
|
||||
>
|
||||
<div className="grid grid-cols-2 gap-8">
|
||||
{metrics.map((metric, index) => (
|
||||
<div key={index} className="flex flex-col">
|
||||
<span
|
||||
className={`text-3xl md:text-4xl font-bold ${textClass} mb-2`}
|
||||
>
|
||||
<span className={`${textClass} text-3xl md:text-4xl font-bold mb-2`}>
|
||||
{metric.value}
|
||||
</span>
|
||||
<span className={`${descriptionClass} text-sm font-medium`}>
|
||||
<span className={`${descriptionClass} text-sm md:text-base font-medium`}>
|
||||
{metric.title}
|
||||
</span>
|
||||
</div>
|
||||
@@ -95,15 +117,16 @@ export default function MetricSplitMediaAbout({
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Right Image */}
|
||||
{/* Right Media */}
|
||||
<div className={`${getAnimationClass(mediaAnimation)}`}>
|
||||
<div className="relative overflow-hidden rounded-2xl shadow-2xl">
|
||||
<img
|
||||
<div className="relative w-full aspect-square rounded-lg overflow-hidden shadow-xl">
|
||||
<Image
|
||||
src={imageSrc}
|
||||
alt={imageAlt}
|
||||
className="w-full h-auto object-cover aspect-square md:aspect-auto"
|
||||
fill
|
||||
className="object-cover"
|
||||
priority
|
||||
/>
|
||||
<div className="absolute inset-0 bg-gradient-to-t from-black/20 to-transparent" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -12,7 +12,7 @@ interface FaqBaseProps {
|
||||
title: string;
|
||||
description: string;
|
||||
tag: string;
|
||||
textboxLayout: "default" | "compact" | "wide";
|
||||
textboxLayout: "default" | "centered" | "wide";
|
||||
useInvertedBackground: boolean;
|
||||
faqsAnimation: "slide-up" | "fade-in" | "bounce";
|
||||
faqs: FaqItem[];
|
||||
@@ -29,40 +29,39 @@ export default function FaqBase({
|
||||
}: FaqBaseProps) {
|
||||
const [expandedId, setExpandedId] = useState<string | null>(null);
|
||||
|
||||
const toggleExpanded = (id: string) => {
|
||||
const toggleFaq = (id: string) => {
|
||||
setExpandedId(expandedId === id ? null : id);
|
||||
};
|
||||
|
||||
const getAnimationClass = () => {
|
||||
switch (faqsAnimation) {
|
||||
case "fade-in":
|
||||
return "animate-fade-in";
|
||||
case "bounce":
|
||||
return "animate-bounce";
|
||||
case "slide-up":
|
||||
default:
|
||||
return "animate-slide-up";
|
||||
}
|
||||
};
|
||||
|
||||
const getTextboxLayoutClass = () => {
|
||||
switch (textboxLayout) {
|
||||
case "compact":
|
||||
return "max-w-2xl";
|
||||
case "centered":
|
||||
return "text-center max-w-2xl mx-auto";
|
||||
case "wide":
|
||||
return "max-w-6xl";
|
||||
case "default":
|
||||
return "max-w-4xl mx-auto";
|
||||
default:
|
||||
return "max-w-4xl";
|
||||
return "max-w-3xl";
|
||||
}
|
||||
};
|
||||
|
||||
const getAnimationClass = (index: number) => {
|
||||
switch (faqsAnimation) {
|
||||
case "fade-in":
|
||||
return `opacity-0 animate-fadeIn`;
|
||||
case "bounce":
|
||||
return `opacity-0 animate-bounce`;
|
||||
case "slide-up":
|
||||
default:
|
||||
return `opacity-0 animate-slideUp`;
|
||||
}
|
||||
};
|
||||
|
||||
const bgClass = useInvertedBackground
|
||||
? "bg-gray-900 text-white"
|
||||
: "bg-white text-gray-900";
|
||||
? "bg-slate-900 text-white"
|
||||
: "bg-white text-slate-900";
|
||||
|
||||
return (
|
||||
<section className={`py-16 px-4 ${bgClass}`}>
|
||||
<section className={`py-16 px-4 sm:px-6 lg:px-8 ${bgClass}`}>
|
||||
<style>{`
|
||||
@keyframes slideUp {
|
||||
from {
|
||||
@@ -82,90 +81,76 @@ export default function FaqBase({
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
.animate-slide-up {
|
||||
animation: slideUp 0.6s ease-out;
|
||||
.animate-slideUp {
|
||||
animation: slideUp 0.6s ease-out forwards;
|
||||
}
|
||||
.animate-fade-in {
|
||||
animation: fadeIn 0.6s ease-out;
|
||||
.animate-fadeIn {
|
||||
animation: fadeIn 0.6s ease-out forwards;
|
||||
}
|
||||
`}</style>
|
||||
|
||||
<div className={`mx-auto ${getTextboxLayoutClass()}`}>
|
||||
{/* Header Section */}
|
||||
<div className="mb-12 text-center">
|
||||
{tag && (
|
||||
<div className="mb-4 inline-block">
|
||||
<span className="inline-block bg-blue-100 text-blue-800 px-4 py-1 rounded-full text-sm font-semibold">
|
||||
{tag}
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
<h2 className="text-4xl font-bold mb-4">{title}</h2>
|
||||
<p className={`text-lg ${useInvertedBackground ? "text-gray-300" : "text-gray-600"}`}>
|
||||
{description}
|
||||
</p>
|
||||
<div className={`${getTextboxLayoutClass()} mb-12`}>
|
||||
<div className="mb-4">
|
||||
<span className="inline-block px-3 py-1 text-sm font-semibold text-blue-600 bg-blue-100 rounded-full">
|
||||
{tag}
|
||||
</span>
|
||||
</div>
|
||||
<h2 className="text-4xl font-bold mb-4">{title}</h2>
|
||||
<p className="text-lg opacity-75">{description}</p>
|
||||
</div>
|
||||
|
||||
{/* FAQ Items */}
|
||||
<div className="space-y-4">
|
||||
{faqs.map((faq, index) => (
|
||||
<div
|
||||
key={faq.id}
|
||||
className={`${getAnimationClass()} border rounded-lg overflow-hidden transition-all duration-300 ${
|
||||
<div className="max-w-3xl mx-auto space-y-4">
|
||||
{faqs.map((faq, index) => (
|
||||
<div
|
||||
key={faq.id}
|
||||
className={`${getAnimationClass(index)} border rounded-lg overflow-hidden transition-all duration-300 ${
|
||||
useInvertedBackground
|
||||
? "border-slate-700 hover:border-blue-500"
|
||||
: "border-slate-200 hover:border-blue-400"
|
||||
}`}
|
||||
style={{
|
||||
animationDelay: `${index * 0.1}s`,
|
||||
}}
|
||||
>
|
||||
<button
|
||||
onClick={() => toggleFaq(faq.id)}
|
||||
className={`w-full px-6 py-4 flex items-center justify-between font-semibold transition-colors duration-200 ${
|
||||
useInvertedBackground
|
||||
? "border-gray-700 hover:border-blue-500"
|
||||
: "border-gray-200 hover:border-blue-500"
|
||||
? "hover:bg-slate-800"
|
||||
: "hover:bg-slate-50"
|
||||
}`}
|
||||
style={{
|
||||
animationDelay: `${index * 0.1}s`,
|
||||
}}
|
||||
>
|
||||
<button
|
||||
onClick={() => toggleExpanded(faq.id)}
|
||||
className={`w-full px-6 py-4 flex items-center justify-between font-semibold transition-colors ${
|
||||
<span className="text-left">{faq.title}</span>
|
||||
<svg
|
||||
className={`w-5 h-5 transition-transform duration-300 ${
|
||||
expandedId === faq.id ? "rotate-180" : ""
|
||||
}`}
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth={2}
|
||||
d="M19 14l-7 7m0 0l-7-7m7 7V3"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
{expandedId === faq.id && (
|
||||
<div
|
||||
className={`px-6 py-4 border-t ${
|
||||
useInvertedBackground
|
||||
? "bg-gray-800 hover:bg-gray-700"
|
||||
: "bg-gray-50 hover:bg-gray-100"
|
||||
? "border-slate-700 bg-slate-800"
|
||||
: "border-slate-200 bg-slate-50"
|
||||
}`}
|
||||
>
|
||||
<span className="text-left">{faq.title}</span>
|
||||
<svg
|
||||
className={`w-5 h-5 transition-transform duration-300 ${
|
||||
expandedId === faq.id ? "rotate-180" : ""
|
||||
}`}
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth={2}
|
||||
d="M19 14l-7 7m0 0l-7-7m7 7V3"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
{expandedId === faq.id && (
|
||||
<div
|
||||
className={`px-6 py-4 border-t ${
|
||||
useInvertedBackground
|
||||
? "border-gray-700 bg-gray-900"
|
||||
: "border-gray-200 bg-gray-50"
|
||||
}`}
|
||||
>
|
||||
<p
|
||||
className={`${
|
||||
useInvertedBackground ? "text-gray-300" : "text-gray-700"
|
||||
}`}
|
||||
>
|
||||
{faq.content}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
<p className="opacity-90">{faq.content}</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
|
||||
@@ -51,88 +51,71 @@ export default function FeatureBorderGlow({
|
||||
key={index}
|
||||
className="group relative h-80 rounded-xl overflow-hidden bg-gradient-to-br from-gray-50 to-gray-100 dark:from-gray-900 dark:to-gray-800 border border-gray-200 dark:border-gray-700 transition-all duration-300 hover:shadow-xl"
|
||||
>
|
||||
{/* Border Glow Effect */}
|
||||
{/* Glow Border Effect */}
|
||||
<div className="absolute inset-0 opacity-0 group-hover:opacity-100 transition-opacity duration-300">
|
||||
<div className="absolute inset-0 bg-gradient-to-r from-blue-500/20 via-purple-500/20 to-pink-500/20 rounded-xl blur-xl" />
|
||||
</div>
|
||||
|
||||
{/* Front Content */}
|
||||
<div className="absolute inset-0 p-6 flex flex-col justify-center items-center text-center z-10 group-hover:opacity-0 transition-opacity duration-300">
|
||||
<div className="mb-4 p-3 rounded-lg bg-blue-500/10 dark:bg-blue-500/20">
|
||||
<Icon className="w-8 h-8 text-blue-600 dark:text-blue-400" />
|
||||
{/* Front Side */}
|
||||
<div className="absolute inset-0 p-6 flex flex-col items-start justify-start group-hover:opacity-0 transition-opacity duration-300 z-10">
|
||||
<div className="w-12 h-12 rounded-lg bg-blue-500/10 flex items-center justify-center mb-4 group-hover:scale-110 transition-transform duration-300">
|
||||
<Icon className="w-6 h-6 text-blue-600 dark:text-blue-400" />
|
||||
</div>
|
||||
<h3 className="text-xl font-bold text-gray-900 dark:text-white mb-3">
|
||||
{feature.title}
|
||||
</h3>
|
||||
<p className="text-sm text-gray-600 dark:text-gray-300 leading-relaxed">
|
||||
<p className="text-gray-600 dark:text-gray-300 text-sm leading-relaxed">
|
||||
{feature.description}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Back Content (Hover) */}
|
||||
<div className="absolute inset-0 p-6 flex flex-col justify-center items-center text-center z-10 opacity-0 group-hover:opacity-100 transition-opacity duration-300">
|
||||
<div className="mb-6">
|
||||
<h3 className="text-xl font-bold text-gray-900 dark:text-white mb-4">
|
||||
Connect
|
||||
</h3>
|
||||
</div>
|
||||
<div className="flex gap-4 justify-center">
|
||||
<a
|
||||
href="#"
|
||||
className="p-3 rounded-full bg-blue-500 hover:bg-blue-600 text-white transition-colors duration-200"
|
||||
aria-label="LinkedIn"
|
||||
>
|
||||
<svg
|
||||
className="w-5 h-5"
|
||||
fill="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
{/* Back Side */}
|
||||
<div className="absolute inset-0 p-6 flex flex-col items-center justify-center opacity-0 group-hover:opacity-100 transition-opacity duration-300 z-20 bg-gradient-to-br from-blue-600 to-purple-600">
|
||||
<div className="text-center">
|
||||
<h4 className="text-white font-bold text-lg mb-4">
|
||||
{feature.title}
|
||||
</h4>
|
||||
<div className="flex gap-3 justify-center">
|
||||
<a
|
||||
href="#"
|
||||
className="w-10 h-10 rounded-full bg-white/20 hover:bg-white/30 flex items-center justify-center text-white transition-colors duration-200"
|
||||
aria-label="LinkedIn"
|
||||
>
|
||||
<path d="M19 0h-14c-2.761 0-5 2.239-5 5v14c0 2.761 2.239 5 5 5h14c2.762 0 5-2.239 5-5v-14c0-2.761-2.238-5-5-5zm-11 19h-3v-11h3v11zm-1.5-12.268c-.966 0-1.75-.79-1.75-1.764s.784-1.764 1.75-1.764 1.75.79 1.75 1.764-.783 1.764-1.75 1.764zm13.5 12.268h-3v-5.604c0-3.368-4-3.113-4 0v5.604h-3v-11h3v1.765c1.396-2.586 7-2.777 7 2.476v6.759z" />
|
||||
</svg>
|
||||
</a>
|
||||
<a
|
||||
href="#"
|
||||
className="p-3 rounded-full bg-blue-400 hover:bg-blue-500 text-white transition-colors duration-200"
|
||||
aria-label="Twitter"
|
||||
>
|
||||
<svg
|
||||
className="w-5 h-5"
|
||||
fill="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
<svg
|
||||
className="w-5 h-5"
|
||||
fill="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path d="M19 0h-14c-2.761 0-5 2.239-5 5v14c0 2.761 2.239 5 5 5h14c2.762 0 5-2.239 5-5v-14c0-2.761-2.238-5-5-5zm-11 19h-3v-11h3v11zm-1.5-12.268c-.966 0-1.75-.79-1.75-1.764s.784-1.764 1.75-1.764 1.75.79 1.75 1.764-.783 1.764-1.75 1.764zm13.5 12.268h-3v-5.604c0-3.368-4-3.113-4 0v5.604h-3v-11h3v1.765c1.396-2.586 7-2.777 7 2.476v6.759z" />
|
||||
</svg>
|
||||
</a>
|
||||
<a
|
||||
href="#"
|
||||
className="w-10 h-10 rounded-full bg-white/20 hover:bg-white/30 flex items-center justify-center text-white transition-colors duration-200"
|
||||
aria-label="Twitter"
|
||||
>
|
||||
<path d="M23 3a10.9 10.9 0 01-3.14 1.53 4.48 4.48 0 00-7.86 3v1A10.66 10.66 0 013 4s-4 9 5 13a11.64 11.64 0 01-7 2s9 5 20 5a9.5 9.5 0 00-9-5.5c4.75 2.25 9-1 9-5.5a4.5 4.5 0 00-.08-.83A7.72 7.72 0 0023 3z" />
|
||||
</svg>
|
||||
</a>
|
||||
<a
|
||||
href="#"
|
||||
className="p-3 rounded-full bg-gradient-to-r from-purple-500 to-pink-500 hover:from-purple-600 hover:to-pink-600 text-white transition-colors duration-200"
|
||||
aria-label="Instagram"
|
||||
>
|
||||
<svg
|
||||
className="w-5 h-5"
|
||||
fill="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
<svg
|
||||
className="w-5 h-5"
|
||||
fill="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path d="M23 3a10.9 10.9 0 01-3.14 1.53 4.48 4.48 0 00-7.86 3v1A10.66 10.66 0 013 4s-4 9 5 13a11.64 11.64 0 01-7 2s9 5 20 5a9.5 9.5 0 00-9-5.5c4.75 2.25 7-7 7-7a10.6 10.6 0 01-9.5 5" />
|
||||
</svg>
|
||||
</a>
|
||||
<a
|
||||
href="#"
|
||||
className="w-10 h-10 rounded-full bg-white/20 hover:bg-white/30 flex items-center justify-center text-white transition-colors duration-200"
|
||||
aria-label="GitHub"
|
||||
>
|
||||
<rect
|
||||
x="2"
|
||||
y="2"
|
||||
width="20"
|
||||
height="20"
|
||||
rx="5"
|
||||
ry="5"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
strokeWidth="2"
|
||||
/>
|
||||
<path
|
||||
d="M16 11.37A4 4 0 1112.63 8 4 4 0 0116 11.37z"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
strokeWidth="2"
|
||||
/>
|
||||
<circle cx="17.5" cy="6.5" r="1.5" fill="currentColor" />
|
||||
</svg>
|
||||
</a>
|
||||
<svg
|
||||
className="w-5 h-5"
|
||||
fill="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path d="M12 0c-6.626 0-12 5.373-12 12 0 5.302 3.438 9.8 8.207 11.387.599.111.793-.261.793-.577v-2.234c-3.338.726-4.033-1.416-4.033-1.416-.546-1.387-1.333-1.756-1.333-1.756-1.089-.745.083-.729.083-.729 1.205.084 1.839 1.237 1.839 1.237 1.07 1.834 2.807 1.304 3.492.997.107-.775.418-1.305.762-1.604-2.665-.305-5.467-1.334-5.467-5.931 0-1.311.469-2.381 1.236-3.221-.124-.303-.535-1.524.117-3.176 0 0 1.008-.322 3.301 1.23.957-.266 1.983-.399 3.003-.404 1.02.005 2.047.138 3.006.404 2.291-1.552 3.297-1.23 3.297-1.23.653 1.653.242 2.874.118 3.176.77.84 1.235 1.911 1.235 3.221 0 4.609-2.807 5.624-5.479 5.921.43.372.823 1.102.823 2.222v 3.293c0 .319.192.694.801.576 4.765-1.589 8.199-6.086 8.199-11.386 0-6.627-5.373-12-12-12z" />
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -25,23 +25,28 @@ export default function FooterLogoEmphasis({
|
||||
<div className="max-w-6xl mx-auto">
|
||||
{/* Logo Section */}
|
||||
<div className="mb-12 pb-8 border-b border-slate-700">
|
||||
<h2 className="text-3xl font-bold bg-gradient-to-r from-blue-400 to-cyan-400 bg-clip-text text-transparent">
|
||||
{logoText}
|
||||
</h2>
|
||||
<p className="text-slate-400 mt-2">
|
||||
Building the future of technology together
|
||||
<div className="flex items-center gap-3 mb-2">
|
||||
<div className="w-10 h-10 bg-gradient-to-br from-blue-400 to-purple-600 rounded-lg flex items-center justify-center font-bold text-lg">
|
||||
C
|
||||
</div>
|
||||
<h2 className="text-2xl font-bold bg-gradient-to-r from-blue-400 to-purple-400 bg-clip-text text-transparent">
|
||||
{logoText}
|
||||
</h2>
|
||||
</div>
|
||||
<p className="text-slate-400 text-sm">
|
||||
Building amazing digital experiences together
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Links Grid */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-8 mb-12">
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-8 mb-8">
|
||||
{columns.map((column, columnIndex) => (
|
||||
<div key={columnIndex} className="space-y-4">
|
||||
{column.items.map((item, itemIndex) => (
|
||||
<Link
|
||||
key={itemIndex}
|
||||
href={item.href}
|
||||
className="block text-slate-300 hover:text-blue-400 transition-colors duration-200 font-medium"
|
||||
className="block text-slate-300 hover:text-blue-400 transition-colors duration-200 text-sm font-medium"
|
||||
>
|
||||
{item.label}
|
||||
</Link>
|
||||
@@ -51,22 +56,36 @@ export default function FooterLogoEmphasis({
|
||||
</div>
|
||||
|
||||
{/* Bottom Section */}
|
||||
<div className="border-t border-slate-700 pt-8 flex flex-col md:flex-row justify-between items-center">
|
||||
<div className="border-t border-slate-700 pt-8 flex flex-col md:flex-row justify-between items-center gap-4">
|
||||
<p className="text-slate-400 text-sm">
|
||||
© 2024 {logoText}. All rights reserved.
|
||||
</p>
|
||||
<div className="flex gap-6 mt-4 md:mt-0">
|
||||
<div className="flex gap-6">
|
||||
<Link
|
||||
href="#"
|
||||
className="text-slate-400 hover:text-blue-400 transition-colors"
|
||||
className="text-slate-400 hover:text-blue-400 transition-colors duration-200"
|
||||
>
|
||||
Privacy
|
||||
<span className="sr-only">Twitter</span>
|
||||
<svg
|
||||
className="w-5 h-5"
|
||||
fill="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path d="M8.29 20c7.547 0 11.675-6.253 11.675-11.675 0-.178 0-.355-.012-.53A8.348 8.348 0 0022 5.92a8.19 8.19 0 01-2.357.646 4.118 4.118 0 001.804-2.27 8.224 8.224 0 01-2.605.996 4.107 4.107 0 00-7.007 3.743 11.65 11.65 0 01-8.457-4.287 4.106 4.106 0 001.27 5.477A4.072 4.072 0 012.8 9.713v.052a4.105 4.105 0 003.292 4.022 4.095 4.095 0 01-1.853.07 4.108 4.108 0 003.834 2.85A8.233 8.233 0 012 18.407a11.616 11.616 0 006.29 1.84" />
|
||||
</svg>
|
||||
</Link>
|
||||
<Link
|
||||
href="#"
|
||||
className="text-slate-400 hover:text-blue-400 transition-colors"
|
||||
className="text-slate-400 hover:text-blue-400 transition-colors duration-200"
|
||||
>
|
||||
Terms
|
||||
<span className="sr-only">Discord</span>
|
||||
<svg
|
||||
className="w-5 h-5"
|
||||
fill="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path d="M20.317 4.37a19.791 19.791 0 00-4.885-1.515.074.074 0 00-.079.037c-.211.375-.444.864-.607 1.25a18.27 18.27 0 00-5.487 0c-.163-.386-.395-.875-.607-1.25a.077.077 0 00-.079-.037A19.736 19.736 0 003.677 4.37a.07.07 0 00-.032.027C.533 9.046-.32 13.58.099 18.057a.082.082 0 00.031.057 19.9 19.9 0 005.993 3.03.078.078 0 00.084-.028c.462-.63.874-1.295 1.226-1.994a.076.076 0 00-.042-.106 13.107 13.107 0 01-1.872-.892.077.077 0 01-.008-.128 10.2 10.2 0 00.372-.294.075.075 0 01.078-.01c3.928 1.793 8.18 1.793 12.062 0a.075.075 0 01.079.009c.12.098.246.198.373.295a.077.077 0 01-.006.127 12.299 12.299 0 01-1.873.892.076.076 0 00-.041.107c.352.699.764 1.364 1.225 1.994a.076.076 0 00.084.028 19.839 19.839 0 006.002-3.03.077.077 0 00.032-.057c.5-4.761-.838-8.898-3.549-12.562a.06.06 0 00-.031-.03zM8.02 15.33c-1.183 0-2.157-.965-2.157-2.156 0-1.193.964-2.157 2.157-2.157 1.193 0 2.156.964 2.157 2.157 0 1.19-.964 2.156-2.157 2.156zm7.975 0c-1.183 0-2.157-.965-2.157-2.156 0-1.193.964-2.157 2.157-2.157 1.192 0 2.156.964 2.157 2.157 0 1.19-.965 2.156-2.157 2.156z" />
|
||||
</svg>
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -9,7 +9,7 @@ interface Button {
|
||||
href: string;
|
||||
}
|
||||
|
||||
interface Background {
|
||||
interface BackgroundConfig {
|
||||
variant: "animated-grid" | "solid" | "gradient";
|
||||
}
|
||||
|
||||
@@ -18,12 +18,12 @@ interface HeroBillboardScrollProps {
|
||||
description: string;
|
||||
tag: string;
|
||||
tagIcon: LucideIcon;
|
||||
tagAnimation?: string;
|
||||
background?: Background;
|
||||
tagAnimation: string;
|
||||
background: BackgroundConfig;
|
||||
imageSrc: string;
|
||||
imageAlt: string;
|
||||
buttons: Button[];
|
||||
buttonAnimation?: string;
|
||||
buttonAnimation: string;
|
||||
}
|
||||
|
||||
export default function HeroBillboardScroll({
|
||||
@@ -31,28 +31,33 @@ export default function HeroBillboardScroll({
|
||||
description,
|
||||
tag,
|
||||
tagIcon: TagIcon,
|
||||
tagAnimation = "slide-up",
|
||||
background = { variant: "animated-grid" },
|
||||
tagAnimation,
|
||||
background,
|
||||
imageSrc,
|
||||
imageAlt,
|
||||
buttons,
|
||||
buttonAnimation = "slide-up",
|
||||
buttonAnimation,
|
||||
}: HeroBillboardScrollProps) {
|
||||
const getBackgroundClass = () => {
|
||||
switch (background.variant) {
|
||||
case "animated-grid":
|
||||
return "bg-gradient-to-br from-slate-900 via-slate-800 to-slate-900";
|
||||
case "solid":
|
||||
return "bg-slate-900";
|
||||
case "gradient":
|
||||
return "bg-gradient-to-r from-blue-600 to-purple-600";
|
||||
case "solid":
|
||||
return "bg-slate-900";
|
||||
default:
|
||||
return "bg-slate-900";
|
||||
}
|
||||
};
|
||||
|
||||
const getAnimationDelay = (index: number) => {
|
||||
return `${index * 100}ms`;
|
||||
const getAnimationClass = (animation: string) => {
|
||||
switch (animation) {
|
||||
case "slide-up":
|
||||
return "animate-in fade-in slide-in-from-bottom-4 duration-700";
|
||||
default:
|
||||
return "animate-in fade-in duration-700";
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -64,50 +69,43 @@ export default function HeroBillboardScroll({
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Gradient Orbs */}
|
||||
<div className="absolute top-0 left-1/4 w-96 h-96 bg-blue-500 rounded-full mix-blend-multiply filter blur-3xl opacity-20 animate-pulse" />
|
||||
<div className="absolute bottom-0 right-1/4 w-96 h-96 bg-purple-500 rounded-full mix-blend-multiply filter blur-3xl opacity-20 animate-pulse" />
|
||||
{/* Gradient Overlay */}
|
||||
<div className="absolute inset-0 bg-gradient-to-b from-transparent via-transparent to-slate-900/50" />
|
||||
|
||||
<div className="relative z-10 flex items-center justify-between min-h-screen px-6 md:px-12 lg:px-20">
|
||||
<div className="relative z-10 flex items-center justify-between min-h-screen px-6 sm:px-8 lg:px-12">
|
||||
{/* Left Content */}
|
||||
<div className="flex-1 max-w-2xl">
|
||||
{/* Tag */}
|
||||
<div
|
||||
className="inline-flex items-center gap-2 px-4 py-2 rounded-full bg-blue-500/10 border border-blue-500/30 mb-6 animate-fade-in"
|
||||
style={{
|
||||
animation: `fadeInUp 0.6s ease-out ${getAnimationDelay(0)}`,
|
||||
}}
|
||||
className={`inline-flex items-center gap-2 mb-6 px-4 py-2 rounded-full bg-slate-800/50 border border-slate-700 ${getAnimationClass(
|
||||
tagAnimation
|
||||
)}`}
|
||||
>
|
||||
<TagIcon className="w-4 h-4 text-blue-400" />
|
||||
<span className="text-sm font-medium text-blue-300">{tag}</span>
|
||||
<span className="text-sm font-medium text-slate-300">{tag}</span>
|
||||
</div>
|
||||
|
||||
{/* Title */}
|
||||
<h1
|
||||
className="text-5xl md:text-6xl lg:text-7xl font-bold text-white mb-6 leading-tight animate-fade-in"
|
||||
style={{
|
||||
animation: `fadeInUp 0.6s ease-out ${getAnimationDelay(1)}`,
|
||||
}}
|
||||
className={`text-5xl sm:text-6xl lg:text-7xl font-bold text-white mb-6 leading-tight ${getAnimationClass(
|
||||
tagAnimation
|
||||
)}`}
|
||||
>
|
||||
{title}
|
||||
</h1>
|
||||
|
||||
{/* Description */}
|
||||
<p
|
||||
className="text-lg md:text-xl text-gray-300 mb-8 leading-relaxed max-w-xl animate-fade-in"
|
||||
style={{
|
||||
animation: `fadeInUp 0.6s ease-out ${getAnimationDelay(2)}`,
|
||||
}}
|
||||
className={`text-lg sm:text-xl text-slate-300 mb-8 leading-relaxed max-w-xl ${getAnimationClass(
|
||||
tagAnimation
|
||||
)}`}
|
||||
>
|
||||
{description}
|
||||
</p>
|
||||
|
||||
{/* Buttons */}
|
||||
<div
|
||||
className="flex flex-wrap gap-4 animate-fade-in"
|
||||
style={{
|
||||
animation: `fadeInUp 0.6s ease-out ${getAnimationDelay(3)}`,
|
||||
}}
|
||||
className={`flex flex-wrap gap-4 ${getAnimationClass(buttonAnimation)}`}
|
||||
>
|
||||
{buttons.map((button, index) => (
|
||||
<Link
|
||||
@@ -115,8 +113,8 @@ export default function HeroBillboardScroll({
|
||||
href={button.href}
|
||||
className={`px-8 py-3 rounded-lg font-semibold transition-all duration-300 ${
|
||||
index === 0
|
||||
? "bg-blue-600 text-white hover:bg-blue-700 shadow-lg hover:shadow-blue-500/50"
|
||||
: "bg-transparent text-white border-2 border-white hover:bg-white hover:text-slate-900"
|
||||
? "bg-blue-600 text-white hover:bg-blue-700 shadow-lg hover:shadow-blue-600/50"
|
||||
: "bg-slate-800 text-white border border-slate-700 hover:bg-slate-700 hover:border-slate-600"
|
||||
}`}
|
||||
>
|
||||
{button.text}
|
||||
@@ -126,12 +124,7 @@ export default function HeroBillboardScroll({
|
||||
</div>
|
||||
|
||||
{/* Right Image */}
|
||||
<div
|
||||
className="hidden lg:flex flex-1 justify-end animate-fade-in"
|
||||
style={{
|
||||
animation: `fadeInUp 0.6s ease-out ${getAnimationDelay(4)}`,
|
||||
}}
|
||||
>
|
||||
<div className="hidden lg:flex flex-1 items-center justify-center">
|
||||
<div className="relative w-full max-w-md h-96 rounded-2xl overflow-hidden shadow-2xl">
|
||||
<img
|
||||
src={imageSrc}
|
||||
@@ -145,40 +138,13 @@ export default function HeroBillboardScroll({
|
||||
|
||||
{/* Scroll Indicator */}
|
||||
<div className="absolute bottom-8 left-1/2 transform -translate-x-1/2 z-10">
|
||||
<div className="flex flex-col items-center gap-2 animate-bounce">
|
||||
<span className="text-sm text-gray-400">Scroll to explore</span>
|
||||
<svg
|
||||
className="w-6 h-6 text-gray-400"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path
|
||||
strokeLinecap="round"
|
||||
strokeLinejoin="round"
|
||||
strokeWidth={2}
|
||||
d="M19 14l-7 7m0 0l-7-7m7 7V3"
|
||||
/>
|
||||
</svg>
|
||||
<div className="flex flex-col items-center gap-2">
|
||||
<span className="text-sm text-slate-400">Scroll to explore</span>
|
||||
<div className="w-6 h-10 border-2 border-slate-600 rounded-full flex items-start justify-center p-2">
|
||||
<div className="w-1 h-2 bg-slate-400 rounded-full animate-bounce" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style jsx>{`
|
||||
@keyframes fadeInUp {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(30px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
.animate-fade-in {
|
||||
opacity: 0;
|
||||
}
|
||||
`}</style>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
@@ -61,212 +61,169 @@ export default function ProductCardFour({
|
||||
const getAnimationClass = () => {
|
||||
switch (animationType) {
|
||||
case "slide-up":
|
||||
return "animate-slide-up";
|
||||
return "animate-in slide-in-from-bottom-4 duration-500";
|
||||
case "fade-in":
|
||||
return "animate-fade-in";
|
||||
return "animate-in fade-in duration-500";
|
||||
case "scale":
|
||||
return "animate-scale";
|
||||
return "animate-in zoom-in-50 duration-500";
|
||||
default:
|
||||
return "animate-fade-in";
|
||||
return "animate-in fade-in duration-500";
|
||||
}
|
||||
};
|
||||
|
||||
const bgClass = useInvertedBackground ? "bg-gray-900" : "bg-white";
|
||||
const bgClass = useInvertedBackground ? "bg-slate-900" : "bg-white";
|
||||
const textColorClass = useInvertedBackground ? "text-white" : "text-slate-900";
|
||||
|
||||
return (
|
||||
<section className={`py-16 px-4 sm:px-6 lg:px-8 ${bgClass}`}>
|
||||
<section className={`${bgClass} py-16 px-4 md:px-8 lg:px-12`}>
|
||||
<div className="max-w-7xl mx-auto">
|
||||
<div className="mb-12">
|
||||
<div className="flex items-center gap-2 mb-4">
|
||||
<TagIcon className="w-5 h-5 text-blue-600" />
|
||||
<TagIcon className="w-5 h-5" />
|
||||
<span className="text-sm font-semibold text-blue-600 uppercase tracking-wide">
|
||||
{tag}
|
||||
</span>
|
||||
</div>
|
||||
<h2
|
||||
className={`text-4xl sm:text-5xl font-bold mb-4 ${
|
||||
useInvertedBackground ? "text-white" : "text-gray-900"
|
||||
}`}
|
||||
>
|
||||
<h2 className={`text-4xl md:text-5xl font-bold mb-4 ${textColorClass}`}>
|
||||
{title}
|
||||
</h2>
|
||||
<p
|
||||
className={`text-lg max-w-2xl ${
|
||||
useInvertedBackground ? "text-gray-300" : "text-gray-600"
|
||||
}`}
|
||||
className={`text-lg ${
|
||||
useInvertedBackground ? "text-slate-300" : "text-slate-600"
|
||||
} max-w-2xl`}
|
||||
>
|
||||
{description}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className={`grid ${getGridClass()} gap-8`}>
|
||||
{products.map((product) => (
|
||||
{products.map((product, index) => (
|
||||
<div
|
||||
key={product.id}
|
||||
className={`h-96 cursor-pointer perspective ${getAnimationClass()}`}
|
||||
onClick={() => toggleFlip(product.id)}
|
||||
className={`${getAnimationClass()}`}
|
||||
style={{
|
||||
animationDelay: `${index * 100}ms`,
|
||||
}}
|
||||
>
|
||||
<div
|
||||
className="relative w-full h-full transition-transform duration-500 transform-gpu"
|
||||
style={{
|
||||
transformStyle: "preserve-3d",
|
||||
transform: flipped[product.id]
|
||||
? "rotateY(180deg)"
|
||||
: "rotateY(0deg)",
|
||||
}}
|
||||
className="h-96 cursor-pointer perspective"
|
||||
onClick={() => toggleFlip(product.id)}
|
||||
>
|
||||
{/* Front of card */}
|
||||
<div
|
||||
className="absolute w-full h-full bg-white rounded-lg shadow-lg overflow-hidden"
|
||||
style={{ backfaceVisibility: "hidden" }}
|
||||
>
|
||||
<div className="relative w-full h-64">
|
||||
<Image
|
||||
src={product.imageSrc}
|
||||
alt={product.imageAlt}
|
||||
fill
|
||||
className="object-cover"
|
||||
/>
|
||||
</div>
|
||||
<div className="p-6">
|
||||
<h3 className="text-xl font-bold text-gray-900 mb-2">
|
||||
{product.name}
|
||||
</h3>
|
||||
<p className="text-sm text-gray-600 mb-3">
|
||||
{product.variant}
|
||||
</p>
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="text-lg font-semibold text-blue-600">
|
||||
{product.price}
|
||||
</span>
|
||||
<span className="text-xs text-gray-500">Click to flip</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Back of card */}
|
||||
<div
|
||||
className="absolute w-full h-full bg-blue-600 rounded-lg shadow-lg overflow-hidden flex flex-col items-center justify-center p-6"
|
||||
className="relative w-full h-full transition-transform duration-500 transform-gpu"
|
||||
style={{
|
||||
backfaceVisibility: "hidden",
|
||||
transform: "rotateY(180deg)",
|
||||
transformStyle: "preserve-3d",
|
||||
transform: flipped[product.id]
|
||||
? "rotateY(180deg)"
|
||||
: "rotateY(0deg)",
|
||||
}}
|
||||
>
|
||||
<h3 className="text-white text-xl font-bold mb-6 text-center">
|
||||
Connect With Us
|
||||
</h3>
|
||||
<div className="flex gap-4 flex-wrap justify-center">
|
||||
<a
|
||||
href="#"
|
||||
className="w-12 h-12 bg-white bg-opacity-20 hover:bg-opacity-30 rounded-full flex items-center justify-center text-white transition-all duration-300"
|
||||
title="LinkedIn"
|
||||
>
|
||||
<svg
|
||||
className="w-6 h-6"
|
||||
fill="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path d="M19 0h-14c-2.761 0-5 2.239-5 5v14c0 2.761 2.239 5 5 5h14c2.762 0 5-2.239 5-5v-14c0-2.761-2.238-5-5-5zm-11 19h-3v-11h3v11zm-1.5-12.268c-.966 0-1.75-.79-1.75-1.764s.784-1.764 1.75-1.764 1.75.79 1.75 1.764-.783 1.764-1.75 1.764zm13.5 12.268h-3v-5.604c0-3.368-4-3.113-4 0v5.604h-3v-11h3v1.765c1.396-2.586 7-2.777 7 2.476v6.759z" />
|
||||
</svg>
|
||||
</a>
|
||||
<a
|
||||
href="#"
|
||||
className="w-12 h-12 bg-white bg-opacity-20 hover:bg-opacity-30 rounded-full flex items-center justify-center text-white transition-all duration-300"
|
||||
title="Twitter"
|
||||
>
|
||||
<svg
|
||||
className="w-6 h-6"
|
||||
fill="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path d="M23 3a10.9 10.9 0 01-3.14 1.53 4.48 4.48 0 00-7.86 3v1A10.66 10.66 0 013 4s-4 9 5 13a11.64 11.64 0 01-7 2s9 5 20 5a9.5 9.5 0 00-9-5.5c4.75 2.25 9 0 11-4s1-8.75 0-10c-.5-.75-1-2-3-4z" />
|
||||
</svg>
|
||||
</a>
|
||||
<a
|
||||
href="#"
|
||||
className="w-12 h-12 bg-white bg-opacity-20 hover:bg-opacity-30 rounded-full flex items-center justify-center text-white transition-all duration-300"
|
||||
title="Facebook"
|
||||
>
|
||||
<svg
|
||||
className="w-6 h-6"
|
||||
fill="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path d="M24 12.073c0-6.627-5.373-12-12-12s-12 5.373-12 12c0 5.99 4.388 10.954 10.125 11.854v-8.385H7.078v-3.47h3.047V9.43c0-3.007 1.792-4.669 4.533-4.669 1.312 0 2.686.235 2.686.235v2.953H15.83c-1.491 0-1.956.925-1.956 1.874v2.25h3.328l-.532 3.47h-2.796v8.385C19.612 23.027 24 18.062 24 12.073z" />
|
||||
</svg>
|
||||
</a>
|
||||
<a
|
||||
href="#"
|
||||
className="w-12 h-12 bg-white bg-opacity-20 hover:bg-opacity-30 rounded-full flex items-center justify-center text-white transition-all duration-300"
|
||||
title="Email"
|
||||
>
|
||||
<svg
|
||||
className="w-6 h-6"
|
||||
fill="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path d="M20 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm0 4l-8 5-8-5V6l8 5 8-5v2z" />
|
||||
</svg>
|
||||
</a>
|
||||
{/* Front of card */}
|
||||
<div
|
||||
className="absolute w-full h-full bg-white rounded-lg shadow-lg overflow-hidden"
|
||||
style={{
|
||||
backfaceVisibility: "hidden",
|
||||
}}
|
||||
>
|
||||
<div className="relative w-full h-64">
|
||||
<Image
|
||||
src={product.imageSrc}
|
||||
alt={product.imageAlt}
|
||||
fill
|
||||
className="object-cover"
|
||||
/>
|
||||
</div>
|
||||
<div className="p-6">
|
||||
<h3 className="text-xl font-bold text-slate-900 mb-2">
|
||||
{product.name}
|
||||
</h3>
|
||||
<p className="text-sm text-slate-600 mb-3">
|
||||
{product.variant}
|
||||
</p>
|
||||
<div className="text-lg font-semibold text-blue-600">
|
||||
{product.price}
|
||||
</div>
|
||||
<p className="text-xs text-slate-500 mt-3">
|
||||
Hover to see more
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Back of card */}
|
||||
<div
|
||||
className="absolute w-full h-full bg-gradient-to-br from-blue-600 to-blue-800 rounded-lg shadow-lg p-6 flex flex-col justify-center items-center"
|
||||
style={{
|
||||
backfaceVisibility: "hidden",
|
||||
transform: "rotateY(180deg)",
|
||||
}}
|
||||
>
|
||||
<h3 className="text-white text-xl font-bold mb-6 text-center">
|
||||
Connect With Us
|
||||
</h3>
|
||||
<div className="flex gap-4 justify-center flex-wrap">
|
||||
<a
|
||||
href="#"
|
||||
className="w-12 h-12 rounded-full bg-white bg-opacity-20 hover:bg-opacity-30 flex items-center justify-center text-white transition-all duration-300 transform hover:scale-110"
|
||||
title="LinkedIn"
|
||||
>
|
||||
<svg
|
||||
className="w-6 h-6"
|
||||
fill="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path d="M19 0h-14c-2.761 0-5 2.239-5 5v14c0 2.761 2.239 5 5 5h14c2.762 0 5-2.239 5-5v-14c0-2.761-2.238-5-5-5zm-11 19h-3v-11h3v11zm-1.5-12.268c-.966 0-1.75-.79-1.75-1.764s.784-1.764 1.75-1.764 1.75.79 1.75 1.764-.783 1.764-1.75 1.764zm13.5 12.268h-3v-5.604c0-3.368-4-3.113-4 0v5.604h-3v-11h3v1.765c1.396-2.586 7-2.777 7 2.476v6.759z" />
|
||||
</svg>
|
||||
</a>
|
||||
<a
|
||||
href="#"
|
||||
className="w-12 h-12 rounded-full bg-white bg-opacity-20 hover:bg-opacity-30 flex items-center justify-center text-white transition-all duration-300 transform hover:scale-110"
|
||||
title="Twitter"
|
||||
>
|
||||
<svg
|
||||
className="w-6 h-6"
|
||||
fill="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path d="M23 3a10.9 10.9 0 01-3.14 1.53 4.48 4.48 0 00-7.86 3v1A10.66 10.66 0 013 4s-4 9 5 13a11.64 11.64 0 01-7 2s9 5 20 5a9.5 9.5 0 00-9-5.5c4.75 2.25 7-7 7-7a10.6 10.6 0 01-9-5.5z" />
|
||||
</svg>
|
||||
</a>
|
||||
<a
|
||||
href="#"
|
||||
className="w-12 h-12 rounded-full bg-white bg-opacity-20 hover:bg-opacity-30 flex items-center justify-center text-white transition-all duration-300 transform hover:scale-110"
|
||||
title="Facebook"
|
||||
>
|
||||
<svg
|
||||
className="w-6 h-6"
|
||||
fill="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path d="M24 12.073c0-6.627-5.373-12-12-12s-12 5.373-12 12c0 5.99 4.388 10.954 10.125 11.854v-8.385H7.078v-3.47h3.047V9.43c0-3.007 1.792-4.669 4.533-4.669 1.312 0 2.686.235 2.686.235v2.953H15.83c-1.491 0-1.956.925-1.956 1.874v2.25h3.328l-.532 3.47h-2.796v8.385C19.612 23.027 24 18.062 24 12.073z" />
|
||||
</svg>
|
||||
</a>
|
||||
<a
|
||||
href="#"
|
||||
className="w-12 h-12 rounded-full bg-white bg-opacity-20 hover:bg-opacity-30 flex items-center justify-center text-white transition-all duration-300 transform hover:scale-110"
|
||||
title="Email"
|
||||
>
|
||||
<svg
|
||||
className="w-6 h-6"
|
||||
fill="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
<path d="M20 4H4c-1.1 0-1.99.9-1.99 2L2 18c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2zm0 4l-8 5-8-5V6l8 5 8-5v2z" />
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
<p className="text-white text-xs mt-6 text-center opacity-75">
|
||||
Click to flip back
|
||||
</p>
|
||||
</div>
|
||||
<p className="text-white text-sm mt-6 text-center">
|
||||
Click to flip back
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style jsx>{`
|
||||
@keyframes slide-up {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(20px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fade-in {
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes scale {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: scale(0.95);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: scale(1);
|
||||
}
|
||||
}
|
||||
|
||||
.animate-slide-up {
|
||||
animation: slide-up 0.6s ease-out;
|
||||
}
|
||||
|
||||
.animate-fade-in {
|
||||
animation: fade-in 0.6s ease-out;
|
||||
}
|
||||
|
||||
.animate-scale {
|
||||
animation: scale 0.6s ease-out;
|
||||
}
|
||||
|
||||
.perspective {
|
||||
perspective: 1000px;
|
||||
}
|
||||
`}</style>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
@@ -1,148 +1,193 @@
|
||||
"use client";
|
||||
|
||||
import CardStackTextBox from "@/components/cardStack/CardStackTextBox";
|
||||
import MediaContent from "@/components/shared/MediaContent";
|
||||
import { useCardAnimation } from "@/components/cardStack/hooks/useCardAnimation";
|
||||
import { cls } from "@/lib/utils";
|
||||
import type { LucideIcon } from "lucide-react";
|
||||
import type { ButtonConfig, CardAnimationType, TitleSegment, ButtonAnimationType } from "@/components/cardStack/types";
|
||||
import type { TextboxLayout, InvertedBackground } from "@/providers/themeProvider/config/constants";
|
||||
import { useState } from "react";
|
||||
import { Mail, Linkedin, Twitter, Github } from "lucide-react";
|
||||
|
||||
type TeamMember = {
|
||||
id: string;
|
||||
interface TeamMember {
|
||||
id: number;
|
||||
name: string;
|
||||
role: string;
|
||||
imageSrc?: string;
|
||||
videoSrc?: string;
|
||||
imageAlt?: string;
|
||||
videoAriaLabel?: string;
|
||||
};
|
||||
|
||||
interface TeamCardFiveProps {
|
||||
team: TeamMember[];
|
||||
animationType: CardAnimationType;
|
||||
title: string;
|
||||
titleSegments?: TitleSegment[];
|
||||
description: string;
|
||||
textboxLayout: TextboxLayout;
|
||||
useInvertedBackground: InvertedBackground;
|
||||
tag?: string;
|
||||
tagIcon?: LucideIcon;
|
||||
tagAnimation?: ButtonAnimationType;
|
||||
buttons?: ButtonConfig[];
|
||||
buttonAnimation?: ButtonAnimationType;
|
||||
ariaLabel?: string;
|
||||
className?: string;
|
||||
containerClassName?: string;
|
||||
textBoxTitleClassName?: string;
|
||||
textBoxTitleImageWrapperClassName?: string;
|
||||
textBoxTitleImageClassName?: string;
|
||||
textBoxDescriptionClassName?: string;
|
||||
textBoxClassName?: string;
|
||||
textBoxTagClassName?: string;
|
||||
textBoxButtonContainerClassName?: string;
|
||||
textBoxButtonClassName?: string;
|
||||
textBoxButtonTextClassName?: string;
|
||||
gridClassName?: string;
|
||||
cardClassName?: string;
|
||||
mediaWrapperClassName?: string;
|
||||
mediaClassName?: string;
|
||||
nameClassName?: string;
|
||||
roleClassName?: string;
|
||||
image: string;
|
||||
email?: string;
|
||||
linkedin?: string;
|
||||
twitter?: string;
|
||||
github?: string;
|
||||
}
|
||||
|
||||
const TeamCardFive = ({
|
||||
team,
|
||||
animationType,
|
||||
title,
|
||||
titleSegments,
|
||||
description,
|
||||
textboxLayout,
|
||||
useInvertedBackground,
|
||||
tag,
|
||||
tagIcon,
|
||||
tagAnimation,
|
||||
buttons,
|
||||
buttonAnimation,
|
||||
ariaLabel = "Team section",
|
||||
className = "",
|
||||
containerClassName = "",
|
||||
textBoxTitleClassName = "",
|
||||
textBoxTitleImageWrapperClassName = "",
|
||||
textBoxTitleImageClassName = "",
|
||||
textBoxDescriptionClassName = "",
|
||||
textBoxClassName = "",
|
||||
textBoxTagClassName = "",
|
||||
textBoxButtonContainerClassName = "",
|
||||
textBoxButtonClassName = "",
|
||||
textBoxButtonTextClassName = "",
|
||||
gridClassName = "",
|
||||
cardClassName = "",
|
||||
mediaWrapperClassName = "",
|
||||
mediaClassName = "",
|
||||
nameClassName = "",
|
||||
roleClassName = "",
|
||||
}: TeamCardFiveProps) => {
|
||||
const { itemRefs } = useCardAnimation({ animationType, itemCount: team.length });
|
||||
interface Props {
|
||||
members?: TeamMember[];
|
||||
}
|
||||
|
||||
const defaultMembers: TeamMember[] = [
|
||||
{
|
||||
id: 1,
|
||||
name: "Sarah Johnson",
|
||||
role: "Chief Executive Officer",
|
||||
image: "https://images.unsplash.com/photo-1494790108377-be9c29b29330?w=400&h=400&fit=crop",
|
||||
email: "sarah@example.com",
|
||||
linkedin: "https://linkedin.com",
|
||||
twitter: "https://twitter.com",
|
||||
github: "https://github.com",
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: "Michael Chen",
|
||||
role: "Chief Technology Officer",
|
||||
image: "https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?w=400&h=400&fit=crop",
|
||||
email: "michael@example.com",
|
||||
linkedin: "https://linkedin.com",
|
||||
twitter: "https://twitter.com",
|
||||
github: "https://github.com",
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: "Emily Rodriguez",
|
||||
role: "Chief Financial Officer",
|
||||
image: "https://images.unsplash.com/photo-1438761681033-6461ffad8d80?w=400&h=400&fit=crop",
|
||||
email: "emily@example.com",
|
||||
linkedin: "https://linkedin.com",
|
||||
twitter: "https://twitter.com",
|
||||
github: "https://github.com",
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
name: "David Park",
|
||||
role: "Chief Product Officer",
|
||||
image: "https://images.unsplash.com/photo-1500648767791-00dcc994a43e?w=400&h=400&fit=crop",
|
||||
email: "david@example.com",
|
||||
linkedin: "https://linkedin.com",
|
||||
twitter: "https://twitter.com",
|
||||
github: "https://github.com",
|
||||
},
|
||||
];
|
||||
|
||||
export default function TeamCardFive({ members = defaultMembers }: Props) {
|
||||
const [flipped, setFlipped] = useState<{ [key: number]: boolean }>({});
|
||||
|
||||
const toggleFlip = (id: number) => {
|
||||
setFlipped((prev) => ({
|
||||
...prev,
|
||||
[id]: !prev[id],
|
||||
}));
|
||||
};
|
||||
|
||||
return (
|
||||
<section
|
||||
aria-label={ariaLabel}
|
||||
className={cls("relative py-20 w-full", useInvertedBackground && "bg-foreground", className)}
|
||||
>
|
||||
<div className={cls("w-content-width mx-auto flex flex-col gap-8", containerClassName)}>
|
||||
<CardStackTextBox
|
||||
title={title}
|
||||
titleSegments={titleSegments}
|
||||
description={description}
|
||||
tag={tag}
|
||||
tagIcon={tagIcon}
|
||||
tagAnimation={tagAnimation}
|
||||
buttons={buttons}
|
||||
buttonAnimation={buttonAnimation}
|
||||
textboxLayout={textboxLayout}
|
||||
useInvertedBackground={useInvertedBackground}
|
||||
textBoxClassName={textBoxClassName}
|
||||
titleClassName={textBoxTitleClassName}
|
||||
titleImageWrapperClassName={textBoxTitleImageWrapperClassName}
|
||||
titleImageClassName={textBoxTitleImageClassName}
|
||||
descriptionClassName={textBoxDescriptionClassName}
|
||||
tagClassName={textBoxTagClassName}
|
||||
buttonContainerClassName={textBoxButtonContainerClassName}
|
||||
buttonClassName={textBoxButtonClassName}
|
||||
buttonTextClassName={textBoxButtonTextClassName}
|
||||
/>
|
||||
<section className="py-16 px-4 sm:px-6 lg:px-8 bg-gradient-to-b from-white to-gray-50">
|
||||
<div className="max-w-7xl mx-auto">
|
||||
<div className="text-center mb-12">
|
||||
<h2 className="text-4xl font-bold text-gray-900 mb-4">
|
||||
Meet Our Leadership
|
||||
</h2>
|
||||
<p className="text-xl text-gray-600">
|
||||
Hover over cards to see social links
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className={cls("flex flex-row flex-wrap gap-y-6 md:gap-x-0 justify-center", gridClassName)}>
|
||||
{team.map((member, index) => (
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
|
||||
{members.map((member) => (
|
||||
<div
|
||||
key={member.id}
|
||||
ref={(el) => { itemRefs.current[index] = el; }}
|
||||
className={cls("relative flex flex-col items-center text-center w-[55%] md:w-[28%] -mx-[4%] md:-mx-[2%]", cardClassName)}
|
||||
className="h-80 cursor-pointer perspective"
|
||||
onClick={() => toggleFlip(member.id)}
|
||||
>
|
||||
<div className={cls("relative card w-full aspect-square rounded-theme overflow-hidden p-2 mb-4", mediaWrapperClassName)}>
|
||||
<MediaContent
|
||||
imageSrc={member.imageSrc}
|
||||
videoSrc={member.videoSrc}
|
||||
imageAlt={member.imageAlt || member.name}
|
||||
videoAriaLabel={member.videoAriaLabel || member.name}
|
||||
imageClassName={cls("relative z-1 w-full h-full object-cover rounded-theme!", mediaClassName)}
|
||||
/>
|
||||
<div
|
||||
className="relative w-full h-full transition-transform duration-500 transform-gpu"
|
||||
style={{
|
||||
transformStyle: "preserve-3d",
|
||||
transform: flipped[member.id]
|
||||
? "rotateY(180deg)"
|
||||
: "rotateY(0deg)",
|
||||
}}
|
||||
>
|
||||
{/* Front of card */}
|
||||
<div
|
||||
className="absolute w-full h-full bg-white rounded-lg shadow-lg overflow-hidden"
|
||||
style={{
|
||||
backfaceVisibility: "hidden",
|
||||
}}
|
||||
>
|
||||
<div className="relative w-full h-full flex flex-col items-center justify-center">
|
||||
<img
|
||||
src={member.image}
|
||||
alt={member.name}
|
||||
className="w-full h-full object-cover"
|
||||
/>
|
||||
<div className="absolute inset-0 bg-gradient-to-t from-black via-transparent to-transparent opacity-60"></div>
|
||||
<div className="absolute bottom-0 left-0 right-0 p-6 text-white">
|
||||
<h3 className="text-2xl font-bold mb-2">{member.name}</h3>
|
||||
<p className="text-sm text-gray-200">{member.role}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Back of card */}
|
||||
<div
|
||||
className="absolute w-full h-full bg-gradient-to-br from-blue-600 to-blue-800 rounded-lg shadow-lg p-6 flex flex-col items-center justify-center"
|
||||
style={{
|
||||
backfaceVisibility: "hidden",
|
||||
transform: "rotateY(180deg)",
|
||||
}}
|
||||
>
|
||||
<h3 className="text-white text-xl font-bold mb-6 text-center">
|
||||
{member.name}
|
||||
</h3>
|
||||
<div className="flex flex-col gap-4 w-full">
|
||||
{member.email && (
|
||||
<a
|
||||
href={`mailto:${member.email}`}
|
||||
className="flex items-center justify-center gap-3 bg-white bg-opacity-20 hover:bg-opacity-30 text-white py-2 px-4 rounded-lg transition-all duration-200 transform hover:scale-105"
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
<Mail size={20} />
|
||||
<span className="text-sm">Email</span>
|
||||
</a>
|
||||
)}
|
||||
{member.linkedin && (
|
||||
<a
|
||||
href={member.linkedin}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="flex items-center justify-center gap-3 bg-white bg-opacity-20 hover:bg-opacity-30 text-white py-2 px-4 rounded-lg transition-all duration-200 transform hover:scale-105"
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
<Linkedin size={20} />
|
||||
<span className="text-sm">LinkedIn</span>
|
||||
</a>
|
||||
)}
|
||||
{member.twitter && (
|
||||
<a
|
||||
href={member.twitter}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="flex items-center justify-center gap-3 bg-white bg-opacity-20 hover:bg-opacity-30 text-white py-2 px-4 rounded-lg transition-all duration-200 transform hover:scale-105"
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
<Twitter size={20} />
|
||||
<span className="text-sm">Twitter</span>
|
||||
</a>
|
||||
)}
|
||||
{member.github && (
|
||||
<a
|
||||
href={member.github}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="flex items-center justify-center gap-3 bg-white bg-opacity-20 hover:bg-opacity-30 text-white py-2 px-4 rounded-lg transition-all duration-200 transform hover:scale-105"
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
<Github size={20} />
|
||||
<span className="text-sm">GitHub</span>
|
||||
</a>
|
||||
)}
|
||||
</div>
|
||||
<p className="text-white text-xs mt-6 text-center opacity-75">
|
||||
Click to flip back
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<h3 className={cls("relative z-1 w-8/10 text-2xl font-medium leading-tight truncate", useInvertedBackground ? "text-background" : "text-foreground", nameClassName)}>
|
||||
{member.name}
|
||||
</h3>
|
||||
<p className={cls("relative z-1 w-8/10 text-base leading-tight mt-1 truncate", useInvertedBackground ? "text-background/75" : "text-foreground/75", roleClassName)}>
|
||||
{member.role}
|
||||
</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
TeamCardFive.displayName = "TeamCardFive";
|
||||
|
||||
export default TeamCardFive;
|
||||
}
|
||||
@@ -44,29 +44,27 @@ export default function TestimonialCardTwelve({
|
||||
];
|
||||
|
||||
return (
|
||||
<section className={`py-16 px-4 ${useInvertedBackground ? 'bg-gray-900' : 'bg-white'}`}>
|
||||
<section className={`py-16 px-4 ${useInvertedBackground ? 'bg-gray-900 text-white' : 'bg-white text-gray-900'}`}>
|
||||
<div className="max-w-6xl mx-auto">
|
||||
<div className="text-center mb-12">
|
||||
<div className="flex items-center justify-center gap-2 mb-4">
|
||||
{TagIcon && <TagIcon className="w-5 h-5 text-blue-600" />}
|
||||
<span className="text-sm font-semibold text-blue-600 uppercase tracking-wide">
|
||||
{cardTag}
|
||||
</span>
|
||||
{TagIcon && <TagIcon className="w-5 h-5" />}
|
||||
<span className="text-sm font-semibold text-blue-600">{cardTag}</span>
|
||||
</div>
|
||||
<h2 className={`text-3xl md:text-4xl font-bold ${useInvertedBackground ? 'text-white' : 'text-gray-900'}`}>
|
||||
{cardTitle}
|
||||
</h2>
|
||||
<h2 className="text-3xl md:text-4xl font-bold mb-4">{cardTitle}</h2>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
|
||||
{testimonials.map((testimonial) => (
|
||||
<div
|
||||
key={testimonial.id}
|
||||
className={`h-80 cursor-pointer perspective ${cardAnimation === 'slide-up' ? 'animate-slide-up' : ''}`}
|
||||
className="h-80 cursor-pointer perspective"
|
||||
onClick={() => toggleFlip(testimonial.id)}
|
||||
>
|
||||
<div
|
||||
className="relative w-full h-full transition-transform duration-500 transform-gpu"
|
||||
className={`relative w-full h-full transition-transform duration-500 transform-gpu ${
|
||||
flipped[testimonial.id] ? '[transform:rotateY(180deg)]' : ''
|
||||
}`}
|
||||
style={{
|
||||
transformStyle: 'preserve-3d',
|
||||
transform: flipped[testimonial.id] ? 'rotateY(180deg)' : 'rotateY(0deg)',
|
||||
@@ -74,10 +72,8 @@ export default function TestimonialCardTwelve({
|
||||
>
|
||||
{/* Front of card */}
|
||||
<div
|
||||
className="absolute w-full h-full bg-white rounded-lg shadow-lg overflow-hidden"
|
||||
style={{
|
||||
backfaceVisibility: 'hidden',
|
||||
}}
|
||||
className="absolute w-full h-full bg-gray-100 rounded-lg overflow-hidden shadow-lg"
|
||||
style={{ backfaceVisibility: 'hidden' }}
|
||||
>
|
||||
<div className="relative w-full h-full">
|
||||
<Image
|
||||
@@ -100,9 +96,7 @@ export default function TestimonialCardTwelve({
|
||||
transform: 'rotateY(180deg)',
|
||||
}}
|
||||
>
|
||||
<h3 className="text-white text-lg font-semibold mb-6 text-center">
|
||||
{testimonial.name}
|
||||
</h3>
|
||||
<h3 className="text-white text-lg font-semibold mb-6 text-center">{testimonial.name}</h3>
|
||||
<div className="flex flex-col gap-4 w-full">
|
||||
{socialLinks.map((link) => (
|
||||
<a
|
||||
@@ -116,33 +110,13 @@ export default function TestimonialCardTwelve({
|
||||
</a>
|
||||
))}
|
||||
</div>
|
||||
<p className="text-white/70 text-xs mt-6 text-center">Click to flip back</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style jsx>{`
|
||||
@keyframes slide-up {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(20px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
.animate-slide-up {
|
||||
animation: slide-up 0.6s ease-out forwards;
|
||||
}
|
||||
|
||||
.perspective {
|
||||
perspective: 1000px;
|
||||
}
|
||||
`}</style>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
217
src/tag/Tag.tsx
217
src/tag/Tag.tsx
@@ -57,131 +57,122 @@ const defaultMembers: TeamMember[] = [
|
||||
},
|
||||
];
|
||||
|
||||
export default function Tag({ members = defaultMembers }: TagProps) {
|
||||
const [flipped, setFlipped] = useState<{ [key: string]: boolean }>({});
|
||||
|
||||
const toggleFlip = (id: string) => {
|
||||
setFlipped((prev) => ({
|
||||
...prev,
|
||||
[id]: !prev[id],
|
||||
}));
|
||||
};
|
||||
function TeamCard({ member }: { member: TeamMember }) {
|
||||
const [isFlipped, setIsFlipped] = useState(false);
|
||||
|
||||
return (
|
||||
<section className="py-16 px-4 sm:px-6 lg:px-8 bg-gradient-to-b from-white to-gray-50">
|
||||
<div className="max-w-7xl mx-auto">
|
||||
<div
|
||||
className="h-80 cursor-pointer perspective"
|
||||
onMouseEnter={() => setIsFlipped(true)}
|
||||
onMouseLeave={() => setIsFlipped(false)}
|
||||
>
|
||||
<div
|
||||
className={`relative w-full h-full transition-transform duration-500 transform-gpu ${
|
||||
isFlipped ? "[transform:rotateY(180deg)]" : ""
|
||||
}`}
|
||||
style={{
|
||||
transformStyle: "preserve-3d",
|
||||
transform: isFlipped ? "rotateY(180deg)" : "rotateY(0deg)",
|
||||
}}
|
||||
>
|
||||
{/* Front of card */}
|
||||
<div
|
||||
className="absolute w-full h-full bg-white rounded-lg shadow-lg overflow-hidden flex flex-col items-center justify-center p-6"
|
||||
style={{ backfaceVisibility: "hidden" }}
|
||||
>
|
||||
<img
|
||||
src={member.image}
|
||||
alt={member.name}
|
||||
className="w-32 h-32 rounded-full object-cover mb-4"
|
||||
/>
|
||||
<h3 className="text-xl font-bold text-gray-900 text-center">
|
||||
{member.name}
|
||||
</h3>
|
||||
<p className="text-sm text-gray-600 text-center mt-2">
|
||||
{member.title}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Back of card */}
|
||||
<div
|
||||
className="absolute w-full h-full bg-gradient-to-br from-blue-600 to-blue-800 rounded-lg shadow-lg overflow-hidden flex flex-col items-center justify-center p-6"
|
||||
style={{
|
||||
backfaceVisibility: "hidden",
|
||||
transform: "rotateY(180deg)",
|
||||
}}
|
||||
>
|
||||
<h3 className="text-white font-bold text-lg mb-6 text-center">
|
||||
Connect
|
||||
</h3>
|
||||
<div className="flex flex-wrap gap-4 justify-center">
|
||||
{member.email && (
|
||||
<a
|
||||
href={`mailto:${member.email}`}
|
||||
className="bg-white bg-opacity-20 hover:bg-opacity-30 text-white p-3 rounded-full transition-all duration-200 transform hover:scale-110"
|
||||
title="Email"
|
||||
>
|
||||
<Mail size={20} />
|
||||
</a>
|
||||
)}
|
||||
{member.linkedin && (
|
||||
<a
|
||||
href={member.linkedin}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="bg-white bg-opacity-20 hover:bg-opacity-30 text-white p-3 rounded-full transition-all duration-200 transform hover:scale-110"
|
||||
title="LinkedIn"
|
||||
>
|
||||
<Linkedin size={20} />
|
||||
</a>
|
||||
)}
|
||||
{member.twitter && (
|
||||
<a
|
||||
href={member.twitter}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="bg-white bg-opacity-20 hover:bg-opacity-30 text-white p-3 rounded-full transition-all duration-200 transform hover:scale-110"
|
||||
title="Twitter"
|
||||
>
|
||||
<Twitter size={20} />
|
||||
</a>
|
||||
)}
|
||||
{member.github && (
|
||||
<a
|
||||
href={member.github}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="bg-white bg-opacity-20 hover:bg-opacity-30 text-white p-3 rounded-full transition-all duration-200 transform hover:scale-110"
|
||||
title="GitHub"
|
||||
>
|
||||
<Github size={20} />
|
||||
</a>
|
||||
)}
|
||||
</div>
|
||||
<p className="text-white text-xs mt-6 text-center opacity-75">
|
||||
Hover to flip back
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default function Tag({ members = defaultMembers }: TagProps) {
|
||||
return (
|
||||
<section className="py-16 px-4 bg-gray-50">
|
||||
<div className="max-w-6xl mx-auto">
|
||||
<div className="text-center mb-12">
|
||||
<h2 className="text-4xl font-bold text-gray-900 mb-4">
|
||||
Meet Our Leadership
|
||||
</h2>
|
||||
<p className="text-lg text-gray-600">
|
||||
Exceptional leaders driving innovation and excellence
|
||||
Hover over each card to see social links
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
|
||||
{members.map((member) => (
|
||||
<div
|
||||
key={member.id}
|
||||
className="h-80 cursor-pointer perspective"
|
||||
onClick={() => toggleFlip(member.id)}
|
||||
>
|
||||
<div
|
||||
className="relative w-full h-full transition-transform duration-500 transform-gpu"
|
||||
style={{
|
||||
transformStyle: "preserve-3d",
|
||||
transform: flipped[member.id]
|
||||
? "rotateY(180deg)"
|
||||
: "rotateY(0deg)",
|
||||
}}
|
||||
>
|
||||
{/* Front of card */}
|
||||
<div
|
||||
className="absolute w-full h-full bg-white rounded-lg shadow-lg overflow-hidden"
|
||||
style={{ backfaceVisibility: "hidden" }}
|
||||
>
|
||||
<img
|
||||
src={member.image}
|
||||
alt={member.name}
|
||||
className="w-full h-64 object-cover"
|
||||
/>
|
||||
<div className="p-6 text-center">
|
||||
<h3 className="text-xl font-bold text-gray-900 mb-2">
|
||||
{member.name}
|
||||
</h3>
|
||||
<p className="text-sm text-gray-600">{member.title}</p>
|
||||
<p className="text-xs text-gray-400 mt-3">
|
||||
Hover to see social links
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Back of card */}
|
||||
<div
|
||||
className="absolute w-full h-full bg-gradient-to-br from-blue-600 to-blue-800 rounded-lg shadow-lg p-6 flex flex-col justify-center items-center"
|
||||
style={{
|
||||
backfaceVisibility: "hidden",
|
||||
transform: "rotateY(180deg)",
|
||||
}}
|
||||
>
|
||||
<h3 className="text-white text-lg font-bold mb-6 text-center">
|
||||
{member.name}
|
||||
</h3>
|
||||
|
||||
<div className="flex flex-col gap-4 w-full">
|
||||
{member.email && (
|
||||
<a
|
||||
href={`mailto:${member.email}`}
|
||||
className="flex items-center justify-center gap-3 bg-white bg-opacity-20 hover:bg-opacity-30 text-white py-2 px-4 rounded-lg transition-all duration-200"
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
<Mail size={18} />
|
||||
<span className="text-sm">Email</span>
|
||||
</a>
|
||||
)}
|
||||
|
||||
{member.linkedin && (
|
||||
<a
|
||||
href={member.linkedin}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="flex items-center justify-center gap-3 bg-white bg-opacity-20 hover:bg-opacity-30 text-white py-2 px-4 rounded-lg transition-all duration-200"
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
<Linkedin size={18} />
|
||||
<span className="text-sm">LinkedIn</span>
|
||||
</a>
|
||||
)}
|
||||
|
||||
{member.twitter && (
|
||||
<a
|
||||
href={member.twitter}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="flex items-center justify-center gap-3 bg-white bg-opacity-20 hover:bg-opacity-30 text-white py-2 px-4 rounded-lg transition-all duration-200"
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
<Twitter size={18} />
|
||||
<span className="text-sm">Twitter</span>
|
||||
</a>
|
||||
)}
|
||||
|
||||
{member.github && (
|
||||
<a
|
||||
href={member.github}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="flex items-center justify-center gap-3 bg-white bg-opacity-20 hover:bg-opacity-30 text-white py-2 px-4 rounded-lg transition-all duration-200"
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
<Github size={18} />
|
||||
<span className="text-sm">GitHub</span>
|
||||
</a>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<TeamCard key={member.id} member={member} />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user