Video

<div class="rtds-video ">
    <button type="button" class="rtds-video__play rtds-group">
        <span class="rtds-video__play-icon rtds-btn rtds-btn--icon rtds-w-16 rtds-h-16 rtds-text-white rtds-cursor-pointer rtds-rounded-full rtds-border-4">
            <svg class="rtds-icon rtds-fill-current rtds-w-8 rtds-h-8 rtds-transition-all" aria-hidden="true" focusable="false" role="img">
                <use href="../../icons.svg#mini--play" />
            </svg>

            <span class="rtds-sr-only">Riproduci il video: Video youtube: titolo video</span>
        </span>

        <div class="rtds-video__overlay"></div>

        <picture class="rtds-video__overlay-image">
            <img class="rtds-object-cover rtds-object-center rtds-w-full rtds-h-full" src="/images/feathers.jpg" alt="" />
        </picture>

    </button>
    <iframe class="rtds-video__iframe rtds-invisible" src="https://www.youtube.com/embed/mkggXE5e2yk?si=dqKsArDWXeMSAXnZ" title="Video youtube: titolo video" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
</div>
<div class="rtds-video{% if aspectRatio %} {{ aspectRatio }}{% endif %} {% if containerClasses %} {{ containerClasses }}{% endif %}">
    <button type="button" class="rtds-video__play rtds-group">
        <span class="rtds-video__play-icon rtds-btn rtds-btn--icon rtds-w-16 rtds-h-16 rtds-text-white rtds-cursor-pointer rtds-rounded-full rtds-border-4">
            {% render '@icon--small', { id: 'mini--play', classes: 'rtds-transition-all', size: 'rtds-w-8 rtds-h-8' }, true %}
            <span class="rtds-sr-only">Riproduci il video: {{ videoTitle }}</span>
        </span>

        <div class="rtds-video__overlay"></div>
        {% if overlayImage %}
            <picture class="rtds-video__overlay-image{% if aspectRatio %} {{ aspectRatio }}{% endif %}">
                <img class="rtds-object-cover rtds-object-center rtds-w-full rtds-h-full" src="{{ overlayImage }}" alt="{{ overlayImageAlt }}" />
            </picture>
       {% endif %}
    </button>
    <iframe class="rtds-video__iframe{% if aspectRatio %} {{ aspectRatio }}{% endif %} rtds-invisible" src="{{ videoSrc }}" title="{{ videoTitle }}" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
</div>
{
  "title": "video",
  "videoSrc": "https://www.youtube.com/embed/mkggXE5e2yk?si=dqKsArDWXeMSAXnZ",
  "overlayImage": "/images/feathers.jpg",
  "overlayImageAlt": "",
  "videoTitle": "Video youtube: titolo video"
}
  • Content:
    /* Video player custom Component */
    .rtds-video {
        position: relative;
        aspect-ratio: 16 / 9;
    }
    .rtds-video__iframe {
        aspect-ratio: 16 / 9;
        width: 100% !important;
    }
    .rtds-video__overlay {
        position: absolute;
        top: var(--spacing-0);
        right: var(--spacing-0);
        bottom: var(--spacing-0);
        left: var(--spacing-0);
        z-index: 10;
        background-color: rgb(0 0 0 / var(--tw-bg-opacity, 1));
        --tw-bg-opacity: 0.2;
        transition-property: all;
        transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
        transition-duration: 150ms;
    }
    .rtds-group:hover .rtds-video__overlay {
        --tw-bg-opacity: 0.4;
    }
    .rtds-video__overlay-image {
        display: block;
        height: 100%;
        width: 100%;
        -o-object-fit: cover;
           object-fit: cover;
        -o-object-position: center;
           object-position: center;
    }
    .rtds-video__play {
        position: absolute;
        top: var(--spacing-0);
        right: var(--spacing-0);
        bottom: var(--spacing-0);
        left: var(--spacing-0);
        z-index: 20;
        width: 100%;
        transition-property: all;
        transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
        transition-duration: 150ms;
    }
    .rtds-video__iframe:focus-visible,
        .rtds-video__play:focus-visible {
        --tw-shadow: 0 0 0 7px rgba(255,255,255,1);
        --tw-shadow-colored: 0 0 0 7px var(--tw-shadow-color);
        box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow);
        outline: 2px solid transparent;
        outline-offset: 2px;
        --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
        --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color);
        box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000);
        --tw-ring-color: var(--color-focusring);
        --tw-ring-offset-width: 2px;
        --tw-ring-offset-color: #ffffff;
    }
    .rtds-video__play-icon {
        position: absolute;
        top: 50%;
        left: 50%;
        z-index: 20;
        --tw-translate-x: -50%;
        --tw-translate-y: -50%;
        transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
            background-color: var(--color-background-primary);
    }
    
  • URL: /components/raw/video/video.built.css
  • Filesystem Path: components/04-organisms/video/video.built.css
  • Size: 2.4 KB
  • Content:
    /* Video player custom Component */
    @layer components {
        .rtds-video {
            @apply rtds-aspect-video rtds-relative;
        }
    
        .rtds-video__iframe {
            @apply rtds-aspect-video !rtds-w-full;
        }
    
        .rtds-video__overlay {
            @apply rtds-absolute rtds-z-10 rtds-top-0 rtds-right-0 rtds-bottom-0 rtds-left-0 rtds-bg-black rtds-bg-opacity-20 group-hover:rtds-bg-opacity-40 rtds-transition-all;
        }
    
        .rtds-video__overlay-image {
            @apply rtds-object-cover rtds-object-center rtds-block rtds-w-full rtds-h-full;
        }
    
        .rtds-video__play {
            @apply  rtds-transition-all rtds-absolute rtds-top-0 rtds-right-0 rtds-bottom-0 rtds-left-0 rtds-z-20 rtds-w-full;
        }
    
        .rtds-video__iframe,
        .rtds-video__play {
            @apply focus-visible:rtds-ring focus-visible:rtds-ring-offset-2 focus-visible:rtds-ring-offset-white focus-visible:rtds-ring-focusring focus-visible:rtds-shadow-[0_0_0_7px_rgba(255,255,255,1)] focus-visible:rtds-outline-none;
        }
    
        .rtds-video__play-icon {
            @apply rtds-absolute rtds-z-20 rtds-top-1/2 rtds-left-1/2 -rtds-translate-x-1/2 -rtds-translate-y-1/2 rtds-background-primary;
        }
    }
  • URL: /components/raw/video/video.css
  • Filesystem Path: components/04-organisms/video/video.css
  • Size: 1.2 KB
  • Content:
    /* VIDEO SCRIPT
    * Manage cover and video play
     */
    document.addEventListener('DOMContentLoaded', function () {
        'use strict';
    
        // Selezionare tutti gli elementi videoContainer sulla pagina
        var videoContainers = document.querySelectorAll('.rtds-video');
        console.log('Video containers trovati:', videoContainers.length);
    
        // Iterare su ogni videoContainer trovato
        videoContainers.forEach(function (videoContainer) {
            var playButton = videoContainer.querySelector('.rtds-video__play');
            var videoIframe = videoContainer.querySelector('.rtds-video__iframe');
    
            function viewVideo() {
    
                // Nascondi il pulsante play che contiene anche l'overlay
                playButton.style.display = 'none';
                videoIframe.classList.remove('rtds-invisible');
                videoIframe.setAttribute('tabindex', '0');
                videoIframe.focus();
                
                // Aggiungi autoplay al src dell'iframe solo se non è già presente
                if (!videoIframe.src.includes('autoplay=1')) {
                    videoIframe.src += (videoIframe.src.includes('?') ? '&' : '?') + 'autoplay=1';
                }
            }
    
            if (playButton) {
                playButton.addEventListener('click', viewVideo);
                
                // listener per keydown per l'accessibilità
                playButton.addEventListener('keydown', function(e) {
                    if (e.key === 'Enter' || e.key === ' ') {
                        e.preventDefault();
                        viewVideo();
                    }
                });
            }
        });
    });
    
  • URL: /components/raw/video/video.js
  • Filesystem Path: components/04-organisms/video/video.js
  • Size: 1.6 KB

Video

Componente per l’incorporamento di video YouTube con pulsante play personalizzato e immagine di anteprima sovrapposta. L’iframe viene reso visibile solo dopo l’attivazione del pulsante play.

Accessibilità

WCAG 2.1

Livello AA — criteri pertinenti:

  • 1.1.1 Contenuti non testuali — il pulsante play ha testo rtds-sr-only con il titolo del video; l’immagine overlay ha alt descrittivo
  • 4.1.2 Nome, Ruolo, Valore — il pulsante play ha type="button" e testo accessibile
  • 2.1.1 Tastiera — il pulsante play è raggiungibile e attivabile da tastiera

Struttura e semantica

  • Il componente è renderizzato come <div class="rtds-video"> — wrapper presentazionale
  • Il pulsante play è <button type="button"> — elemento nativo interattivo, accessibile da tastiera
  • L’iframe ha title="" — attributo obbligatorio per identificare il contenuto agli screen reader
  • L’immagine overlay ha alt="" — deve descrivere l’anteprima del video

Attributi ARIA

Attributo Valori Condizione
title sull’<iframe> valore di videoTitle sempre presente
alt sull’immagine overlay valore di overlayImageAlt quando overlayImage è presente
Tasto Azione
Tab Porta il focus sul pulsante play
Enter / Space Attiva il pulsante play — avvia il video (gestito da JavaScript)

Gestione del focus

  • Focus visibile: lo stile :focus-visible è sempre visibile e non viene rimosso via CSS

Screen reader

  • Il testo <span class="rtds-sr-only">Riproduci il video: </span> nel pulsante play fornisce nome accessibile al controllo
  • L’iframe è inizialmente rtds-invisible — lo screen reader potrebbe comunque rilevarlo; assicurarsi che title sia sempre presente

Configurazioni

  • videoSrc: URL del video YouTube con parametri (es. &controls=2&modestbranding=1&rel=0)
  • overlayImage: percorso immagine di anteprima
  • overlayImageAlt: testo alternativo dell’immagine di anteprima
  • videoTitle: titolo del video (usato in title sull’iframe e nel testo nascosto del pulsante play)
  • aspectRatio: classe aspect ratio del componente (default: rtds-aspect-video)
  • containerClasses: classi CSS aggiuntive per il contenitore
  • iframeClasses: classi CSS aggiuntive per l’iframe