Design System PA — LLM-first

Pensato perché siano gli assistenti AI a costruire UI della PA conformi ad AgID. Web Components universali (React, Vue, Angular, HTML puro) con accessibilità incapsulata, generati da spec/. Progetto community, non ufficiale.

▶ Guarda un esempio completo: home di un Comune (con form)  ·  ⌨ Codice su GitHub

<it-accordion>

Sezioni di contenuto espandibili (disclosure)

Risposta.
PropValoriDefault
multiplebooleanfalse

Accessibilità (incapsulata nel componente)

  • Ogni intestazione è un <button> con aria-expanded gestito dal componente
  • Il pannello ha role=region e aria-labelledby verso l'header
  • Navigazione tra le intestazioni con frecce Su/Giù, Home ed End
<it-accordion>
  <div data-header="Domanda">Risposta.</div>
</it-accordion>

<it-alert>

Messaggio di feedback contestuale

Si è verificato un errore nei dati inseriti.
PropValoriDefault
variantinfo success danger warning"info"

Accessibilità (incapsulata nel componente)

  • role=alert per l'annuncio agli screen reader
  • Tipo veicolato da testo, non dal solo colore
<it-alert variant="danger">Si è verificato un errore nei dati inseriti.</it-alert>

<it-avatar>

Rappresentazione di un utente con iniziali

MC
PropValoriDefault
namestring""

Accessibilità (incapsulata nel componente)

  • Le iniziali sono decorative (aria-hidden); il nome completo è per screen reader
<it-avatar name="Mario Colombo">MC</it-avatar>

<it-badge>

Etichetta breve per stati o marcatori

Attivo
PropValoriDefault
variantprimary success warning secondary"primary"

Accessibilità (incapsulata nel componente)

  • Il significato è nel testo, mai nel solo colore
<it-badge variant="success">Attivo</it-badge>

<it-breadcrumb>

Percorso di navigazione (breadcrumb)

Nessuna prop.

Accessibilità (incapsulata nel componente)

  • <nav aria-label>
  • L'elemento corrente usa aria-current=page e non è un link
<it-breadcrumb>
  <a href="/">Home</a>
  <a href="/servizi">Servizi</a>
  <a>Iscrizione mensa</a>
</it-breadcrumb>

<it-button>

Bottone per un'azione dell'utente

Annulla
PropValoriDefault
variantprimary secondary outline success danger warning"primary"
sizesm md lg"md"
typebutton submit"button"
disabledbooleanfalse

Accessibilità (incapsulata nel componente)

  • Emette sempre un <button> nativo (mai <div> cliccabili)
  • Se privo di testo (solo icona) richiede aria-label
  • Indicatore di focus sempre visibile
<it-button variant="outline">Annulla</it-button>

<it-callout>

Riquadro informativo per evidenziare un contenuto

Controlla i dati.
PropValoriDefault
variantinfo warning success"info"
titlestring"Informazione"

Accessibilità (incapsulata nel componente)

  • role=note sul contenitore
  • Il tipo (info/attenzione/successo) è veicolato da titolo + icona, non dal solo colore
<it-callout variant="warning" title="Attenzione">Controlla i dati.</it-callout>

<it-card>

Contenitore per un contenuto sintetico

Consulta e paga le rette del servizio mensa.
PropValoriDefault
titlestring"Titolo"

Accessibilità (incapsulata nel componente)

  • Il titolo usa un livello di heading coerente con la pagina
<it-card title="Rette e pagamenti">Consulta e paga le rette del servizio mensa.</it-card>

<it-checkbox>

Casella di spunta con etichetta

Ho letto e accetto l'informativa sulla privacy

Nessuna prop.

Accessibilità (incapsulata nel componente)

  • La label avvolge l'input (associazione implicita)
<it-checkbox>Ho letto e accetto l'informativa sulla privacy</it-checkbox>

<it-chip>

Elemento compatto per un attributo o filtro

Filtro attivo

Nessuna prop.

Accessibilità (incapsulata nel componente)

  • Se rimovibile, il pulsante di rimozione ha testo accessibile
<it-chip>Filtro attivo</it-chip>

<it-collapsible> @zag-js/collapsible

Contenuto mostra/nascondi

Contenuto nascondibile.
PropValoriDefault
triggerstring"Mostra"

Accessibilità (incapsulata nel componente)

  • Trigger con aria-expanded e aria-controls (Zag)
  • Funziona da tastiera
<it-collapsible trigger="Mostra dettagli">Contenuto nascondibile.</it-collapsible>

<it-combobox> @zag-js/combobox

Campo con suggerimenti (combobox)

Roma
Milano
PropValoriDefault
labelstring"Cerca"

Accessibilità (incapsulata nel componente)

  • Pattern ARIA combobox, navigazione da tastiera (Zag)
  • Il filtro lato client è responsabilità del consumer
<it-combobox label="Comune">
  <div data-value="rm">Roma</div>
  <div data-value="mi">Milano</div>
</it-combobox>

<it-datatable>

Tabella dati con ordinamento, ricerca e paginazione

Pagamenti
DataDescrizioneImporto
01/03/2026Mensa marzo45,00
01/04/2026Mensa aprile45,00
10/04/2026Trasporto30,00
05/05/2026Mensa maggio48,50
12/05/2026Materiale12,00
01/06/2026Mensa giugno45,00
20/06/2026Gita25,00
PropValoriDefault
page-sizestring"10"
searchablebooleanfalse

Accessibilità (incapsulata nel componente)

  • Intestazioni ordinabili con aria-sort (none/ascending/descending)
  • Live region annuncia numero risultati e pagina
  • Ricerca con label; paginazione come <nav aria-label>
  • Niente macchina Zag: è logica sui dati, non stato UI
<it-datatable page-size="4" searchable>
  <table>
    <caption>Pagamenti</caption>
    <thead><tr><th>Data</th><th>Descrizione</th><th>Importo</th></tr></thead>
    <tbody>
      <tr><td>01/03/2026</td><td>Mensa marzo</td><td>45,00</td></tr>
      <tr><td>01/04/2026</td><td>Mensa aprile</td><td>45,00</td></tr>
      <tr><td>10/04/2026</td><td>Trasporto</td><td>30,00</td></tr>
      <tr><td>05/05/2026</td><td>Mensa maggio</td><td>48,50</td></tr>
      <tr><td>12/05/2026</td><td>Materiale</td><td>12,00</td></tr>
      <tr><td>01/06/2026</td><td>Mensa giugno</td><td>45,00</td></tr>
      <tr><td>20/06/2026</td><td>Gita</td><td>25,00</td></tr>
    </tbody>
  </table>
</it-datatable>

<it-datepicker> @zag-js/date-picker

Selezione data con calendario

PropValoriDefault
labelstring"Data"

Accessibilità (incapsulata nel componente)

  • Griglia calendario navigabile da tastiera, ARIA e input digitabile da Zag
<it-datepicker label="Data di nascita"></it-datepicker>

<it-dialog> @zag-js/dialog

Finestra di dialogo modale accessibile

Contenuto del dialog…
PropValoriDefault
triggerstring"Apri"
titlestring"Finestra di dialogo"

Accessibilità (incapsulata nel componente)

  • role=dialog + aria-modal + aria-labelledby verso il titolo (forniti da Zag)
  • Focus-trap: il focus resta dentro il dialog mentre è aperto
  • Chiusura con ESC e con click sul backdrop
  • Alla chiusura il focus torna al trigger
<it-dialog trigger="Apri" title="Conferma">Contenuto del dialog…</it-dialog>

<it-divider>

Separatore orizzontale tra blocchi di contenuto

Nessuna prop.

Accessibilità (incapsulata nel componente)

  • <hr> semantico: separazione tematica del contenuto
<it-divider></it-divider>

<it-drawer> @zag-js/dialog

Pannello off-canvas (menu laterale, filtri) che scivola da un lato

PropValoriDefault
triggerstring"Apri"
titlestring"Pannello"
sideleft right"left"

Accessibilità (incapsulata nel componente)

  • role=dialog + focus-trap + ESC + backdrop (da Zag)
  • Alla chiusura il focus torna al trigger
  • Blocco dello scroll di sfondo mentre è aperto
<it-drawer trigger="Apri menu laterale" side="left" title="Menu">
  <it-linklist>
    <a href="#">Anagrafe</a>
    <a href="#">Tributi</a>
    <a href="#">Servizi scolastici</a>
  </it-linklist>
</it-drawer>

<it-header>

Testata istituzionale dell'ente

PropValoriDefault
entestring"Ente di appartenenza"
nomestring"Nome dell'Ente"
taglinestring""

Accessibilità (incapsulata nel componente)

  • Un solo <header> landmark per pagina
  • Il nome dell'ente linka alla home
<it-header ente="Comune di Esempio" nome="Comune di Esempio" tagline="Servizi al cittadino"></it-header>

<it-hero>

Blocco di apertura ad alto impatto (testata di pagina)

Trova e accedi ai servizi del Comune.
PropValoriDefault
titlestring"Titolo"
categorystring""

Accessibilità (incapsulata nel componente)

  • Se contiene il titolo di pagina deve essere l'unico <h1>
  • Verifica il contrasto del testo sullo sfondo
<it-hero title="Servizi al cittadino">Trova e accedi ai servizi del Comune.</it-hero>

<it-input>

Campo di testo con etichetta

PropValoriDefault
labelstring"Etichetta"
typestring"text"
placeholderstring""

Accessibilità (incapsulata nel componente)

  • La label avvolge l'input (associazione implicita)
  • Il placeholder non sostituisce la label
<it-input label="Nome e cognome" placeholder="Es. Mario Rossi"></it-input>

<it-megamenu> @zag-js/popover

Menu esteso su più colonne

PropValoriDefault
triggerstring"Argomenti"

Accessibilità (incapsulata nel componente)

  • Apertura/chiusura, focus ed ESC dal popover Zag
  • Colonne di link navigabili da tastiera
<it-megamenu trigger="Argomenti">
  <div data-col="Servizi"><a href="#">Anagrafe</a><a href="#">Tributi</a></div>
  <div data-col="Vivere"><a href="#">Scuola</a><a href="#">Trasporti</a></div>
</it-megamenu>

<it-menu> @zag-js/menu

Menu a discesa di azioni

PropValoriDefault
triggerstring"Menu"

Accessibilità (incapsulata nel componente)

  • role=menu/menuitem, navigazione con frecce, focus e ARIA da Zag
<it-menu trigger="Azioni">
  <div data-item="Modifica"></div>
  <div data-item="Elimina"></div>
</it-menu>

<it-navbar>

Barra di navigazione principale

Nessuna prop.

Accessibilità (incapsulata nel componente)

  • <nav aria-label='Navigazione principale'>
  • Su mobile: toggle hamburger con aria-expanded/aria-controls
  • La voce corrente usa aria-current=page
<it-navbar>
  <a href="/">Home</a>
  <a href="/servizi">Servizi</a>
  <a href="/amministrazione">Amministrazione</a>
</it-navbar>

<it-navscroll>

Indice a scorrimento con evidenziazione della sezione (scroll-spy)

PropValoriDefault
titlestring"In questa pagina"

Accessibilità (incapsulata nel componente)

  • <nav aria-label>
  • La sezione visibile riceve aria-current (IntersectionObserver)
  • Nota: nessuna macchina Zag per lo scroll-spy
<it-navscroll title="In questa pagina">
  <a href="#sez-1">Descrizione</a>
  <a href="#sez-2">Come fare</a>
</it-navscroll>

<it-number> @zag-js/number-input

Campo numerico con incremento/decremento

PropValoriDefault
labelstring"Valore"

Accessibilità (incapsulata nel componente)

  • Label collegata, spinbutton ARIA, tastiera (frecce) da Zag
<it-number label="Quantità"></it-number>

<it-pagination>

Navigazione tra pagine di un elenco

PropValoriDefault
totalstring"1"
currentstring"1"

Accessibilità (incapsulata nel componente)

  • <nav aria-label>
  • La pagina corrente usa aria-current=page
<it-pagination total="5" current="2"></it-pagination>

<it-pin> @zag-js/pin-input

Inserimento codice a più cifre (OTP)

PropValoriDefault
labelstring"Codice"
lengthstring"4"

Accessibilità (incapsulata nel componente)

  • Focus e auto-avanzamento gestiti da Zag
<it-pin label="Codice di verifica" length="4"></it-pin>

<it-popover> @zag-js/popover

Riquadro di approfondimento posizionato accanto a un elemento

Testo di approfondimento.
PropValoriDefault
triggerstring"Apri"
titlestring""

Accessibilità (incapsulata nel componente)

  • Posizionamento, gestione del focus, ESC e collegamenti ARIA forniti da Zag
  • Attivabile e chiudibile da tastiera
  • Il contenuto è annunciato agli screen reader quando compare
<it-popover trigger="Maggiori info" title="Dettagli">Testo di approfondimento.</it-popover>

<it-progress>

Barra di avanzamento

PropValoriDefault
valuestring"0"
labelstring"Avanzamento"

Accessibilità (incapsulata nel componente)

  • role=progressbar con aria-valuenow/min/max e aria-label
<it-progress value="60" label="Completamento del modulo"></it-progress>

<it-radio>

Opzione singola di un gruppo

Email
PropValoriDefault
namestring"gruppo"

Accessibilità (incapsulata nel componente)

  • Radio con lo stesso name formano un gruppo
  • Avvolgi il gruppo in un fieldset con legend
<it-radio name="canale">Email</it-radio>

<it-rating> @zag-js/rating-group

Valutazione a stelle

PropValoriDefault
labelstring"Valutazione"
countstring"5"

Accessibilità (incapsulata nel componente)

  • radiogroup accessibile con tastiera e ARIA (Zag)
  • Ogni stella ha un valore
<it-rating label="Quanto sei soddisfatto?" count="5"></it-rating>

<it-section>

Blocco di pagina con sfondo differenziato

Contenuto della sezione.
PropValoriDefault
titlestring""

Accessibilità (incapsulata nel componente)

  • Usa il tag semantico <section> con un'intestazione
<it-section title="In evidenza">Contenuto della sezione.</it-section>

<it-select> @zag-js/select

Menu di selezione custom accessibile

Roma
Milano
PropValoriDefault
labelstring"Seleziona"

Accessibilità (incapsulata nel componente)

  • role=listbox/option, tastiera, typeahead e ARIA da Zag
<it-select label="Comune">
  <div data-value="rm">Roma</div>
  <div data-value="mi">Milano</div>
</it-select>

<it-sidebar>

Menu laterale di sezione

PropValoriDefault
titlestring"In questa sezione"

Accessibilità (incapsulata nel componente)

  • <nav aria-label>
  • La voce corrente usa aria-current
<it-sidebar title="In questa sezione">
  <a href="#">Panoramica</a>
  <a href="#">Come fare</a>
  <a href="#">Contatti</a>
</it-sidebar>

<it-slider> @zag-js/slider

Cursore per selezionare un valore

PropValoriDefault
labelstring"Valore"

Accessibilità (incapsulata nel componente)

  • role=slider con aria-valuenow, tastiera (frecce) da Zag
<it-slider label="Volume"></it-slider>

<it-spinner>

Indicatore di caricamento

PropValoriDefault
labelstring"Caricamento in corso"

Accessibilità (incapsulata nel componente)

  • role=status con testo visually-hidden che comunica l'attesa
<it-spinner label="Caricamento dei dati"></it-spinner>

<it-steps> @zag-js/steps

Procedura a passi (wizard)

Passo 1
Passo 2
Passo 3

Nessuna prop.

Accessibilità (incapsulata nel componente)

  • Stato del passo e collegamenti ARIA gestiti da Zag
  • Navigazione Avanti/Indietro
<it-steps>
  <div data-step="Dati">Passo 1</div>
  <div data-step="Documenti">Passo 2</div>
  <div data-step="Conferma">Passo 3</div>
</it-steps>

<it-switch> @zag-js/switch

Interruttore on/off

Ricevi notifiche via email

Nessuna prop.

Accessibilità (incapsulata nel componente)

  • Stato comunicato da input nativo + ARIA (Zag)
  • Etichetta collegata al controllo
<it-switch>Ricevi notifiche via email</it-switch>

<it-table>

Contenitore responsive per una tabella dati

Pagamenti effettuati
DataImporto
01/03/202645,00 €

Nessuna prop.

Accessibilità (incapsulata nel componente)

  • Usa <caption>, <th scope>, thead/tbody nativi
  • Scroll orizzontale su mobile
<it-table>
  <table>
    <caption>Pagamenti effettuati</caption>
    <thead><tr><th scope="col">Data</th><th scope="col">Importo</th></tr></thead>
    <tbody><tr><td>01/03/2026</td><td>45,00 €</td></tr></tbody>
  </table>
</it-table>

<it-tabs> @zag-js/tabs

Navigazione a schede tra pannelli di contenuto

Cosa offre il servizio.
I passaggi per la domanda.

Nessuna prop.

Accessibilità (incapsulata nel componente)

  • role=tablist / tab / tabpanel e aria-selected forniti da Zag
  • Navigazione tra le schede con le frecce (roving tabindex)
  • Ogni pannello è collegato alla sua scheda con aria-labelledby
<it-tabs>
  <div data-tab="Descrizione">Cosa offre il servizio.</div>
  <div data-tab="Come fare">I passaggi per la domanda.</div>
</it-tabs>

<it-tags> @zag-js/tags-input

Inserimento di più voci come tag

PropValoriDefault
labelstring"Voci"

Accessibilità (incapsulata nel componente)

  • Gestione tastiera e rimozione tag con ARIA da Zag
<it-tags label="Interessi"></it-tags>

<it-textarea>

Campo di testo su più righe

PropValoriDefault
labelstring"Etichetta"

Accessibilità (incapsulata nel componente)

  • La label avvolge il campo (associazione implicita)
<it-textarea label="Note aggiuntive"></it-textarea>

<it-timeline>

Cronologia di eventi (linea del tempo)

Fase conclusa.
In corso.

Nessuna prop.

Accessibilità (incapsulata nel componente)

  • Comprensibile senza la resa grafica; date in formato testuale
<it-timeline>
  <div data-date="12 marzo 2026" data-title="Presentazione domanda">Fase conclusa.</div>
  <div data-date="20 marzo 2026" data-title="Istruttoria">In corso.</div>
</it-timeline>

<it-toast> @zag-js/toast

Notifica temporanea (toast) con coda

Domanda inviata correttamente.
PropValoriDefault
triggerstring"Mostra notifica"
typesuccess error info warning"success"
titlestring"Notifica"

Accessibilità (incapsulata nel componente)

  • Regione live: role=status/alert, aria-atomic
  • Coda e timer gestiti dallo store Zag
  • Pulsante di chiusura con testo accessibile
<it-toast trigger="Invia" type="success" title="Fatto">Domanda inviata correttamente.</it-toast>

<it-tooltip> @zag-js/tooltip

Suggerimento contestuale al passaggio del mouse o al focus

Passa qui sopra
PropValoriDefault
contentstring""

Accessibilità (incapsulata nel componente)

  • Mostrato su hover E su focus da tastiera (non solo mouse)
  • role=tooltip e collegamenti ARIA forniti da Zag
  • Non inserire informazioni essenziali disponibili solo qui
<it-tooltip content="Informazione aggiuntiva">Passa qui sopra</it-tooltip>

<it-upload> @zag-js/file-upload

Caricamento file con dropzone

PropValoriDefault
labelstring"Allegati"

Accessibilità (incapsulata nel componente)

  • Dropzone e input file accessibili da Zag
<it-upload label="Allegati"></it-upload>
Colore: