chore: retira Carrusel, sin consumidores desde que el recorrido se apila

PuntosInflexion era el único que lo montaba. Se va también la referencia
que le quedaba colgando en el comentario de useAutoStep.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
erikghandClaude Opus 5 committed 2026-08-03 11:15:39 -06:00
1 parent c1a5e79c63
commit a200346780
3 files changed
+1 -140

No files matched your search

-90
View File
@@ -1,90 +0,0 @@
'use client';
import { useCallback, useEffect, useState, type ReactNode } from 'react';
import useEmblaCarousel from 'embla-carousel-react';
import Autoplay from 'embla-carousel-autoplay';
import { usePrefersReducedMotion } from '@/lib/motion';
// Thin Embla wrapper shared by the hero's pain-point rotator and the mobile
// row of inflection points. Autoplay pauses on hover/focus/interaction, and
// never runs at all for users who asked for less motion — it's still a fully
// usable carousel (drag, dots, keyboard) with it off, just static.
export function Carrusel({
slides,
autoplayMs,
className = '',
slideClassName = '',
ariaLabel,
mostrarContador = false,
}: {
slides: ReactNode[];
autoplayMs?: number;
className?: string;
slideClassName?: string;
ariaLabel: string;
// "01 / 06" + flechas prev/next, en vez de puntos — el patrón de
// en-ti.com ("desliza para explorar") para carruseles con más peso.
mostrarContador?: boolean;
}) {
const reduced = usePrefersReducedMotion();
const plugins = autoplayMs && !reduced ? [Autoplay({ delay: autoplayMs, stopOnInteraction: false, stopOnMouseEnter: true })] : [];
const [emblaRef, embla] = useEmblaCarousel({ loop: true }, plugins);
const [selected, setSelected] = useState(0);
useEffect(() => {
if (!embla) return;
const onSelect = () => setSelected(embla.selectedScrollSnap());
embla.on('select', onSelect);
onSelect();
return () => {
embla.off('select', onSelect);
};
}, [embla]);
const scrollTo = useCallback((i: number) => embla?.scrollTo(i), [embla]);
const scrollPrev = useCallback(() => embla?.scrollPrev(), [embla]);
const scrollNext = useCallback(() => embla?.scrollNext(), [embla]);
return (
<div className={`min-w-0 ${className}`}>
<div className="overflow-hidden" ref={emblaRef} role="group" aria-label={ariaLabel}>
<div className="flex">
{slides.map((slide, i) => (
<div key={i} className={`min-w-0 shrink-0 grow-0 basis-full ${slideClassName}`}>
{slide}
</div>
))}
</div>
</div>
{slides.length > 1 && mostrarContador && (
<div className="mt-6 flex items-center justify-center gap-5">
<button type="button" onClick={scrollPrev} aria-label="Anterior"
className="grid place-items-center w-9 h-9 rounded-full border border-azul-profundo/20 text-azul-profundo transition-colors hover:border-dorado hover:text-dorado">
←
</button>
<p className="font-sans font-bold text-sm tabular-nums text-azul-profundo tracking-wider">
{String(selected + 1).padStart(2, '0')} <span className="text-gris-medio font-normal">/ {String(slides.length).padStart(2, '0')}</span>
</p>
<button type="button" onClick={scrollNext} aria-label="Siguiente"
className="grid place-items-center w-9 h-9 rounded-full border border-azul-profundo/20 text-azul-profundo transition-colors hover:border-dorado hover:text-dorado">
→
</button>
</div>
)}
{slides.length > 1 && !mostrarContador && (
<div className="mt-5 flex justify-center gap-2">
{slides.map((_, i) => (
<button
key={i}
type="button"
onClick={() => scrollTo(i)}
aria-label={`Ir a la tarjeta ${i + 1} de ${slides.length}`}
aria-current={selected === i}
className={`h-2 rounded-full transition-all duration-300 ${selected === i ? 'w-6 bg-dorado' : 'w-2 bg-gris-medio/50 hover:bg-gris-medio'}`}
/>
))}
</div>
)}
</div>
);
}
@@ -1,48 +0,0 @@
import { render, screen } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
import { describe, it, expect } from 'vitest';
import { Carrusel } from '../Carrusel';
describe('<Carrusel />', () => {
it('renders every slide', () => {
render(<Carrusel ariaLabel="test" slides={[<p key="a">Uno</p>, <p key="b">Dos</p>, <p key="c">Tres</p>]} />);
expect(screen.getByText('Uno')).toBeInTheDocument();
expect(screen.getByText('Dos')).toBeInTheDocument();
expect(screen.getByText('Tres')).toBeInTheDocument();
});
it('renders one position dot per slide, and marks the current one', () => {
render(<Carrusel ariaLabel="test" slides={[<p key="a">Uno</p>, <p key="b">Dos</p>]} />);
const dots = screen.getAllByRole('button', { name: /ir a la tarjeta/i });
expect(dots).toHaveLength(2);
expect(dots[0]).toHaveAttribute('aria-current', 'true');
});
it('moves to a slide when its dot is clicked', async () => {
const user = userEvent.setup();
render(<Carrusel ariaLabel="test" slides={[<p key="a">Uno</p>, <p key="b">Dos</p>]} />);
const dots = screen.getAllByRole('button', { name: /ir a la tarjeta/i });
await user.click(dots[1]);
expect(dots[1]).toHaveAttribute('aria-current', 'true');
});
it('hides the dots entirely for a single slide', () => {
render(<Carrusel ariaLabel="test" slides={[<p key="a">Solo una</p>]} />);
expect(screen.queryByRole('button', { name: /ir a la tarjeta/i })).not.toBeInTheDocument();
});
it('exposes the slide group with the given accessible name', () => {
render(<Carrusel ariaLabel="Frases de ejemplo" slides={[<p key="a">Uno</p>]} />);
expect(screen.getByRole('group', { name: 'Frases de ejemplo' })).toBeInTheDocument();
});
it('shows a numbered counter with prev/next arrows instead of dots when mostrarContador is set', () => {
render(<Carrusel ariaLabel="test" mostrarContador slides={[<p key="a">Uno</p>, <p key="b">Dos</p>, <p key="c">Tres</p>]} />);
expect(screen.getByText('01')).toBeInTheDocument();
expect(screen.getByText(/\/ 03/)).toBeInTheDocument();
expect(screen.getByRole('button', { name: 'Siguiente' })).toBeInTheDocument();
expect(screen.getByRole('button', { name: 'Anterior' })).toBeInTheDocument();
expect(screen.queryByRole('button', { name: /ir a la tarjeta/i })).not.toBeInTheDocument();
});
it('advances the counter when the next arrow is clicked', async () => {
const user = userEvent.setup();
render(<Carrusel ariaLabel="test" mostrarContador slides={[<p key="a">Uno</p>, <p key="b">Dos</p>]} />);
await user.click(screen.getByRole('button', { name: 'Siguiente' }));
expect(screen.getByText('02')).toBeInTheDocument();
});
});
+1 -2
View File
@@ -66,8 +66,7 @@ export const motionProps = (reduced: boolean) =>
// Cycles through `count` steps on its own (Mecanismo, ComoEmpezar): each
// manual change restarts the dwell timer, hovering pauses it, and it never
// advances at all for reduced-motion users — same shape as the Carrusel
// autoplay, for step indicators that aren't a carousel.
// advances at all for reduced-motion users.
export function useAutoStep(count: number, intervalMs = 3500) {
const reduced = usePrefersReducedMotion();
const [active, setActive] = useState(0);