feat: Implement initial portfolio website structure and core components including main page, header, hero, contact, and work modalities.

This commit is contained in:
Evandro Fonseca Junior committed 2026-03-07 15:17:05 -03:00
1 parent 0523052864
commit 6299ae040a
7 files changed
+332 -206

No files matched your search

+13 -5
View File
@@ -39,8 +39,7 @@ export default function Contact() {
<h3 className="ds-card-title">Retorno inicial em até 24h</h3> <h3 className="ds-card-title">Retorno inicial em até 24h</h3>
<p className="ds-copy"> <p className="ds-copy">
Ideal para discovery técnico, revisão de arquitetura, rescue de Ideal para discovery técnico, revisão de arquitetura, rescue de
projeto, otimização de performance ou construção de produto do projeto, otimização de performance ou construção de produto do zero.
zero.
</p> </p>
<div className="mt-sp-6 space-y-sp-4 text-[12px] leading-7 text-[rgba(255,255,255,.7)]"> <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>WhatsApp: +55 47 99274-2365</div>
@@ -63,7 +62,10 @@ export default function Contact() {
setFormData({ ...formData, name: e.target.value }) setFormData({ ...formData, name: e.target.value })
} }
className="mt-sp-2 w-full border border-[rgba(255,255,255,.12)] bg-[rgba(255,255,255,.06)] px-sp-4 py-[14px] text-[12px] outline-none transition-colors focus:border-slash" className="mt-sp-2 w-full border border-[rgba(255,255,255,.12)] bg-[rgba(255,255,255,.06)] px-sp-4 py-[14px] text-[12px] outline-none transition-colors focus:border-slash"
style={{ color: "#fff", backgroundColor: "rgba(255,255,255,0.06)" }} style={{
color: "#fff",
backgroundColor: "rgba(255,255,255,0.06)",
}}
/> />
</div> </div>
<div> <div>
@@ -79,7 +81,10 @@ export default function Contact() {
setFormData({ ...formData, email: e.target.value }) setFormData({ ...formData, email: e.target.value })
} }
className="mt-sp-2 w-full border border-[rgba(255,255,255,.12)] bg-[rgba(255,255,255,.06)] px-sp-4 py-[14px] text-[12px] outline-none transition-colors focus:border-slash" className="mt-sp-2 w-full border border-[rgba(255,255,255,.12)] bg-[rgba(255,255,255,.06)] px-sp-4 py-[14px] text-[12px] outline-none transition-colors focus:border-slash"
style={{ color: "#fff", backgroundColor: "rgba(255,255,255,0.06)" }} style={{
color: "#fff",
backgroundColor: "rgba(255,255,255,0.06)",
}}
/> />
</div> </div>
<div> <div>
@@ -114,7 +119,10 @@ export default function Contact() {
setFormData({ ...formData, message: e.target.value }) setFormData({ ...formData, message: e.target.value })
} }
className="mt-sp-2 w-full resize-none border border-[rgba(255,255,255,.12)] bg-[rgba(255,255,255,.06)] px-sp-4 py-[14px] text-[12px] outline-none transition-colors focus:border-slash" className="mt-sp-2 w-full resize-none border border-[rgba(255,255,255,.12)] bg-[rgba(255,255,255,.06)] px-sp-4 py-[14px] text-[12px] outline-none transition-colors focus:border-slash"
style={{ color: "#fff", backgroundColor: "rgba(255,255,255,0.06)" }} style={{
color: "#fff",
backgroundColor: "rgba(255,255,255,0.06)",
}}
/> />
</div> </div>
<button type="submit" className="ds-link ds-link-accent border-0"> <button type="submit" className="ds-link ds-link-accent border-0">
+10 -6
View File
@@ -17,9 +17,7 @@ export function Header() {
const [mobileMenuOpen, setMobileMenuOpen] = useState(false); const [mobileMenuOpen, setMobileMenuOpen] = useState(false);
return ( return (
<header <header className="ds-section-dark fixed inset-x-0 top-0 z-50 h-[52px] w-full border-b border-[rgba(255,255,255,0.06)] bg-[var(--ink)]/95 px-sp-6 backdrop-blur-xl lg:px-sp-16">
className="ds-section-dark fixed inset-x-0 top-0 z-50 h-[52px] w-full border-b border-[rgba(255,255,255,0.06)] bg-[var(--ink)]/95 px-sp-6 backdrop-blur-xl lg:px-sp-16"
>
<div className="ds-section-shell flex h-full items-center justify-between"> <div className="ds-section-shell flex h-full items-center justify-between">
<a href="#home" className="flex items-center gap-3 no-underline"> <a href="#home" className="flex items-center gap-3 no-underline">
<Logo variant="mark" size="sm" theme="dark" className="shrink-0" /> <Logo variant="mark" size="sm" theme="dark" className="shrink-0" />
@@ -61,9 +59,15 @@ export function Header() {
aria-label="Menu" aria-label="Menu"
aria-expanded={mobileMenuOpen} aria-expanded={mobileMenuOpen}
> >
<span className={`h-0.5 w-5 bg-white transition-transform duration-300 ${mobileMenuOpen ? "translate-y-[6px] rotate-45" : ""}`} /> <span
<span className={`h-0.5 w-5 bg-white transition-opacity duration-300 ${mobileMenuOpen ? "opacity-0" : ""}`} /> className={`h-0.5 w-5 bg-white transition-transform duration-300 ${mobileMenuOpen ? "translate-y-[6px] rotate-45" : ""}`}
<span className={`h-0.5 w-5 bg-white transition-transform duration-300 ${mobileMenuOpen ? "-translate-y-[6px] -rotate-45" : ""}`} /> />
<span
className={`h-0.5 w-5 bg-white transition-opacity duration-300 ${mobileMenuOpen ? "opacity-0" : ""}`}
/>
<span
className={`h-0.5 w-5 bg-white transition-transform duration-300 ${mobileMenuOpen ? "-translate-y-[6px] -rotate-45" : ""}`}
/>
</button> </button>
</div> </div>
</div> </div>
+172 -111
View File
@@ -1,5 +1,7 @@
"use client"; "use client";
import { useState, useEffect } from "react";
import { motion, AnimatePresence } from "framer-motion";
import { Logo } from "./Logo"; import { Logo } from "./Logo";
const SOCIAL_LINKS = [ const SOCIAL_LINKS = [
@@ -30,13 +32,103 @@ const SOCIAL_LINKS = [
}, },
]; ];
const STATS = [ const textToType = "evandro.dev.br";
{ value: "4", accent: "px", label: "Base unit" },
{ value: "9", accent: "x", label: "Type scale" },
{ value: "4", accent: "+", label: "Core tokens" },
];
export default function Hero() { export default function Hero() {
const [phase, setPhase] = useState<"typing" | "idle" | "glitch" | "logo">(
"typing",
);
const [typedCount, setTypedCount] = useState(0);
useEffect(() => {
let timeout: NodeJS.Timeout;
if (phase === "typing") {
if (typedCount < textToType.length) {
timeout = setTimeout(() => {
setTypedCount((c) => c + 1);
}, 120); // typing speed
} else {
timeout = setTimeout(() => {
setPhase("idle");
}, 1200); // Wait after typing finishes
}
} else if (phase === "idle") {
timeout = setTimeout(() => {
setPhase("glitch");
}, 100); // trigger glitch
} else if (phase === "glitch") {
timeout = setTimeout(() => {
setPhase("logo");
}, 600); // Glitch out duration
} else if (phase === "logo") {
timeout = setTimeout(() => {
setTypedCount(0);
setPhase("typing");
}, 3500); // Logo display and blink duration
}
return () => clearTimeout(timeout);
}, [phase, typedCount]);
const renderTypedText = () => {
const chars = [];
for (let i = 0; i < typedCount; i++) {
const char = textToType[i];
if (i < 7) {
chars.push(
<span key={i} style={{ color: "#FFFFFF" }}>
{char}
</span>,
);
} else if (i === 7) {
chars.push(<br key="br1" />);
chars.push(
<span key={i} style={{ color: "#E8FF00" }}>
{char}
</span>,
);
} else if (i < 11) {
chars.push(
<span key={i} style={{ color: "#E8FF00" }}>
{char}
</span>,
);
} else if (i === 11) {
chars.push(<br key="br2" />);
chars.push(
<span key={i} style={{ color: "#FFFFFF" }}>
{char}
</span>,
);
} else {
chars.push(
<span key={i} style={{ color: "#FFFFFF" }}>
{char}
</span>,
);
}
}
// blinking cursor
if (phase === "typing" || phase === "idle") {
chars.push(
<motion.span
key="cursor"
animate={{ opacity: [1, 0] }}
transition={{ repeat: Infinity, duration: 0.8 }}
style={{
color: "#E8FF00",
display: "inline-block",
marginLeft: "4px",
}}
>
_
</motion.span>,
);
}
return chars;
};
const hour = new Date().getHours(); const hour = new Date().getHours();
const greeting = const greeting =
hour >= 8 && hour < 12 hour >= 8 && hour < 12
@@ -53,8 +145,13 @@ export default function Hero() {
<div className="pointer-events-none absolute inset-0 bg-grid-light opacity-70" /> <div className="pointer-events-none absolute inset-0 bg-grid-light opacity-70" />
<div className="pointer-events-none absolute inset-x-0 top-0 h-40 bg-[radial-gradient(circle_at_top,rgba(232,255,0,0.18),transparent_60%)]" /> <div className="pointer-events-none absolute inset-x-0 top-0 h-40 bg-[radial-gradient(circle_at_top,rgba(232,255,0,0.18),transparent_60%)]" />
<div className="relative z-10 mx-auto grid min-h-[calc(100vh-52px)] w-full max-w-[1240px] grid-cols-1 items-center gap-8 lg:grid-cols-2"> <div className="relative z-10 mx-auto grid min-h-[calc(100vh)] w-full max-w-[1000px] grid-cols-1 items-center gap-8">
<div> <motion.div
initial={{ opacity: 0, y: 30 }}
whileInView={{ opacity: 1, y: 0 }}
viewport={{ once: true, margin: "-100px" }}
transition={{ duration: 0.8, ease: "easeOut" }}
>
<div className="mb-sp-8 inline-flex items-center gap-sp-2"> <div className="mb-sp-8 inline-flex items-center gap-sp-2">
<span <span
className="h-1.5 w-1.5 animate-pulse rounded-full" className="h-1.5 w-1.5 animate-pulse rounded-full"
@@ -68,16 +165,61 @@ export default function Hero() {
</span> </span>
</div> </div>
<h1 <div className="relative mb-sp-6 flex min-h-[40vw] sm:min-h-[220px] md:min-h-[280px] lg:min-h-[350px] items-center">
className="mb-sp-6 text-[13vw] sm:text-7xl md:text-[6rem] lg:text-[7rem] xl:text-[8rem] leading-[0.9] tracking-[-0.01em]" <AnimatePresence mode="wait">
style={{ color: "#FFFFFF", fontFamily: "'Monument Extended', sans-serif", fontWeight: 800 }} {(phase === "typing" || phase === "idle") && (
> <motion.h1
evandro key="text"
<br /> initial={{ opacity: 0 }}
<span style={{ color: "#E8FF00" }}>.dev</span> animate={{ opacity: 1, filter: "blur(0px)", scale: 1 }}
<br /> exit={{ opacity: 0, filter: "blur(12px)", scale: 1.05 }}
.br transition={{ duration: 0.5, ease: "easeInOut" }}
</h1> className="absolute text-[13vw] sm:text-7xl md:text-[6rem] lg:text-[7rem] xl:text-[8rem] leading-[0.9] tracking-[-0.01em]"
style={{
color: "#FFFFFF",
fontFamily: "'Monument Extended', sans-serif",
fontWeight: 800,
}}
aria-label="evandro.dev.br"
>
{renderTypedText()}
</motion.h1>
)}
{phase === "logo" && (
<motion.div
key="logo"
initial={{ opacity: 0, scale: 0.95 }}
animate={{
opacity: [0, 1, 0, 1, 1, 0.5, 1, 0],
scale: 1,
filter: [
"blur(4px)",
"blur(0px)",
"blur(0px)",
"blur(0px)",
"blur(0px)",
"blur(2px)",
"blur(0px)",
"blur(10px)",
],
}}
transition={{
duration: 3.2,
times: [0, 0.05, 0.1, 0.15, 0.8, 0.85, 0.9, 1],
}}
className="absolute flex items-center justify-start w-full"
>
<Logo
variant="mark"
size="xl"
theme="dark"
className="w-[80%] max-w-[320px] h-auto drop-shadow-[0_0_20px_rgba(232,255,0,0.3)]"
/>
</motion.div>
)}
</AnimatePresence>
</div>
<p <p
className="mb-sp-10 max-w-[460px] text-[13px] leading-7" className="mb-sp-10 max-w-[460px] text-[13px] leading-7"
@@ -88,15 +230,24 @@ export default function Hero() {
React, Tauri e arquitetura escalavel. React, Tauri e arquitetura escalavel.
</p> </p>
<div className="mb-sp-8 flex flex-wrap items-center gap-sp-4"> <div className="mb-sp-8 mt-sp-6 flex flex-wrap items-center gap-sp-4">
<a <a
href={`https://wa.me/5547992742365?text=${encodeURIComponent(greeting)}`} href={`https://wa.me/5547992742365?text=${encodeURIComponent(greeting)}`}
className="inline-flex h-11 items-center rounded-sm px-sp-6 text-[11px] font-semibold uppercase tracking-[0.08em] no-underline transition-all duration-200 hover:-translate-y-0.5 hover:shadow-[0_0_0_1px_rgba(232,255,0,.8),0_8px_24px_rgba(232,255,0,.35)]" className="inline-flex h-11 items-center justify-center rounded-sm px-sp-6 text-[11px] font-semibold uppercase tracking-[0.08em] no-underline transition-all duration-200 hover:-translate-y-0.5 hover:shadow-[0_0_0_1px_rgba(232,255,0,.8),0_8px_24px_rgba(232,255,0,.35)]"
style={{ background: "#E8FF00", color: "#0A0A0A" }} style={{ background: "#E8FF00", color: "#0A0A0A" }}
> >
Iniciar projeto Iniciar projeto
</a> </a>
<a
href="/assets/Evandro_Fonseca_Junior_CV.pdf"
download
className="inline-flex h-11 items-center justify-center rounded-sm border px-sp-6 text-[11px] font-semibold uppercase tracking-[0.08em] no-underline transition-all duration-200 hover:-translate-y-0.5 hover:bg-white/5"
style={{ borderColor: "rgba(255,255,255,.18)", color: "#FFFFFF" }}
>
Download CV
</a>
<div className="flex items-center gap-sp-2"> <div className="flex items-center gap-sp-2">
{SOCIAL_LINKS.map((link) => ( {SOCIAL_LINKS.map((link) => (
<a <a
@@ -108,9 +259,8 @@ export default function Hero() {
? "noopener noreferrer" ? "noopener noreferrer"
: undefined : undefined
} }
className="inline-flex h-11 w-11 items-center justify-center rounded-sm border transition-all duration-200 hover:bg-white/10" className="inline-flex h-11 w-11 items-center justify-center rounded-full transition-all duration-200 hover:bg-white/10 hover:scale-110"
style={{ style={{
borderColor: "rgba(255,255,255,.18)",
color: "rgba(255,255,255,.84)", color: "rgba(255,255,255,.84)",
}} }}
aria-label={link.label} aria-label={link.label}
@@ -139,96 +289,7 @@ export default function Hero() {
Garuva, SC | Remote worldwide Garuva, SC | Remote worldwide
</div> </div>
<div </motion.div>
className="mt-sp-10 grid max-w-[440px] grid-cols-3 gap-px border max-sm:grid-cols-1"
style={{
borderColor: "rgba(255,255,255,.12)",
background: "rgba(255,255,255,.08)",
}}
>
{STATS.map((item) => (
<div
key={item.label}
className="p-5"
style={{ background: "rgba(255,255,255,.03)" }}
>
<div
className="font-display text-2xl font-extrabold tracking-[-0.03em]"
style={{ color: "#FFFFFF" }}
>
{item.value}
<span style={{ color: "#E8FF00" }}>{item.accent}</span>
</div>
<div
className="mt-sp-1 text-[9px] uppercase tracking-[0.12em]"
style={{ color: "rgba(255,255,255,.35)" }}
>
{item.label}
</div>
</div>
))}
</div>
</div>
<div className="flex flex-col items-end gap-sp-6 max-lg:items-start">
<div
className="relative flex aspect-square w-full max-w-[440px] items-center justify-center border max-lg:max-w-[320px]"
style={{
borderColor: "rgba(255,255,255,.12)",
background: "rgba(255,255,255,.03)",
}}
>
<span
className="absolute left-6 top-5 text-[9px] tracking-[0.14em]"
style={{ color: "rgba(255,255,255,.32)" }}
>
EV / LOGO MARK
</span>
<svg
width="280"
height="280"
viewBox="0 0 120 120"
fill="none"
xmlns="http://www.w3.org/2000/svg"
className="shrink-0 transition-transform duration-700 hover:scale-110"
>
<rect x="20" y="30" width="12" height="60" fill="currentColor" />
<rect x="32" y="30" width="28" height="12" fill="currentColor" />
<rect x="32" y="54" width="18" height="12" fill="currentColor" />
<rect x="32" y="78" width="28" height="12" fill="currentColor" />
<polygon points="62,90 74,90 92,30 80,30" fill="var(--slash)" />
<circle cx="104" cy="84" r="6" fill="currentColor" />
</svg>
<span
className="absolute bottom-5 right-6 text-[9px] tracking-[0.14em]"
style={{ color: "var(--slash)", opacity: 0.78 }}
>
CONCEITO ESCOLHIDO
</span>
</div>
<div
className="flex items-center gap-sp-3 text-[9px] tracking-[0.12em]"
style={{ color: "rgba(255,255,255,.32)" }}
>
<span
className="h-px w-6"
style={{ background: "rgba(255,255,255,.18)" }}
/>
EV / Full mark · identidade visual
</div>
<div
className="flex items-center gap-sp-3 text-[9px] tracking-[0.12em]"
style={{ color: "rgba(255,255,255,.32)" }}
>
<span
className="h-px w-6"
style={{ background: "rgba(255,255,255,.18)" }}
/>
Escala: 280x280 · svg viewbox
</div>
</div>
</div> </div>
</section> </section>
); );
+38 -7
View File
@@ -92,7 +92,9 @@ function TierCard({ tier }: { tier: Tier }) {
onBlur={() => setHovered(false)} onBlur={() => setHovered(false)}
tabIndex={0} tabIndex={0}
style={{ style={{
border: tier.featured ? "2px solid #0A0A0A" : "1px solid rgba(10,10,10,0.1)", border: tier.featured
? "2px solid #0A0A0A"
: "1px solid rgba(10,10,10,0.1)",
background: tier.featured ? "#0A0A0A" : "#fff", background: tier.featured ? "#0A0A0A" : "#fff",
padding: "var(--sp-6)", padding: "var(--sp-6)",
display: "flex", display: "flex",
@@ -108,7 +110,13 @@ function TierCard({ tier }: { tier: Tier }) {
}} }}
> >
{/* Top row */} {/* Top row */}
<div style={{ display: "flex", justifyContent: "space-between", alignItems: "flex-start" }}> <div
style={{
display: "flex",
justifyContent: "space-between",
alignItems: "flex-start",
}}
>
<span <span
style={{ style={{
fontSize: "9px", fontSize: "9px",
@@ -123,7 +131,9 @@ function TierCard({ tier }: { tier: Tier }) {
style={{ style={{
fontFamily: "var(--font-display)", fontFamily: "var(--font-display)",
fontSize: "11px", fontSize: "11px",
color: tier.featured ? "rgba(255,255,255,0.15)" : "rgba(10,10,10,0.12)", color: tier.featured
? "rgba(255,255,255,0.15)"
: "rgba(10,10,10,0.12)",
fontWeight: 800, fontWeight: 800,
letterSpacing: "0.04em", letterSpacing: "0.04em",
}} }}
@@ -150,7 +160,9 @@ function TierCard({ tier }: { tier: Tier }) {
style={{ style={{
marginTop: "var(--sp-2)", marginTop: "var(--sp-2)",
fontSize: "11px", fontSize: "11px",
color: tier.featured ? "rgba(232,255,0,0.85)" : "rgba(10,10,10,0.5)", color: tier.featured
? "rgba(232,255,0,0.85)"
: "rgba(10,10,10,0.5)",
lineHeight: 1.6, lineHeight: 1.6,
}} }}
> >
@@ -159,7 +171,15 @@ function TierCard({ tier }: { tier: Tier }) {
</div> </div>
{/* Description */} {/* Description */}
<p style={{ fontSize: "12px", color: tier.featured ? "rgba(255,255,255,0.7)" : "rgba(10,10,10,0.65)", lineHeight: 1.8 }}> <p
style={{
fontSize: "12px",
color: tier.featured
? "rgba(255,255,255,0.7)"
: "rgba(10,10,10,0.65)",
lineHeight: 1.8,
}}
>
{tier.description} {tier.description}
</p> </p>
@@ -183,7 +203,9 @@ function TierCard({ tier }: { tier: Tier }) {
{/* Pricing */} {/* Pricing */}
<div <div
style={{ style={{
borderTop: tier.featured ? "1px solid rgba(255,255,255,0.1)" : "1px solid rgba(10,10,10,0.08)", borderTop: tier.featured
? "1px solid rgba(255,255,255,0.1)"
: "1px solid rgba(10,10,10,0.08)",
paddingTop: "var(--sp-4)", paddingTop: "var(--sp-4)",
}} }}
> >
@@ -198,7 +220,16 @@ function TierCard({ tier }: { tier: Tier }) {
> >
{tier.pricing} {tier.pricing}
</div> </div>
<div style={{ fontSize: "10px", color: tier.featured ? "rgba(255,255,255,0.3)" : "rgba(10,10,10,0.35)", marginTop: "4px", letterSpacing: "0.06em" }}> <div
style={{
fontSize: "10px",
color: tier.featured
? "rgba(255,255,255,0.3)"
: "rgba(10,10,10,0.35)",
marginTop: "4px",
letterSpacing: "0.06em",
}}
>
{tier.pricingNote} {tier.pricingNote}
</div> </div>
</div> </div>
+93 -69
View File
@@ -1,5 +1,5 @@
// src/components/ui/NumberIcons.tsx // src/components/ui/NumberIcons.tsx
import React from 'react'; import React from "react";
interface NumberIconProps extends React.SVGProps<SVGSVGElement> { interface NumberIconProps extends React.SVGProps<SVGSVGElement> {
/** Tamanho em pixels. Escala mantendo o viewBox 80x80 */ /** Tamanho em pixels. Escala mantendo o viewBox 80x80 */
@@ -9,9 +9,9 @@ interface NumberIconProps extends React.SVGProps<SVGSVGElement> {
} }
const baseProps = { const baseProps = {
fill: 'none', fill: "none",
xmlns: 'http://www.w3.org/2000/svg', xmlns: "http://www.w3.org/2000/svg",
viewBox: '0 0 80 80', viewBox: "0 0 80 80",
}; };
/** /**
@@ -22,44 +22,53 @@ const GraphicShell = () => (
<> <>
{/* Base Background */} {/* Base Background */}
<rect width="80" height="80" rx="8" className="fill-[#0A0A0A]" /> <rect width="80" height="80" rx="8" className="fill-[#0A0A0A]" />
{/* Borda reativa ao hover */} {/* Borda reativa ao hover */}
<rect <rect
x="1" y="1" width="78" height="78" rx="7" x="1"
className="stroke-white/5 transition-colors duration-400 ease-[var(--ease-out)] group-hover:stroke-white/15" y="1"
strokeWidth="1" width="78"
height="78"
rx="7"
className="stroke-white/5 transition-colors duration-400 ease-[var(--ease-out)] group-hover:stroke-white/15"
strokeWidth="1"
/> />
{/* Grid de background sutil (Cyberpunk/Tech feel) */} {/* Grid de background sutil (Cyberpunk/Tech feel) */}
<g className="stroke-white/[0.03]" strokeWidth="1"> <g className="stroke-white/[0.03]" strokeWidth="1">
<path d="M0 20H80M0 60H80M20 0V80M60 0V80" /> <path d="M0 20H80M0 60H80M20 0V80M60 0V80" />
</g> </g>
{/* Brand Slash (Acento) com Motion */} {/* Brand Slash (Acento) com Motion */}
<polygon <polygon
points="58,66 62,66 70,50 66,50" points="58,66 62,66 70,50 66,50"
className="fill-[#E8FF00] transition-transform duration-400 ease-[var(--ease-out)] origin-bottom-right group-hover:-translate-y-1 group-hover:scale-110" className="fill-[#E8FF00] transition-transform duration-400 ease-[var(--ease-out)] origin-bottom-right group-hover:-translate-y-1 group-hover:scale-110"
/> />
</> </>
); );
export const NumberOne = ({ size = 80, className = '', ...props }: NumberIconProps) => ( export const NumberOne = ({
<svg size = 80,
width={size} className = "",
height={size} ...props
className={`group ${className}`} }: NumberIconProps) => (
role="img" <svg
aria-label="Passo 1" width={size}
{...baseProps} height={size}
className={`group ${className}`}
role="img"
aria-label="Passo 1"
{...baseProps}
{...props} {...props}
> >
<GraphicShell /> <GraphicShell />
<text <text
x="40" y="54" x="40"
fontFamily="Syne, sans-serif" y="54"
fontSize="40" fontFamily="Syne, sans-serif"
fontWeight="800" fontSize="40"
textAnchor="middle" fontWeight="800"
textAnchor="middle"
className="fill-white transition-transform duration-400 ease-[var(--ease-out)] group-hover:-translate-y-0.5" className="fill-white transition-transform duration-400 ease-[var(--ease-out)] group-hover:-translate-y-0.5"
> >
1 1
@@ -67,23 +76,28 @@ export const NumberOne = ({ size = 80, className = '', ...props }: NumberIconPro
</svg> </svg>
); );
export const NumberTwo = ({ size = 80, className = '', ...props }: NumberIconProps) => ( export const NumberTwo = ({
<svg size = 80,
width={size} className = "",
height={size} ...props
className={`group ${className}`} }: NumberIconProps) => (
role="img" <svg
aria-label="Passo 2" width={size}
{...baseProps} height={size}
className={`group ${className}`}
role="img"
aria-label="Passo 2"
{...baseProps}
{...props} {...props}
> >
<GraphicShell /> <GraphicShell />
<text <text
x="40" y="54" x="40"
fontFamily="Syne, sans-serif" y="54"
fontSize="40" fontFamily="Syne, sans-serif"
fontWeight="800" fontSize="40"
textAnchor="middle" fontWeight="800"
textAnchor="middle"
className="fill-white transition-transform duration-400 ease-[var(--ease-out)] group-hover:-translate-y-0.5" className="fill-white transition-transform duration-400 ease-[var(--ease-out)] group-hover:-translate-y-0.5"
> >
2 2
@@ -91,23 +105,28 @@ export const NumberTwo = ({ size = 80, className = '', ...props }: NumberIconPro
</svg> </svg>
); );
export const NumberThree = ({ size = 80, className = '', ...props }: NumberIconProps) => ( export const NumberThree = ({
<svg size = 80,
width={size} className = "",
height={size} ...props
className={`group ${className}`} }: NumberIconProps) => (
role="img" <svg
aria-label="Passo 3" width={size}
{...baseProps} height={size}
className={`group ${className}`}
role="img"
aria-label="Passo 3"
{...baseProps}
{...props} {...props}
> >
<GraphicShell /> <GraphicShell />
<text <text
x="40" y="54" x="40"
fontFamily="Syne, sans-serif" y="54"
fontSize="40" fontFamily="Syne, sans-serif"
fontWeight="800" fontSize="40"
textAnchor="middle" fontWeight="800"
textAnchor="middle"
className="fill-white transition-transform duration-400 ease-[var(--ease-out)] group-hover:-translate-y-0.5" className="fill-white transition-transform duration-400 ease-[var(--ease-out)] group-hover:-translate-y-0.5"
> >
3 3
@@ -115,23 +134,28 @@ export const NumberThree = ({ size = 80, className = '', ...props }: NumberIconP
</svg> </svg>
); );
export const NumberFour = ({ size = 80, className = '', ...props }: NumberIconProps) => ( export const NumberFour = ({
<svg size = 80,
width={size} className = "",
height={size} ...props
className={`group ${className}`} }: NumberIconProps) => (
role="img" <svg
aria-label="Passo 4" width={size}
{...baseProps} height={size}
className={`group ${className}`}
role="img"
aria-label="Passo 4"
{...baseProps}
{...props} {...props}
> >
<GraphicShell /> <GraphicShell />
<text <text
x="40" y="54" x="40"
fontFamily="Syne, sans-serif" y="54"
fontSize="40" fontFamily="Syne, sans-serif"
fontWeight="800" fontSize="40"
textAnchor="middle" fontWeight="800"
textAnchor="middle"
className="fill-white transition-transform duration-400 ease-[var(--ease-out)] group-hover:-translate-y-0.5" className="fill-white transition-transform duration-400 ease-[var(--ease-out)] group-hover:-translate-y-0.5"
> >
4 4
+6 -6
View File
@@ -1,16 +1,16 @@
@import url("https://fonts.googleapis.com/css2?family=Syne:wght@400;500;600;700;800&family=Geist+Mono:wght@300;400;500;600&display=swap"); @import url("https://fonts.googleapis.com/css2?family=Syne:wght@400;500;600;700;800&family=Geist+Mono:wght@300;400;500;600&display=swap");
@font-face { @font-face {
font-family: 'Monument Extended'; font-family: "Monument Extended";
src: url('/fonts/MonumentExtended-Regular.otf') format('opentype'); src: url("/fonts/MonumentExtended-Regular.otf") format("opentype");
font-weight: 400; font-weight: 400;
font-style: normal; font-style: normal;
font-display: swap; font-display: swap;
} }
@font-face { @font-face {
font-family: 'Monument Extended'; font-family: "Monument Extended";
src: url('/fonts/MonumentExtended-Ultrabold.otf') format('opentype'); src: url("/fonts/MonumentExtended-Ultrabold.otf") format("opentype");
font-weight: 800; font-weight: 800;
font-style: normal; font-style: normal;
font-display: swap; font-display: swap;
@@ -66,7 +66,7 @@
--r-lg: 16px; --r-lg: 16px;
--r-full: 999px; --r-full: 999px;
--font-display: "Syne", sans-serif; --font-display: "Syne", sans-serif;
--font-hero: 'Monument Extended', sans-serif; --font-hero: "Monument Extended", sans-serif;
--font-mono: "Geist Mono", monospace; --font-mono: "Geist Mono", monospace;
--ease-out: cubic-bezier(0.16, 1, 0.3, 1); --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
--ease-in: cubic-bezier(0.4, 0, 1, 1); --ease-in: cubic-bezier(0.4, 0, 1, 1);
@@ -124,7 +124,7 @@ textarea {
} }
.ds-main { .ds-main {
padding-top: 52px; /* padding-top: 52px; removed since there is no header now */
} }
.ds-section { .ds-section {
-2
View File
@@ -1,7 +1,6 @@
import About from "./components/About"; import About from "./components/About";
import Contact from "./components/Contact"; import Contact from "./components/Contact";
import Experience from "./components/Experience"; import Experience from "./components/Experience";
import { Header } from "./components/Header";
import Hero from "./components/Hero"; import Hero from "./components/Hero";
import Projects from "./components/Projects"; import Projects from "./components/Projects";
import Skills from "./components/Skills"; import Skills from "./components/Skills";
@@ -10,7 +9,6 @@ import { WorkModalities } from "./components/WorkModalities";
export default function Home() { export default function Home() {
return ( return (
<div className="flex min-h-screen flex-col overflow-x-hidden"> <div className="flex min-h-screen flex-col overflow-x-hidden">
<Header />
<main className="ds-main"> <main className="ds-main">
<Hero /> <Hero />
<About /> <About />