list-04-due-rows

Liste d'échéances à quatre zones

Rendre une liste d'échéances balayable sans un seul filet : quatre zones tenues par une grille commune, une seule ligne surlignée, une seule pilule d'imminence, et le montant en unique colonne alignée à droite.

listslideweb1512×254px12 benchmarks

Télécharger le .zip

Le fragment RÉEL, dans son propre document, sur le sol de sa charte — pas une image. Ce que vous voyez est exactement ce que vous collerez.

Employer quand

Trois à six échéances, abonnements ou factures à venir, où l'œil doit trouver l'urgente et comparer les montants sans lire les lignes.

Éviter quand

Il faut plus de quatre informations par ligne (c'est un tableau qu'il faut, avec ses en-têtes), ou plus d'une ligne est urgente : la pilule d'imminence ne code quelque chose que tant qu'elle est unique.

Notes

Les deux benchmarks d'alignement (montants à droite, offres à gauche) sont ce qui distingue ce pattern d'une suite de lignes en flex : ils tombent à la première tentative de « laisser le contenu respirer » ligne par ligne, et c'est exactement le moment où une liste cesse d'être balayable. Le surlignage vit en marge négative (`margin: 0 -14px` sur la pile) pour dépasser les marges du titre : une ligne survolée qui s'arrête à l'alignement du texte se lit comme un bloc décalé, pas comme une ligne. La zone d'imminence reste présente et VIDE sur les lignes non urgentes — la supprimer casserait la grille et déplacerait les trois autres colonnes.

Mots-clés

listeecheancespaiementsabonnementslignesgrillemontantimminencesurlignagedashboardverre

Benchmarks — la géométrie, en assertions vérifiables

Rejouables par node bin/check.mjs list-04-due-rows : le pattern se prouve, il ne se croit pas.

assertionmesureattendu
une seule ligne surlignéedocument.querySelectorAll('.vl-due__row--on').length1 ± 0
une seule pilule d'imminencedocument.querySelectorAll('.vl-due__flag').length1 ± 0
les montants sont alignés à droite sur la même verticale (± 1 px)Math.max(...[...document.querySelectorAll('.vl-due__amount')].map((e) => e.getBoundingClientRect().right)) - Math.min(...[...document.querySelectorAll('.vl-due__amount')].map((e) => e.getBoundingClientRect().right))≤ 1
les libellés d'offre démarrent sur la même verticale (grille commune, pas un flux)Math.max(...[...document.querySelectorAll('.vl-due__plan')].map((e) => e.getBoundingClientRect().left)) - Math.min(...[...document.querySelectorAll('.vl-due__plan')].map((e) => e.getBoundingClientRect().left))≤ 1
la zone d'identité tient ≈ 28 % de la largeurbox('.vl-due__who').w / W0.2646 ± 0.05
aucun filet de séparation entre les lignesnum('.vl-due__row','borderBottomWidth') + num('.vl-due__row','borderTopWidth')≤ 0
le surlignage déborde des marges du titre : il tient toute la largeur utilebox('.vl-due__row--on').w / W≥ 0.94
le montant est plus lourd que l'offre qu'il chiffrenum('.vl-due__amount','fontWeight') - num('.vl-due__plan','fontWeight')≥ 100
contraste du nom d'échéance ≥ 7contrast('.vl-due__name')≥ 7
contraste des dates atténuées ≥ 4,5contrast('.vl-due__date')≥ 4.5
contraste de la pilule d'imminence sur son aplat ≥ 3contrast('.vl-due__flag')≥ 3
aucun débordement du contenu hors de la carteoverflow('.vl-due')≤ 0

Le code

fragment — patterns/list-04-due-rows.html Télécharger
<!-- list-04-due-rows — fragment autonome. Couleurs via --vl-* uniquement, aucune valeur en dur. -->
<div class="vl-due">
  <div class="vl-due__head">
    <h2 class="vl-due__title">Upcoming payments</h2>
    <span class="vl-due__all">View All</span>
  </div>
  <div class="vl-due__list">

    <div class="vl-due__row">
      <span class="vl-due__who">
        <span class="vl-due__mark">
          <svg viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
            <path d="M3.4 9.6c1.6-3.6 3-3.6 4.6 0s3 3.6 4.6 0" stroke="var(--vl-ink)" stroke-width="1.4" stroke-linecap="round"/>
          </svg>
        </span>
        <span>
          <span class="vl-due__name">Northbeam Pricing</span>
          <span class="vl-due__date">Jul 31</span>
        </span>
      </span>
      <span><span class="vl-due__flag">Today</span></span>
      <span class="vl-due__plan">Payment Links</span>
      <span class="vl-due__amount">$1,200</span>
    </div>

    <div class="vl-due__row vl-due__row--on">
      <span class="vl-due__who">
        <span class="vl-due__mark">
          <svg viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
            <rect x="3.2" y="3.2" width="9.6" height="9.6" rx="2.4" stroke="var(--vl-ink)" stroke-width="1.4"/>
            <path d="M8 3.2v9.6M3.2 8h9.6" stroke="var(--vl-ink)" stroke-width="1.4"/>
          </svg>
        </span>
        <span>
          <span class="vl-due__name">Atlas Membership</span>
          <span class="vl-due__date">Jun 23</span>
        </span>
      </span>
      <span></span>
      <span class="vl-due__plan">Professional</span>
      <span class="vl-due__amount">$155</span>
    </div>

    <div class="vl-due__row">
      <span class="vl-due__who">
        <span class="vl-due__mark">
          <svg viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
            <circle cx="8" cy="8" r="2.4" stroke="var(--vl-ink)" stroke-width="1.4"/>
            <path d="M8 1.8v2.6M8 11.6v2.6M1.8 8h2.6M11.6 8h2.6M3.6 3.6l1.9 1.9M10.5 10.5l1.9 1.9M12.4 3.6l-1.9 1.9M5.5 10.5l-1.9 1.9"
                  stroke="var(--vl-ink)" stroke-width="1.3" stroke-linecap="round"/>
        </svg>
        </span>
        <span>
          <span class="vl-due__name">Relay Subscription</span>
          <span class="vl-due__date">Jul 15</span>
        </span>
      </span>
      <span></span>
      <span class="vl-due__plan">Relay Business</span>
      <span class="vl-due__amount">$100</span>
    </div>

  </div>
</div>

<style>
/* Une liste d'échéances en QUATRE zones fixes — identité (pastille + nom + date), imminence,
   offre, montant — tenues par une grille commune : c'est l'alignement des colonnes qui rend
   la liste balayable, pas un filet. Aucune ligne de séparation ; une seule ligne porte un fond
   (le survol), et une seule porte la pilule d'imminence — deux « une seule » qui font que
   l'œil trouve l'urgent sans lire. Le montant est la seule colonne alignée à droite : c'est ce
   qui le rend comparable d'une ligne à l'autre. */
.vl-due {
  position: relative; width: 1512px; height: 254px; padding: 24px 28px;
  display: flex; flex-direction: column;
  border-radius: var(--vl-radius-card);
  background-color: var(--vl-surface-glass);
  backdrop-filter: blur(var(--vl-blur));
  box-shadow: inset 0 1px 0 var(--vl-sheen);
  font-family: Inter, -apple-system, "Helvetica Neue", Arial, sans-serif;
  color: var(--vl-ink);
}
.vl-due__head { display: flex; align-items: center; justify-content: space-between; }
.vl-due__title { margin: 0; font-size: 15px; font-weight: 500; letter-spacing: -0.01em; }
.vl-due__all {
  display: inline-flex; align-items: center; padding: 9px 18px; border-radius: 999px;
  font-size: 12px; font-weight: 500;
  background-color: var(--vl-surface-dark); color: var(--vl-ink-invert);
}
.vl-due__list { flex: 1; display: flex; flex-direction: column; justify-content: center; gap: 4px; margin: 0 -14px; }
.vl-due__row {
  display: grid; grid-template-columns: 400px 190px 1fr 130px;
  align-items: center; gap: 16px;
  padding: 10px 14px; border-radius: var(--vl-radius-sub);
}
.vl-due__row--on { background-color: var(--vl-surface-glass-strong); box-shadow: inset 0 1px 0 var(--vl-sheen); }
.vl-due__who { display: flex; align-items: center; gap: 13px; }
.vl-due__mark {
  width: 36px; height: 36px; border-radius: 50%; flex: 0 0 36px;
  display: inline-flex; align-items: center; justify-content: center;
  background-color: var(--vl-surface-glass-strong);
  box-shadow: inset 0 1px 0 var(--vl-sheen);
}
.vl-due__mark svg { width: 16px; height: 16px; }
.vl-due__name { display: block; font-size: 13px; font-weight: 500; letter-spacing: -0.01em; }
.vl-due__date { display: block; margin-top: 2px; font-size: 11px; color: var(--vl-ink-muted); }
.vl-due__flag {
  display: inline-flex; align-items: center; padding: 6px 14px; border-radius: 999px;
  font-size: 11px; font-weight: 500;
  background-color: var(--vl-blue); color: var(--vl-ink-invert);
}
.vl-due__plan { font-size: 13px; font-weight: 500; }
.vl-due__amount { font-size: 14px; font-weight: 600; letter-spacing: -0.02em; text-align: right; }
</style>
tokens de la charte — systems/ref-13-glass-fintech-dashboard.json Télécharger
:root {
  --vl-bg: #B4BEDD;
  --vl-grad-1: #A3B0DA;
  --vl-grad-2: #98A9D6;
  --vl-grad-3: #C8CEDA;
  --vl-surface-glass: rgba(255, 255, 255, 0.45);
  --vl-surface-glass-strong: rgba(255, 255, 255, 0.68);
  --vl-surface-glass-soft: rgba(255, 255, 255, 0.24);
  --vl-surface-dark: #101625;
  --vl-sheen: rgba(255, 255, 255, 0.45);
  --vl-blue: #4F7CF7;
  --vl-blue-light: #8FB6FA;
  --vl-violet: #8B5CF6;
  --vl-violet-deep: #5B7CF0;
  --vl-violet-halo: rgba(123, 106, 240, 0.42);
  --vl-ink: #1A1F2E;
  --vl-ink-muted: #565C72;
  --vl-ink-invert: #FFFFFF;
  --vl-ink-invert-muted: rgba(255, 255, 255, 0.72);
  --vl-radius-card: 28px;
  --vl-radius-sub: 18px;
  --vl-gap: 22px;
  --vl-margin: 44px;
  --vl-blur: 18px;
}
les métadonnées — patterns/list-04-due-rows.json (télécharger)
{
  "name": "Liste d'échéances à quatre zones",
  "family": "list",
  "ref": "ref-13-glass-fintech-dashboard",
  "intent": "Rendre une liste d'échéances balayable sans un seul filet : quatre zones tenues par une grille commune, une seule ligne surlignée, une seule pilule d'imminence, et le montant en unique colonne alignée à droite.",
  "when_to_use": "Trois à six échéances, abonnements ou factures à venir, où l'œil doit trouver l'urgente et comparer les montants sans lire les lignes.",
  "avoid_when": "Il faut plus de quatre informations par ligne (c'est un tableau qu'il faut, avec ses en-têtes), ou plus d'une ligne est urgente : la pilule d'imminence ne code quelque chose que tant qu'elle est unique.",
  "media": [
    "slide",
    "web"
  ],
  "tags": [
    "liste",
    "echeances",
    "paiements",
    "abonnements",
    "lignes",
    "grille",
    "montant",
    "imminence",
    "surlignage",
    "dashboard",
    "verre"
  ],
  "vars": [
    {
      "name": "--vl-surface-glass",
      "role": "verre de la carte",
      "default": "rgba(255, 255, 255, 0.45)"
    },
    {
      "name": "--vl-surface-glass-strong",
      "role": "fond de la ligne surlignée + pastilles de logo",
      "default": "rgba(255, 255, 255, 0.68)"
    },
    {
      "name": "--vl-blue",
      "role": "pilule d'imminence (la seule couleur de la liste)",
      "default": "#4F7CF7"
    },
    {
      "name": "--vl-surface-dark",
      "role": "aplat du bouton « tout voir »",
      "default": "#101625"
    },
    {
      "name": "--vl-ink-muted",
      "role": "dates, second rang de l'identité",
      "default": "#6B7186"
    }
  ],
  "slots": [
    "title",
    "action",
    "rows"
  ],
  "geometry": {
    "root": ".vl-due",
    "frame": [
      1512,
      254
    ],
    "ratios": {
      "identity_over_width": 0.2646,
      "amount_over_width": 0.086,
      "row_over_height": 0.2205,
      "mark_over_width": 0.0238
    },
    "type_px": {
      "title": 15,
      "name": 13,
      "plan": 13,
      "amount": 14,
      "micro": 11
    },
    "pad_ratio": {
      "top": 0.0159,
      "x": 0.0185,
      "bottom": 0.0159
    }
  },
  "benchmarks": [
    {
      "name": "une seule ligne surlignée",
      "measure": "document.querySelectorAll('.vl-due__row--on').length",
      "expect": 1,
      "tol": 0
    },
    {
      "name": "une seule pilule d'imminence",
      "measure": "document.querySelectorAll('.vl-due__flag').length",
      "expect": 1,
      "tol": 0
    },
    {
      "name": "les montants sont alignés à droite sur la même verticale (± 1 px)",
      "measure": "Math.max(...[...document.querySelectorAll('.vl-due__amount')].map((e) => e.getBoundingClientRect().right)) - Math.min(...[...document.querySelectorAll('.vl-due__amount')].map((e) => e.getBoundingClientRect().right))",
      "max": 1
    },
    {
      "name": "les libellés d'offre démarrent sur la même verticale (grille commune, pas un flux)",
      "measure": "Math.max(...[...document.querySelectorAll('.vl-due__plan')].map((e) => e.getBoundingClientRect().left)) - Math.min(...[...document.querySelectorAll('.vl-due__plan')].map((e) => e.getBoundingClientRect().left))",
      "max": 1
    },
    {
      "name": "la zone d'identité tient ≈ 28 % de la largeur",
      "measure": "box('.vl-due__who').w / W",
      "expect": 0.2646,
      "tol": 0.05
    },
    {
      "name": "aucun filet de séparation entre les lignes",
      "measure": "num('.vl-due__row','borderBottomWidth') + num('.vl-due__row','borderTopWidth')",
      "max": 0
    },
    {
      "name": "le surlignage déborde des marges du titre : il tient toute la largeur utile",
      "measure": "box('.vl-due__row--on').w / W",
      "min": 0.94
    },
    {
      "name": "le montant est plus lourd que l'offre qu'il chiffre",
      "measure": "num('.vl-due__amount','fontWeight') - num('.vl-due__plan','fontWeight')",
      "min": 100
    },
    {
      "name": "contraste du nom d'échéance ≥ 7",
      "measure": "contrast('.vl-due__name')",
      "min": 7
    },
    {
      "name": "contraste des dates atténuées ≥ 4,5",
      "measure": "contrast('.vl-due__date')",
      "min": 4.5
    },
    {
      "name": "contraste de la pilule d'imminence sur son aplat ≥ 3",
      "measure": "contrast('.vl-due__flag')",
      "min": 3
    },
    {
      "name": "aucun débordement du contenu hors de la carte",
      "measure": "overflow('.vl-due')",
      "max": 0
    }
  ],
  "notes": "Les deux benchmarks d'alignement (montants à droite, offres à gauche) sont ce qui distingue ce pattern d'une suite de lignes en flex : ils tombent à la première tentative de « laisser le contenu respirer » ligne par ligne, et c'est exactement le moment où une liste cesse d'être balayable. Le surlignage vit en marge négative (`margin: 0 -14px` sur la pile) pour dépasser les marges du titre : une ligne survolée qui s'arrête à l'alignement du texte se lit comme un bloc décalé, pas comme une ligne. La zone d'imminence reste présente et VIDE sur les lignes non urgentes — la supprimer casserait la grille et déplacerait les trois autres colonnes.",
  "id": "list-04-due-rows"
}

À côté