<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
}
/**
* 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));
}
/**
* 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;
}
}
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
});
}
});
Componente basato su Accessible Autocomplete. Per informazioni, esempi e documentazione completa del componente, consultare il link sopra e gli esempi del componente.
Il componente implementa un campo di selezione con funzionalità di autocompletamento accessibile, utilizzando la libreria Accessible Autocomplete. Supporta due modalità di utilizzo:
is-required: Campo obbligatoriohas-error-markup: Markup per la gestione degli errorihas-description: Campo con descrizionehas-error: Campo con errore e descrizionesm: Versione compattalg: Versione grandeprogressive-enhancement: Versione con select nativoContesto di sviluppo Fractal/Nunjucks — Questa sezione riguarda esclusivamente i parametri del context
.config.ymlusati 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.
label (stringa, obbligatorio): Testo della label del campolabelClasses (stringa, opzionale): Classi CSS aggiuntive per la labelselectId (stringa, obbligatorio): ID del componente select — per l’autocompletamento con input, l’ID dell’input sarà ContainerhiddenLabel (booleano, opzionale): Nasconde visivamente la label (rimane disponibile per screen reader)selectAriaDescribedBy (stringa, opzionale): ID dell’elemento che descrive il campo (necessario se c’è una descrizione)selectHasErrorControl (booleano, opzionale): Attiva la validazione del camposelectDescription (stringa, opzionale): Testo descrittivo del campo (richiede selectAriaDescribedBy)selectAriaInvalid (booleano, opzionale): Indica che il campo contiene un erroreselectIconPlaceholder (stringa, opzionale): ID dell’icona da mostrare come placeholderselectAlertIcon (stringa, opzionale): ID dell’icona di alertselectHasError (booleano, opzionale): Applica lo stile di errore al selecterrorDescription (stringa, opzionale): Descrizione dell’errore (richiede selectAriaDescribedError)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)selectPadding (stringa, opzionale): Personalizzazione del padding del selectselectBorder (stringa, opzionale): Personalizzazione del bordo del selectselectRadius (stringa, opzionale): Personalizzazione del border-radius del selectselectClasses (stringa, opzionale): Classi CSS aggiuntive per il selectselectPlaceholder (stringa, opzionale): Placeholder per lo stato predefinito del selectLivello AA — criteri pertinenti:
for / id; i messaggi di errore sono collegati tramite aria-describedbyaria-invalid e annunciati con aria-live="assertive"<label> visibile o nascosta disponibile per screen readeraria-required, aria-describedby e aria-invalid comunicano lo stato del campo<div class="rtds-input-field rtds-select-field"> contenente una <label> e un contenitore per l’autocomplete inizializzato via JavaScript<label> è associata al campo tramite for="" (o for="Container" nella modalità input)<abbr title="obbligatorio">*</abbr>, leggibile anche senza colore<span aria-live="assertive"> per garantire l’annuncio immediato agli screen reader| 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 |
hiddenLabel: true), rimane disponibile per screen reader tramite la classe rtds-sr-onlyaria-live="assertive"<!-- 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>showAllValues: true per mostrare tutti i valori disponibili<select> nativo esistente