<div class="rtds-space-y-6 md:rtds-space-y-8">
    <div class="rtds-space-y-4">

        <div class="rtds-grid rtds-gap-6 lg:rtds-flex lg:rtds-justify-between">
            <div class="rtds-loading-status" aria-live="polite" aria-busy="false" role="status">

                <h2 class="rtds-heading-3">Nessun risultato trovato</h2>

            </div>

            <div>

                <div class="rtds-grid md:rtds-flex md:rtds-items-center rtds-gap-2 md:rtds-gap-6 md:rtds-justify-end">
                    <div class="rtds-flex-1 md:rtds-flex-none">
                        <div class="rtds-input-field rtds-select-field rtds-field-inline rtds-select-field--sm">
                            <label for="select-field-1" class="rtds-input-field__label">
                                Rivolto a

                            </label>

                            <div class="rtds-select rtds-select--light">

                                <select id="select-field-1" class="">
                                    <option value="1">Text</option>
                                    <option value="2">Option 1</option>
                                    <option value="3">Option 2</option>
                                    <option value="4">Option 3</option>
                                    <option value="5">Option 4</option>
                                    <option value="6">Option 5</option>

                                </select>
                            </div>

                        </div>
                    </div>
                    <div class="rtds-flex-1 md:rtds-flex-none">
                        <div class="rtds-input-field rtds-select-field rtds-field-inline rtds-select-field--sm">
                            <label for="select-field-2" class="rtds-input-field__label">
                                Ordina per

                            </label>

                            <div class="rtds-select rtds-select--light">

                                <select id="select-field-2" class="">
                                    <option value="1">Text</option>
                                    <option value="2">Option 1</option>
                                    <option value="3">Option 2</option>
                                    <option value="4">Option 3</option>
                                    <option value="5">Option 4</option>
                                    <option value="6">Option 5</option>

                                </select>
                            </div>

                        </div>
                    </div>
                </div>

            </div>

        </div>

        <!-- CONTAINER PER EMPTY STATE - HA CONTENUTO SOLO SE NON CI SONO RISULTATI - DEVE ESSERE SEMPRE PRESENTE - CON I RISULTATI HA CLASSE -> rtds-sr-only -->
        <div class="rtds-empty-state rtds-grid rtds-gap-4" aria-live="assertive" aria-atomic="true">
            <!-- CONTENUTO EMPTY STATE - PRESENTE SOLO SE NON CI SONO RISULTATI -->
            <div class="rtds-font-bold rtds-text-center rtds-grid rtds-gap-8 rtds-justify-center rtds-justify-items-center rtds-py-20">
                <svg class="rtds-icon rtds-fill-current rtds-w-16 rtds-h-16 rtds-content-03" aria-hidden="true" focusable="false" role="img">
                    <use href="../../icons.svg#outline--exclamation-circle" />
                </svg>

                <h3 class="rtds-heading-4">Non ci sono risultati per questi criteri di ricerca</h3>
            </div>
        </div>

    </div>

</div>
{% extends '@search-results' %}

{% block title %}
    <h2 class="rtds-heading-3">Nessun risultato trovato</h2>
{% endblock title %}

{% block emptyState %}
    <!-- CONTENUTO EMPTY STATE - PRESENTE SOLO SE NON CI SONO RISULTATI -->
    <div class="rtds-font-bold rtds-text-center rtds-grid rtds-gap-8 rtds-justify-center rtds-justify-items-center rtds-py-20">
        {% render '@icon',{id: 'outline--exclamation-circle', size: 'rtds-w-16 rtds-h-16', classes: 'rtds-content-03'},true %}
        <h3 class="rtds-heading-4">Non ci sono risultati per questi criteri di ricerca</h3>
    </div>
{% endblock emptyState %}

{% block results %}
{% endblock results %}

{% block pagination %}
{% endblock pagination %}
{
  "ariaBusy": false,
  "srOnlyTitle": true,
  "emptyState": true,
  "sorting": true,
  "resultsCount": 6,
  "title": "<strong>230</strong> Servizi",
  "resultsGridClasses": "md:rtds-grid-cols-2 lg:rtds-grid-cols-3",
  "resultsCard": {
    "variant": "--information-with-gradient"
  }
}
  • Content:
    @layer components {
        .rtds-loading-status[aria-busy="true"] {
            @apply rtds-w-full;
        }
    }
  • URL: /components/raw/search-results/search-results.css
  • Filesystem Path: components/04-organisms/sections/search-results/search-results.css
  • Size: 100 Bytes

Componente Search Results

Descrizione

Il componente Search Results è stato sviluppato per visualizzare i risultati di una ricerca con filtri e ordinamento. Supporta diversi stati (caricamento, vuoto, con risultati) e include funzionalità di accessibilità integrate.

Funzionalità Principali

Stati del Componente

  • Stato di Caricamento: Gestito tramite l’attributo aria-busy e la classe rtds-loading-status
  • Stato Vuoto: Gestito tramite il blocco emptyState e la classe rtds-empty-state
  • Stato con Risultati: Visualizzazione standard dei risultati in griglia

Accessibilità

  • Utilizzo di aria-live="polite" per gli aggiornamenti dei risultati
  • Utilizzo di aria-live="assertive" per lo stato vuoto
  • Supporto per titoli nascosti (srOnlyTitle) per screen reader
  • Gestione appropriata degli stati di caricamento con aria-busy

Note Importanti per il Markup

Struttura Base

Il componente deve essere utilizzato all’interno di un contesto di ricerca appropriato, tipicamente dopo un form di ricerca o una search box.

Blocchi Disponibili (per sviluppo in NJK)

  • title: Personalizzazione del titolo della sezione
  • emptyState: Contenuto da mostrare quando non ci sono risultati
  • results: Personalizzazione della griglia dei risultati
  • pagination: Personalizzazione della paginazione

Varianti Disponibili

Il componente supporta diverse varianti configurabili tramite il file di configurazione:

  • has-container: Aggiunge un container responsive
  • has-padding: Aggiunge padding verticale
  • has-mobile-filters: Abilita i filtri per mobile
  • loading: Mostra lo stato di caricamento
  • empty-state: Mostra lo stato vuoto

Configurazioni per lo Sviluppo in Nunjucks

Variabili e Impostazioni di Configurazione

Configurazioni Base

  • ariaBusy: boolean - gestisce lo stato di caricamento (default: false)
  • srOnlyTitle: boolean - nasconde il titolo visivamente (default: true)
  • emptyState: boolean - mostra lo stato vuoto (default: false)
  • resultsCount: number - numero di risultati da mostrare (default: 6)
  • resultsCard: string - tipo di card da utilizzare (default: ‘card–information-with-gradient’)
  • resultsGridClasses: string - classi per la griglia dei risultati

Configurazioni di Layout

  • hasContainer: boolean - aggiunge un container responsive
  • padding: boolean - aggiunge padding verticale
  • mobileFilters: boolean - abilita i filtri per mobile

Note per l’Accessibilità

  1. Il componente utilizza aria-live per annunciare i cambiamenti di stato
  2. Lo stato di caricamento è gestito tramite aria-busy
  3. Il titolo può essere nascosto visivamente ma rimane accessibile agli screen reader
  4. Lo stato vuoto è annunciato in modo assertivo per garantire che l’utente sia informato
  5. I filtri mobili sono gestiti tramite un dialog modale accessibile

Dettagli Implementativi per l’Accessibilità

Gestione degli Stati e Attributi ARIA

Stato di Caricamento

<div class="rtds-loading-status" aria-live="polite" aria-busy="true" role="status">
    <!-- contenuto del titolo -->
</div>
<div class="rtds-hidden">
    <!-- contenuto dei filtri e risultati -->
</div>
  • aria-live="polite": annuncia i cambiamenti in modo non interruttivo
  • aria-busy="true": indica che il contenuto è in fase di aggiornamento
  • role="status": identifica l’elemento come un elemento di stato
  • La classe rtds-hidden nasconde i filtri durante il caricamento

Stato Vuoto

<div class="rtds-empty-state rtds-grid rtds-gap-4" aria-live="assertive" aria-atomic="true">
    <!-- contenuto empty state -->
</div>
  • aria-live="assertive": annuncia i cambiamenti in modo prioritario
  • aria-atomic="true": annuncia l’intero contenuto dell’elemento
  • La classe rtds-empty-state è sempre presente, ma viene nascosta con rtds-sr-only quando ci sono risultati o in fase di loading
  • Durante lo stato vuoto, l’h2 all’interno di rtds-loading-status mostrerà il testo “Nessun risultato trovato”
  • Il div rtds-empty-state non avrà la classe rtds-sr-only e conterrà il markup dell’empty state

Stato con Risultati

<div class="rtds-loading-status" aria-live="polite" aria-busy="false" role="status">
    <h2 class="rtds-heading-3 rtds-font-normal">
        <strong>230</strong> risultati
    </h2>
</div>
  • aria-busy="false": indica che il contenuto è stabile
  • srOnlyTitle: gestisce la visibilità del titolo per screen reader
  • La classe rtds-sr-only nasconde visivamente il titolo ma lo mantiene accessibile

Gestione dei Filtri Mobili

  • Il dialog modale gestisce automaticamente:
    • role="dialog"
    • aria-modal="true"
    • aria-labelledby per il titolo del dialog
    • Focus trap all’interno del dialog
    • Gestione della chiusura con ESC

Comportamento Dinamico

  1. Transizione Caricamento → Risultati:

    • aria-busy passa da true a false
    • Il contenuto dei filtri diventa visibile (rimuove rtds-hidden)
    • Il contenuto dello stato vuoto viene nascosto (aggiunge rtds-sr-only)
  2. Transizione Risultati → Vuoto:

    • Il contenuto dello stato vuoto diventa visibile (rimuove rtds-sr-only)
    • aria-live="assertive" annuncia il cambiamento
    • La griglia dei risultati viene nascosta
  3. Transizione Vuoto → Risultati:

    • Il contenuto dello stato vuoto viene nascosto (aggiunge rtds-sr-only)
    • La griglia dei risultati diventa visibile
    • aria-live="polite" annuncia il cambiamento

Best Practices Implementate

  1. Annunci Contestuali:

    • Usa aria-live="polite" per aggiornamenti non critici
    • Usa aria-live="assertive" per cambiamenti di stato importanti
  2. Gestione del Focus:

    • I filtri mobili mantengono il focus all’interno del dialog
    • Il focus ritorna al pulsante di apertura alla chiusura
  3. Feedback Visivi e Semantici:

    • Stati di caricamento chiaramente identificabili
    • Transizioni di stato annunciate appropriatamente
    • Struttura gerarchica mantenuta in tutti gli stati