<div class="rtds-input-field rtds-select-field rtds-gap-1 rtds-autocomplete rtds-autocomplete--select ">
    <label for="autocompleteInputId" class="rtds-input-field__label">
        Text label

    </label>

    <div class="rtds-input-autocomplete" id="autocompleteInputIdContainer"></div>

    <span class="rtds-input-field__hint">

        <span class="rtds-input-field__error" id="autocompleteInputIdError" aria-live="assertive">
            il campo *nome campo* non può essere vuoto
        </span>

        <span class="rtds-input-field__description" id="idselectDescription">
            descrizione
        </span>

    </span>

</div>
<div class="rtds-input-field rtds-select-field{% if gap %} {{ gap }}{% else %} rtds-gap-1{% endif %}{% if classes %} {{ classes }}{% endif %} {% if hasError %} has-error{% endif %}">
    <label for="{{ selectId }}" class="rtds-input-field__label{% if hiddenLabel %} rtds-sr-only{% endif %}{% if labelClasses %} {{ labelClasses }}{% endif %}">
        {{ label }}
         {% if selectRequired %}
            <abbr class="rtds-font-bold rtds-no-underline" title="obbligatorio">*</abbr>
        {% endif %}
    </label>
    {% block input %}
        <div class="rtds-input-autocomplete" id="{{ selectId }}Container"></div>
    {% endblock input %}
    {% if selectRequired or selectAriaDescribedBy or selectHasErrorControl %}
    <span class="rtds-input-field__hint">
        {% if selectRequired or selectHasErrorControl %}
        <span class="rtds-input-field__error" id="{{ selectId }}Error" aria-live="assertive">
            {{ errorDescription }}
        </span>
        {% endif %}
        {% if selectDescription %}
        <span class="rtds-input-field__description" id="{{ selectAriaDescribedBy }}">
            {{ selectDescription }}
        </span>
        {% endif %}
    </span>
    {% endif %}
</div>
{
  "label": "Text label",
  "selectId": "autocompleteInputId",
  "classes": "rtds-autocomplete rtds-autocomplete--select",
  "selectAriaDescribedError": "idselectErrorDescription",
  "errorDescription": "il campo *nome campo* non può essere vuoto",
  "selectHasErrorControl": true,
  "selectAriaDescribedBy": "idselectDescription",
  "selectDescription": "descrizione",
  "selectAriaInvalid": true,
  "selectIconAlert": true,
  "selectHasError": true
}
  • Content:
    /**
     * SELECT COMPONENT WITH ACCESSIBLE AUTOCOMPLETE
     *
     *
    */
    .rtds-input-field .autocomplete__input {
        width: 100%;
        background-repeat: no-repeat;
        padding-top: var(--spacing-2);
        padding-bottom: var(--spacing-2);
        padding-left: var(--spacing-3);
        padding-right: var(--spacing-9);
            border-color: var(--color-border-input);
        border-radius: 0.5rem;
        border-width: 1px;
        background-image: url('data:image/svg+xml,%3Csvg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true" data-slot="icon"%3E%3Cpath fill-rule="evenodd" d="M12.53 16.28a.75.75 0 0 1-1.06 0l-7.5-7.5a.75.75 0 0 1 1.06-1.06L12 14.69l6.97-6.97a.75.75 0 1 1 1.06 1.06l-7.5 7.5Z" clip-rule="evenodd"/%3E%3C/svg%3E');
        background-position: right var(--spacing-2) top var(--spacing-2);
        background-size: var(--spacing-5) var(--spacing-5);
    }
    .rtds-select--sm .autocomplete__input {
        height: var(--spacing-8);
        padding-top: var(--spacing-0-5);
        padding-bottom: var(--spacing-0-5);
        padding-left: var(--spacing-2);
        padding-right: var(--spacing-7);
            background-size: var(--spacing-4) var(--spacing-4);
    }
    .rtds-select--lg .autocomplete__input {
        height: var(--spacing-12);
        padding-left: var(--spacing-3);
        padding-right: var(--spacing-9);
        padding-top: var(--spacing-3);
        padding-bottom: var(--spacing-3);
            background-position: right var(--spacing-2-5) top var(--spacing-2-5);
            background-size: var(--spacing-6) var(--spacing-6);
    }
    .rtds-autocomplete .has-error .rtds-icon {
        top: var(--spacing-2);
    }
    .rtds-autocomplete .rtds-select--sm.has-error .rtds-icon {
        top: var(--spacing-1-5);
    }
    .rtds-autocomplete .rtds-select--lg.has-error .rtds-icon {
        top: var(--spacing-2-5);
    }
    .has-error .autocomplete__input {
        border-width: 2px;
        border-color: var(--color-error-dark);
    }
    .rtds-select :where(div:not([class])) {
        width: 100%;
    }
    .rtds-input-field .autocomplete__dropdown-arrow-down-wrapper {
        position: absolute;
        right: var(--spacing-2);
        top: var(--spacing-2);
            color: var(--color-content-placeholder);
        width: var(--spacing-5);
        height: var(--spacing-5);
    }
    .rtds-input-field .autocomplete__menu {
            border-color: var(--color-border-input);
        border-radius: 0.5rem;
        border-width: 1px;
    }
    .rtds-input-field .autocomplete__hint, .rtds-input-field .autocomplete__input, .rtds-input-field .autocomplete__option {
        font-size: var(--fontsize-text-sm);
        font-weight: 500;
            color: var(--color-content-03);
    }
    .rtds-input-field .autocomplete__option {
        border-bottom-width: 1px;
        border-top-width: 0px;
        padding-left: var(--spacing-3);
        padding-right: var(--spacing-3);
        padding-top: var(--spacing-2);
        padding-bottom: var(--spacing-2);
            border-color: var(--color-border-input);
    }
    .rtds-input-field .autocomplete__option:last-child {
        border-bottom-width: 0px;
    }
    .rtds-input-field .autocomplete__option:hover {
            color: var(--color-content-inverse);
            background-color: var(--color-background-secondary);
        }
    .rtds-input-field .autocomplete__option:focus {
            color: var(--color-content-inverse);
            background-color: var(--color-background-secondary);
        }
    .rtds-input-field .autocomplete__option--focused {
            color: var(--color-content-inverse);
            background-color: var(--color-background-secondary);
        }
    .rtds-input-field .autocomplete__option--odd {
        --tw-bg-opacity: 1;
        background-color: rgb(255 255 255 / var(--tw-bg-opacity, 1));
    }
    
  • URL: /components/raw/autocomplete-select-field/autocomplete-select-field.built.css
  • Filesystem Path: components/03-molecules/forms/autocomplete-select-field/autocomplete-select-field.built.css
  • Size: 3.6 KB
  • Content:
    /**
     * SELECT COMPONENT WITH ACCESSIBLE AUTOCOMPLETE
     *
     *
    */
    @layer components {
       .rtds-input-field .autocomplete__input {
        @apply rtds-w-full rtds-py-2 rtds-pl-3 rtds-pr-9 rtds-border rtds-border-input rtds-rounded-lg rtds-bg-no-repeat;
        background-image: url('data:image/svg+xml,%3Csvg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true" data-slot="icon"%3E%3Cpath fill-rule="evenodd" d="M12.53 16.28a.75.75 0 0 1-1.06 0l-7.5-7.5a.75.75 0 0 1 1.06-1.06L12 14.69l6.97-6.97a.75.75 0 1 1 1.06 1.06l-7.5 7.5Z" clip-rule="evenodd"/%3E%3C/svg%3E');
        background-position: right theme('spacing.2') top theme('spacing.2');
        background-size: theme('spacing.5') theme('spacing.5');
       }
    
       .rtds-select--sm .autocomplete__input {
            @apply rtds-h-8 rtds-py-0.5 rtds-pl-2 rtds-pr-7;
            background-size: theme('spacing.4') theme('spacing.4');
        }
    
        .rtds-select--lg .autocomplete__input {
            @apply rtds-h-12 rtds-py-3 rtds-pl-3 rtds-pr-9;
            background-position: right theme('spacing.[2.5]') top theme('spacing.[2.5]');
            background-size: theme('spacing.6') theme('spacing.6');
        }
    
         .rtds-autocomplete .has-error .rtds-icon {
            @apply rtds-top-2;
        }
    
        .rtds-autocomplete .rtds-select--sm.has-error .rtds-icon {
            @apply rtds-top-1.5;
        }
    
        .rtds-autocomplete .rtds-select--lg.has-error .rtds-icon {
            @apply rtds-top-2.5;
        }
    
    
       .has-error .autocomplete__input {
        @apply rtds-border-2 rtds-border-error-dark;
       }
    
    
    
       .rtds-select :where(div:not([class])) {
        @apply rtds-w-full;
       }
    
       .rtds-input-field .autocomplete__dropdown-arrow-down-wrapper {
        @apply rtds-absolute rtds-right-2 rtds-top-2 rtds-content-placeholder rtds-w-5 rtds-h-5;
       }
    
        .rtds-input-field .autocomplete__menu {
            @apply rtds-border rtds-border-input rtds-rounded-lg;
        }
    
        .rtds-input-field .autocomplete__hint, .rtds-input-field .autocomplete__input, .rtds-input-field .autocomplete__option {
            @apply rtds-text-sm rtds-font-medium rtds-content-03;
        }
    
        .rtds-input-field .autocomplete__option {
            @apply rtds-px-3 rtds-py-2 rtds-border-b rtds-border-t-0 rtds-border-input last:rtds-border-b-0 hover:rtds-background-secondary hover:rtds-content-inverse focus:rtds-background-secondary focus:rtds-content-inverse;
        }
    
        .rtds-input-field .autocomplete__option--focused {
            @apply rtds-background-secondary rtds-content-inverse;
        }
    
        .rtds-input-field .autocomplete__option--odd {
            @apply rtds-bg-white;
        }
    }
  • URL: /components/raw/autocomplete-select-field/autocomplete-select-field.css
  • Filesystem Path: components/03-molecules/forms/autocomplete-select-field/autocomplete-select-field.css
  • Size: 2.6 KB
  • Content:
    import accessibleAutocomplete from 'accessible-autocomplete'
    
    window.addEventListener('load', function() {
      const inputElement = document.querySelector('#autocompleteInputIdContainer');
      const options = [
        'Option 1',
        'Option 2',
        'Option 3',
        'Option 4',
        'Option 5',
        'Option 6',
        'Option 7',
        'Option 8',
        'Option 9',
        'Option 10'
      ]
    
      if (inputElement && !inputElement.dataset.sbInit) {
        inputElement.dataset.sbInit = '1';
        accessibleAutocomplete({
            element: inputElement,
            id: 'autocompleteInputId', // To match it to the existing <label>.
            source: options,
            showAllValues: true,
            dropdownArrow: () => {}
        })
      }
    
      // Progressive enhancement with select element
      const selectElement = document.querySelector('#autocompleteSelectId');
      if (selectElement && !selectElement.dataset.sbInit) {
        selectElement.dataset.sbInit = '1';
        accessibleAutocomplete.enhanceSelectElement({
            selectElement: selectElement,
            showAllValues: true
        });
      }
    });
    
  • URL: /components/raw/autocomplete-select-field/autocomplete-select-field.js
  • Filesystem Path: components/03-molecules/forms/autocomplete-select-field/autocomplete-select-field.js
  • Size: 1 KB

Autocomplete Select Field

Componente basato su Accessible Autocomplete. Per informazioni, esempi e documentazione completa del componente, consultare il link sopra e gli esempi del componente.


Comportamento

Il componente implementa un campo di selezione con funzionalità di autocompletamento accessibile, utilizzando la libreria Accessible Autocomplete. Supporta due modalità di utilizzo:

  1. Input con autocompletamento
  2. Select con autocompletamento (progressive enhancement)

Varianti

Varianti di Stato

  • is-required: Campo obbligatorio
  • has-error-markup: Markup per la gestione degli errori
  • has-description: Campo con descrizione
  • has-error: Campo con errore e descrizione

Varianti di Dimensione

  • sm: Versione compatta
  • lg: Versione grande

Varianti di Stile

  • progressive-enhancement: Versione con select nativo

Parametri di configurazione

Contesto di sviluppo Fractal/Nunjucks — Questa sezione riguarda esclusivamente i parametri del context .config.yml usati durante lo sviluppo nella libreria. Non descrive attributi HTML o proprietà da usare nei temi, CMS o ambienti di implementazione: per quello, fare riferimento alla sezione Esempi di utilizzo.

Parametri Base

  • label (stringa, obbligatorio): Testo della label del campo
  • labelClasses (stringa, opzionale): Classi CSS aggiuntive per la label
  • selectId (stringa, obbligatorio): ID del componente select — per l’autocompletamento con input, l’ID dell’input sarà Container
  • hiddenLabel (booleano, opzionale): Nasconde visivamente la label (rimane disponibile per screen reader)

Parametri di Accessibilità e Descrizione

  • selectAriaDescribedBy (stringa, opzionale): ID dell’elemento che descrive il campo (necessario se c’è una descrizione)
  • selectHasErrorControl (booleano, opzionale): Attiva la validazione del campo
  • selectDescription (stringa, opzionale): Testo descrittivo del campo (richiede selectAriaDescribedBy)
  • selectAriaInvalid (booleano, opzionale): Indica che il campo contiene un errore
  • selectIconPlaceholder (stringa, opzionale): ID dell’icona da mostrare come placeholder
  • selectAlertIcon (stringa, opzionale): ID dell’icona di alert
  • selectHasError (booleano, opzionale): Applica lo stile di errore al select
  • errorDescription (stringa, opzionale): Descrizione dell’errore (richiede selectAriaDescribedError)

Parametri Aggiuntivi

  • selectShortLabel (stringa, opzionale): Label breve per l’attributo data-label (necessario per la gestione degli errori in JS)
  • gap (stringa, opzionale): Personalizzazione dello spacing interno (default: gap-1)
  • selectRequired (booleano, opzionale): Indica che il campo è obbligatorio (usa aria-required="true" invece dell’attributo required)

Parametri per Progressive Enhancement (Select con Autocompletamento)

  • selectPadding (stringa, opzionale): Personalizzazione del padding del select
  • selectBorder (stringa, opzionale): Personalizzazione del bordo del select
  • selectRadius (stringa, opzionale): Personalizzazione del border-radius del select
  • selectClasses (stringa, opzionale): Classi CSS aggiuntive per il select
  • selectPlaceholder (stringa, opzionale): Placeholder per lo stato predefinito del select

Accessibilità

WCAG 2.1

Livello AA — criteri pertinenti:

  • 1.3.1 Informazioni e correlazioni — la label è sempre associata al campo tramite for / id; i messaggi di errore sono collegati tramite aria-describedby
  • 3.3.1 Identificazione degli errori — gli errori sono comunicati tramite aria-invalid e annunciati con aria-live="assertive"
  • 3.3.2 Etichette o istruzioni — ogni campo ha una <label> visibile o nascosta disponibile per screen reader
  • 4.1.2 Nome, ruolo, valore — aria-required, aria-describedby e aria-invalid comunicano lo stato del campo

Struttura e semantica

  • Il componente è renderizzato come <div class="rtds-input-field rtds-select-field"> contenente una <label> e un contenitore per l’autocomplete inizializzato via JavaScript
  • La <label> è associata al campo tramite for="" (o for="Container" nella modalità input)
  • L’indicatore di campo obbligatorio è un <abbr title="obbligatorio">*</abbr>, leggibile anche senza colore
  • I messaggi di errore sono racchiusi in <span aria-live="assertive"> per garantire l’annuncio immediato agli screen reader

Attributi ARIA

Attributo Valori Condizione
aria-required "true" quando selectRequired è true
aria-describedby ID del messaggio di errore e/o descrizione quando presenti errori o descrizione
aria-invalid "true" quando selectAriaInvalid è true
aria-live "assertive" sullo span del messaggio di errore

Screen reader

  • La libreria Accessible Autocomplete gestisce autonomamente gli attributi ARIA del componente combobox (role, aria-expanded, aria-autocomplete, aria-activedescendant)
  • Quando la label è nascosta (hiddenLabel: true), rimane disponibile per screen reader tramite la classe rtds-sr-only
  • I messaggi di errore vengono annunciati immediatamente grazie ad aria-live="assertive"

Esempi di utilizzo

<!-- Esempio base -->
<div class="rtds-input-field rtds-select-field">
  <label for="mySelectContainer">Seleziona un'opzione</label>
  <div id="mySelectContainer">
    <!-- Inizializzato da Accessible Autocomplete JS -->
  </div>
</div>

<!-- Esempio con errore -->
<div class="rtds-input-field rtds-select-field rtds-input-field--has-error">
  <label for="mySelectContainer">
    Seleziona un'opzione <abbr title="obbligatorio">*</abbr>
  </label>
  <div id="mySelectContainer" aria-required="true" aria-invalid="true" aria-describedby="mySelect-error">
    <!-- Inizializzato da Accessible Autocomplete JS -->
  </div>
  <span class="rtds-input-field__hint">
    <span id="mySelect-error" aria-live="assertive" class="rtds-input-field__error">
      Questo campo è obbligatorio
    </span>
  </span>
</div>

Note

  • Il componente utilizza la libreria Accessible Autocomplete per l’autocompletamento
  • La configurazione JavaScript supporta showAllValues: true per mostrare tutti i valori disponibili
  • Per la variante progressive enhancement, la libreria migliora un elemento <select> nativo esistente