<div class="rtds-container">

    <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-sr-only">Risultati di ricerca</h2>
                    <span class="rtds-heading-3 rtds-font-normal">
                        <strong>230</strong> Servizi
                    </span>

                </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 rtds-sr-only" aria-live="assertive" aria-atomic="true"></div>

            <div class="rtds-grid rtds-gap-4 rtds-grid-cols-1 md:rtds-grid-cols-2 lg:rtds-grid-cols-3">

                <article class="rtds-card rtds-card--information rtds-bg-gradient-04
 is-card-fullclickable rtds-group/card">

                    <div class="rtds-card__content">

                        <div class="rtds-card__heading">

                            <h3 class="rtds-card__title">
                                <a class="group-hover/card:rtds-underline" href="">

                                    Nunc aliquam phasellus molestie blandit. Nisi, amet, id maecenas diam

                                </a>
                            </h3>

                        </div>

                        <div class="rtds-card__description ">
                            <p>
                                Neque blandit pellentesque nunc sed amet. Nisl, semper sed aliquam amet proin purus augue et.
                            </p>
                        </div>

                        <ul class="rtds-card__tags" aria-label="Categorie">

                            <li><span class="rtds-chip rtds-chip--category rtds-chip--sm">
                                    label</span></li>

                            <li><span class="rtds-chip rtds-chip--category rtds-chip--sm">
                                    label</span></li>

                            <li><span class="rtds-chip rtds-chip--category rtds-chip--sm">
                                    label</span></li>

                            <li><span class="rtds-chip rtds-chip--category rtds-chip--sm">
                                    label</span></li>

                        </ul>

                    </div>

                </article>

                <article class="rtds-card rtds-card--information rtds-bg-gradient-04
 is-card-fullclickable rtds-group/card">

                    <div class="rtds-card__content">

                        <div class="rtds-card__heading">

                            <h3 class="rtds-card__title">
                                <a class="group-hover/card:rtds-underline" href="">

                                    Nunc aliquam phasellus molestie blandit. Nisi, amet, id maecenas diam

                                </a>
                            </h3>

                        </div>

                        <div class="rtds-card__description ">
                            <p>
                                Neque blandit pellentesque nunc sed amet. Nisl, semper sed aliquam amet proin purus augue et.
                            </p>
                        </div>

                        <ul class="rtds-card__tags" aria-label="Categorie">

                            <li><span class="rtds-chip rtds-chip--category rtds-chip--sm">
                                    label</span></li>

                            <li><span class="rtds-chip rtds-chip--category rtds-chip--sm">
                                    label</span></li>

                            <li><span class="rtds-chip rtds-chip--category rtds-chip--sm">
                                    label</span></li>

                            <li><span class="rtds-chip rtds-chip--category rtds-chip--sm">
                                    label</span></li>

                        </ul>

                    </div>

                </article>

                <article class="rtds-card rtds-card--information rtds-bg-gradient-04
 is-card-fullclickable rtds-group/card">

                    <div class="rtds-card__content">

                        <div class="rtds-card__heading">

                            <h3 class="rtds-card__title">
                                <a class="group-hover/card:rtds-underline" href="">

                                    Nunc aliquam phasellus molestie blandit. Nisi, amet, id maecenas diam

                                </a>
                            </h3>

                        </div>

                        <div class="rtds-card__description ">
                            <p>
                                Neque blandit pellentesque nunc sed amet. Nisl, semper sed aliquam amet proin purus augue et.
                            </p>
                        </div>

                        <ul class="rtds-card__tags" aria-label="Categorie">

                            <li><span class="rtds-chip rtds-chip--category rtds-chip--sm">
                                    label</span></li>

                            <li><span class="rtds-chip rtds-chip--category rtds-chip--sm">
                                    label</span></li>

                            <li><span class="rtds-chip rtds-chip--category rtds-chip--sm">
                                    label</span></li>

                            <li><span class="rtds-chip rtds-chip--category rtds-chip--sm">
                                    label</span></li>

                        </ul>

                    </div>

                </article>

                <article class="rtds-card rtds-card--information rtds-bg-gradient-04
 is-card-fullclickable rtds-group/card">

                    <div class="rtds-card__content">

                        <div class="rtds-card__heading">

                            <h3 class="rtds-card__title">
                                <a class="group-hover/card:rtds-underline" href="">

                                    Nunc aliquam phasellus molestie blandit. Nisi, amet, id maecenas diam

                                </a>
                            </h3>

                        </div>

                        <div class="rtds-card__description ">
                            <p>
                                Neque blandit pellentesque nunc sed amet. Nisl, semper sed aliquam amet proin purus augue et.
                            </p>
                        </div>

                        <ul class="rtds-card__tags" aria-label="Categorie">

                            <li><span class="rtds-chip rtds-chip--category rtds-chip--sm">
                                    label</span></li>

                            <li><span class="rtds-chip rtds-chip--category rtds-chip--sm">
                                    label</span></li>

                            <li><span class="rtds-chip rtds-chip--category rtds-chip--sm">
                                    label</span></li>

                            <li><span class="rtds-chip rtds-chip--category rtds-chip--sm">
                                    label</span></li>

                        </ul>

                    </div>

                </article>

                <article class="rtds-card rtds-card--information rtds-bg-gradient-04
 is-card-fullclickable rtds-group/card">

                    <div class="rtds-card__content">

                        <div class="rtds-card__heading">

                            <h3 class="rtds-card__title">
                                <a class="group-hover/card:rtds-underline" href="">

                                    Nunc aliquam phasellus molestie blandit. Nisi, amet, id maecenas diam

                                </a>
                            </h3>

                        </div>

                        <div class="rtds-card__description ">
                            <p>
                                Neque blandit pellentesque nunc sed amet. Nisl, semper sed aliquam amet proin purus augue et.
                            </p>
                        </div>

                        <ul class="rtds-card__tags" aria-label="Categorie">

                            <li><span class="rtds-chip rtds-chip--category rtds-chip--sm">
                                    label</span></li>

                            <li><span class="rtds-chip rtds-chip--category rtds-chip--sm">
                                    label</span></li>

                            <li><span class="rtds-chip rtds-chip--category rtds-chip--sm">
                                    label</span></li>

                            <li><span class="rtds-chip rtds-chip--category rtds-chip--sm">
                                    label</span></li>

                        </ul>

                    </div>

                </article>

                <article class="rtds-card rtds-card--information rtds-bg-gradient-04
 is-card-fullclickable rtds-group/card">

                    <div class="rtds-card__content">

                        <div class="rtds-card__heading">

                            <h3 class="rtds-card__title">
                                <a class="group-hover/card:rtds-underline" href="">

                                    Nunc aliquam phasellus molestie blandit. Nisi, amet, id maecenas diam

                                </a>
                            </h3>

                        </div>

                        <div class="rtds-card__description ">
                            <p>
                                Neque blandit pellentesque nunc sed amet. Nisl, semper sed aliquam amet proin purus augue et.
                            </p>
                        </div>

                        <ul class="rtds-card__tags" aria-label="Categorie">

                            <li><span class="rtds-chip rtds-chip--category rtds-chip--sm">
                                    label</span></li>

                            <li><span class="rtds-chip rtds-chip--category rtds-chip--sm">
                                    label</span></li>

                            <li><span class="rtds-chip rtds-chip--category rtds-chip--sm">
                                    label</span></li>

                            <li><span class="rtds-chip rtds-chip--category rtds-chip--sm">
                                    label</span></li>

                        </ul>

                    </div>

                </article>

            </div>

        </div>

        <nav class="rtds-pagination rtds-justify-center" role="navigation" aria-label="Paginazione">
            <ul class="rtds-pagination__list rtds-justify-center">

                <li>
                    <a class="rtds-pagination__link rtds-pagination__link-button " href="#" aria-label="Pagina iniziale">
                        <svg class="rtds-icon rtds-fill-current rtds-w-4 rtds-h-5 md:rtds-w-5 md:rtds-h-5" aria-hidden="true" focusable="false" role="img">
                            <use href="../../icons.svg#mini--chevron-double-left" />
                        </svg>

                    </a>
                </li>
                <li>
                    <a class="rtds-pagination__link rtds-pagination__link-button" href="#" aria-label="Pagina precedente">
                        <svg class="rtds-icon rtds-fill-current rtds-w-4 rtds-h-5 md:rtds-w-5 md:rtds-h-5" aria-hidden="true" focusable="false" role="img">
                            <use href="../../icons.svg#mini--chevron-left" />
                        </svg>

                    </a>
                </li>

                <li>
                    <a class="rtds-pagination__link rtds-pagination__link-button rtds-pagination__link-text " href="#" aria-label="pagina 1">1</a>
                </li>

                <li>
                    <a class="rtds-pagination__link rtds-pagination__link-button rtds-pagination__link-text  rtds-background-primary rtds-border-primary rtds-text-white hover:rtds-content-01" href="#" aria-label="Pagina corrente, pagina 2" aria-current="true">2</a>
                </li>

                <li>
                    <a class="rtds-pagination__link rtds-pagination__link-button rtds-pagination__link-text " href="#" aria-label="pagina 3">3</a>
                </li>

                <li>
                    <a class="rtds-pagination__link rtds-pagination__link-button rtds-pagination__link-text " href="#" aria-label="pagina 4">4</a>
                </li>

                <li>
                    <a class="rtds-pagination__link rtds-pagination__link-button" href="#" aria-label="Pagina successiva">
                        <svg class="rtds-icon rtds-fill-current rtds-w-4 rtds-h-5 md:rtds-w-5 md:rtds-h-5" aria-hidden="true" focusable="false" role="img">
                            <use href="../../icons.svg#mini--chevron-right" />
                        </svg>

                    </a>
                </li>
                <li>
                    <a class="rtds-pagination__link rtds-pagination__link-button " href="#" aria-label="Pagina finale">
                        <svg class="rtds-icon rtds-fill-current rtds-w-4 rtds-h-5 md:rtds-w-5 md:rtds-h-5" aria-hidden="true" focusable="false" role="img">
                            <use href="../../icons.svg#mini--chevron-double-right" />
                        </svg>

                    </a>
                </li>

            </ul>
        </nav>

    </div>

</div>
{% if hasContainer %}
<div class="rtds-container">
{% endif %}
<div class="rtds-space-y-6 md:rtds-space-y-8{% if padding %} rtds-py-6{% endif %}">
    <div class="rtds-space-y-4">
        {% block filters %}
        {% if filtersSelected %}
        <div class="rtds-pb-6">
            {% render '@filters--v2-selected', true %}
        </div>
        {% endif %}
        {% endblock filters %}

        <div class="rtds-grid rtds-gap-6 lg:rtds-flex lg:rtds-justify-between">
            <div class="rtds-loading-status" aria-live="polite" aria-busy="{{ ariaBusy }}" role="status">
                {% block title %}
                {% if srOnlyTitle %}
                <h2 class="rtds-sr-only">Risultati di ricerca</h2>
                <span class="rtds-heading-3 rtds-font-normal">
                    {{ title|safe }}
                </span>
                {% else %}
                <h2 class="rtds-heading-3 rtds-font-normal">
                   {{ title|safe }}
                </h2>
                {% endif %}
                {% endblock title %}
            </div>
            {% block rightContent %}
            {% if sorting or mobileFilters or rightContent %}
            <div{% if ariaBusy == true %} class="rtds-hidden"{% endif %}>
                {% block rightContentInner %}
                {% if sorting %}
                <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">
                    {% render '@select-field--sm',{label: 'Rivolto a', selectId: 'select-field-1', inline: 'true', variant: '--light' }, true  %}
                    </div>
                    <div class="rtds-flex-1 md:rtds-flex-none">
                    {% render '@select-field--sm',{label: 'Ordina per', selectId: 'select-field-2', inline: 'true', variant: '--light' }, true  %}
                    </div>
                </div>
                {% endif %}
                {% if mobileFilters %}
                <div class="rtds-pt-6 lg:rtds-hidden">
                    {% render '@button--icon-left', {icon: 'mini--adjustments-horizontal',iconTransformType: 'scale', classes: 'rtds-btn--inverted', label: 'Filtra la ricerca', callback:'openDialog("mobileFilters", this)' }, true %}
                    {% render '@modal-dialog--filters', {dialogId: 'mobileFilters'}, true %}
                </div>
                {% endif %}
                {% endblock rightContentInner %}
            </div>
            {% endif %}
            {% endblock rightContent %}
        </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{% if emptyState == false %} rtds-sr-only{% endif %}" aria-live="assertive" aria-atomic="true">
            {%- block emptyState -%}
            {%- endblock emptyState -%}
        </div>

        {% block results %}
        <div class="rtds-grid rtds-gap-4 rtds-grid-cols-1{% if resultsGridClasses %} {{ resultsGridClasses }}{% endif %}">
            {% for i in range(0, resultsCount) %}
            {% render '@card' + resultsCard.variant, resultsCard.context, true %}
            {% endfor %}
        </div>
        {% endblock results %}
    </div>
    {% block pagination %}
    {% render '@pagination--centered' %} 
    {% endblock pagination %}
</div>
{% if hasContainer %}
</div>
{% endif %}
{
  "ariaBusy": false,
  "srOnlyTitle": true,
  "emptyState": false,
  "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"
  },
  "hasContainer": true
}
  • 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