Communitygithub.com

karero/website-hero-carousel

Carrusel héroe del sitio web: fotos que se turnan, y las pruebas que las mantienen honestas

¿Qué es website-hero-carousel?

Este skill implementa un carrusel de fotos para la sección hero de un sitio web, donde las imágenes se alternan automáticamente cada pocos segundos con indicadores de puntos. Está diseñado para evitar problemas comunes como saltos en la página causados por cambios de altura, puntos de navegación ilegibles sobre fondos claros, y falta de accesibilidad. Compatible con Astro, TypeScript y pruebas con Playwright, el carrusel funciona sin JavaScript (las fotos se muestran una debajo de otra), se detiene al pasar el ratón, al ocultar la pestaña, al recibir enfoque de teclado, y respeta las preferencias de movimiento reducido. No almacena ni envía datos, y cada foto puede enlazar a una página diferente. Incluye pruebas exhaustivas que verifican desde el contraste de los puntos sobre cada foto hasta la ausencia de cambios de altura en distintos tamaños de pantalla. El skill ofrece dos modos de pausa: botón visible (por defecto) o pausa mediante puntos, y soporta múltiples idiomas (inglés y alemán incluidos).

Compatible con~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/karero/croftweaver/tree/HEAD/skills/website-hero-carousel

Preguntar en tu IA favorita

Abre un nuevo chat con esta habilidad de agente ya precargada.

Documentación

Carrusel héroe del sitio web: fotos que se turnan, y las pruebas que las mantienen honestas

Un lugar para fotos en la parte superior de una página donde dos o más fotos se turnan cada pocos segundos, con un punto para cada una. Parece fácil y no lo es: un pie de foto en una imagen hace que la página salte en cada cambio; los puntos blancos desaparecen sobre una foto pálida; un teléfono necesita objetivos más grandes que un ratón; y el contenido en movimiento tiene su propia regla de accesibilidad. Este skill entrega el componente y, más importante, las pruebas que detectan todo esto.

Por qué está construido así (díselo al propietario, con tus propias palabras)

  • La página nunca salta. Todas las fotos comparten un mismo lugar, recortadas a una misma forma, por lo que la página es tan alta para la primera foto como para la última. No hay pies de foto ni créditos en las imágenes: ellos eran lo que movía la página en el sitio del que proviene esto. Los créditos pertenecen a la página de créditos de imágenes del sitio.
  • Los puntos se pueden leer sobre cualquier foto. Se asientan sobre una pequeña píldora oscura, por lo que se ven tanto sobre un cielo pálido como sobre una pared oscura. Una prueba mide esto en los píxeles de una foto clara y una oscura.
  • Funciona sin JavaScript. Las fotos se muestran entonces una debajo de la otra y no se muestra ningún botón.
  • Es educado. Se detiene cuando el ratón está sobre él, cuando la pestaña está oculta, cuando el enfoque del teclado entra en él, y desde el inicio para los visitantes que piden a su dispositivo menos movimiento.
  • No se almacena ni envía nada. Sin cookie, sin almacenamiento, sin petición a otro sitio.

Y los puntos débiles honestos, para que el propietario los escuche de ti primero:

  • Las fotos rotativas no siempre son el mejor diseño. Una sola foto fuerte es más tranquila, carga más rápido y no puede irritar a nadie. Dilo; el propietario decide.
  • Cada foto extra le cuesta al visitante tiempo de descarga en un teléfono. Tres fotos en cuatro tamaños cada una están bien; diez no. Mantén un puñado.
  • El modo de pausa "puntos" cambia un control visible por una foto más limpia (la sección "Pausa" a continuación).

0. ¿Es esta la herramienta adecuada? (pregunta antes de instalar)

  1. ¿Está el propietario seguro de la rotación? Una foto no necesita nada de esto. Pregunta una vez, claramente.
  2. ¿Cuántas fotos, y tienen la misma forma? De dos a cinco. Cualquier forma funciona (cada una se recorta a la forma del carrusel), pero una foto con su sujeto en el borde se pierde en el recorte: mira cada una en la forma del carrusel (16 / 9 por defecto) y en la de un teléfono.
  3. ¿Enlazan las fotos a algún sitio? Cualquier diapositiva puede enlazar a una página (un proyecto, por ejemplo); mezclar diapositivas con y sin enlace está bien (la página CI lo hace).
  4. ¿Qué modo de pausa? Lee "Pausa" a continuación al propietario y deja que elija. Por defecto: el botón.

1. Lo que añade al sitio

ArchivoDe la carpeta templates/ de este skillQué es
src/components/HeroCarousel.astroHeroCarousel.astroel marcado, los puntos, los estilos
src/components/hero-carousel-text.tshero-carousel-text.tslas palabras que dice, en inglés y alemán
public/js/hero-carousel.jshero-carousel.jsel script: coloca las diapositivas en un solo lugar, rota, maneja los controles
tests/hero-carousel.spec.tshero-carousel.spec.tsel carrusel tal como lo encuentra un visitante (lista abajo)

Instala los cuatro. Las plantillas no contienen ningún archivo de imagen: las fotos son propias del sitio, pasadas como props.

Cómo funciona, en un párrafo. El servidor envía cada diapositiva, una debajo de la otra, y los controles ocultos. El script, un archivo propio del sitio en public/js/ en lugar de un script en línea (para que un script-src 'self' estricto lo permita), luego coloca las diapositivas en una sola celda de cuadrícula, muestra los controles y marca la diapositiva que se muestra. Qué diapositiva se muestra es un atributo de datos; el CSS hace el resto, incluyendo el fundido de un segundo. Una diapositiva solo se muestra cuando su imagen está completa, por lo que una imagen tardía o fallida nunca deja un espacio en blanco.

Lo que verifica la especificación (la vista de un visitante, en la página tal como está construida): el marcado y el nombre de cada punto; el intervalo al milisegundo en un reloj congelado; el botón de Pausa o el punto que lo detiene, con las etiquetas y la región en vivo; el enfoque del teclado (lo detiene, se mantiene detenido, Reanudar); el puntero manteniéndolo y un nuevo intervalo después de salir; movimiento reducido; una pestaña oculta; una segunda imagen tardía y otra fallida; la página sin JavaScript; ningún salto de altura a 1280, 768 y 390 px; que una diapositiva no mostrada no se pueda alcanzar con el teclado ni en el árbol de accesibilidad; que el enlace de una foto funcione y un punto nunca lo abra; objetivos de 32 px (44 en pantallas táctiles); los puntos contra la píldora sobre cada foto, leídos de los píxeles renderizados; colores forzados; axe en ambos temas; nada almacenado ni enviado; el script es un archivo, no en línea; el fundido se ejecuta en un fotograma intermedio y se asienta, y no se ejecuta bajo movimiento reducido.

2. Instalación (en una rama, como pull request: AGENTS.md §2)

  1. Copia los cuatro archivos a los lugares de la §1 (mkdir -p public/js primero).
  2. Coloca el carrusel en una página, dentro del <Base> de esa página, cerca de la parte superior:
    ---
    import HeroCarousel from '../components/HeroCarousel.astro';
    import first from '../assets/hero-1.jpg';
    import second from '../assets/hero-2.jpg';
    ---
    <HeroCarousel label="Fotos de nuestro trabajo" slides={[
      { image: first,  alt: 'Lo que muestra la primera foto', label: 'Nombre corto', href: '/proyectos/uno' },
      { image: second, alt: 'Lo que muestra la segunda',      label: 'Otro nombre' },
    ]} />
    
    • label: qué es el carrusel, para un lector de pantalla. Obligatorio.
    • cada diapositiva: image (una foto importada), alt (una oración que diga lo que hay en ella, al menos 10 caracteres: la compilación se detiene si es menos), label (el nombre corto del punto), href (opcional).
    • pause: "button" (por defecto) o "dots". swap: "instant" (por defecto) o "fade". intervalMs: por defecto 6000, nunca por debajo de 2000. ratio: por defecto "16 / 9". lang: el idioma de la página. Fotos: JPEG o PNG, de aproximadamente 2.400 px de ancho, limitadas a lo que la página necesita (la compilación hace cuatro tamaños de cada una, AVIF con respaldo WebP). La primera foto se carga primero (alta prioridad); las demás se cargan con baja prioridad y mantienen su lugar.
  3. Idioma. El inglés y el alemán están integrados, y el componente toma el idioma de la página (Base.astro lo pasa como Astro.locals.lang). Cualquier otro: "Añadir un idioma" abajo, primero.
  4. En tests/hero-carousel.spec.ts establece PAGE (la página con el carrusel), PAUSE y SWAP a lo que la página pasa (los valores por defecto del componente son button e instant; la especificación necesita que estén escritos). La especificación falla mientras uno está vacío. LANG solo si la página pasa lang. Fotos para la prueba de contraste: la especificación lee las fotos reales del carrusel, por lo que se encuentra con las del propietario. Si cada una es oscura, la prueba de "puntos blancos sobre la píldora" no puede fallar; para verla fallar, introduce manualmente una foto pálida (la comprobación de mutación en §3 lo hace).
  5. npm run check && npm test.

Pausa (léelo al propietario antes de que elija)

El contenido en movimiento que comienza por sí mismo, dura más de cinco segundos y se encuentra junto a otro contenido cae bajo WCAG 2.2.2, Nivel A, que pide "un mecanismo para que el usuario lo pause, detenga u oculte" (léelo en https://www.w3.org/WAI/WCAG22/Understanding/pause-stop-hide.html). La misma página define pausa como "detenido por solicitud del usuario y no reanudado hasta que el usuario lo solicite", y no dice que el mecanismo deba ser visible. No discute los indicadores de diapositiva.

  • pause="button" (el valor por defecto). Un botón de Pausa junto a los puntos (Reanudar mientras está detenido). Visible, nombrado, la lectura que nadie discute, y la que un visitante encuentra. Su precio: una pequeña palabra sobre la foto.
  • pause="dots". Sin botón. Elegir un punto muestra esa foto y detiene la rotación hasta que el visitante recargue; el enfoque del teclado al entrar también lo detiene, y el movimiento reducido lo inicia detenido. Eso es probablemente un mecanismo en el sentido de 2.2.2, pero nada le dice a un visitante que un punto lo detiene, y no hay manera de reanudar. El primer sitio que usó este modo lo eligió por la foto más limpia, sabiéndolo.

Este skill no saca una conclusión de conformidad: si "puntos" se acepta es para el propio auditor del sitio. Si el propietario lo elige, escribe una línea en la documentación del sitio diciéndolo, con la fecha.

Añadir un idioma

En un sitio nuevo en ese idioma, o cuando un sitio lo adquiere más tarde.

  1. Lee primero la voz del sitio (CONTENT_GUIDE.md; en alemán el registro, "du" o "Sie"). Los textos son un puñado de palabras: donde el idioma lo permita, no te dirijas a nadie.
  2. En src/components/hero-carousel-text.ts, copia la entrada en de TEXT bajo el código de dos letras del idioma (fr, no fr-CA) y traduce cada valor; npm run check falla mientras falte uno.
  3. La página y su prueba, como en los pasos 3 y 4 de §2.

3. Pruébalo una vez (el propietario), y las comprobaciones detrás de este skill

Después de npm run build && npm run preview, o en la dirección de vista previa del pull request, el propietario:

  1. Espera: las fotos cambian solas, el punto mostrado las sigue.
  2. Mueve el ratón sobre él: se detiene. Lo retira: continúa, después de un intervalo completo.
  3. En un teléfono: toca un punto (muestra su foto); sin desplazamiento lateral; los puntos son fáciles de pulsar.
  4. En el modo de botón: presiona Pausa, ve que dice Reanudar, lo presiona de nuevo.

Las comprobaciones con las que se construyó este skill, para que un cambio en una plantilla pueda juzgarse: la especificación lleva una prueba para cada una de estas, y cada una falla cuando se elimina lo que protege. Ejecuta una vez manualmente cuando las plantillas cambien (el trabajo de CI las instala en un sitio nuevo y ejecuta la especificación, en las tres combinaciones de configuraciones que usa):

Elimina esto de HeroCarousel.astroEsta prueba falla
las reglas de cuadrícula (display: grid, grid-area)"las diapositivas comparten un mismo lugar …"
aspect-ratio en la fotola misma prueba (una foto 4:3 es más alta)
el background de la píldora"representado sobre cada foto …" (blanco sobre una foto pálida es aproximadamente 1:1)
border-width: 5px en el punto mostradola prueba de colores forzados
las reglas de transitionla prueba de fundido ("un fotograma intermedio")
pointer-events: none en las diapositivas no mostradas"el enlace de la foto va a su página …" (una diapositiva que se desvanece captura el clic)
el inert y aria-hidden que el script establece en las diapositivas no mostradas (hero-carousel.js)las pruebas de tecla Tab y del árbol de accesibilidad (el enlace de la diapositiva que se va sigue siendo alcanzable y legible mientras se desvanece)
el recover() del script (una foto fallida mostrada se reemplaza por la primera otra foto que esté allí, ahora o cuando llegue)"una primera imagen que falla …"

4. La página de privacidad, y el camino de vuelta

El carrusel no almacena ni envía nada: nada que añadir a la página de privacidad.

Para eliminarlo: borra los cuatro archivos, el bloque <HeroCarousel> y la línea import HeroCarousel (con las importaciones de fotos que solo él usaba) de la página; vuelve a poner una foto. Nada más hace referencia a él, aparte de los conjuntos impulsados por PAGES que solo ven la página.

5. No está en este skill (para que nadie asuma)

Flechas de anterior/siguiente, gestos de deslizamiento, pies de foto en las imágenes, créditos en las imágenes, diapositivas de vídeo, más de un carrusel en una página (sus IDs son fijos), carga diferida de las fotos posteriores. Cada uno puede añadirse más tarde; ninguno es necesario para la primera versión.

Individual skills in this repo

This repo contains 2 individual skills — each has its own dedicated page.

Skills relacionados