ui: refocus message input after chat generation completes

- Add ref prop to ExpandableTextarea to expose the underlying textarea
- Track streaming state transitions in ChatInterface and refocus the
  input via $effect when isStreaming flips to false
This commit is contained in:
Benson Wong
2026-06-28 04:16:23 +00:00
parent a0578f0007
commit e46cbeb2bf
2 changed files with 13 additions and 0 deletions
@@ -37,6 +37,7 @@
let reasoningStartTime = $state<number>(0);
let abortController = $state<AbortController | null>(null);
let messagesContainer: HTMLDivElement | undefined = $state();
let inputRef: HTMLTextAreaElement | null = $state(null);
let showSettings = $state(false);
let attachedImages = $state<string[]>([]);
let fileInput = $state<HTMLInputElement | null>(null);
@@ -49,6 +50,14 @@
playgroundStores.chatStreaming.set(isStreaming);
});
let wasStreaming = $state(false);
$effect(() => {
if (wasStreaming && !isStreaming) {
inputRef?.focus();
}
wasStreaming = isStreaming;
});
function handleMessagesScroll() {
if (!messagesContainer) return;
const { scrollTop, scrollHeight, clientHeight } = messagesContainer;
@@ -454,6 +463,7 @@
/>
<ExpandableTextarea
bind:ref={inputRef}
bind:value={userInput}
placeholder="Type a message..."
rows={3}
@@ -6,6 +6,7 @@
interface Props {
value: string;
ref?: HTMLTextAreaElement | null;
placeholder?: string;
rows?: number;
disabled?: boolean;
@@ -14,6 +15,7 @@
let {
value = $bindable(),
ref = $bindable(null),
placeholder = "",
rows = 3,
disabled = false,
@@ -57,6 +59,7 @@
<div class="group relative flex min-h-0 flex-1 items-stretch">
<Textarea
class="resize-none pr-10"
bind:ref
{placeholder}
{rows}
bind:value