Thema-wissel met cirkel New
Light, Dark or System view choice in a small till dashboard: the new theme reveals as a circle from the clicked button, scoped to its own block. View Transitions with a clip-path animation on ::view-transition-new, instant without support or with reduced motion. Across pages, store the choice in localStorage and apply it before first render; the reveal itself needs no navigation.
Bakkerij Mulder · kassa
Omzet vandaag, di 7 okt€ 2.184,50+12% op vorige dinsdag
142 bonnenGem. € 15,38Pin 81%
How to use it
- Paste the HTML where the components 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.
<!-- Thema-wissel met cirkel · NedDev · eigen werk. -->
<div class="jouw-container">
<!-- Scoped: alleen .vtw__box krijgt tijdens de wissel view-transition-name: vtw-box; de rest van de pagina doet niet mee.
Hele site: zet de naam op <html> (of laat hem weg en gebruik ::view-transition-new(root)), bewaar de keuze in localStorage
en zet data-theme in een klein inline script in de <head>, zodat een volgende pagina direct in het juiste thema opent.
Multi-page overgangen tussen pagina's: @view-transition { navigation: auto; }.
Reduced motion: sla startViewTransition over (zie JS) en/of @media (prefers-reduced-motion: reduce) { ::view-transition-group(*), ::view-transition-old(*), ::view-transition-new(*) { animation: none !important; } } -->
<div class="vtw">
<div class="vtw__box" data-thema="licht">
<div class="vtw__top">
<span class="vtw__logo">Bakkerij Mulder · kassa</span>
<div class="vtw__seg" role="group" aria-label="Weergave">
<button class="vtw__opt" type="button" data-t="licht" aria-pressed="true"><svg viewBox="0 0 24 24" aria-hidden="true"><circle cx="12" cy="12" r="4.5"/><path d="M12 2.5v2M12 19.5v2M2.5 12h2M19.5 12h2M5.3 5.3l1.4 1.4M17.3 17.3l1.4 1.4M5.3 18.7l1.4-1.4M17.3 6.7l1.4-1.4"/></svg>Licht</button>
<button class="vtw__opt" type="button" data-t="donker" aria-pressed="false"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M20 14.5A8 8 0 0 1 9.5 4a8 8 0 1 0 10.5 10.5z"/></svg>Donker</button>
<button class="vtw__opt" type="button" data-t="systeem" aria-pressed="false"><svg viewBox="0 0 24 24" aria-hidden="true"><rect x="3" y="4.5" width="18" height="12" rx="1.5"/><path d="M9 20h6M12 16.5V20"/></svg>Systeem</button>
</div>
</div>
<div class="vtw__main">
<div class="vtw__kpi"><small>Omzet vandaag, di 7 okt</small><b>€ 2.184,50</b><span>+12% op vorige dinsdag</span></div>
<div class="vtw__chart" aria-hidden="true"><i style="height:48%"></i><i style="height:62%"></i><i style="height:55%"></i><i style="height:71%"></i><i style="height:88%"></i><i style="height:100%"></i><i class="is-nu" style="height:66%"></i></div>
</div>
<div class="vtw__foot"><span>142 bonnen</span><span>Gem. € 15,38</span><span>Pin 81%</span></div>
</div>
<span class="vtw__sr" aria-live="polite"></span>
</div>
</div>/* Thema-wissel met cirkel · NedDev · eigen werk. */
.vtw{position:absolute;inset:0;background:#f4f3f1;font-family:'Switzer',system-ui,sans-serif}
.vtw__box{--vtw-bg:#fff;--vtw-fg:#0a0a0a;--vtw-mut:rgba(10,10,10,.58);--vtw-line:rgba(10,10,10,.1);--vtw-seg:#f4f3f1;--vtw-bar:#d9d6d1;position:absolute;inset:12px;display:flex;flex-direction:column;gap:8px;padding:11px 13px;border-radius:6px;background:var(--vtw-bg);color:var(--vtw-fg);box-shadow:inset 0 0 0 1px var(--vtw-line)}
.vtw__box[data-thema="donker"]{--vtw-bg:#121212;--vtw-fg:#f4f3f1;--vtw-mut:rgba(244,243,241,.62);--vtw-line:rgba(244,243,241,.14);--vtw-seg:#1f1f1f;--vtw-bar:#3a3a3a}
.vtw__top{display:flex;justify-content:space-between;align-items:center;gap:8px}
.vtw__logo{font-weight:700;font-size:12.5px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0}
.vtw__seg{display:flex;gap:2px;padding:2px;border-radius:999px;background:var(--vtw-seg);flex:none}
.vtw__opt{all:unset;box-sizing:border-box;display:inline-flex;align-items:center;gap:4px;font-size:11px;font-weight:500;padding:4px 8px;border-radius:999px;color:var(--vtw-mut);cursor:pointer;transition:color .15s,background-color .15s}
.vtw__opt svg{width:12px;height:12px;fill:none;stroke:currentColor;stroke-width:1.9;stroke-linecap:round;stroke-linejoin:round}
.vtw__opt:hover{color:var(--vtw-fg)}
.vtw__opt[aria-pressed="true"]{background:var(--vtw-bg);color:var(--vtw-fg);box-shadow:0 1px 2px rgba(10,10,10,.18)}
.vtw__opt:focus-visible{outline:2px solid #F5480F;outline-offset:1px}
.vtw__main{flex:1;min-height:0;display:flex;align-items:flex-end;justify-content:space-between;gap:14px}
.vtw__kpi small{display:block;font-size:10.5px;color:var(--vtw-mut)}
.vtw__kpi b{display:block;font-family:'JetBrains Mono',monospace;font-size:22px;font-variant-numeric:tabular-nums;letter-spacing:-.02em;margin:3px 0 2px}
.vtw__kpi span{font-size:10.5px;color:#1f8a4c}
.vtw__box[data-thema="donker"] .vtw__kpi span{color:#5fd08f}
.vtw__chart{flex:1;max-width:170px;height:70%;display:flex;align-items:flex-end;gap:4px}
.vtw__chart i{flex:1;background:var(--vtw-bar);border-radius:2px 2px 0 0}
.vtw__chart i.is-nu{background:#F5480F}
.vtw__foot{display:flex;gap:12px;border-top:1px solid var(--vtw-line);padding-top:7px;font:500 10px 'JetBrains Mono',monospace;color:var(--vtw-mut);white-space:nowrap}
.vtw__sr{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}
@media (max-width:420px){.vtw__box{inset:8px;padding:9px 10px}.vtw__logo{font-size:11px}.vtw__opt{padding:4px 6px;font-size:10.5px}.vtw__opt svg{display:none}.vtw__kpi b{font-size:18px}.vtw__foot span:last-child{display:none}}
::view-transition-group(vtw-box){animation:none}
::view-transition-old(vtw-box),::view-transition-new(vtw-box){animation:none;mix-blend-mode:normal}// Thema-wissel met cirkel · NedDev · eigen werk.
// root = het element waarin de HTML staat
function init(root){
var w=root.querySelector('.vtw');if(!w)return;var box=w.querySelector('.vtw__box'),opts=[].slice.call(w.querySelectorAll('.vtw__opt')),sr=w.querySelector('.vtw__sr');
var rm=matchMedia('(prefers-reduced-motion: reduce)'),dark=matchMedia('(prefers-color-scheme: dark)');var keuze='licht',busy=false;
function resolve(k){return k==='systeem'?(dark.matches?'donker':'licht'):k;}
function setPressed(){opts.forEach(function(o){o.setAttribute('aria-pressed',o.dataset.t===keuze?'true':'false');});}
function pick(btn){var k=btn.dataset.t;if(k===keuze||busy)return;var nieuw=resolve(k),oud=box.dataset.thema;keuze=k;
var upd=function(){box.dataset.thema=nieuw;setPressed();};sr.textContent='Weergave: '+btn.textContent.trim()+(k==='systeem'?' ('+nieuw+')':'');
if(nieuw===oud||!document.startViewTransition||rm.matches){upd();return;}
var b=box.getBoundingClientRect(),r=btn.getBoundingClientRect();var cx=r.left+r.width/2-b.left,cy=r.top+r.height/2-b.top;var R=Math.hypot(Math.max(cx,b.width-cx),Math.max(cy,b.height-cy));
busy=true;box.style.viewTransitionName='vtw-box';var t=document.startViewTransition(upd);
t.ready.then(function(){document.documentElement.animate({clipPath:['circle(0px at '+cx+'px '+cy+'px)','circle('+R+'px at '+cx+'px '+cy+'px)']},{duration:520,easing:'cubic-bezier(.4,0,.2,1)',pseudoElement:'::view-transition-new(vtw-box)'});}).catch(function(){});
t.finished.finally(function(){box.style.viewTransitionName='';busy=false;});}
opts.forEach(function(o){o.addEventListener('click',function(){pick(o);});});
dark.addEventListener&&dark.addEventListener('change',function(){if(keuze==='systeem'){box.dataset.thema=resolve('systeem');}});
}
init(document.querySelector('.jouw-container'));
More components
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 →