FlowWeb / src /features /landing /components /HeroSection.jsx
danylokhodus's picture
feat: rebrand QuestboardAI -> TaskFlow everywhere (UI, locales, index.html)
abb5ee1
Raw
History Blame Contribute Delete
6.28 kB
import React from 'react';
import { motion } from 'framer-motion';
import { useTranslation } from 'react-i18next';
const HeroSection = () => {
const { t } = useTranslation();
return (
<section className="w-full flex flex-col items-center text-center gap-10 px-margin_edge max-w-screen-2xl mx-auto py-12 md:py-24">
<div className="max-w-4xl flex flex-col gap-6">
<motion.h1
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.6 }}
className="text-5xl md:text-8xl font-display-lg text-primary leading-tight"
>
{t('landing.hero_title_p1', 'Plans break.')} <br />
<span className="highlighter-bg px-4">{t('landing.hero_title_p2', 'TaskFlow adapts.')}</span>
</motion.h1>
<motion.p
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.6, delay: 0.2 }}
className="text-2xl md:text-3xl text-on-surface-variant max-w-3xl mx-auto leading-relaxed"
>
{t('landing.hero_desc', "The first visual goal constructor designed for focus. Move from linear lists to adaptive graphs that handle life's \"If/Then\" moments.")}
</motion.p>
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.6, delay: 0.4 }}
className="mt-6 font-accent-note text-3xl text-secondary flex items-center justify-center gap-3"
>
<span className="material-symbols-outlined text-4xl" style={{ fontVariationSettings: '"FILL" 1' }}>psychology</span>
{t('landing.hero_badge', 'ADHD-friendly. Resilience-driven.')}
</motion.div>
</div>
{/* Hero Visual: Mockup */}
<motion.div
initial={{ opacity: 0, scale: 0.95 }}
whileInView={{ opacity: 1, scale: 1 }}
viewport={{ once: true }}
transition={{ duration: 1, ease: "easeOut" }}
className="w-full max-w-5xl mt-12 relative min-h-[500px] flex items-center justify-center border-2 border-dashed border-primary/30 rounded-2xl bg-white rough-shadow p-12 overflow-visible"
>
{/* SVG Connections */}
<svg className="absolute inset-0 w-full h-full pointer-events-none overflow-visible" style={{ zIndex: 0 }}>
<defs>
<marker id="arrowhead" markerWidth="10" markerHeight="7" refX="0" refY="3.5" orient="auto">
<polygon points="0 0, 10 3.5, 0 7" fill="#181919" />
</marker>
</defs>
<motion.path
initial={{ pathLength: 0 }}
whileInView={{ pathLength: 1 }}
viewport={{ once: true }}
transition={{ duration: 1.5, ease: "easeInOut" }}
d="M 180 250 Q 260 220 340 250"
fill="none" stroke="#181919" strokeWidth="4" strokeLinecap="round" strokeDasharray="8 6"
/>
<motion.path
initial={{ pathLength: 0 }}
whileInView={{ pathLength: 1 }}
viewport={{ once: true }}
transition={{ duration: 1.2, delay: 0.5 }}
d="M 460 250 Q 530 250 580 250"
fill="none" stroke="#181919" strokeWidth="4" strokeLinecap="round"
/>
<motion.path
initial={{ pathLength: 0 }}
whileInView={{ pathLength: 1 }}
viewport={{ once: true }}
transition={{ duration: 1.2, delay: 1.5 }}
d="M 720 250 Q 780 160 850 160"
fill="none" stroke="#45a84a" strokeWidth="4" strokeLinecap="round"
/>
<motion.path
initial={{ pathLength: 0 }}
whileInView={{ pathLength: 1 }}
viewport={{ once: true }}
transition={{ duration: 1.2, delay: 1.7 }}
d="M 720 250 Q 780 340 850 340"
fill="none" stroke="#ba1a1a" strokeWidth="4" strokeLinecap="round"
/>
</svg>
{/* Nodes */}
{[
{ label: t('landing.node_a', 'Task A'), pos: 'left-12 top-[210px]', rot: -2, delay: 0.2 },
{ label: t('landing.node_b', 'Task B'), pos: 'left-[340px] top-[210px]', rot: 1, delay: 0.4 },
{ label: t('landing.node_failed', 'Failed?'), pos: 'left-[580px] top-[180px]', rot: 45, diamond: true, delay: 0.6 },
{ label: t('landing.node_c', 'Task C'), pos: 'right-12 top-[120px]', rot: 2, delay: 0.8, color: '#45a84a' },
{ label: t('landing.node_d', 'Task D'), pos: 'right-12 top-[300px]', rot: -1, delay: 1.0, color: '#ba1a1a' }
].map((node, i) => (
<motion.div
key={i}
initial={{ opacity: 0, scale: 0 }}
whileInView={{ opacity: 1, scale: 1 }}
animate={{
y: [0, i % 2 === 0 ? -8 : 8, 0],
rotate: node.diamond ? [45, 47, 43, 45] : [node.rot, node.rot + 1, node.rot - 1, node.rot]
}}
transition={{
initial: { delay: node.delay, type: "spring", stiffness: 200 },
animate: { repeat: Infinity, duration: 5 + i, ease: "easeInOut" }
}}
viewport={{ once: true }}
className={`absolute ${node.pos} z-10 flex items-center justify-center p-2 group overflow-visible`}
>
{node.diamond ? (
<div className="w-36 h-36 flex items-center justify-center relative">
<div className="absolute inset-0 border-4 border-primary bg-white shadow-[8px_8px_0px_0px_rgba(0,0,0,0.15)] rotate-45 transform transition-transform group-hover:scale-105" />
<span className="relative font-display-lg text-2xl text-primary font-bold">{node.label}</span>
</div>
) : (
<div
style={{ borderColor: node.color || 'var(--color-primary)' }}
className={`bg-white p-6 border-4 rounded-xl shadow-[8px_8px_0px_0px_rgba(0,0,0,0.1)] w-40 text-center transform transition-transform group-hover:scale-105 group-hover:-rotate-2`}
>
<span className="text-2xl font-bold">{node.label}</span>
</div>
)}
</motion.div>
))}
</motion.div>
</section>
);
};
export default HeroSection;