Replace native confirm() with a branded modal on every delete action, both tools

This commit is contained in:
2026-08-24 16:32:44 -07:00
parent 18da00addf
commit 88f2bf3782
2 changed files with 127 additions and 21 deletions

View File

@@ -214,6 +214,13 @@
opacity:0; pointer-events:none; transition:opacity .2s;
}
.toast.show{opacity:1;}
.btn.danger{background:var(--danger); color:#fff; border:none;}
.btn.danger:hover{background:#b3121d;}
.confirm-backdrop{position:fixed; inset:0; background:rgba(22,22,22,.5); display:flex; align-items:center; justify-content:center; z-index:70; padding:20px;}
.confirm-card{background:var(--layer); border:1px solid var(--border); border-left:4px solid var(--danger); padding:22px 26px; max-width:420px; width:100%;}
.confirm-card h3{font-size:16px; font-weight:600; margin-bottom:8px;}
.confirm-card p{font-size:14px; color:var(--text-secondary); line-height:1.5; margin-bottom:20px;}
.confirm-actions{display:flex; justify-content:flex-end; gap:10px;}
@media (max-width:1100px){ .board{grid-template-columns:repeat(2,1fr);} .reg-form{grid-template-columns:1fr 1fr;} }
@media (prefers-reduced-motion: reduce){ *{transition:none !important;} }
</style>
@@ -502,8 +509,12 @@ document.getElementById('panel-board').addEventListener('click', e=>{
if(item){ item.b = (item.b === t.dataset.b) ? '' : t.dataset.b; save(); renderScope(); }
}
if(t.dataset && t.dataset.del){
S.scope = S.scope.filter(i=>i.id!==t.dataset.del);
save(); renderScope();
const iid = t.dataset.del;
confirmModal({
title: 'Remove item?',
message: 'Remove this item from the Scope Boundary Board? This cannot be undone.',
confirmLabel: 'Remove item'
}, ()=>{ S.scope = S.scope.filter(i=>i.id!==iid); save(); renderScope(); });
}
});
@@ -553,9 +564,16 @@ document.getElementById('rankList').addEventListener('click', e=>{
[S.rank[i], S.rank[i+1]] = [S.rank[i+1], S.rank[i]];
save(); renderRank();
} else if(t.dataset.rdel !== undefined){
S.rank.splice(+t.dataset.rdel, 1);
if(S.cutAfter > S.rank.length) S.cutAfter = S.rank.length;
save(); renderRank();
const idx = +t.dataset.rdel;
confirmModal({
title: 'Remove item?',
message: 'Remove this item from the priority ranking? This cannot be undone.',
confirmLabel: 'Remove item'
}, ()=>{
S.rank.splice(idx, 1);
if(S.cutAfter > S.rank.length) S.cutAfter = S.rank.length;
save(); renderRank();
});
}
});
@@ -609,8 +627,12 @@ document.getElementById('btnAddDecision').addEventListener('click', ()=>{
document.getElementById('regTableWrap').addEventListener('click', e=>{
if(e.target.dataset.ddel !== undefined){
S.decisions.splice(+e.target.dataset.ddel, 1);
save(); renderRegistry();
const idx = +e.target.dataset.ddel;
confirmModal({
title: 'Remove decision?',
message: 'Remove this decision from the registry? This cannot be undone.',
confirmLabel: 'Remove decision'
}, ()=>{ S.decisions.splice(idx, 1); save(); renderRegistry(); });
}
});
@@ -719,10 +741,14 @@ document.getElementById('btnExport').addEventListener('click', ()=>{
/* ================= RESET ================= */
document.getElementById('btnReset').addEventListener('click', ()=>{
if(confirm('Reset all four tools to their starting state? This clears everything entered in this meeting.')){
confirmModal({
title: 'Reset everything?',
message: 'Reset all four tools to their starting state? This clears everything entered in this meeting.',
confirmLabel: 'Reset'
}, ()=>{
S = JSON.parse(JSON.stringify(DEFAULT_STATE));
save(); renderAll(); toast('Reset complete');
}
});
});
/* ================= TOAST ================= */
@@ -735,6 +761,27 @@ function toast(msg){
toastTimer = setTimeout(()=>t.classList.remove('show'), 2000);
}
function confirmModal(opts, onConfirm){
const backdrop = document.createElement('div');
backdrop.className = 'confirm-backdrop';
backdrop.innerHTML = `<div class="confirm-card" role="alertdialog" aria-modal="true" aria-labelledby="confirmTitle">
<h3 id="confirmTitle">${esc(opts.title || 'Remove this?')}</h3>
<p>${esc(opts.message || 'This cannot be undone.')}</p>
<div class="confirm-actions">
<button class="btn ghost" data-cc="cancel">Cancel</button>
<button class="btn danger" data-cc="ok">${esc(opts.confirmLabel || 'Delete')}</button>
</div>
</div>`;
document.body.appendChild(backdrop);
function close(){ document.removeEventListener('keydown', onKey); backdrop.remove(); }
function onKey(e){ if(e.key==='Escape') close(); }
document.addEventListener('keydown', onKey);
backdrop.addEventListener('click', e=>{ if(e.target===backdrop) close(); });
backdrop.querySelector('[data-cc="cancel"]').addEventListener('click', close);
backdrop.querySelector('[data-cc="ok"]').addEventListener('click', ()=>{ close(); onConfirm(); });
backdrop.querySelector('[data-cc="ok"]').focus();
}
function renderAll(){ renderScope(); renderRank(); renderRegistry(); renderReady(); }
renderAll();
</script>