Statustijdlijn van een aanvraag New
Status timeline for a repair, order or quote request: four steps (received, scheduled, on the way, done) with dates, the current step marked (aria-current="step", calm pulse that stops under prefers-reduced-motion) and an expandable activity log. The log uses with ::details-content and interpolate-size for smooth height (fallback: opens instantly). Horizontal on wide tiles, vertical via a container query on narrow ones. "Next status" walks through every state, including completed.
Activiteit
How to use it
- Paste the HTML where the numbers & charts should appear.
- Add the CSS to your stylesheet. All classes are prefixed, so nothing clashes with your own styles.
- Add the JavaScript and call init() with the element that contains the HTML.
<!-- Statustijdlijn van een aanvraag · NedDev · eigen werk. -->
<div class="jouw-container">
<div class="bst"><div class="bst__hd"><div><p class="bst__k"></p><p class="bst__t"></p></div><div class="bst__sw" role="group" aria-label="Voorbeeld"><button type="button" data-s="0" aria-pressed="true">Reparatie</button><button type="button" data-s="1" aria-pressed="false">Bestelling</button><button type="button" data-s="2" aria-pressed="false">Aanvraag</button></div></div><ol class="bst__steps"></ol><div class="bst__now" aria-live="polite"></div><div class="bst__ft"><details class="bst__log"><summary>Activiteit</summary><ul class="bst__ul"></ul></details><button type="button" class="bst__next">Volgende status</button></div></div>
</div>/* Statustijdlijn van een aanvraag · NedDev · eigen werk. */
.bst{position:absolute;inset:0;padding:10px 14px;background:#fff;font-family:'Switzer',system-ui,sans-serif;color:#0a0a0a;overflow:auto;display:flex;flex-direction:column;gap:8px;container-type:inline-size}
.bst__hd{display:flex;justify-content:space-between;align-items:flex-start;gap:8px}
.bst__k{margin:0;font:500 9.5px 'JetBrains Mono',monospace;text-transform:uppercase;letter-spacing:.07em;color:#5c5a56}
.bst__t{margin:1px 0 0;font-size:14px;font-weight:700;line-height:1.2}
.bst__sw{display:flex;flex:none;border:1px solid rgba(10,10,10,.18);border-radius:4px;overflow:hidden}
.bst__sw button{padding:3px 6px;border:0;background:#fff;font:600 10.5px 'Switzer',system-ui,sans-serif;color:#5c5a56;cursor:pointer;transition:background-color .15s,color .15s}
.bst__sw button+button{border-left:1px solid rgba(10,10,10,.18)}
.bst__sw button:hover{color:#0a0a0a;background:#f4f3f1}
.bst__sw button:focus-visible{outline:2px solid #0a0a0a;outline-offset:-2px}
.bst__sw button[aria-pressed="true"]{background:#0a0a0a;color:#fff}
.bst__steps{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));margin:2px 0 0;padding:0;list-style:none;counter-reset:bst}
.bst__s{position:relative;padding-top:24px;font-size:11.5px;line-height:1.3;min-width:0}
.bst__s::before{content:'';position:absolute;top:9px;left:0;right:0;height:2px;background:#e4e1dc}
.bst__s:first-child::before{left:9px}
.bst__s:last-child::before{right:auto;width:9px}
.bst__s.is-done::before,.bst__s.is-cur::before{background:#0a0a0a}
.bst__s.is-cur::before{background:linear-gradient(90deg,#0a0a0a 0 12px,#e4e1dc 12px)}
.bst__dot{position:absolute;top:2px;left:0;width:16px;height:16px;box-sizing:border-box;border-radius:50%;border:2px solid #cfcbc4;background:#fff;display:grid;place-items:center}
.bst__s.is-done .bst__dot{border-color:#0a0a0a;background:#0a0a0a}
.bst__s.is-done .bst__dot::after{content:'';width:6px;height:3px;border-left:1.6px solid #fff;border-bottom:1.6px solid #fff;transform:translateY(-1px) rotate(-45deg)}
.bst__s.is-cur .bst__dot{border-color:#F5480F;background:#F5480F;box-shadow:0 0 0 3px #fde3d8}
@media (prefers-reduced-motion:no-preference){.bst__s.is-cur .bst__dot{animation:bst-p 2s ease-in-out infinite}}
@keyframes bst-p{50%{box-shadow:0 0 0 6px rgba(245,72,15,.12)}}
.bst__s b{display:block;font-size:12px;font-weight:700;padding-right:6px}
.bst__s span{display:block;color:#5c5a56;font-size:10.5px;font-variant-numeric:tabular-nums;padding-right:6px}
.bst__s.is-todo b{color:#76736d;font-weight:600}
.bst__vh{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
.bst__now{padding:7px 10px;border-radius:4px;background:#f4f3f1;font-size:12px;line-height:1.4}
.bst__now b{font-weight:700}
.bst__now.is-fin{background:#e8f3ec;color:#14532d}
.bst__ft{display:flex;align-items:flex-start;gap:8px;margin-top:auto}
.bst__log{flex:1;min-width:0;font-size:11.5px}
.bst__log summary{display:inline-flex;align-items:center;gap:6px;padding:2px 0;font-weight:600;cursor:pointer;list-style:none;border-radius:3px}
.bst__log summary::-webkit-details-marker{display:none}
.bst__log summary::before{content:'';width:5px;height:5px;border-right:1.5px solid currentColor;border-bottom:1.5px solid currentColor;transform:rotate(-45deg);transition:transform .2s}
.bst__log[open] summary::before{transform:rotate(45deg)}
.bst__log summary:focus-visible{outline:2px solid #0a0a0a;outline-offset:2px}
.bst__ul{margin:4px 0 0;padding:0;list-style:none;color:#3d3b37}
.bst__ul li{display:grid;grid-template-columns:86px 1fr;gap:6px;padding:2px 0;border-top:1px solid rgba(10,10,10,.08)}
.bst__ul time{font:500 10px/1.6 'JetBrains Mono',monospace;color:#5c5a56}
@supports (interpolate-size:allow-keywords){.bst__log{interpolate-size:allow-keywords}.bst__log::details-content{height:0;overflow:hidden;transition:height .25s ease,content-visibility .25s allow-discrete}.bst__log[open]::details-content{height:auto}}
.bst__next{flex:none;height:28px;padding:0 10px;border:1px solid #0a0a0a;border-radius:4px;background:#fff;font:600 11.5px 'Switzer',system-ui,sans-serif;color:#0a0a0a;cursor:pointer;transition:background-color .15s,color .15s}
.bst__next:hover{background:#0a0a0a;color:#fff}
.bst__next:active{transform:translateY(1px)}
.bst__next:focus-visible{outline:2px solid #0a0a0a;outline-offset:2px}
@container (max-width:370px){.bst__hd{flex-direction:column}.bst__steps{grid-template-columns:1fr;gap:0}.bst__s{padding:0 0 10px 26px}.bst__s::before{top:16px;bottom:-2px;left:7px;right:auto;width:2px;height:auto}.bst__s:first-child::before{left:7px}.bst__s:last-child::before{display:none}.bst__s.is-cur::before{background:#e4e1dc}.bst__dot{top:0}}
@media (prefers-reduced-motion:reduce){.bst *{transition:none!important}}// Statustijdlijn van een aanvraag · NedDev · eigen werk.
// root = het element waarin de HTML staat
function init(root){
var w=root.querySelector('.bst');if(!w)return;
var stepsEl=w.querySelector('.bst__steps'),now=w.querySelector('.bst__now'),ul=w.querySelector('.bst__ul'),k=w.querySelector('.bst__k'),t=w.querySelector('.bst__t'),nextB=w.querySelector('.bst__next');
var DAG=['zo','ma','di','wo','do','vr','za'],MK=['jan','feb','mrt','apr','mei','jun','jul','aug','sep','okt','nov','dec'];
function d(n){var x=new Date();x.setHours(0,0,0,0);x.setDate(x.getDate()+n);return DAG[x.getDay()]+' '+x.getDate()+' '+MK[x.getMonth()]}
/* statussen: in productie uit je planning- of ordersysteem */
var S=[
{k:'Dossier R-30418',t:'Reparatie wasmachine, voorlader 8 kg',cur:2,steps:[['Ontvangen',d(-3)+' 09:12','We hebben je melding ontvangen.'],['Ingepland',d(-2),'Monteur Ahmed komt '+d(0)+' tussen 13:00 en 15:00.'],['Onderweg',d(0)+' 13:20','Ahmed is onderweg en is er rond 13:45. Zorg dat de machine leeg is.'],['Klaar',d(0)+', verwacht','De reparatie is klaar. De factuur staat in je account.']],
log:[[d(-3)+' 09:12','Melding ontvangen via de website'],[d(-2)+' 11:40','Onderdeel besteld: deurrubber'],[d(-2)+' 16:05','Afspraak ingepland met Ahmed'],[d(0)+' 13:20','Monteur vertrokken uit Schiedam']]},
{k:'Bestelling HA-108233',t:'3 artikelen, Het Anker Haarlem',cur:1,steps:[['Besteld',d(-1)+' 21:47','Je betaling is binnen.'],['Ingepakt',d(0)+' 08:30','Vers gebrand en ingepakt. Gaat vandaag mee met PostNL.'],['Onderweg',d(1)+', verwacht','Je pakket is onderweg. Volg het met je track-en-tracecode.'],['Bezorgd',d(1)+' 18:00 tot 22:00','Bezorgd. Veel koffieplezier.']],
log:[[d(-1)+' 21:47','Betaald met iDEAL'],[d(0)+' 07:15','Bonen gebrand, batch 4412'],[d(0)+' 08:30','Ingepakt en klaar voor PostNL']]},
{k:'Aanvraag Q-2291',t:'Offerte dakkapel, 4 m, antraciet',cur:0,steps:[['Ontvangen',d(0)+' 10:02','We bekijken je aanvraag en bellen binnen 2 werkdagen.'],['Inmeten',d(3)+', voorstel','We meten bij je thuis in, duurt ongeveer 30 minuten.'],['Offerte',d(5)+', verwacht','Je offerte staat klaar in je mail, 30 dagen geldig.'],['Akkoord',d(12)+', streefdatum','Akkoord ontvangen. We plannen de montage in.']],
log:[[d(0)+' 10:02','Aanvraag ontvangen via de configurator']]}];
var si=0,cur=S[0].cur;
function render(){var s=S[si];k.textContent=s.k;t.textContent=s.t;var fin=cur>=s.steps.length;
stepsEl.innerHTML=s.steps.map(function(st,i){var c=i<cur||fin&&i===s.steps.length-1?'is-done':(i===cur?'is-cur':'is-todo');if(fin)c='is-done';return '<li class="bst__s '+c+'"'+(c==='is-cur'?' aria-current="step"':'')+'><span class="bst__dot" aria-hidden="true"></span><b>'+st[0]+'</b><span>'+st[1]+'</span><span class="bst__vh">'+(c==='is-done'?'afgerond':c==='is-cur'?'huidige stap':'nog niet')+'</span></li>'}).join('');
var last=s.steps[Math.min(cur,s.steps.length-1)];now.className='bst__now'+(fin?' is-fin':'');now.innerHTML='<b>'+(fin?'Afgerond: ':'Nu: ')+last[0].toLowerCase()+'.</b> '+last[2];
ul.innerHTML=s.log.slice().reverse().map(function(l){return '<li><time>'+l[0]+'</time><span>'+l[1]+'</span></li>'}).join('');
nextB.textContent=fin?'Opnieuw':'Volgende status'}
w.querySelector('.bst__sw').addEventListener('click',function(e){var b=e.target.closest('button[data-s]');if(!b)return;si=+b.dataset.s;cur=S[si].cur;w.querySelectorAll('.bst__sw button').forEach(function(x){x.setAttribute('aria-pressed',x===b)});render()});
nextB.addEventListener('click',function(){var s=S[si];if(cur>=s.steps.length){cur=0;s.log=s.log.slice(0,1)}else{cur++;var st=s.steps[Math.min(cur,s.steps.length-1)];if(cur<=s.steps.length)s.log.push([st[1].replace(/, (verwacht|voorstel|streefdatum)$/,''),cur>=s.steps.length?s.steps[s.steps.length-1][0]+': afgerond':'Status: '+st[0].toLowerCase()])}render()});
render();
}
init(document.querySelector('.jouw-container'));
More numbers & charts
Seen something you like?
Add it to your selection and send it over. We build your site around it, in your brand.
Get in touch →