Add inline button confirmations for Reset Chat and Restart

keyboardstaff committed Dec 29, 2025 at 05:08 UTC 9fe10807054f16467b49d99a44e6c3ec12f045e8
2 files changed +35 -20
webui/components/sidebar/top-section/quick-actions.html
+13 -12
@@ -8,21 +8,12 @@
8
9 <body>
10 <div class="config-section" x-data>
11 - <button class="config-button" id="resetChat" @click="$store.chats.resetChat()">Reset Chat</button>
11 + <button class="config-button" id="resetChat" @click="$confirmClick($event, () => $store.chats.resetChat())">Reset Chat</button>
12 <button class="config-button" id="newChat" @click="$store.chats.newChat()">New Chat</button>
13 <button class="config-button" id="loadChats" @click="$store.chats.loadChats()">Load Chat</button>
14 <button class="config-button" id="loadChat" @click="$store.chats.saveChat()">Save Chat</button>
15 - <button class="config-button" id="restart" @click="$store.chats.restart()">Restart</button>
16 - <button class="config-button" id="settings" @click="settingsModalProxy.openModal()"><svg
17 - xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="-5.0 -17.0 110.0 135.0" fill="currentColor" width="24"
18 - height="24">
19 - <path
20 - d="m52.301 90.102h-4.1016c-3 0-5 0-6.8984-1.3984-1.8984-1.3984-2.5-3.3008-3.5-6.1016l-1.1016-3.6016c-0.19922-0.60156-0.69922-1.1992-1.3984-1.6016l-1.1016-0.60156c-0.60156-0.30078-1.5-0.39844-2.3008-0.19922l-4.3008 1.1992c-3.1016 0.89844-5.1016 1.5-7.3984 0.5-2.3008-0.89844-3.3984-2.8008-5-5.6016l-1.8008-3.1016c-1.5-2.5-2.5-4.3008-2.3008-6.6992 0.19922-2.3984 1.6016-3.8008 3.6016-6.1016l3.8008-4.1992c0.19922-0.19922 0.60156-1.3984 0.60156-2.6016 0-1.1016-0.5-2.3008-0.80078-2.6992l-3.6016-4c-2-2.1992-3.3008-3.6992-3.6016-6.1016-0.19922-2.3984 0.80078-4.1992 2.3008-6.6992l1.8008-3.1016c1.6016-2.8008 2.6992-4.6016 5-5.6016 2.3008-0.89844 4.3008-0.39844 7.3984 0.5l4.3984 1.1992c0.69922 0.10156 1.5 0 2.3008-0.30078l1.1016-0.60156c0.5-0.30078 1-0.89844 1.3008-1.6992l1.1992-3.5c0.89844-2.8008 1.6016-4.6992 3.5-6.1016 1.8984-1.3984 3.8984-1.3984 6.8984-1.3984h4.1016c3 0 5 0 6.8984 1.3984 1.8984 1.3984 2.5 3.1992 3.5 6.1016l1.1992 3.6016c0.19922 0.60156 0.69922 1.1992 1.3984 1.6016l1.1016 0.60156c0.60156 0.30078 1.5 0.39844 2.3008 0.19922l4.3008-1.1992c3.1016-0.89844 5.1016-1.5 7.3984-0.5 2.3008 0.89844 3.3984 2.8008 5 5.5l1.8008 3.1016c1.3984 2.5 2.5 4.3008 2.3008 6.6992-0.19922 2.3984-1.6016 3.8008-3.6016 6.1016l-3.9961 4.4062c-0.19922 0.19922-0.60156 1.3984-0.60156 2.6016 0 1.1016 0.5 2.3008 0.80078 2.6992l3.6016 4c2 2.1992 3.3008 3.6992 3.6016 6.1016 0.19922 2.3984-0.80078 4.1992-2.3008 6.6992l-1.8008 3.1016c-1.6016 2.8008-2.6992 4.6016-5 5.6016-2.3008 0.89844-4.3984 0.39844-7.3984-0.5l-4.3984-1.1992c-0.69922-0.10156-1.5 0-2.3008 0.30078l-1.1016 0.60156c-0.5 0.30078-1 0.89844-1.3008 1.6992l-1.1992 3.5c-0.89844 2.8008-1.6016 4.6992-3.5 6.1016-1.8008 1.293-3.8008 1.293-6.8008 1.293zm-6.6016-7.3008c0.5 0.10156 1.6016 0.10156 2.6016 0.10156h4.1016c1 0 2 0 2.6016-0.10156 0.19922-0.5 0.60156-1.5 0.89844-2.3984l1.1992-3.6016c0.89844-2.3008 2.3984-4.1992 4.3984-5.3984l1.3984-0.80078c2.3984-1.3008 5.1016-1.6016 7.6016-1l4.6016 1.3008c1 0.30078 2.1016 0.60156 2.6992 0.69922 0.30078-0.5 0.89844-1.5 1.3984-2.3984l1.8008-3.1016c0.5-0.80078 1-1.8008 1.1992-2.3008-0.30078-0.39844-1-1.1992-1.6992-2l-3.8008-4.1992c-1.6016-2-2.5-4.8008-2.5-7.3984 0-2.6016 0.89844-5.3984 2.3008-7.3008l3.8984-4.3984c0.69922-0.69922 1.3984-1.5 1.6992-2-0.19922-0.5-0.80078-1.3984-1.1992-2.3008l-1.8984-3.1016c-0.5-0.89844-1.1016-1.8984-1.3984-2.3984-0.60156 0.10156-1.6992 0.39844-2.6992 0.69922l-4.3984 1.3008c-2.6992 0.60156-5.3008 0.30078-7.6016-0.89844l-1.4023-0.80469c-2.1016-1.3984-3.6016-3.1992-4.3984-5.3984l-1.3008-3.8008c-0.30078-0.89844-0.60156-1.8984-0.89844-2.3984-0.5-0.10156-1.6016-0.10156-2.6016-0.10156h-4.1016c-1 0-2 0-2.6016 0.10156-0.19922 0.5-0.60156 1.5-0.89844 2.3984l-1.1992 3.6016c-0.89844 2.3008-2.3984 4.1992-4.3984 5.3984l-1.3984 0.80078c-2.3984 1.3008-5.1016 1.6016-7.6016 1l-4.6016-1.3008c-1-0.30078-2.1016-0.60156-2.6992-0.69922-0.30078 0.5-0.89844 1.5-1.3984 2.3984l-1.8008 3.1016c-0.5 0.80078-1 1.8008-1.1992 2.3008 0.30078 0.39844 1 1.1992 1.6992 2l3.8008 4.1992c1.6016 2 2.5 4.8008 2.5 7.3984 0 2.6016-0.89844 5.3984-2.3008 7.3008l-3.8984 4.3984c-0.69922 0.69922-1.3984 1.5-1.6992 2 0.19922 0.5 0.80078 1.3984 1.1992 2.3008l1.8008 3.1016c0.5 0.89844 1.1016 1.8984 1.3984 2.3984 0.60156-0.10156 1.6992-0.39844 2.6992-0.69922l4.3984-1.1992c2.6992-0.60156 5.3008-0.30078 7.6016 0.89844l1.3984 0.80078c2.1016 1.3008 3.6016 3.1992 4.3984 5.3984l1.3008 3.8008c0.5 0.80078 0.80078 1.8008 1 2.3008z">
21 - </path>
22 - <path
23 - d="m50.301 66.5c-9 0-16.398-7.3008-16.398-16.398 0-9.1016 7.3008-16.398 16.398-16.398 9.1016 0 16.398 7.3008 16.398 16.398 0 9.0977-7.3984 16.398-16.398 16.398zm0-25.5c-5 0-9.1016 4.1016-9.1016 9.1016s4.1016 9.1016 9.1016 9.1016 9.1016-4.1016 9.1016-9.1016c-0.003906-5-4.1016-9.1016-9.1016-9.1016z">
24 - </path>
25 - </svg>Settings</button>
15 + <button class="config-button" id="restart" @click="$confirmClick($event, () => $store.chats.restart())">Restart</button>
16 + <button class="config-button" id="settings" @click="settingsModalProxy.openModal()"><span class="material-symbols-outlined">settings</span>Settings</button>
17 <button class="config-button" id="memory-dash"
18 @click="openModal('settings/memory/memory-dashboard.html');">Memory</button>
19 <button class="config-button" id="dashboard" @click="deselectChat()">Dashboard</button>
@@ -47,6 +38,10 @@
38 max-height: 2.3rem;
39 -webkit-transition: all var(--transition-speed), transform 0.1s ease-in-out;
40 transition: all var(--transition-speed), transform 0.1s ease-in-out;
41 + .material-symbols-outlined {
42 + font-size: 18px;
43 + margin-right: 2px;
44 + }
45 }
46
47 .config-button:hover {
@@ -58,6 +53,12 @@
53 opacity: 0.5;
54 }
55
56 + .config-button.confirming {
57 + display: flex;
58 + align-items: center;
59 + justify-content: center;
60 + }
61 +
62 #settings {
63 display: flex;
64 align-items: center;
webui/js/confirmClick.js
+22 -8
@@ -4,6 +4,7 @@
4 const CONFIRM_TIMEOUT = 2000;
5 const CONFIRM_CLASS = 'confirming';
6 const CONFIRM_ICON = 'check';
7 +const CONFIRM_TEXT = 'Confirm';
8
9 const buttonStates = new WeakMap();
10
@@ -21,11 +22,13 @@ export function confirmClick(event, action) {
22 action();
23 } else {
24 const iconEl = button.querySelector('.material-symbols-outlined, .material-icons-outlined');
24 - const originalIcon = iconEl?.textContent?.trim();
25 + const isIconButton = iconEl && button.textContent.trim() === iconEl.textContent.trim();
26
27 const newState = {
28 confirming: true,
28 - originalIcon,
29 + isIconButton,
30 + originalIcon: iconEl?.textContent?.trim(),
31 + originalHTML: isIconButton ? null : button.innerHTML,
32 timeoutId: setTimeout(() => {
33 resetButton(button, newState);
34 buttonStates.delete(button);
@@ -33,11 +36,18 @@ export function confirmClick(event, action) {
36 };
37
38 buttonStates.set(button, newState);
36 -
37 - // Apply confirming state
39 button.classList.add(CONFIRM_CLASS);
39 - if (iconEl) {
40 +
41 + if (isIconButton && iconEl) {
42 + // Icon-only button: just swap icon
43 iconEl.textContent = CONFIRM_ICON;
44 + } else {
45 + // Text button: show icon + optional "Confirm" text
46 + const originalText = button.textContent.trim();
47 + const confirmContent = originalText.length >= 4
48 + ? `<span class="material-symbols-outlined">${CONFIRM_ICON}</span>${CONFIRM_TEXT}`
49 + : `<span class="material-symbols-outlined">${CONFIRM_ICON}</span>`;
50 + button.innerHTML = confirmContent;
51 }
52 }
53 }
@@ -45,9 +55,13 @@ export function confirmClick(event, action) {
55 // Reset button to original state
56 function resetButton(button, state) {
57 button.classList.remove(CONFIRM_CLASS);
48 - const iconEl = button.querySelector('.material-symbols-outlined, .material-icons-outlined');
49 - if (iconEl && state.originalIcon) {
50 - iconEl.textContent = state.originalIcon;
58 + if (state.isIconButton) {
59 + const iconEl = button.querySelector('.material-symbols-outlined, .material-icons-outlined');
60 + if (iconEl && state.originalIcon) {
61 + iconEl.textContent = state.originalIcon;
62 + }
63 + } else if (state.originalHTML) {
64 + button.innerHTML = state.originalHTML;
65 }
66 }
67