feat: Awwwards transformation Phases 1-6
Phase 1 — Design System: - Glassmorphism tokens (--glass-bg, --glass-border, --blur-glass) - Gradient tokens (--hds-gradient-hero, --hds-gradient-section) - Motion tokens (--ease-spring, --ease-out-expo) - .glass-card component class with hover uplift + mouse-tracking glow - .noise-overlay: SVG feTurbulence texture at 0.025 opacity - Buttons with spring easing, prefers-reduced-motion support Phase 2 — Preloader + Hero: - Preloader.astro: vanilla JS logo fade-in + loading bar + slide-up - Uses sessionStorage to skip on repeat visits - Hero.astro: full-bleed 100dvh, GSAP timeline, glass ring decoration - Parallax floating SVG shapes (sine yoyo animation) - i18n: hero.scrollDown key Phase 3 — 'Por qué elegirnos' Bento Grid: - DifferenceCards.astro: asymmetric 3-column bento grid - Glass cards with mouse-tracking glow (--mouse-x/--mouse-y) - GSAP ScrollTrigger stagger reveal (opacity 0→1, y: 40→0) Phase 4 — Pricing + Process: - planes.astro: 5 visible + 4 in details accordion - Empresarial as hero card, price annual only (no toggle) - ProcessSteps.astro: timeline + ScrollTrigger progress bar Phase 5 — Global Polish: - LenisScroll.astro: smooth scroll (duration 1.2, cubic easing) - GSAP ticker sync, noise overlay in BaseLayout Phase 6 — Deploy: - deploy.sh: auto-detects repo path, auto-builds if stale - Relative paths instead of hardcoded /root/opencode/development
This commit is contained in:
@@ -1,6 +1,12 @@
|
||||
---
|
||||
// "Cómo trabajamos" — Timeline with GSAP ScrollTrigger progress bar
|
||||
// Phase 4 — Organic Fluidity Premium
|
||||
import SectionEyebrow from './SectionEyebrow.astro';
|
||||
import type { TranslationKey } from '@/i18n/ui';
|
||||
import gsap from 'gsap';
|
||||
import { ScrollTrigger } from 'gsap/ScrollTrigger';
|
||||
|
||||
gsap.registerPlugin(ScrollTrigger);
|
||||
|
||||
interface Props {
|
||||
t: (key: TranslationKey) => string;
|
||||
@@ -14,32 +20,133 @@ const steps = [
|
||||
{ num: '04', titleKey: 'process.step4.title' as TranslationKey, bodyKey: 'process.step4.body' as TranslationKey },
|
||||
];
|
||||
---
|
||||
<section class="py-20 md:py-28" style="background: var(--hds-bg-soft);">
|
||||
<section class="py-24 md:py-32 relative overflow-hidden" style="background: var(--hds-bg-soft);" id="como-trabajamos">
|
||||
<div class="absolute inset-0 pointer-events-none" style="background: var(--hds-gradient-section);" aria-hidden="true"></div>
|
||||
|
||||
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div class="max-w-3xl mb-14 md:mb-20 reveal">
|
||||
<div class="max-w-3xl mb-16 md:mb-20 reveal">
|
||||
<SectionEyebrow text={t('process.eyebrow')} />
|
||||
<h2 class="font-display leading-tight mt-5" style="font-size: clamp(2rem, 5vw, 3.5rem); color: var(--hds-fg);">
|
||||
{t('process.title')}
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<ol class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-10 md:gap-8 relative stagger">
|
||||
<div class="hidden lg:block absolute top-12 left-[12.5%] right-[12.5%] h-px" style="background: linear-gradient(to right, transparent, var(--color-hds-naranja) 20%, var(--color-hds-naranja) 80%, transparent);" aria-hidden="true"></div>
|
||||
<!-- Timeline with progress bar -->
|
||||
<div class="process-timeline">
|
||||
<!-- Vertical progress bar track -->
|
||||
<div class="process-progress-track" aria-hidden="true">
|
||||
<div id="process-progress-fill" class="process-progress-fill"></div>
|
||||
</div>
|
||||
|
||||
{steps.map((step) => (
|
||||
<li class="relative">
|
||||
<div class="font-display leading-none mb-4 relative inline-block" style="font-size: 5rem; color: var(--color-hds-naranja); font-weight: 500; opacity: 0.85;" aria-hidden="true">
|
||||
{step.num}
|
||||
<span class="absolute -bottom-1 left-0 w-10 h-1" style="background: var(--color-hds-naranja);"></span>
|
||||
<div class="process-steps">
|
||||
{steps.map((step, i) => (
|
||||
<div id={`process-step-${i}`} class="process-step-wrap">
|
||||
<article class="glass-card process-step-card p-8 md:p-10">
|
||||
<div class="flex items-start gap-6">
|
||||
<div class="font-display leading-none flex-shrink-0" style="font-size: 3.5rem; color: var(--color-hds-naranja); font-weight: 500; opacity: 0.9;">
|
||||
{step.num}
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xl md:text-2xl font-semibold mb-3" style="color: var(--hds-fg);">
|
||||
{t(step.titleKey)}
|
||||
</h3>
|
||||
<p class="text-[15px] md:text-base leading-relaxed" style="color: var(--hds-fg-soft);">
|
||||
{t(step.bodyKey)}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
||||
<h3 class="text-xl md:text-2xl font-semibold mb-3" style="color: var(--hds-fg);">
|
||||
{t(step.titleKey)}
|
||||
</h3>
|
||||
<p class="text-[15px] leading-relaxed" style="color: var(--hds-fg-soft);">
|
||||
{t(step.bodyKey)}
|
||||
</p>
|
||||
</li>
|
||||
))}
|
||||
</ol>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<script>
|
||||
import gsap from 'gsap';
|
||||
import { ScrollTrigger } from 'gsap/ScrollTrigger';
|
||||
|
||||
gsap.registerPlugin(ScrollTrigger);
|
||||
|
||||
const prefersReduced = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
|
||||
if (!prefersReduced) {
|
||||
const steps = document.querySelectorAll('.process-step-card');
|
||||
const progressFill = document.getElementById('process-progress-fill');
|
||||
|
||||
if (steps.length && progressFill) {
|
||||
// Animate progress bar as user scrolls through the section
|
||||
ScrollTrigger.create({
|
||||
trigger: '.process-steps',
|
||||
start: 'top 70%',
|
||||
end: 'bottom bottom',
|
||||
onUpdate: (self) => {
|
||||
progressFill.style.setProperty('--progress', `${self.progress * 100}%`);
|
||||
},
|
||||
});
|
||||
|
||||
// Stagger reveal each step card
|
||||
gsap.from('.process-step-card', {
|
||||
scrollTrigger: {
|
||||
trigger: '.process-steps',
|
||||
start: 'top 75%',
|
||||
toggleActions: 'play none none none',
|
||||
},
|
||||
opacity: 0,
|
||||
x: -30,
|
||||
duration: 0.7,
|
||||
stagger: 0.15,
|
||||
ease: 'power3.out',
|
||||
});
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.process-timeline {
|
||||
display: flex;
|
||||
gap: 2rem;
|
||||
max-width: 48rem;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.process-progress-track {
|
||||
flex-shrink: 0;
|
||||
width: 3px;
|
||||
border-radius: 3px;
|
||||
background: var(--hds-line);
|
||||
position: relative;
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.process-progress-fill {
|
||||
position: sticky;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 40vh;
|
||||
background: var(--color-hds-naranja);
|
||||
border-radius: inherit;
|
||||
clip-path: inset(0 0 calc(100% - var(--progress, 0%)) 0);
|
||||
transition: clip-path 0.1s linear;
|
||||
}
|
||||
|
||||
.process-steps {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1.5rem;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.process-step-card {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
@media (max-width: 767px) {
|
||||
.process-timeline {
|
||||
gap: 1rem;
|
||||
}
|
||||
.process-progress-track {
|
||||
width: 2px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user