card-08-orb-chain-total
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
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
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.
| assertion | mesure | attendu |
|---|---|---|
| une seule ligne surlignée | document.querySelectorAll('.vl-due__row--on').length | 1 ± 0 |
| une seule pilule d'imminence | document.querySelectorAll('.vl-due__flag').length | 1 ± 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 largeur | box('.vl-due__who').w / W | 0.2646 ± 0.05 |
| aucun filet de séparation entre les lignes | num('.vl-due__row','borderBottomWidth') + num('.vl-due__row','borderTopWidth') | ≤ 0 |
| le surlignage déborde des marges du titre : il tient toute la largeur utile | box('.vl-due__row--on').w / W | ≥ 0.94 |
| le montant est plus lourd que l'offre qu'il chiffre | num('.vl-due__amount','fontWeight') - num('.vl-due__plan','fontWeight') | ≥ 100 |
| contraste du nom d'échéance ≥ 7 | contrast('.vl-due__name') | ≥ 7 |
| contraste des dates atténuées ≥ 4,5 | contrast('.vl-due__date') | ≥ 4.5 |
| contraste de la pilule d'imminence sur son aplat ≥ 3 | contrast('.vl-due__flag') | ≥ 3 |
| aucun débordement du contenu hors de la carte | overflow('.vl-due') | ≤ 0 |
Le code
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>
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é
card-09-gradient-metric-curve
KPI sur aplat coloré à courbe annotée
chart-03-accent-column-callout
Histogramme à colonne accentuée et info-bulle
layout-03-glass-board
Écran en verre dépoli — fond dégradé + modules
list-01-giant-numbers
Colonnes à numéro géant
list-02-ruled-index