Knop met bevestiging erboven New
For actions you do not want to trigger by accident, without a full dialog: clicking Cancel shows a small bubble right above the button saying "Are you sure?" with the choices No (gets focus, the safe option) and Yes. Escape, clicking elsewhere or tabbing away closes it; after Yes a line with Undo appears. For cancelling appointments, removing a line from a cart or pausing a subscription; with reduced motion the bubble appears without animation.
Intake fysiotherapie
Do 16 okt, 14:30 in Vlaardingen
Weet je het zeker?
How to use it
- Paste the HTML where the buttons 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.
<!-- Knop met bevestiging erboven · NedDev · eigen werk. -->
<div class="jouw-container">
<div class="kib">
<div class="kib__card">
<div class="kib__info"><p class="kib__what">Intake fysiotherapie</p><p class="kib__when">Do 16 okt, 14:30 in Vlaardingen</p></div>
<div class="kib__act">
<button class="kib__btn" type="button" aria-expanded="false" aria-controls="kib-pop">Annuleren</button>
<div class="kib__pop" id="kib-pop" role="group" aria-label="Annuleren bevestigen" hidden>
<p class="kib__q">Weet je het zeker?</p>
<div class="kib__opts"><button class="kib__no" type="button">Nee</button><button class="kib__yes" type="button">Ja, annuleer</button></div>
</div>
<button class="kib__undo" type="button" hidden>Ongedaan maken</button>
</div>
</div>
<p class="kib__st" role="status"></p>
</div>
</div>/* Knop met bevestiging erboven · NedDev · eigen werk. */
.kib{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:flex-end;gap:6px;padding:12px 12px 10px;background:#f4f3f1;font-family:'Switzer',sans-serif;color:#0a0a0a}
.kib *,.kib *::before,.kib *::after{box-sizing:border-box}
.kib__card{width:min(340px,100%);display:flex;align-items:center;justify-content:space-between;gap:12px;padding:12px 12px 12px 16px;background:#fff;border:1px solid #e2dfda;border-radius:8px}
.kib__info{min-width:0}
.kib__what{margin:0;font:600 15px/1.3 'Switzer',sans-serif;transition:color .2s ease}
.kib__when{margin:2px 0 0;font:400 13px/1.3 'Switzer',sans-serif;color:#5d5953}
.kib__card.is-gone .kib__what{color:#8a857d;text-decoration:line-through;text-decoration-color:#F5480F;text-decoration-thickness:2px}
.kib__act{position:relative;flex:none}
.kib__btn,.kib__undo{appearance:none;min-height:40px;margin:0;padding:0 14px;border:1px solid #0a0a0a;border-radius:4px;background:#fff;color:#0a0a0a;font:600 14px/1 'Switzer',sans-serif;cursor:pointer;transition:background-color .16s ease}
.kib__btn:hover,.kib__undo:hover{background:#e8e5e0}
.kib__btn[aria-expanded="true"]{background:#0a0a0a;color:#fff}
.kib__pop{position:absolute;right:0;bottom:calc(100% + 12px);width:206px;padding:12px;background:#0a0a0a;color:#fff;border-radius:8px;transform-origin:85% 100%;animation:kib-in .18s cubic-bezier(.3,.7,.3,1)}
.kib__pop::after{content:'';position:absolute;right:26px;bottom:-6px;width:12px;height:12px;background:#0a0a0a;transform:rotate(45deg)}
@keyframes kib-in{from{opacity:0;transform:translateY(4px) scale(.96)}to{opacity:1;transform:none}}
.kib__q{margin:0 0 10px;font:600 14px/1.3 'Switzer',sans-serif}
.kib__opts{display:flex;gap:8px}
.kib__no,.kib__yes{appearance:none;flex:1;min-height:36px;margin:0;padding:0 10px;border-radius:4px;font:600 13px/1 'Switzer',sans-serif;cursor:pointer;transition:background-color .16s ease}
.kib__no{border:1px solid #fff;background:#fff;color:#0a0a0a}
.kib__no:hover{background:#e8e5e0}
.kib__yes{flex:1.4;border:1px solid #F5480F;background:#F5480F;color:#0a0a0a}
.kib__yes:hover{background:#ff5d24}
.kib__btn:focus-visible,.kib__undo:focus-visible{outline:2px solid #F5480F;outline-offset:3px}
.kib__no:focus-visible,.kib__yes:focus-visible{outline:2px solid #fff;outline-offset:2px}
.kib__st{min-height:18px;margin:0;font:400 13px/1.35 'Switzer',sans-serif;color:#5d5953;text-align:center}
@media (max-width:400px){.kib__pop{width:222px;padding:10px;bottom:calc(100% + 10px)}.kib__q{margin-bottom:8px}.kib__no,.kib__yes{min-height:32px}}
@media (prefers-reduced-motion:reduce){.kib__pop{animation:none}}// Knop met bevestiging erboven · NedDev · eigen werk.
// root = het element waarin de HTML staat
function init(root){
var w=root.querySelector('.kib');if(!w)return;
var card=w.querySelector('.kib__card'),btn=w.querySelector('.kib__btn'),pop=w.querySelector('.kib__pop'),no=w.querySelector('.kib__no'),yes=w.querySelector('.kib__yes'),undo=w.querySelector('.kib__undo'),st=w.querySelector('.kib__st');
function open(){pop.hidden=false;btn.setAttribute('aria-expanded','true');no.focus();}
function close(f){if(pop.hidden)return;pop.hidden=true;btn.setAttribute('aria-expanded','false');if(f)btn.focus();}
btn.addEventListener('click',function(){pop.hidden?open():close(true);});
no.addEventListener('click',function(){close(true);});
yes.addEventListener('click',function(){close(false);card.classList.add('is-gone');btn.hidden=true;undo.hidden=false;undo.focus();st.textContent='Afspraak van donderdag 16 oktober geannuleerd.';});
undo.addEventListener('click',function(){card.classList.remove('is-gone');undo.hidden=true;btn.hidden=false;btn.focus();st.textContent='Afspraak staat weer gepland.';});
pop.addEventListener('keydown',function(e){if(e.key==='Escape'){e.preventDefault();close(true);}});
w.addEventListener('focusout',function(e){if(!pop.hidden&&!pop.contains(e.relatedTarget)&&e.relatedTarget!==btn)close(false);});
document.addEventListener('pointerdown',function(e){if(!pop.hidden&&!pop.contains(e.target)&&e.target!==btn)close(false);});
}
init(document.querySelector('.jouw-container'));
More buttons
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 →