Vai al contenuto
animorio
EN
Tutti i componenti

La tabella con le tasche

Tabelle, Transizioni, SVGGSAPImpegnativaPeso compresso: Demo 17 KBGSAP 28 KBGratisScarica lo zip

Gli ordini all’ingrosso di una torrefazione, con un filtro dove ogni stato è una tasca. Cambiando filtro, gli ordini nuovi escono dalla loro tasca e si aprono al loro posto, fra le righe di prima che si scostano; poi ogni ordine che non c’entra più si stringe sulla sua etichetta di stato, l’etichetta vola nella sua tasca, sparisce dietro il bordo e la tasca la prende con una mossa sua (la fiamma guizza, il sacchetto si gonfia, il furgone molleggia), e la tabella si stringe. Mai vuota, ferma in meno di un secondo. Aperto, un ordine mostra la curva di tostatura del suo lotto, disegnata col colore dei chicchi a ogni temperatura.

Il codice

Una cartella che funziona da sola: index.html, style.css, script.js e le librerie da CDN. Nelle schede React e Vue la stessa demo è già un componente, che spegne le sue animazioni quando esce dalla pagina.

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <title>The table with pockets</title>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@fontsource-variable/bricolage-grotesque@5.3.0/standard.css">
  <link rel="stylesheet" href="style.css">
</head>
<body>
  <main class="stage">
    <!-- the table with pockets: a coffee roastery's wholesale orders. Every status tab is a pocket: filtering, the
         orders that do not belong close in on their status label and the label flies into its pocket; choosing a
         pocket, its orders come out and open up in their places. An order opens on the roast curve of its batch -->
    <section class="orders" aria-labelledby="orders-title" data-orders data-autoclic>
      <header class="orders__head">
        <h2 class="orders__title" id="orders-title">Wholesale orders</h2>
        <p class="orders__note">Roasted this week</p>
      </header>

      <div class="tabs" role="group" aria-label="Show orders" data-tabs>
        <span class="tabs__knob" aria-hidden="true" data-knob></span>
        <button class="tab" type="button" aria-pressed="true" data-filter="all">
          <span class="tab__in">
            <span class="tab__label">All</span>
            <span class="tab__count" data-count></span>
          </span>
        </button>
        <button class="tab tab--roasting" type="button" aria-pressed="false" data-filter="roasting">
          <span class="tab__in">
            <span class="tab__icon" aria-hidden="true"><svg viewBox="0 0 24 24"><path d="M12 3.2c1.3 3.4 5.8 5.6 5.8 11a5.8 5.8 0 0 1-11.6 0c0-2.8 1.5-4.6 2.9-5.8.2 1.8.9 2.8 1.9 3.2-.5-3 .1-5.8 1-8.4z"/><path d="M12 20.2a2.5 2.5 0 0 1-2.5-2.5c0-1.5 1.2-2.4 2-3.6.4 1.1 1.1 1.7 1.8 2.1.7.4 1.2 1 1.2 1.6a2.5 2.5 0 0 1-2.5 2.4z"/></svg></span>
            <span class="tab__label">Roasting</span>
            <span class="tab__count" data-count></span>
          </span>
        </button>
        <button class="tab tab--packed" type="button" aria-pressed="false" data-filter="packed">
          <span class="tab__in">
            <span class="tab__icon" aria-hidden="true"><svg viewBox="0 0 24 24"><path d="M6.3 8.6h11.4v10.6a1.4 1.4 0 0 1-1.4 1.4H7.7a1.4 1.4 0 0 1-1.4-1.4z"/><path d="M6.9 8.6 7.8 3.8h8.4l.9 4.8"/><path d="M10 6.2h4"/><circle cx="12" cy="13.6" r="1.9"/></svg></span>
            <span class="tab__label">Packed</span>
            <span class="tab__count" data-count></span>
          </span>
        </button>
        <button class="tab tab--shipped" type="button" aria-pressed="false" data-filter="shipped">
          <span class="tab__in">
            <span class="tab__icon" aria-hidden="true"><svg viewBox="0 0 24 24"><path d="M2.8 6.4h11v10.2h-11z"/><path d="M13.8 9.6h3.9l3.5 3.6v3.4h-7.4"/><circle cx="7" cy="17.4" r="1.9"/><circle cx="17.2" cy="17.4" r="1.9"/></svg></span>
            <span class="tab__label">Shipped</span>
            <span class="tab__count" data-count></span>
          </span>
        </button>
      </div>

      <div class="sheet" data-sheet>
        <table class="table" aria-labelledby="orders-title" data-table>
          <thead>
            <tr>
              <th class="c-cafe" scope="col">Café</th>
              <th class="c-coffee" scope="col">Coffee</th>
              <th class="c-kg num" scope="col">Weight</th>
              <th class="c-total num" scope="col">Total</th>
              <th class="c-state" scope="col">Status</th>
            </tr>
          </thead>
          <tbody data-rows></tbody>
        </table>
      </div>

      <div class="flight" aria-hidden="true" data-flight></div>
      <p class="sr" aria-live="polite" data-live></p>
    </section>
  </main>

  <script src="https://cdn.jsdelivr.net/npm/gsap@3.15.0/dist/gsap.min.js"></script>
  <script src="script.js"></script>
</body>
</html>

Playground

Cambia valori, colori e testi con le manopole e guarda l’animazione rispondere dal vivo. Oppure scrivi tu nel codice. Poi scarica la cartella con le tue modifiche.

114 valori da cambiare

Oppure chiedila a Claude Code

Col connettore di Animorio, Claude Code la prende da qui con tutta la sua guida e la adatta al tuo progetto. Incolla questa richiesta:

Prendi «La tabella con le tasche» da Animorio e adattala al mio sito

Cosa fa

Su un fondo bianco Wholesale orders e Roasted this week, poi una fila di quattro tasche su un binario color pietra, All, Roasting, Packed e Shipped, ognuna col suo conto (7, 2, 2, 3) e le ultime tre con la loro icona disegnata: una fiamma color brace, un sacchetto da caffè color carta da pacchi, un furgone verde scuro. Una pillola bianca sta sotto la tasca scelta. Sotto, una tabella vera con Café, Coffee, Weight, Total e Status: sette ordini di caffè e panetterie inventati (Little Owl Café, Tamarind House, Copper Pot, Bramble & Bean, Kiosk Nord, Halcyon Bakery, Saltmarsh Deli), l’origine del caffè, i chili, il totale in euro e lo stato in un’etichetta tinta con la sua icona. Scegliendo una tasca la pillola ci scivola sotto. Prima escono le etichette degli ordini che arrivano: scendono dalla loro tasca fino al posto della loro riga, fra le righe che ci sono già, che si scostano per far posto, e lì la finestra si riapre dall’etichetta a tutta la riga. Appena l’ultima è arrivata, ogni ordine che non c’entra si stringe sulla sua etichetta, come una finestra arrotondata che si chiude intorno a lei e prende la sua tinta, e l’etichetta parte subito verso l’alto, si piega verso la sua tasca inclinandosi da quella parte con un’ombra che cresce, e ci entra dritta da sotto, sparendo dietro il bordo del binario. La tasca la prende: le sue scritte saltano un poco, il conto si gonfia e l’icona fa la sua mossa (la fiamma si allunga in su, il sacchetto si schiaccia, il furgone sobbalza e si inclina). Poi le righe che restano scivolano su a chiudere i buchi, tutte insieme. La tabella non resta mai vuota e tutto è fermo in meno di un secondo. Cliccando un ordine (o la riga) la freccetta gira e sotto si apre la sua tostatura: la curva della temperatura dei chicchi si disegna da sinistra, scende da 200 gradi fino al punto di svolta e risale sempre più piano, con la temperatura scritta sulla punta e sotto un’area che passa dal verde del chicco crudo al giallo, al color cannella e ai marroni, fino al quasi nero di una tostatura scura; passando i 196 gradi compare la linea tratteggiata del First crack. Accanto Roast, Drop, In the cup e Delivery. Per un ordine ancora nel tamburo la curva si ferma ad adesso, con la temperatura e now, e il resto del piano compare tratteggiato.

Come funziona

Passare per tutte e due

Ogni ordine ha un posto nella tabella: row (la riga vera), wait (il posto tenuto, invisibile, mentre la sua etichetta arriva), hold (il posto tenuto mentre la finestra si chiude), free (il posto vuoto, l’etichetta è partita) e none (in tasca). Al cambio di filtro la tabella passa per l’unione dei due elenchi, nell’ordine dei dati: i posti degli ordini che arrivano compaiono, invisibili (visibility hidden), fra le righe di prima, che scivolano per far posto con una trasformazione sul tr. Gli ordini che arrivano escono subito dalla tasca; quelli che vanno via restano righe vere finché l’ultimo nuovo sta per atterrare (e mai oltre il momento in cui il primo comincia ad aprirsi, così c’è sempre una riga da leggere). Poi, una volta sola, i posti vuoti spariscono e le righe salgono. I due stormi non volano mai insieme.

La finestra e il volo

Una riga che va via è sostituita, nello stesso fotogramma, da una copia (la riga clonata in una tabella con le stesse colonne, lette dalle intestazioni in un colgroup, e la sua tostatura se era aperta) dentro una finestra: un div con overflow hidden i cui bordi vanno da quelli della riga a quelli dell’etichetta in CLOSE secondi, mentre la copia sfuma e il fondo prende la tinta dell’etichetta. L’etichetta vola su una Bézier cubica col primo punto di controllo dritto sopra la partenza e il secondo dritto sotto la tasca (SWING della salita): parte e arriva in verticale, si inclina fino a 8 gradi verso dove va, si alza verso chi guarda fino al 28% in più con la sua ombra, in FLY secondi (più o meno secondo la strada), accelerando verso la tasca e frenando verso la riga.

La tasca

Lo strato delle etichette in volo sta sopra la tabella e sotto le tasche (z-index): l’etichetta passa dietro il bordo di sotto del binario e lì sparisce, senza dissolvenza. La tasca la prende: il suo contenuto salta di 3 pixel con un back.out in 0,22 secondi (un filtro si usa tante volte di fila), il conto si gonfia, e l’icona fa la sua mossa, la fiamma si allunga dalla base, il sacchetto si schiaccia, il furgone sobbalza inclinandosi sulle ruote di dietro. Le mosse sono sull’svg, la pressione del pulsante (scale 0,96) sul pulsante: un elemento per GSAP e uno per il CSS.

Interrompere, e i tempi

Un clic a metà riprende ogni ordine da dov’è: un’etichetta che stava arrivando torna in tasca (il suo posto si libera), una che stava andando via torna al suo posto (se la finestra si stava ancora chiudendo, si riapre lì), una riga che doveva ancora partire viene decisa di nuovo; se la meta di un’etichetta non è cambiata, continua per la sua strada. Un clic su una riga durante il cambio aspetta che la tabella sia ferma. Coi valori di partenza, misurati fotogramma per fotogramma: le prime righe nuove si leggono fra 250 e 333 millisecondi, la tabella è ferma entro 750 e tutto, tasche comprese, entro 900.

La curva di tostatura

Costruita alla larghezza vera del suo riquadro, così le scritte restano alla loro misura. La temperatura dei chicchi è una curva di Hermite cubica che passa per la carica (200 gradi), il punto di svolta (92 gradi a 1:15), l’ingiallimento (150), il first crack (196) e lo scarico, con le pendenze prese dai ritmi di salita vicini, che quindi rallentano come in un tamburo vero; un punto ogni 4 secondi. A ogni fotogramma si ridisegna fino a q della strada: la linea, l’area sotto, un filo verticale e la temperatura sulla punta. L’area ha un gradiente con una fermata ogni ventiquattresimo del tempo, del colore del chicco alla temperatura di quel momento (verde, giallo, cannella al first crack, marroni), e una maschera che la schiarisce verso il fondo. Per un ordine ancora nel tamburo la curva si ferma ad adesso e il resto del piano compare tratteggiato.

Tabella vera, tastiera e anteprima

Una table con th scope col e scope row, il nome del caffè è un pulsante con aria-expanded e aria-controls sulla riga del dettaglio, le tasche sono pulsanti con aria-pressed in un gruppo (le frecce passano dall’una all’altra), una regione aria-live dice Showing 2 packed orders, Esc chiude il dettaglio. La tabella tiene l’altezza di tutte le sue righe (min-height), così quello che viene dopo non salta. Un clic da script (l’anteprima della libreria) fa il giro: Shipped e apre Copper Pot, Packed, All, Roasting e apre Tamarind House, chiude e All.

Valori da cambiare

NomeFileDi partenzaCosa cambia
ORDERSscript.js[['Little Owl Café', 'Huila, Colombia', 12, 318, 'packed'], …]Gli ordini: caffè, origine, chili, totale in euro e stato (roasting, packed o shipped).
ROASTSscript.js[['Medium', '8:52', '10:40', 212, 'Red apple, panela', 'Thu 8 Oct'], …]La tostatura di ogni ordine: livello, first crack, scarico (minuti:secondi), temperatura di scarico, cosa c’è nella tazza, consegna e, per quelli ancora nel tamburo, da quanto ci sono.
FLYscript.js0.28I secondi del volo di un’etichetta verso la sua tasca, o fuori.
CLOSEscript.js0.12I secondi in cui una riga si stringe sulla sua etichetta (e poco di più per riaprirsi).
STAGGERscript.js0.025I secondi fra la partenza di un ordine e del successivo.
SWINGscript.js0.45Quanto sale dritta un’etichetta prima di piegare verso la tasca, in parte della salita: 0 è una linea dritta.
DRAWscript.js1.3I secondi in cui si disegna la curva di tostatura.

Provali nel Playground

Quando usarla

Per gli ordini di un negozio all’ingrosso, le spedizioni di un magazzino, le pratiche di uno studio, i ticket di un’assistenza, le candidature di un annuncio: ogni elenco diviso per stato, dove aiuta vedere dove sono andate le righe che il filtro nasconde.

Sul telefono

A 390 pixel le colonne Coffee e Weight scompaiono e passano sotto il nome del caffè (la regione e i chili); le etichette si stringono all’86% con l’asse della larghezza di Bricolage Grotesque, le righe sono alte 62 pixel e le quattro tasche si dividono la larghezza, alte 44, con le parole e i conti (le icone restano nelle etichette). La tostatura va sopra i suoi dati. Le animazioni sono le stesse: le etichette salgono lungo la colonna degli stati fino alle tasche.

Con il movimento ridotto

Niente vola e niente scivola: le righe che escono spariscono, quelle che entrano compaiono sfumando al loro posto, la pillola è subito sotto la tasca scelta e la tostatura si apre già disegnata, con una dissolvenza.

Trappole

  • Una riga di tabella non si ritaglia in una finestra e non vola: l’etichetta in volo è una copia della riga in uno strato sopra, in una tabella con le stesse larghezze di colonna (lette dalle intestazioni in un colgroup) e le stesse classi; la riga vera diventa hidden nello stesso fotogramma, così il passaggio non si vede.
  • La copia di un ordine aperto si porta via anche la tostatura: nella copia gli id del gradiente e della maschera vanno rinominati, o url(#...) punterebbe all’originale, che nello stesso istante diventa display none (e lì i gradienti non si dipingono).
  • Una riga che torna deve avere il suo posto prima di farsi vedere: visibility hidden sul tr (non display none), così le altre si scostano mentre l’etichetta è ancora in volo.
  • L’attributo opacity di un elemento SVG perde contro una regola CSS con opacity: la linea tratteggiata del piano e il filo del cursore hanno la trasparenza in stroke-opacity, così lo script li accende e li spegne con l’attributo.
  • In uno scambio (da Packed a Shipped) la tabella restava vuota per quasi mezzo secondo fra le righe che se ne andavano e quelle che arrivavano: ora passa per l’unione dei due elenchi, le nuove si aprono fra le vecchie e le vecchie se ne vanno solo dopo. Il momento in cui partono è legato a CLOSE (prima che il primo nuovo si apra meno 0,55 CLOSE più 30 millisecondi), o con le finestre velocissime restavano uno o due fotogrammi senza righe.
  • Con le code elastiche delle tasche (0,7 secondi) un cambio durava più di un secondo e mezzo: un filtro si usa tante volte di fila, quindi tutto è stato accorciato (volo 0,28, finestra 0,12, scosse 0,22 con back.out).
  • La riga del dettaglio di un ordine che va via aperto deve tenere il suo posto invisibile fino a quando la tabella si stringe: la regola visibility hidden valeva solo per .row, e la tostatura restava lì scoperta dopo che la sua finestra si era chiusa.
  • Al telefono le quattro tasche con le icone non stavano in 358 pixel: le icone vanno via, parole e conti restano.
  • Un clic su una riga durante il cambio di filtro avrebbe aperto la tostatura mentre i posti si spostano, e le etichette in volo sarebbero atterrate nel posto sbagliato: il clic aspetta che la tabella sia ferma (meno di un secondo).

Librerie

GSAP 3.15.0, Bricolage Grotesque (font variabile) 5.3.0.

Compressi con gzip, i tre file della demo pesano 17 KB; le librerie: GSAP 28 KB.

Collaudo

Provata il 7 ottobre 2026

  • Computer: Fatto
  • Telefono: Fatto
  • Movimento ridotto: Fatto
  • Safari su iPhone: Da fare

Licenza d’uso

Puoi usarla nei tuoi progetti e in quelli dei tuoi clienti. Non puoi rivenderla né ridistribuirla così com’è. GSAP resta sotto la sua licenza Standard. Licenza completa.

Tutti i componenti