fix: improve web chat scroll and text

This commit is contained in:
Peter Steinberger
2026-01-01 21:09:28 +01:00
parent 15fd030fa4
commit f6c0618596
5 changed files with 18 additions and 1 deletions

View File

@@ -12,6 +12,7 @@
--chrome: rgba(10, 14, 20, 0.75); --chrome: rgba(10, 14, 20, 0.75);
--chrome-strong: rgba(10, 14, 20, 0.82); --chrome-strong: rgba(10, 14, 20, 0.82);
--text: rgba(246, 248, 252, 0.95); --text: rgba(246, 248, 252, 0.95);
--chat-text: rgba(246, 248, 252, 0.88);
--muted: rgba(210, 218, 230, 0.62); --muted: rgba(210, 218, 230, 0.62);
--border: rgba(255, 255, 255, 0.08); --border: rgba(255, 255, 255, 0.08);
--accent: #ff7a3d; --accent: #ff7a3d;
@@ -40,6 +41,7 @@
--chrome: rgba(255, 255, 255, 0.72); --chrome: rgba(255, 255, 255, 0.72);
--chrome-strong: rgba(255, 255, 255, 0.82); --chrome-strong: rgba(255, 255, 255, 0.82);
--text: rgba(20, 24, 36, 0.96); --text: rgba(20, 24, 36, 0.96);
--chat-text: rgba(20, 24, 36, 0.82);
--muted: rgba(50, 58, 76, 0.6); --muted: rgba(50, 58, 76, 0.6);
--border: rgba(16, 24, 40, 0.12); --border: rgba(16, 24, 40, 0.12);
--accent: #ff7a3d; --accent: #ff7a3d;

View File

@@ -504,6 +504,7 @@
white-space: pre-wrap; white-space: pre-wrap;
overflow-wrap: anywhere; overflow-wrap: anywhere;
word-break: break-word; word-break: break-word;
color: var(--chat-text);
} }
.chat-stamp { .chat-stamp {

View File

@@ -213,6 +213,7 @@ export function renderApp(state: AppViewState) {
onPasswordChange: (next) => (state.password = next), onPasswordChange: (next) => (state.password = next),
onSessionKeyChange: (next) => { onSessionKeyChange: (next) => {
state.sessionKey = next; state.sessionKey = next;
state.chatMessage = "";
state.applySettings({ ...state.settings, sessionKey: next }); state.applySettings({ ...state.settings, sessionKey: next });
}, },
onRefresh: () => state.loadOverview(), onRefresh: () => state.loadOverview(),

View File

@@ -168,6 +168,7 @@ export class ClawdisApp extends LitElement {
client: GatewayBrowserClient | null = null; client: GatewayBrowserClient | null = null;
private chatScrollFrame: number | null = null; private chatScrollFrame: number | null = null;
private chatScrollTimeout: number | null = null;
private nodesPollInterval: number | null = null; private nodesPollInterval: number | null = null;
basePath = ""; basePath = "";
private popStateHandler = () => this.onPopState(); private popStateHandler = () => this.onPopState();
@@ -202,6 +203,7 @@ export class ClawdisApp extends LitElement {
(changed.has("chatMessages") || (changed.has("chatMessages") ||
changed.has("chatStream") || changed.has("chatStream") ||
changed.has("chatLoading") || changed.has("chatLoading") ||
changed.has("chatMessage") ||
changed.has("tab")) changed.has("tab"))
) { ) {
this.scheduleChatScroll(); this.scheduleChatScroll();
@@ -241,11 +243,21 @@ export class ClawdisApp extends LitElement {
private scheduleChatScroll() { private scheduleChatScroll() {
if (this.chatScrollFrame) cancelAnimationFrame(this.chatScrollFrame); if (this.chatScrollFrame) cancelAnimationFrame(this.chatScrollFrame);
if (this.chatScrollTimeout != null) {
clearTimeout(this.chatScrollTimeout);
this.chatScrollTimeout = null;
}
this.chatScrollFrame = requestAnimationFrame(() => { this.chatScrollFrame = requestAnimationFrame(() => {
this.chatScrollFrame = null; this.chatScrollFrame = null;
const container = this.querySelector(".chat-thread") as HTMLElement | null; const container = this.querySelector(".chat-thread") as HTMLElement | null;
if (!container) return; if (!container) return;
container.scrollTop = container.scrollHeight; container.scrollTop = container.scrollHeight;
this.chatScrollTimeout = window.setTimeout(() => {
this.chatScrollTimeout = null;
const latest = this.querySelector(".chat-thread") as HTMLElement | null;
if (!latest) return;
latest.scrollTop = latest.scrollHeight;
}, 120);
}); });
} }

View File

@@ -46,6 +46,7 @@ export async function sendChat(state: ChatState) {
if (!msg) return; if (!msg) return;
state.chatSending = true; state.chatSending = true;
state.chatMessage = "";
state.lastError = null; state.lastError = null;
const runId = crypto.randomUUID(); const runId = crypto.randomUUID();
state.chatRunId = runId; state.chatRunId = runId;
@@ -57,10 +58,10 @@ export async function sendChat(state: ChatState) {
deliver: false, deliver: false,
idempotencyKey: runId, idempotencyKey: runId,
}); });
state.chatMessage = "";
} catch (err) { } catch (err) {
state.chatRunId = null; state.chatRunId = null;
state.chatStream = null; state.chatStream = null;
state.chatMessage = msg;
state.lastError = String(err); state.lastError = String(err);
} finally { } finally {
state.chatSending = false; state.chatSending = false;