Focus input on submission and fix scroll (#441)

This commit is contained in:
Jeremy 2024-10-14 23:01:46 +05:30 committed by GitHub
parent 23660c5ad1
commit 2705d83d6c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 61 additions and 8 deletions

View file

@ -40,15 +40,16 @@ export function Chat({
> >
{messages.length === 0 && <Overview />} {messages.length === 0 && <Overview />}
{messages.map((message, index) => ( {messages.map((message) => (
<PreviewMessage <PreviewMessage
key={`${id}-${index}`} key={message.id}
role={message.role} role={message.role}
content={message.content} content={message.content}
attachments={message.experimental_attachments} attachments={message.experimental_attachments}
toolInvocations={message.toolInvocations} toolInvocations={message.toolInvocations}
/> />
))} ))}
<div <div
ref={messagesEndRef} ref={messagesEndRef}
className="shrink-0 min-w-[24px] min-h-[24px]" className="shrink-0 min-w-[24px] min-h-[24px]"

View file

@ -15,6 +15,7 @@ import { toast } from "sonner";
import { ArrowUpIcon, PaperclipIcon, StopIcon } from "./icons"; import { ArrowUpIcon, PaperclipIcon, StopIcon } from "./icons";
import { PreviewAttachment } from "./preview-attachment"; import { PreviewAttachment } from "./preview-attachment";
import useWindowSize from "./use-window-size";
import { Button } from "../ui/button"; import { Button } from "../ui/button";
import { Textarea } from "../ui/textarea"; import { Textarea } from "../ui/textarea";
@ -22,7 +23,7 @@ const suggestedActions = [
{ {
title: "What is the weather", title: "What is the weather",
label: "in San Francisco?", label: "in San Francisco?",
action: "what is the weather in San Francisco?", action: "What is the weather in San Francisco?",
}, },
{ {
title: "Answer like I'm 5,", title: "Answer like I'm 5,",
@ -61,6 +62,7 @@ export function MultimodalInput({
) => void; ) => void;
}) { }) {
const textareaRef = useRef<HTMLTextAreaElement>(null); const textareaRef = useRef<HTMLTextAreaElement>(null);
const { width } = useWindowSize();
useEffect(() => { useEffect(() => {
if (textareaRef.current) { if (textareaRef.current) {
@ -89,7 +91,11 @@ export function MultimodalInput({
}); });
setAttachments([]); setAttachments([]);
}, [attachments, handleSubmit, setAttachments]);
if (width && width > 768) {
textareaRef.current?.focus();
}
}, [attachments, handleSubmit, setAttachments, width]);
const uploadFile = async (file: File) => { const uploadFile = async (file: File) => {
const formData = new FormData(); const formData = new FormData();
@ -242,7 +248,8 @@ export function MultimodalInput({
<Button <Button
className="rounded-full p-1.5 h-fit absolute bottom-2 right-2 m-0.5" className="rounded-full p-1.5 h-fit absolute bottom-2 right-2 m-0.5"
onClick={(event) => { onClick={(event) => {
handleSubmit(event); event.preventDefault();
submitForm();
}} }}
disabled={input.length === 0 || uploadQueue.length > 0} disabled={input.length === 0 || uploadQueue.length > 0}
> >

View file

@ -19,6 +19,8 @@ export function useScrollToBottom<T extends HTMLElement>(): [
observer.observe(container, { observer.observe(container, {
childList: true, childList: true,
subtree: true, subtree: true,
attributes: true,
characterData: true,
}); });
return () => observer.disconnect(); return () => observer.disconnect();

View file

@ -0,0 +1,39 @@
"use client";
import { useState, useEffect } from "react";
interface WindowSize {
width: number | undefined;
height: number | undefined;
}
function useWindowSize(): WindowSize {
const [windowSize, setWindowSize] = useState<WindowSize>({
width: undefined,
height: undefined,
});
useEffect(() => {
// Handler to call on window resize
function handleResize() {
// Set window width/height to state
setWindowSize({
width: window.innerWidth,
height: window.innerHeight,
});
}
// Add event listener
window.addEventListener("resize", handleResize);
// Call handler right away so state gets updated with initial window size
handleResize();
// Remove event listener on cleanup
return () => window.removeEventListener("resize", handleResize);
}, []); // Empty array ensures that effect is only run on mount and unmount
return windowSize;
}
export default useWindowSize;

View file

@ -197,6 +197,10 @@ const SAMPLE = {
}, },
}; };
function n(num: number): number {
return Math.ceil(num);
}
export function Weather({ export function Weather({
weatherAtLocation = SAMPLE, weatherAtLocation = SAMPLE,
}: { }: {
@ -270,12 +274,12 @@ export function Weather({
)} )}
/> />
<div className="text-4xl font-medium text-blue-50"> <div className="text-4xl font-medium text-blue-50">
{weatherAtLocation.current.temperature_2m} {n(weatherAtLocation.current.temperature_2m)}
{weatherAtLocation.current_units.temperature_2m} {weatherAtLocation.current_units.temperature_2m}
</div> </div>
</div> </div>
<div className="text-blue-50">{`H:${currentHigh}° L:${currentLow}°`}</div> <div className="text-blue-50">{`H:${n(currentHigh)}° L:${n(currentLow)}°`}</div>
</div> </div>
<div className="flex flex-row justify-between"> <div className="flex flex-row justify-between">
@ -296,7 +300,7 @@ export function Weather({
)} )}
/> />
<div className="text-blue-50 text-sm"> <div className="text-blue-50 text-sm">
{displayTemperatures[index]} {n(displayTemperatures[index])}
{weatherAtLocation.hourly_units.temperature_2m} {weatherAtLocation.hourly_units.temperature_2m}
</div> </div>
</div> </div>