Skip to content

Commit 3656c84

Browse files
committed
feat: textarea with adaptive height
1 parent a8a8bec commit 3656c84

File tree

5 files changed

+28
-108
lines changed

5 files changed

+28
-108
lines changed

app/calcTextareaHeight.js

-104
This file was deleted.

app/components/chat.tsx

+23-1
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ import chatStyle from "./chat.module.scss";
4141

4242
import { Input, Modal, showModal, showToast } from "./ui-lib";
4343

44+
import calcTextareaHeight from "../calcTextareaHeight";
45+
4446
const Markdown = dynamic(
4547
async () => memo((await import("./markdown")).Markdown),
4648
{
@@ -331,6 +333,10 @@ function useScrollToBottom() {
331333
export function Chat(props: {
332334
showSideBar?: () => void;
333335
sideBarShowing?: boolean;
336+
autoSize: {
337+
minRows: number;
338+
maxRows?: number;
339+
};
334340
}) {
335341
type RenderMessage = Message & { preview?: boolean };
336342

@@ -347,6 +353,7 @@ export function Chat(props: {
347353
const { submitKey, shouldSubmit } = useSubmitHandler();
348354
const { scrollRef, setAutoScroll } = useScrollToBottom();
349355
const [hitBottom, setHitBottom] = useState(false);
356+
const [textareaStyle, setTextareaStyle] = useState({});
350357

351358
const onChatBodyScroll = (e: HTMLElement) => {
352359
const isTouchBottom = e.scrollTop + e.clientHeight >= e.scrollHeight - 20;
@@ -380,6 +387,16 @@ export function Chat(props: {
380387
dom.scrollTop = dom.scrollHeight - dom.offsetHeight + paddingBottomNum;
381388
};
382389

390+
// textarea has an adaptive height
391+
const resizeTextarea = () => {
392+
const dom = inputRef.current;
393+
if (!dom) return;
394+
const { minRows, maxRows } = props.autoSize;
395+
setTimeout(() => {
396+
setTextareaStyle(calcTextareaHeight(dom, minRows, maxRows));
397+
}, 50);
398+
};
399+
383400
// only search prompts when user input is short
384401
const SEARCH_TEXT_LIMIT = 30;
385402
const onInput = (text: string) => {
@@ -504,6 +521,11 @@ export function Chat(props: {
504521
// eslint-disable-next-line react-hooks/exhaustive-deps
505522
}, []);
506523

524+
// Textarea Adaptive height
525+
useEffect(() => {
526+
resizeTextarea();
527+
});
528+
507529
return (
508530
<div className={styles.chat} key={session.id}>
509531
<div className={styles["window-header"]}>
@@ -659,8 +681,8 @@ export function Chat(props: {
659681
<textarea
660682
ref={inputRef}
661683
className={styles["chat-input"]}
684+
style={textareaStyle}
662685
placeholder={Locale.Chat.Input(submitKey)}
663-
rows={2}
664686
onInput={(e) => onInput(e.currentTarget.value)}
665687
value={userInput}
666688
onKeyDown={onInputKeyDown}

app/components/home.tsx

-2
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,6 @@ import dynamic from "next/dynamic";
2525
import { REPO_URL } from "../constant";
2626
import { ErrorBoundary } from "./error";
2727

28-
import calcTextareaHeight from "../calcTextareaHeight";
29-
3028
export function Loading(props: { noLogo?: boolean }) {
3129
return (
3230
<div className={styles["loading-content"]}>

app/utils.ts

+4
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,10 @@ export function isMobileScreen() {
5050
return window.innerWidth <= 600;
5151
}
5252

53+
export function isFirefox() {
54+
return /firefox/i.test(navigator.userAgent);
55+
}
56+
5357
export function selectOrCopy(el: HTMLElement, content: string) {
5458
const currentSelection = window.getSelection();
5559

tsconfig.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,6 @@
2323
"@/*": ["./*"]
2424
}
2525
},
26-
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
26+
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts", "app/calcTextareaHeight.ts"],
2727
"exclude": ["node_modules"]
2828
}

0 commit comments

Comments
 (0)