feat: add animated components for enhanced UI/UX
- Introduced DrawLine component for drawing animations. - Added LazyRevealImage component for lazy loading images with reveal animations. - Implemented TextDiffuseReveal for animated text reveals with staggered effects. - Created TopProgressBar for a dynamic loading indicator. - Added PointCloud mock for testing animations. - Developed useReducedMotion hook to handle user preferences for reduced motion. - Centralized animation configurations in config.ts for easier management. - Defined animation variants in variants.ts for consistent animation effects. - Established AnimationProvider to supply global animation settings. - Created tests for AnimationProvider and useReducedMotion hook. - Added SVG assets for branding and UI elements. - Documented frontend review plan and hero circuit board animation plan.
This commit is contained in:
1 parent
0ab6930f92
commit
08dd046887
76 files changed
+21682
-1197
No files matched your search
+82
-14
@@ -2,11 +2,14 @@
|
||||
|
||||
import type React from "react";
|
||||
import { useState } from "react";
|
||||
import { motion, type Variants, useReducedMotion } from "framer-motion";
|
||||
import { Section } from "./Section";
|
||||
import { DrawLine } from "./animations/DrawLine";
|
||||
|
||||
const WHATSAPP_NUMBER = "5547992742365";
|
||||
|
||||
export default function Contact() {
|
||||
const shouldReduceMotion = useReducedMotion();
|
||||
const [formData, setFormData] = useState({
|
||||
name: "",
|
||||
email: "",
|
||||
@@ -25,30 +28,88 @@ export default function Contact() {
|
||||
window.open(whatsappUrl, "_blank", "noopener,noreferrer");
|
||||
};
|
||||
|
||||
const gridVariants: Variants = {
|
||||
hidden: {},
|
||||
visible: {
|
||||
transition: {
|
||||
delayChildren: 0.05,
|
||||
staggerChildren: 0.08,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
const cardVariants: Variants = {
|
||||
hidden: shouldReduceMotion
|
||||
? { opacity: 0 }
|
||||
: { opacity: 0, y: 18, clipPath: "inset(100% 0 0 0)" },
|
||||
visible: {
|
||||
opacity: 1,
|
||||
y: 0,
|
||||
clipPath: "inset(0% 0 0 0)",
|
||||
transition: shouldReduceMotion
|
||||
? { duration: 0.25 }
|
||||
: { duration: 0.75, ease: [0.16, 1, 0.3, 1] },
|
||||
},
|
||||
};
|
||||
|
||||
return (
|
||||
<Section
|
||||
id="contact"
|
||||
eyebrow="CONTACT_PROTOCOL.init"
|
||||
title="Vamos discutir o próximo sistema"
|
||||
title="Vamos discutir o proximo sistema"
|
||||
description="Descreva o contexto, o gargalo ou o produto. O contato abre direto no WhatsApp com briefing estruturado."
|
||||
dark
|
||||
disableChildrenAnimation
|
||||
>
|
||||
<div className="ds-grid-2">
|
||||
<div className="ds-card">
|
||||
<motion.div
|
||||
className="ds-grid-2"
|
||||
initial="hidden"
|
||||
whileInView="visible"
|
||||
viewport={{ once: true, amount: 0.2 }}
|
||||
variants={gridVariants}
|
||||
>
|
||||
<motion.div
|
||||
className="ds-card"
|
||||
variants={cardVariants}
|
||||
whileHover={
|
||||
shouldReduceMotion
|
||||
? undefined
|
||||
: {
|
||||
y: -4,
|
||||
boxShadow: "0 20px 42px rgba(0, 0, 0, 0.4)",
|
||||
}
|
||||
}
|
||||
whileTap={shouldReduceMotion ? undefined : { scale: 0.995 }}
|
||||
transition={{ type: "spring", stiffness: 180, damping: 18 }}
|
||||
>
|
||||
<div className="ds-kicker">Response SLA</div>
|
||||
<h3 className="ds-card-title">Retorno inicial em até 24h</h3>
|
||||
<DrawLine delay={0.04} />
|
||||
<h3 className="ds-card-title">Retorno inicial em ate 24h</h3>
|
||||
<p className="ds-copy">
|
||||
Ideal para discovery técnico, revisão de arquitetura, rescue de
|
||||
projeto, otimização de performance ou construção de produto do zero.
|
||||
Ideal para discovery tecnico, revisao de arquitetura, rescue de
|
||||
projeto, otimizacao de performance ou construcao de produto do zero.
|
||||
</p>
|
||||
<div className="mt-sp-6 space-y-sp-4 text-[12px] leading-7 text-[rgba(255,255,255,.7)]">
|
||||
<div>WhatsApp: +55 47 99274-2365</div>
|
||||
<div>E-mail: evandrofonsecajunior@gmail.com</div>
|
||||
<div>Base: Garuva, Santa Catarina · atuação remota</div>
|
||||
<div>Base: Garuva, Santa Catarina | atuacao remota</div>
|
||||
</div>
|
||||
</div>
|
||||
</motion.div>
|
||||
|
||||
<form onSubmit={handleSubmit} className="ds-card space-y-sp-5">
|
||||
<motion.form
|
||||
onSubmit={handleSubmit}
|
||||
className="ds-card space-y-sp-5"
|
||||
variants={cardVariants}
|
||||
whileHover={
|
||||
shouldReduceMotion
|
||||
? undefined
|
||||
: {
|
||||
y: -4,
|
||||
boxShadow: "0 20px 42px rgba(0, 0, 0, 0.4)",
|
||||
}
|
||||
}
|
||||
transition={{ type: "spring", stiffness: 180, damping: 18 }}
|
||||
>
|
||||
<div>
|
||||
<label htmlFor="contact-name" className="ds-kicker block">
|
||||
Nome completo
|
||||
@@ -103,7 +164,7 @@ export default function Contact() {
|
||||
<option value="full-stack">Desenvolvimento Full-Stack</option>
|
||||
<option value="cloud">Cloud & Infrastructure</option>
|
||||
<option value="iot">Internet of Things (IoT)</option>
|
||||
<option value="consultancy">Consultoria Técnica Sênior</option>
|
||||
<option value="consultancy">Consultoria Tecnica Senior</option>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
@@ -125,11 +186,18 @@ export default function Contact() {
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<button type="submit" className="ds-link ds-link-accent border-0">
|
||||
|
||||
<motion.button
|
||||
type="submit"
|
||||
className="ds-link ds-link-accent border-0"
|
||||
whileHover={shouldReduceMotion ? undefined : { scale: 1.03 }}
|
||||
whileTap={shouldReduceMotion ? undefined : { scale: 0.97 }}
|
||||
transition={{ type: "spring", stiffness: 260, damping: 20 }}
|
||||
>
|
||||
Iniciar protocolo de contato
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</motion.button>
|
||||
</motion.form>
|
||||
</motion.div>
|
||||
</Section>
|
||||
);
|
||||
}
|
||||
Reference in new issue
Block a user