feat(hero): la metáfora de marca sustituye al carrusel de dolores

This commit is contained in:
erikgh committed 2026-07-31 11:16:46 -06:00
1 parent bd16de2aa3
commit a03b6c1f92
2 files changed
+17 -22

No files matched your search

+6 -18
View File
@@ -5,10 +5,9 @@ import { Wordmark } from '@/components/primitives/Wordmark';
import { CTA } from '@/components/primitives/CTA'; import { CTA } from '@/components/primitives/CTA';
import { Container } from '@/components/primitives/Container'; import { Container } from '@/components/primitives/Container';
import { FondoPuntos } from '@/components/primitives/FondoPuntos'; import { FondoPuntos } from '@/components/primitives/FondoPuntos';
import { Carrusel } from '@/components/primitives/Carrusel'; import { SecuenciaClaridad } from '@/components/primitives/SecuenciaClaridad';
import { TextoDesenfoque } from '@/components/primitives/TextoDesenfoque'; import { TextoDesenfoque } from '@/components/primitives/TextoDesenfoque';
import { TarjetaSpotlight } from '@/components/primitives/TarjetaSpotlight'; import { hero } from '@/lib/content';
import { hero, dolores } from '@/lib/content';
import { fadeInUp, staggerContainer, usePrefersReducedMotion, motionProps } from '@/lib/motion'; import { fadeInUp, staggerContainer, usePrefersReducedMotion, motionProps } from '@/lib/motion';
type Variant = 'hormozi' | 'editorial'; type Variant = 'hormozi' | 'editorial';
@@ -25,7 +24,7 @@ export function Hero({ variant = 'editorial' }: { variant?: Variant }) {
return ( return (
<section className="bg-white relative overflow-hidden"> <section className="bg-white relative overflow-hidden">
<FondoPuntos className="top-24 -right-16 w-72 md:w-[28rem] text-azul-profundo/10" interactivo /> <FondoPuntos className="top-24 -right-16 w-72 md:w-[28rem] text-azul-profundo/10" interactivo />
<FondoPuntos className="bottom-16 -left-20 w-64 md:w-96 text-dorado/20" distance={28} rows={2} interactivo /> <FondoPuntos className="bottom-16 -left-20 w-64 md:w-96 text-dorado/20" distance={28} rows={2} />
<Container className="relative min-h-[88vh] flex items-center py-24"> <Container className="relative min-h-[88vh] flex items-center py-24">
<div className="grid gap-14 lg:grid-cols-[1.1fr_0.9fr] lg:items-center w-full"> <div className="grid gap-14 lg:grid-cols-[1.1fr_0.9fr] lg:items-center w-full">
<motion.div variants={staggerContainer} initial="hidden" animate="visible" {...motionProps(reduced)} <motion.div variants={staggerContainer} initial="hidden" animate="visible" {...motionProps(reduced)}
@@ -50,22 +49,11 @@ export function Hero({ variant = 'editorial' }: { variant?: Variant }) {
<CTA href="#mecanismo" label={hero.ctaSecundario} variant="ghost" className="md:whitespace-nowrap" /> <CTA href="#mecanismo" label={hero.ctaSecundario} variant="ghost" className="md:whitespace-nowrap" />
</motion.div> </motion.div>
</motion.div> </motion.div>
{/* Rota las frases textuales de `dolores` — quien llega al hero se ve {/* Complejidad → Enfoque, sin resolver: el hero plantea la tensión y
reflejado antes de haber bajado a leer la sección completa. */} FraseAncla la paga resolviendo en el ≡. */}
<motion.div variants={fadeInUp} initial="hidden" animate="visible" {...motionProps(reduced)} <motion.div variants={fadeInUp} initial="hidden" animate="visible" {...motionProps(reduced)}
className="hidden lg:block min-w-0"> className="hidden lg:block min-w-0">
<Carrusel <SecuenciaClaridad variant="hero" className="w-full max-w-md mx-auto text-azul-profundo" />
ariaLabel="Lo que sienten nuestros clientes"
autoplayMs={4500}
slides={dolores.quotes.map((quote) => (
<TarjetaSpotlight key={quote} className="rounded-2xl border border-azul-profundo/10 bg-white shadow-xl shadow-azul-profundo/5 p-8 lg:p-10 min-h-[15rem] flex flex-col justify-center">
<p className="text-xs uppercase tracking-[0.3em] font-semibold text-dorado">lo que escuchamos</p>
<blockquote className="mt-4 font-sans italic text-xl lg:text-2xl leading-snug text-azul-profundo">
<span className="text-dorado not-italic">&ldquo;</span>{quote}<span className="text-dorado not-italic">&rdquo;</span>
</blockquote>
</TarjetaSpotlight>
))}
/>
</motion.div> </motion.div>
</div> </div>
</Container> </Container>
+11 -4
View File
@@ -25,9 +25,16 @@ describe('<Hero />', () => {
const { container } = render(<Hero variant="editorial" />); const { container } = render(<Hero variant="editorial" />);
expect(container.textContent).not.toMatch(/cupos|cohorte|generación fundadora/i); expect(container.textContent).not.toMatch(/cupos|cohorte|generación fundadora/i);
}); });
it('mirrors the client\'s own words back in a rotating carousel', () => { it('does not pre-empt the Dolores section with its own copy', () => {
render(<Hero variant="editorial" />); const { container } = render(<Hero variant="editorial" />);
expect(screen.getByRole('group', { name: /lo que sienten nuestros clientes/i })).toBeInTheDocument(); // The hero used to rotate the same four quotes that Dolores renders in
expect(screen.getByText(/Trabajo más y gano casi lo mismo/i)).toBeInTheDocument(); // full further down. Duplicating them spent the emotional beat early and
// competed with the headline.
expect(container.textContent).not.toMatch(/Trabajo más y gano casi lo mismo/i);
});
it('carries the brand metaphor as its visual anchor', () => {
const { container } = render(<Hero variant="editorial" />);
expect(container.querySelectorAll('svg').length).toBeGreaterThan(0);
}); });
}); });