diff --git a/static/css/components.css b/static/css/components.css
index 497fe5e..0cf40a3 100644
--- a/static/css/components.css
+++ b/static/css/components.css
@@ -489,9 +489,9 @@
display: flex;
align-items: center;
justify-content: center;
- background: rgba(0, 0, 0, 0.72);
- backdrop-filter: blur(6px);
- -webkit-backdrop-filter: blur(6px);
+ background: color-mix(in srgb, var(--bg-void) 44%, transparent);
+ backdrop-filter: blur(2px);
+ -webkit-backdrop-filter: blur(2px);
}
.auth-card {
@@ -559,6 +559,27 @@
margin: 0;
}
+.confirm-card {
+ max-width: 420px;
+}
+
+.confirm-card__icon--danger {
+ color: var(--red);
+ background: color-mix(in srgb, var(--red) 12%, transparent);
+ border-color: color-mix(in srgb, var(--red) 30%, transparent);
+}
+
+.confirm-card__actions {
+ width: 100%;
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ gap: var(--space-3);
+}
+
+.confirm-card__actions .btn {
+ width: 100%;
+}
+
/* ── Quick shortcuts ─────────────────────────────────────────────────────── */
.shortcuts-container {
diff --git a/static/js/app.js b/static/js/app.js
index 210b9b2..8ceb7eb 100644
--- a/static/js/app.js
+++ b/static/js/app.js
@@ -27,6 +27,64 @@ export function toast(message, type = 'info') {
}, 3000);
}
+export function confirmDialog({
+ title,
+ message,
+ confirmText = 'Confirm',
+ cancelText = 'Cancel',
+ confirmClass = 'btn--danger',
+}) {
+ document.getElementById('confirm-modal')?.remove();
+
+ return new Promise((resolve) => {
+ const overlay = document.createElement('div');
+ overlay.id = 'confirm-modal';
+ overlay.className = 'auth-overlay';
+ overlay.tabIndex = -1;
+ overlay.innerHTML = `
+
+
+
${title}
+
${message}
+
+
+
+
+
+ `;
+
+ document.body.appendChild(overlay);
+
+ const cancelBtn = overlay.querySelector('[data-action="cancel"]');
+ const confirmBtn = overlay.querySelector('[data-action="confirm"]');
+
+ const close = (result) => {
+ overlay.remove();
+ resolve(result);
+ };
+
+ overlay.addEventListener('click', (e) => {
+ if (e.target === overlay) close(false);
+ });
+
+ cancelBtn.addEventListener('click', () => close(false));
+ confirmBtn.addEventListener('click', () => close(true));
+
+ overlay.addEventListener('keydown', (e) => {
+ if (e.key === 'Escape') close(false);
+ });
+
+ overlay.focus();
+ confirmBtn.focus();
+ });
+}
+
// ── Token auth modal ──────────────────────────────────────────────────────
function showTokenModal(onSuccess) {
diff --git a/static/js/instructions.js b/static/js/instructions.js
index 5ffcfe7..a0dffa1 100644
--- a/static/js/instructions.js
+++ b/static/js/instructions.js
@@ -6,7 +6,7 @@
import { state } from './state.js';
import { api } from './api.js';
-import { toast } from './app.js';
+import { confirmDialog, toast } from './app.js';
// ── SVG icon helpers ──────────────────────────────────────────────────────
@@ -137,7 +137,14 @@ function renderPendingCard(item, index) {
});
deleteBtn.addEventListener('click', async () => {
- if (!confirm('Delete this instruction?')) return;
+ const confirmed = await confirmDialog({
+ title: 'Delete instruction?',
+ message: 'This removes the pending instruction from the queue before any agent can consume it.',
+ confirmText: 'Delete Instruction',
+ cancelText: 'Keep Instruction',
+ });
+ if (!confirmed) return;
+
deleteBtn.disabled = true;
try {
await api.deleteInstruction(item.id);
@@ -215,7 +222,14 @@ export function initInstructions() {
// Clear history button
clearHistoryBtn.addEventListener('click', async () => {
- if (!confirm('Clear all consumed instruction history? This cannot be undone.')) return;
+ const confirmed = await confirmDialog({
+ title: 'Clear consumed history?',
+ message: 'This removes all consumed instructions from the history panel. This action cannot be undone.',
+ confirmText: 'Clear History',
+ cancelText: 'Keep History',
+ });
+ if (!confirmed) return;
+
clearHistoryBtn.disabled = true;
try {
const res = await api.clearConsumed();