Aller au contenu
Bibliotheque UIJABS

Etats vides et chargement 15 variantes

Les ecrans que personne ne dessine et que tout le monde voit. Un etat vide dit ce qui manque, pourquoi c'est utile, et porte le bouton qui debloque : sans bouton, c'est un cul-de-sac. Un squelette a exactement la forme du contenu attendu, sinon la page saute a l'arrivee des donnees.

A. Etats vides

Premiere utilisation, liste filtree sans resultat, version compacte, amorces par modele, acces refuse.

Creez votre premier devis

Un devis se remplit en 2 minutes : le client, les operations, le montant. Le PDF est genere et envoye par courriel dans la foulee.

Premiere utilisation

L'ecran d'un utilisateur qui n'a encore rien cree. C'est une page d'accueil deguisee : elle vend la fonction avant de la proposer.

Voir le codeMasquer le code
<div class="etat">
  <svg class="etat__illu" viewBox="0 0 96 96" fill="none" stroke="currentColor" stroke-width="2.5" aria-hidden="true">
    <rect x="18" y="14" width="60" height="72" rx="6"/><path d="M32 34h32M32 48h32M32 62h20"/>
    <circle cx="72" cy="68" r="16" fill="var(--c-surface)"/><path d="M72 61v14M65 68h14"/>
  </svg>
  <h3>Creez votre premier devis</h3>
  <p>Un devis se remplit en 2 minutes : le client, les operations, le montant. Le PDF est genere et envoye par courriel dans la foulee.</p>
  <div class="etat__actions">
    <button class="btn btn--plein btn--lg"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 5v14M5 12h14"/></svg> Nouveau devis</button>
    <button class="btn btn--secondaire btn--lg">Voir un exemple</button>
  </div>
</div>
/* voir le socle .etat en haut du fichier */
flex flex-col items-center gap-3 py-16 text-center

Aucun dossier ne correspond

Aucun resultat pour « martin » avec les filtres Signes et Septembre 2026.

Liste vide apres filtrage

Different de EMP-A1 : ici il existe des donnees, ce sont les criteres qui ne rendent rien. Le bouton efface les filtres, il ne cree pas.

Voir le codeMasquer le code
<div class="etat">
  <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="11" cy="11" r="7"/><path d="m20 20-3.5-3.5"/></svg>
  <h3>Aucun dossier ne correspond</h3>
  <p>Aucun resultat pour <em>&laquo; martin &raquo;</em> avec les filtres <em>Signes</em> et <em>Septembre 2026</em>.</p>
  <div class="etat__actions">
    <button class="btn btn--secondaire">Effacer les filtres</button>
    <button class="btn btn--fantome">Chercher dans les archives</button>
  </div>
</div>
.etat > svg:not(.etat__illu) { width: 42px; height: 42px; color: var(--c-text-muted); opacity: .6; }
.etat em { font-style: normal; font-weight: var(--fw-semi); color: var(--c-text); }
idem A1, message centre sur les criteres et non sur l'absence de donnees

Aucun document dans ce dossier.

Aucune intervention planifiee.

Etat vide compact

Dans un panneau ou une colonne : la version pleine page ecraserait tout. Une phrase, un lien, rien de plus.

Voir le codeMasquer le code
<div class="demo-col demo-col--large">
  <div class="carte"><div class="etat etat--compact"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="3" y="4" width="18" height="5" rx="1"/><path d="M5 9v10a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1V9M10 13h4"/></svg><p>Aucun document dans ce dossier.</p><button class="btn btn--texte">Ajouter un document</button></div></div>
  <div class="carte"><div class="etat etat--compact"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="3" y="4" width="18" height="18" rx="2"/><path d="M16 2v4M8 2v4M3 10h18"/></svg><p>Aucune intervention planifiee.</p><button class="btn btn--texte">Planifier</button></div></div>
</div>
.etat--compact { padding: var(--sp-6) var(--sp-4); gap: var(--sp-2); }
.etat--compact > svg { width: 30px; height: 30px; }
.etat--compact p { font-size: var(--fs-sm); }
gap-2 py-8 [&_svg]:h-8 [&_p]:text-sm

Commencez a partir d'un modele

Choisissez une trame, puis adaptez les lignes a votre chantier.

Etat vide avec liste d'amorce

Plutot qu'une page nue, proposer des modeles a partir desquels demarrer. C'est ce qui transforme un ecran vide en premier pas.

Voir le codeMasquer le code
<div class="etat">
  <h3>Commencez a partir d'un modele</h3>
  <p>Choisissez une trame, puis adaptez les lignes a votre chantier.</p>
  <div class="etat__amorces">
    <button class="btn btn--pointille"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8Z"/><path d="M14 2v6h6M9 15h6"/></svg> Pompe a chaleur air/eau</button>
    <button class="btn btn--pointille"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8Z"/><path d="M14 2v6h6M9 15h6"/></svg> Chauffe-eau thermodynamique</button>
    <button class="btn btn--pointille"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8Z"/><path d="M14 2v6h6M9 15h6"/></svg> Isolation des combles</button>
    <button class="btn btn--pointille"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 5v14M5 12h14"/></svg> Partir d'un devis vierge</button>
  </div>
</div>
.etat__amorces { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--sp-2); margin-top: var(--sp-3); max-width: 520px; }
flex flex-wrap justify-center gap-2

Cette rubrique ne vous est pas ouverte

L'acces a la facturation est reserve aux administrateurs. Demandez a Julien K. de modifier vos droits dans Parametres, Utilisateurs.

Acces refuse

Droits insuffisants. Nommer QUI peut debloquer, sinon l'utilisateur ecrit au support pour rien.

Voir le codeMasquer le code
<div class="etat">
  <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 9v4M12 17h.01M10.3 3.9 1.8 18a2 2 0 0 0 1.7 3h17a2 2 0 0 0 1.7-3L13.7 3.9a2 2 0 0 0-3.4 0Z"/></svg>
  <h3>Cette rubrique ne vous est pas ouverte</h3>
  <p>L'acces a la facturation est reserve aux administrateurs. Demandez a <strong>Julien K.</strong> de modifier vos droits dans Parametres, Utilisateurs.</p>
  <div class="etat__actions"><button class="btn btn--secondaire">Revenir au tableau de bord</button></div>
</div>
/* aucun style specifique : le socle .btn suffit */
idem A1, en nommant la personne qui peut debloquer

B. Chargement

Squelettes de liste et de tableau, chargement de page, de portion, progressif.

Squelette de liste

Le squelette reprend le gabarit reel : avatar rond, deux lignes de texte, une valeur a droite. Toute autre forme fait sauter la page.

Voir le codeMasquer le code
<ul class="liste">
  <li><div class="squel-ligne">
    <span class="doc-squelette squel-rond"></span>
    <span class="squel-bloc"><span class="doc-squelette doc-squelette--ligne" style="width:45%;height:14px"></span><span class="doc-squelette doc-squelette--ligne" style="width:65%;height:10px"></span></span>
    <span class="doc-squelette doc-squelette--ligne" style="width:70px;height:14px"></span>
  </div></li>
  <li><div class="squel-ligne">
    <span class="doc-squelette squel-rond"></span>
    <span class="squel-bloc"><span class="doc-squelette doc-squelette--ligne" style="width:38%;height:14px"></span><span class="doc-squelette doc-squelette--ligne" style="width:55%;height:10px"></span></span>
    <span class="doc-squelette doc-squelette--ligne" style="width:70px;height:14px"></span>
  </div></li>
</ul>
.squel-ligne { display: flex; align-items: center; gap: var(--sp-3); padding: var(--sp-3); }
.squel-rond { width: 40px; height: 40px; flex: none; border-radius: 50%; }
.squel-bloc { display: flex; flex-direction: column; gap: 7px; flex: 1; }
animate-pulse (voir .doc-squelette dans documents.css)
ReferenceClientStatutMontant
Squelette de tableau

Meme nombre de colonnes que le tableau reel, largeurs variees pour ne pas donner l'impression d'une grille figee.

Voir le codeMasquer le code
<div class="tbl__cadre">
  <table class="tbl">
    <thead><tr><th>Reference</th><th>Client</th><th>Statut</th><th class="tbl__nombre">Montant</th></tr></thead>
    <tbody>
      <tr><td><span class="doc-squelette doc-squelette--ligne" style="width:70px"></span></td><td><span class="doc-squelette doc-squelette--ligne" style="width:120px"></span></td><td><span class="doc-squelette doc-squelette--ligne" style="width:60px"></span></td><td><span class="doc-squelette doc-squelette--ligne" style="width:80px"></span></td></tr>
      <tr><td><span class="doc-squelette doc-squelette--ligne" style="width:70px"></span></td><td><span class="doc-squelette doc-squelette--ligne" style="width:90px"></span></td><td><span class="doc-squelette doc-squelette--ligne" style="width:70px"></span></td><td><span class="doc-squelette doc-squelette--ligne" style="width:60px"></span></td></tr>
      <tr><td><span class="doc-squelette doc-squelette--ligne" style="width:70px"></span></td><td><span class="doc-squelette doc-squelette--ligne" style="width:140px"></span></td><td><span class="doc-squelette doc-squelette--ligne" style="width:55px"></span></td><td><span class="doc-squelette doc-squelette--ligne" style="width:90px"></span></td></tr>
    </tbody>
  </table>
</div>
/* aucun style specifique : le socle .btn suffit */
[&_td_span]:block [&_td_span]:h-3 [&_td_span]:animate-pulse [&_td_span]:rounded

Chargement des 24 dossiers...

Chargement de page

Quand le squelette n'est pas possible (premiere ouverture, gabarit inconnu). Le texte dit ce qui charge : « chargement » seul inquiete au-dela de 3 secondes.

Voir le codeMasquer le code
<div class="etat">
  <span class="btn__spin etat__spin"></span>
  <p>Chargement des 24 dossiers...</p>
</div>
.etat__spin {
  width: 34px; height: 34px;
  border-width: 3px;
  border-color: color-mix(in srgb, var(--c-primary) 25%, transparent);
  border-top-color: var(--c-primary);
}
flex flex-col items-center gap-4 py-20
Chargement d'une portion

Un bloc se recharge sans bloquer le reste : le contenu reste lisible sous un voile, ce qui evite le clignotement a chaque filtre applique.

Voir le codeMasquer le code
<div class="voile-charge">
  <ul class="liste">
    <li><a href="#"><span class="liste__bloc"><strong>Krissi Julien</strong><small>Neuilly-sur-Marne (93)</small></span><strong>4 280 EUR</strong></a></li>
    <li><a href="#"><span class="liste__bloc"><strong>Martin Sophie</strong><small>Colombes (92)</small></span><strong>1 890 EUR</strong></a></li>
  </ul>
  <div class="voile-charge__voile"><span class="btn__spin etat__spin"></span></div>
</div>
.voile-charge { position: relative; width: 100%; }
.voile-charge__voile {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  border-radius: var(--r-lg);
  background: color-mix(in srgb, var(--c-surface) 62%, transparent);
  backdrop-filter: blur(1.5px);
  -webkit-backdrop-filter: blur(1.5px);
}
relative [&>div]:absolute [&>div]:inset-0 [&>div]:grid [&>div]:place-items-center [&>div]:bg-white/65
10 sur 24 affiches
Chargement progressif

Longue liste : les elements suivants se chargent en approchant du bas. Le bouton de repli reste present, le defilement infini seul pieges les lecteurs d'ecran.

Voir le codeMasquer le code
<div class="demo-col demo-col--large">
  <ul class="liste">
    <li><a href="#"><span class="liste__bloc"><strong>Dossier 2026-118</strong><small>Colombes (92)</small></span></a></li>
    <li><a href="#"><span class="liste__bloc"><strong>Dossier 2026-121</strong><small>Le Raincy (93)</small></span></a></li>
  </ul>
  <div class="charge-plus">
    <span class="doc-squelette doc-squelette--ligne" style="height:44px"></span>
    <button class="btn btn--secondaire btn--bloc">Charger 10 dossiers de plus</button>
    <small>10 sur 24 affiches</small>
  </div>
</div>
.charge-plus { display: flex; flex-direction: column; align-items: center; gap: var(--sp-3); width: 100%; }
.charge-plus small { font-size: var(--fs-xs); color: var(--c-text-muted); }
flex flex-col items-center gap-3

C. Erreurs

404, 500, hors connexion, erreur d'un bloc isole, conflit de version.

404

Cette page n'existe pas

Le lien est peut-etre obsolete, ou le dossier a ete supprime.

Page introuvable

Erreur 404. Ne jamais laisser sur une impasse : proposer la recherche et le retour a l'accueil, pas seulement un numero.

Voir le codeMasquer le code
<div class="etat">
  <span class="etat__code">404</span>
  <h3>Cette page n'existe pas</h3>
  <p>Le lien est peut-etre obsolete, ou le dossier a ete supprime.</p>
  <div class="etat__actions">
    <button class="btn btn--plein">Revenir a l'accueil</button>
    <button class="btn btn--secondaire"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="11" cy="11" r="7"/><path d="m20 20-3.5-3.5"/></svg> Rechercher</button>
  </div>
</div>
.etat__code {
  font-size: 76px;
  font-weight: 900;
  letter-spacing: -.05em;
  line-height: 1;
  color: var(--c-surface-3);
}
text-8xl font-black tracking-tighter text-slate-200

Un incident est survenu de notre cote

Vos donnees n'ont pas ete perdues. Reessayez dans quelques instants ; si le probleme persiste, transmettez cette reference au support.

INC-2026-09-06-8F3A
Erreur serveur

Erreur 500 : rien n'est de la faute de l'utilisateur, le dire. La reference d'incident sert au support, elle est copiable en un clic.

Voir le codeMasquer le code
<div class="etat">
  <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 9v4M12 17h.01M10.3 3.9 1.8 18a2 2 0 0 0 1.7 3h17a2 2 0 0 0 1.7-3L13.7 3.9a2 2 0 0 0-3.4 0Z"/></svg>
  <h3>Un incident est survenu de notre cote</h3>
  <p>Vos donnees n'ont pas ete perdues. Reessayez dans quelques instants ; si le probleme persiste, transmettez cette reference au support.</p>
  <div class="btn-copier"><code>INC-2026-09-06-8F3A</code><button class="btn btn--icone btn--fantome btn--sm" aria-label="Copier la reference"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="9" y="9" width="12" height="12" rx="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg></button></div>
  <div class="etat__actions">
    <button class="btn btn--plein">Reessayer</button>
    <a href="#" class="btn btn--secondaire">Contacter le support</a>
  </div>
</div>
/* aucun style specifique : le socle .btn suffit */
idem, avec la reference d'incident copiable

Pas de connexion

Les 12 dossiers deja ouverts restent consultables. Les modifications seront envoyees des le retour du reseau.

Hors connexion

Perte de reseau sur mobile. Dire ce qui reste consultable hors ligne evite la fermeture de l'application.

Voir le codeMasquer le code
<div class="etat">
  <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 9v4M12 17h.01M10.3 3.9 1.8 18a2 2 0 0 0 1.7 3h17a2 2 0 0 0 1.7-3L13.7 3.9a2 2 0 0 0-3.4 0Z"/></svg>
  <h3>Pas de connexion</h3>
  <p>Les 12 dossiers deja ouverts restent consultables. Les modifications seront envoyees des le retour du reseau.</p>
  <div class="etat__actions"><button class="btn btn--secondaire">Reessayer</button></div>
</div>
/* aucun style specifique : le socle .btn suffit */
idem, en precisant ce qui reste disponible hors ligne

Les statistiques n'ont pas pu etre chargees.

Erreur en ligne

Un bloc de la page a echoue sans casser le reste. Le reste de l'ecran continue de fonctionner, seul le bloc propose de recharger.

Voir le codeMasquer le code
<div class="carte">
  <div class="carte__corps">
    <div class="etat etat--compact">
      <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 9v4M12 17h.01M10.3 3.9 1.8 18a2 2 0 0 0 1.7 3h17a2 2 0 0 0 1.7-3L13.7 3.9a2 2 0 0 0-3.4 0Z"/></svg>
      <p>Les statistiques n'ont pas pu etre chargees.</p>
      <button class="btn btn--secondaire btn--sm"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M21 12a9 9 0 1 1-3-6.7M21 3v6h-6"/></svg> Recharger ce bloc</button>
    </div>
  </div>
</div>
/* aucun style specifique : le socle .btn suffit */
grid place-items-center gap-2 py-8 text-center
Ce dossier a ete modifie pendant votre saisie

Sophie M. a change le montant il y a 2 minutes. Votre version indique 4 280 EUR, la sienne 4 520 EUR.

Conflit de version

Deux personnes ont modifie la meme fiche. Ne jamais choisir a la place de l'utilisateur : montrer les deux versions et laisser trancher.

Voir le codeMasquer le code
<div class="alerte alerte--attention alerte--actions">
  <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 9v4M12 17h.01M10.3 3.9 1.8 18a2 2 0 0 0 1.7 3h17a2 2 0 0 0 1.7-3L13.7 3.9a2 2 0 0 0-3.4 0Z"/></svg>
  <div>
    <strong>Ce dossier a ete modifie pendant votre saisie</strong>
    <p>Sophie M. a change le montant il y a 2 minutes. Votre version indique <strong>4 280 EUR</strong>, la sienne <strong>4 520 EUR</strong>.</p>
    <div class="alerte__boutons">
      <button class="btn btn--plein btn--sm">Garder ma version</button>
      <button class="btn btn--secondaire btn--sm">Reprendre la sienne</button>
      <button class="btn btn--fantome btn--sm">Comparer</button>
    </div>
  </div>
</div>
/* aucun style specifique : le socle .btn suffit */
idem FBK-A2, avec les deux valeurs affichees cote a cote