chore: scroll in thinking mode, better buttons placement (#7289)

Signed-off-by: Ettore Di Giacinto <mudler@localai.io>
This commit is contained in:
Ettore Di Giacinto
2025-11-17 16:21:14 +01:00
committed by GitHub
parent fb834805db
commit 721c3f962b
4 changed files with 53 additions and 14 deletions

View File

@@ -90,6 +90,23 @@ function updateTokensPerSecond() {
}
}
function scrollThinkingBoxToBottom() {
// Find all thinking/reasoning message containers that are expanded
const thinkingBoxes = document.querySelectorAll('[data-thinking-box]');
thinkingBoxes.forEach(box => {
// Only scroll if the box is visible (expanded) and has overflow
if (box.offsetParent !== null && box.scrollHeight > box.clientHeight) {
box.scrollTo({
top: box.scrollHeight,
behavior: 'smooth'
});
}
});
}
// Make function available globally
window.scrollThinkingBoxToBottom = scrollThinkingBoxToBottom;
function stopRequest() {
if (currentAbortController) {
currentAbortController.abort();
@@ -996,6 +1013,7 @@ async function promptGPT(systemPrompt, input) {
if (now - lastThinkingScrollTime > THINKING_SCROLL_THROTTLE) {
lastThinkingScrollTime = now;
setTimeout(() => {
// Scroll main chat container
const chatContainer = document.getElementById('chat');
if (chatContainer) {
chatContainer.scrollTo({
@@ -1003,6 +1021,8 @@ async function promptGPT(systemPrompt, input) {
behavior: 'smooth'
});
}
// Scroll thinking box to bottom if it's expanded and scrollable
scrollThinkingBoxToBottom();
}, 100);
}
} else {
@@ -1166,8 +1186,8 @@ document.addEventListener("alpine:init", () => {
},
add(role, content, image, audio) {
const N = this.history.length - 1;
// For thinking messages, always create a new message
if (role === "thinking") {
// For thinking and reasoning messages, always create a new message
if (role === "thinking" || role === "reasoning") {
let c = "";
const lines = content.split("\n");
lines.forEach((line) => {
@@ -1209,6 +1229,14 @@ document.addEventListener("alpine:init", () => {
behavior: 'smooth'
});
}
// Also scroll thinking box if it's a thinking/reasoning message
if (role === "thinking" || role === "reasoning") {
setTimeout(() => {
if (typeof window.scrollThinkingBoxToBottom === 'function') {
window.scrollThinkingBoxToBottom();
}
}, 100);
}
const parser = new DOMParser();
const html = parser.parseFromString(
this.history[this.history.length - 1].html,

View File

@@ -178,6 +178,12 @@ SOFTWARE.
behavior: 'smooth'
});
}
// Also scroll thinking box if it's a thinking/reasoning message
if (role === "thinking" || role === "reasoning") {
if (typeof window.scrollThinkingBoxToBottom === 'function') {
window.scrollThinkingBoxToBottom();
}
}
}, 100);
const parser = new DOMParser();
const html = parser.parseFromString(
@@ -566,7 +572,12 @@ SOFTWARE.
x-transition
class="mt-2 pt-2 border-t border-[#38BDF8]/20"
>
<div class="text-[#E5E7EB] text-sm max-h-96 overflow-auto" x-html="message.html"></div>
<div
class="text-[#E5E7EB] text-sm max-h-96 overflow-auto"
x-html="message.html"
data-thinking-box
x-effect="if (message.expanded && message.html) { setTimeout(() => { if ($el.scrollHeight > $el.clientHeight) { $el.scrollTo({ top: $el.scrollHeight, behavior: 'smooth' }); } }, 50); }"
></div>
</div>
</div>
</div>

View File

@@ -346,7 +346,7 @@
<a href="/manage"
class="inline-flex items-center text-sm text-[#94A3B8] hover:text-[#E5E7EB] px-4 py-2 rounded-lg hover:bg-[#1E293B] transition-colors">
<i class="fas fa-cog mr-2"></i>
System
Installed Models and Backends
</a>
<a href="/import-model" class="inline-flex items-center text-sm text-[#94A3B8] hover:text-[#E5E7EB] px-4 py-2 rounded-lg hover:bg-[#1E293B] transition-colors">
<i class="fas fa-upload mr-2"></i>

View File

@@ -34,12 +34,15 @@
<a href="talk/" class="text-[#94A3B8] hover:text-[#E5E7EB] px-2 py-2 rounded-lg transition duration-300 ease-in-out hover:bg-[#1E293B] flex items-center group text-sm">
<i class="fa-solid fa-phone text-[#38BDF8] mr-1.5 text-sm group-hover:scale-110 transition-transform"></i>Talk
</a>
<a href="swagger/" class="text-[#94A3B8] hover:text-[#E5E7EB] px-2 py-2 rounded-lg transition duration-300 ease-in-out hover:bg-[#1E293B] flex items-center group text-sm">
<i class="fas fa-code text-[#38BDF8] mr-1.5 text-sm group-hover:scale-110 transition-transform"></i>API
</a>
<!-- System Dropdown -->
<div class="relative" @click.away="manageOpen = false">
<button @click="manageOpen = !manageOpen"
class="text-[#94A3B8] hover:text-[#E5E7EB] px-2 py-2 rounded-lg transition duration-300 ease-in-out hover:bg-[#1E293B] flex items-center group text-sm">
<i class="fas fa-cog text-[#38BDF8] mr-1.5 text-sm group-hover:scale-110 transition-transform"></i>System
<i class="fas fa-cog text-[#38BDF8] mr-1.5 text-sm group-hover:scale-110 transition-transform"></i>Settings
<i class="fas fa-chevron-down ml-1 text-xs transition-transform" :class="manageOpen ? 'rotate-180' : ''"></i>
</button>
<div x-show="manageOpen"
@@ -60,10 +63,7 @@
<i class="fa-solid fa-circle-nodes text-[#38BDF8] mr-2 text-xs"></i>Swarm
</a>
<a href="/manage" class="block text-[#94A3B8] hover:text-[#E5E7EB] hover:bg-[#101827] px-3 py-2 text-sm transition-colors flex items-center">
<i class="fas fa-cog text-[#38BDF8] mr-2 text-xs"></i>Management
</a>
<a href="swagger/" class="block text-[#94A3B8] hover:text-[#E5E7EB] hover:bg-[#101827] px-3 py-2 text-sm transition-colors flex items-center">
<i class="fas fa-code text-[#38BDF8] mr-2 text-xs"></i>API
<i class="fas fa-cog text-[#38BDF8] mr-2 text-xs"></i>System
</a>
</div>
</div>
@@ -82,7 +82,7 @@
<button @click="manageOpen = !manageOpen"
class="w-full text-left text-[#94A3B8] hover:text-[#E5E7EB] hover:bg-[#1E293B] px-3 py-2 rounded-lg transition duration-300 ease-in-out flex items-center justify-between text-sm">
<div class="flex items-center">
<i class="fas fa-cog text-[#38BDF8] mr-3 w-5 text-center text-sm"></i>System
<i class="fas fa-cog text-[#38BDF8] mr-3 w-5 text-center text-sm"></i>Settings
</div>
<i class="fas fa-chevron-down text-xs transition-transform" :class="manageOpen ? 'rotate-180' : ''"></i>
</button>
@@ -104,10 +104,7 @@
<i class="fa-solid fa-circle-nodes text-[#38BDF8] mr-3 w-5 text-center text-xs"></i>Swarm
</a>
<a href="/manage" class="block text-[#94A3B8] hover:text-[#E5E7EB] hover:bg-[#1E293B] pl-8 pr-3 py-2 rounded-lg transition duration-300 ease-in-out flex items-center text-sm">
<i class="fas fa-cog text-[#38BDF8] mr-3 w-5 text-center text-xs"></i>Management
</a>
<a href="swagger/" class="block text-[#94A3B8] hover:text-[#E5E7EB] hover:bg-[#1E293B] pl-8 pr-3 py-2 rounded-lg transition duration-300 ease-in-out flex items-center text-sm">
<i class="fas fa-code text-[#38BDF8] mr-3 w-5 text-center text-xs"></i>API
<i class="fas fa-cog text-[#38BDF8] mr-3 w-5 text-center text-xs"></i>System
</a>
</div>
</div>
@@ -124,6 +121,9 @@
<a href="talk/" class="block text-[#94A3B8] hover:text-[#E5E7EB] hover:bg-[#1E293B] px-3 py-2 rounded-lg transition duration-300 ease-in-out flex items-center text-sm">
<i class="fa-solid fa-phone text-[#38BDF8] mr-3 w-5 text-center text-sm"></i>Talk
</a>
<a href="swagger/" class="block text-[#94A3B8] hover:text-[#E5E7EB] hover:bg-[#1E293B] px-3 py-2 rounded-lg transition duration-300 ease-in-out flex items-center text-sm">
<i class="fas fa-code text-[#38BDF8] mr-3 w-5 text-center text-sm"></i>API
</a>
</div>
</div>
</div>