<div class="rtds-input-field rtds-gap-1 ">
<label for="inputFileId" class="rtds-input-field__label">
Text label
<abbr class="rtds-font-bold rtds-no-underline" title="obbligatorio">*</abbr>
</label>
<div class="rtds-input">
<input id="inputFileId" class="rtds-text-sm rtds-input-placeholder" type="file" aria-required="true" aria-describedBy="inputFileIdError">
</div>
<span class="rtds-input-field__hint">
<span class="rtds-input-field__error" id="inputFileIdError" aria-live="assertive">
</span>
</span>
</div>
{% extends '@input-field' %}
{
"label": "Text label",
"inputId": "inputFileId",
"inputType": "file",
"inputRequired": true
}
/*
* @file
* Styles for the input file component.
*/
:where(.rtds-input) input[type="file"] {
width: 100%;
}
::file-selector-button {
font-size: var(--fontsize-text-lg);
letter-spacing: 0.025em;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-timing-function: cubic-bezier(0, 0, 0.2, 1);
display: inline-flex;
justify-content: center;
align-items: center;
gap: var(--spacing-1);
padding-left: var(--spacing-4);
padding-right: var(--spacing-4);
padding-top: var(--spacing-3);
padding-bottom: var(--spacing-3);
border-radius: 0.375rem;
line-height: 1;
font-weight: 700;
transition-property: all;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-duration: 200ms;
transition-timing-function: cubic-bezier(0, 0, 0.2, 1);
border-width: 1px;
background-color: var(--color-button-secondary);
border-color: var(--color-button-secondary);
--tw-text-opacity: 1;
color: rgb(255 255 255 / var(--tw-text-opacity, 1));
}
::file-selector-button:hover {
background-color: var(--color-button-secondary-hover);
border-color: var(--color-button-secondary-hover);
}
::file-selector-button:focus {
background-color: var(--color-button-secondary-hover);
border-color: var(--color-button-secondary-hover);
}
::file-selector-button:active {
background-color: var(--color-button-secondary-active);
border-color: var(--color-button-secondary-active);
}
[disabled]::file-selector-button {
background-color: var(--color-background-02);
color: var(--color-button-disabled);
border-color: var(--color-background-02);
cursor: not-allowed;
}
[aria-disabled="true"]::file-selector-button {
background-color: var(--color-background-02);
color: var(--color-button-disabled);
border-color: var(--color-background-02);
cursor: not-allowed;
}
.rtds-dialog__actions ::file-selector-button {
flex: 1 1 0%;
}
@media (min-width: 1024px) {
.rtds-dialog__actions ::file-selector-button {
flex: none;
}
}
::file-selector-button {
margin-right: var(--spacing-4);
cursor: pointer;
display: inline-flex;
gap: var(--spacing-1);
border-radius: 0.375rem;
border-width: 1px;
padding-top: var(--spacing-3);
padding-bottom: var(--spacing-3);
font-size: var(--fontsize-text-lg);
font-weight: 700;
line-height: 1;
letter-spacing: 0.025em;
transition-property: all;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-duration: 200ms;
transition-timing-function: cubic-bezier(0, 0, 0.2, 1);
justify-content: center;
align-items: center;
padding-left: var(--spacing-4);
padding-right: var(--spacing-4);
}
/*:where(.rtds-input) input[type="file"]::before {
}*/
:where(.rtds-input--sm) ::file-selector-button {
gap: var(--spacing-0-5);
font-size: var(--fontsize-text-sm);
}
:where(.rtds-input--sm) :where(.rtds-btn--icon)::file-selector-button,:where(.rtds-input--sm) :where(.rtds-btn--icon-square)::file-selector-button {
width: var(--spacing-6);
height: var(--spacing-6);
}
:where(.rtds-input--sm) :where(.rtds-btn--icon-right)::file-selector-button,:where(.rtds-input--sm) :where(.rtds-btn--icon-left)::file-selector-button {
gap: var(--spacing-1-5);
}
:where(.rtds-input--sm) :where(.rtds-btn--icon-right)::file-selector-button {
padding-right: var(--spacing-3);
}
:where(.rtds-input--sm) :where(.rtds-btn--icon-left)::file-selector-button {
padding-left: var(--spacing-3);
}
:where(.rtds-input--sm) :where(.rtds-btn--icon)::file-selector-button,:where(.rtds-input--sm) :where(.rtds-btn--icon-square)::file-selector-button {
padding-left: var(--spacing-0);
padding-right: var(--spacing-0);
}
:where(.rtds-input--lg) ::file-selector-button {
padding-left: var(--spacing-6);
padding-right: var(--spacing-6);
font-size: var(--fontsize-text-xl);
gap: var(--spacing-2);
padding-top: var(--spacing-3);
padding-bottom: var(--spacing-3);
}
:where(.rtds-input--lg) :where(.rtds-btn--icon)::file-selector-button,:where(.rtds-input--lg) :where(.rtds-btn--icon-square)::file-selector-button {
height: var(--spacing-12);
width: var(--spacing-12);
}
:where(.rtds-input--lg) :where(.rtds-btn--icon-right)::file-selector-button {
padding-right: var(--spacing-4);
}
:where(.rtds-input--lg) :where(.rtds-btn--icon-left)::file-selector-button {
padding-left: var(--spacing-4);
}
:where(.rtds-input--lg) :where(.rtds-btn--icon)::file-selector-button,:where(.rtds-input--lg) :where(.rtds-btn--icon-square)::file-selector-button {
padding-left: var(--spacing-0);
padding-right: var(--spacing-0);
}
/*
* @file
* Styles for the input file component.
*/
:where(.rtds-input) input[type="file"] {
@apply rtds-w-full;
}
::file-selector-button {
@apply rtds-btn rtds-btn--secondary rtds-transition-all rtds-cursor-pointer rtds-mr-4 rtds-border-0;
}
/*:where(.rtds-input) input[type="file"]::before {
}*/
:where(.rtds-input--sm) ::file-selector-button {
@apply rtds-btn--s;
}
:where(.rtds-input--lg) ::file-selector-button {
@apply rtds-btn--l;
}
Campo di upload file. Estende @input-field con inputType: file, ereditandone struttura, label, messaggi di errore e gestione degli stati. Disponibile nelle dimensioni default e sm.
Il componente viene renderizzato come <div class="rtds-input-field"> contenente una <label> e un <input type="file">. Eredita tutti i comportamenti di @input-field: label visibile o nascosta, messaggi di errore con aria-live, descrizioni aggiuntive.
Il selettore file nativo del browser viene attivato al click sulla label o sull’input.
default: campo base con labelis-required: campo obbligatorio (aggiunge aria-required="true" e indicatore *)has-description: con testo descrittivo aggiuntivo collegato tramite aria-describedbyhas-error: con messaggio di errore e stato aria-invalid="true"has-error-markup: variante per errori gestiti via markup esternohas-error-and-description: combinazione di errore e descrizionedefault: dimensione standardsm: dimensione ridotta (estende @input-field--sm)Contesto di sviluppo Fractal/Nunjucks — Questa sezione riguarda esclusivamente i parametri del context
.config.ymlusati durante lo sviluppo nella libreria. Non descrive attributi HTML da usare nei temi o ambienti di implementazione.
label (stringa, obbligatorio): testo della labelinputId (stringa, obbligatorio): ID univoco per collegare <label for> e <input id>inputType (stringa): sempre "file" per questo componenteinputRequired (booleano, opzionale): aggiunge aria-required="true"inputAriaDescribedBy (stringa, opzionale): ID dell’elemento con descrizione aggiuntivainputAriaDescribedError (stringa, opzionale): ID del messaggio di erroreinputAriaInvalid (booleano, opzionale): aggiunge aria-invalid="true" in stato di erroreinputHasErrorControl (booleano, opzionale): attiva la visualizzazione del messaggio di erroreinputHasError (booleano, opzionale): applica lo stile di errore al campoinputIconAlert (booleano, opzionale): mostra icona di alert in stato di erroreerrorDescription (stringa, opzionale): testo del messaggio di erroreinputDescription (stringa, opzionale): testo della descrizione aggiuntivaDocumenta i requisiti WCAG 2.1 e il comportamento del markup HTML per tecnologie assistive.
Livello AA — criteri pertinenti:
<label> associata all’<input> tramite for / idaria-invalid e aria-live="assertive"aria-required, aria-describedby, aria-invalid comunicano lo stato<input type="file"> all’interno di <div class="rtds-input-field"><label> è associata all’input tramite for="" e rimane disponibile anche se nascosta visivamente tramite rtds-sr-only<span aria-live="assertive"> per l’annuncio immediato| Attributo | Valori | Condizione |
|---|---|---|
aria-required |
"true" |
quando inputRequired: true |
aria-describedby |
ID descrizione e/o errore | quando presenti inputAriaDescribedBy o inputAriaDescribedError |
aria-invalid |
"true" |
quando inputAriaInvalid: true (stato di errore) |
aria-live |
"assertive" |
sullo span del messaggio di errore |
aria-live="assertive" al cambio di stato<!-- Esempio base -->
<div class="rtds-input-field">
<label for="upload-cv">Carica il tuo CV</label>
<input type="file" id="upload-cv" name="cv">
</div>
<!-- Esempio con errore -->
<div class="rtds-input-field rtds-input-field--has-error">
<label for="upload-doc">Documento <abbr title="obbligatorio">*</abbr></label>
<input type="file" id="upload-doc" name="doc"
aria-required="true"
aria-invalid="true"
aria-describedby="upload-doc-error">
<span id="upload-doc-error" aria-live="assertive" class="rtds-input-field__error">
Il campo documento non può essere vuoto
</span>
</div>@input-field — fare riferimento al README di input-field per la documentazione completa della struttura@input-field--smhas-description) per rispettare il criterio WCAG 3.3.2