feat(disciplinas): tres hebras que confluyen en una estrategia
This commit is contained in:
1 parent
ca949f35c2
commit
3cb2b1f78b
3 files changed
+68
-2
No files matched your search
@@ -0,0 +1,45 @@
|
||||
'use client';
|
||||
|
||||
import { motion } from 'framer-motion';
|
||||
import { useEnVista } from '@/lib/motion';
|
||||
|
||||
// Three strands — comunicación, digital, experiencias — meeting and leaving as
|
||||
// a single gold line. The section's own lead, drawn: "No son la promesa, son
|
||||
// los medios." The three are grey; only what they produce is gold.
|
||||
const HEBRAS = [
|
||||
'M6 18 C 60 20, 90 52, 120 60',
|
||||
'M6 60 C 60 60, 90 60, 120 60',
|
||||
'M6 102 C 60 100, 90 68, 120 60',
|
||||
];
|
||||
const ESTRATEGIA = 'M120 60 L 214 60';
|
||||
|
||||
export function IlustracionConvergencia({ className = '' }: { className?: string }) {
|
||||
const { ref, enVista, reduced } = useEnVista();
|
||||
|
||||
// Plain <path> under reduced motion — motion.path would hide the drawing.
|
||||
if (reduced) {
|
||||
return (
|
||||
<svg ref={ref} viewBox="0 0 220 120" className={className} aria-hidden="true" focusable="false">
|
||||
{HEBRAS.map((d) => (
|
||||
<path key={d} d={d} fill="none" stroke="currentColor" className="text-gris-medio" strokeWidth={2} strokeLinecap="round" />
|
||||
))}
|
||||
<path d={ESTRATEGIA} fill="none" stroke="currentColor" className="text-dorado" strokeWidth={3.5} strokeLinecap="round" />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
|
||||
const dibuja = (delay: number) => ({
|
||||
initial: { pathLength: 0 },
|
||||
animate: enVista ? { pathLength: 1 } : { pathLength: 0 },
|
||||
transition: { duration: 1, delay, ease: [0.22, 1, 0.36, 1] as const },
|
||||
});
|
||||
|
||||
return (
|
||||
<svg ref={ref} viewBox="0 0 220 120" className={className} aria-hidden="true" focusable="false">
|
||||
{HEBRAS.map((d, i) => (
|
||||
<motion.path key={d} d={d} fill="none" stroke="currentColor" className="text-gris-medio" strokeWidth={2} strokeLinecap="round" {...dibuja(i * 0.12)} />
|
||||
))}
|
||||
<motion.path d={ESTRATEGIA} fill="none" stroke="currentColor" className="text-dorado" strokeWidth={3.5} strokeLinecap="round" {...dibuja(0.7)} />
|
||||
</svg>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import { render } from '@testing-library/react';
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { IlustracionConvergencia } from '../IlustracionConvergencia';
|
||||
|
||||
describe('<IlustracionConvergencia />', () => {
|
||||
it('is decorative: hidden from assistive tech', () => {
|
||||
const { container } = render(<IlustracionConvergencia />);
|
||||
const svg = container.querySelector('svg');
|
||||
expect(svg).toHaveAttribute('aria-hidden', 'true');
|
||||
expect(svg).toHaveAttribute('focusable', 'false');
|
||||
});
|
||||
|
||||
it('draws one strand per discipline plus the strategy they serve', () => {
|
||||
const { container } = render(<IlustracionConvergencia />);
|
||||
expect(container.querySelectorAll('path')).toHaveLength(4);
|
||||
});
|
||||
});
|
||||
@@ -3,6 +3,7 @@ import { motion } from 'framer-motion';
|
||||
import { Container } from '@/components/primitives/Container';
|
||||
import { TarjetaSpotlight } from '@/components/primitives/TarjetaSpotlight';
|
||||
import { Icono, type IconoNombre } from '@/components/primitives/Icono';
|
||||
import { IlustracionConvergencia } from '@/components/primitives/IlustracionConvergencia';
|
||||
import { disciplinas } from '@/lib/content';
|
||||
import { fadeInUp, staggerContainer, viewportOnce, usePrefersReducedMotion, motionProps } from '@/lib/motion';
|
||||
|
||||
@@ -17,8 +18,11 @@ export function Disciplinas() {
|
||||
className="text-xs tracking-[0.3em] uppercase font-black text-dorado">{disciplinas.eyebrow}</motion.p>
|
||||
<motion.h2 variants={fadeInUp} initial="hidden" whileInView="visible" viewport={viewportOnce} {...motionProps(reduced)}
|
||||
className="mt-4 font-sans font-black text-4xl md:text-6xl text-azul-profundo tracking-tight">{disciplinas.title}</motion.h2>
|
||||
<motion.p variants={fadeInUp} initial="hidden" whileInView="visible" viewport={viewportOnce} {...motionProps(reduced)}
|
||||
className="mt-4 text-gris-medio text-lg">{disciplinas.lead}</motion.p>
|
||||
<motion.div variants={fadeInUp} initial="hidden" whileInView="visible" viewport={viewportOnce} {...motionProps(reduced)}
|
||||
className="mt-4 md:flex md:items-center md:justify-between md:gap-10">
|
||||
<p className="text-gris-medio text-lg">{disciplinas.lead}</p>
|
||||
<IlustracionConvergencia className="mt-6 md:mt-0 w-56 md:w-64 h-auto shrink-0" />
|
||||
</motion.div>
|
||||
<motion.ul variants={staggerContainer} initial="hidden" whileInView="visible" viewport={viewportOnce} {...motionProps(reduced)}
|
||||
className="mt-12 grid gap-6 md:grid-cols-3 list-none p-0">
|
||||
{disciplinas.items.map((item, i) => (
|
||||
|
||||
Reference in new issue
Block a user