Questa lezione costruisce una sidebar che fa molto più che scivolare dal bordo. Ogni card di una griglia CMS apre la propria sidebar con dettagli extra, lo scroll della pagina si blocca mentre è aperta, puoi chiuderla cliccando fuori e — la parte che la maggior parte dei tutorial salta — è davvero accessibile: semantica di dialog corretta e un vero focus trap per chi usa tastiera e screen reader.
Le tecniche interessanti sono due: usare i target filter relazionali di GSAP così una sola interazione serve ogni card, e stratificare l’accessibilità che trasforma un bel pannello in un vero dialog.
Come funziona
Una sidebar per item CMS. Dato che la sidebar sta dentro l’item della collezione, ogni card renderizza il proprio pannello legato ai campi di quell’item — thumbnail, titolo, summary, immagine della sidebar. Clicchi una card e la sidebar corrispondente è già lì. Il wrapper della sidebar è position: fixed, a tutto viewport, z-index alto, display: none di default; al suo interno un overlay semi-trasparente (position: absolute, full) e un content wrapper spinto a destra (margin-left: auto, ~50% di larghezza, max-width, overflow: auto così il contenuto alto resta scrollabile).
Targeting guidato da attributi con i filtri. Dato che ci sono molte sidebar identiche, l’interazione non può colpire per classe — deve trovare la sidebar di questa card. Il trucco sono gli attributi custom (data-animate, data-sidebar-open, data-sidebar-close) più i target filter di GSAP, che colpiscono rispetto al trigger: previous sibling of trigger (la sidebar accanto al pulsante di apertura), within parent of trigger (overlay/contenuto dentro l’item condiviso) e contains trigger (la sidebar che avvolge il controllo di chiusura cliccato). Una interazione, target corretto ogni volta.
Apri, chiudi e scroll lock. L’interazione di apertura è una set action che porta il display della sidebar a flex (0s), una animate che fa il fade in dell’overlay (from opacity 0), una animate che fa scivolare dentro il contenuto (from move-X 100%) e una set action che aggiunge una classe overflow-hidden al body per bloccare lo scroll. L’interazione di chiusura è l’inverso: fade out dell’overlay, slide out del contenuto, poi — a start 0.8s, finita l’animazione — set del display a none e remove della classe di scroll lock. Sia il pulsante di chiusura sia l’overlay portano data-sidebar-close, così una sola interazione di chiusura gestisce click sul pulsante e click esterno.
Accessibilità vera, non decorazione. Ogni elemento che attiva un’azione è un vero button (custom element, type="button") con un aria-label, e le icone decorative ricevono aria-hidden="true". La sidebar stessa ottiene role="dialog", aria-modal="true" e aria-labelledby che punta all’id del titolo — impostato dallo slug CMS così il dialog di ogni item annuncia il proprio titolo. Infine tabindex="-1" rende il pannello focusabile via script senza aggiungerlo all’ordine di tab.
Il focus trap. Un dialog non è accessibile finché il focus non è gestito. Un piccolo script (in Before </body>) ricorda quale card ha aperto il pannello, porta il focus dentro la sidebar (sul pulsante di chiusura) all’apertura, intrappola il Tab così cicla tra i controlli del pannello invece che tra la pagina dietro, chiude con Escape e riporta il focus sulla card d’origine alla chiusura. È questo che lo fa comportare come un vero dialog modale per chi usa la tastiera.
Come si usa
-
Struttura (dentro l’item CMS). Div
sidebar:position: fixed, full, z-index ~3000,display: none. Dentro: un overlay (position: absolute, full, nero 50%) e unsidebar_content-wrapper(margin-left: auto, ~50% di larghezza, max-width,overflow: auto,position: relative). Lega immagine/titolo/summary ai campi CMS. -
Marca tutto.
data-animatesu sidebar, overlay e content wrapper (valori distinti);data-sidebar-opensul pulsante di apertura della card;data-sidebar-closesu pulsante di chiusura e overlay. Rendi i controlli apri/chiudi/overlay veributtoncustom element conaria-label. -
Interazione di apertura. set display flex (target sidebar via previous sibling of trigger), animate opacity dell’overlay from 0, animate move-X del contenuto from 100%, set
overflow-hiddensul body — tutto a 0s, 0.8s, ease in-out expo. -
Interazione di chiusura. Trigger su
data-sidebar-close. Inverti le animazioni (overlay a 0, contenuto a 100%), poi a start 0.8s set display none (target via contains trigger) e remove della classeoverflow-hidden. -
Accessibilità. Sulla sidebar:
role="dialog",aria-modal="true",aria-labelledby=<slug>(e imposta l’iddel titolo sullo stesso slug),tabindex="-1". Incolla lo script di focus trap in Before</body>. Pubblica e prova con la tastiera (Tab, Escape) sul link live.
Lo script di focus trap / tastiera viene dal cloneable — copialo da lì invece di ricostruirlo, e verifica che corrisponda ai tuoi nomi di attributo.