Skip to content

Commit

Permalink
Autosize textarea
Browse files Browse the repository at this point in the history
  • Loading branch information
Janaka-Steph committed Nov 4, 2023
1 parent 4c35880 commit 0276260
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 56 deletions.
30 changes: 21 additions & 9 deletions src/assets/css/prem-chat.css
Original file line number Diff line number Diff line change
Expand Up @@ -35,25 +35,37 @@
@apply bg-transparent cursor-pointer border border-grey-400 text-grey-200 w-full z-10 px-4 py-[6px] appearance-none;
}

.prem-chat-input input {
@apply bg-grey-700 text-white md:text-sm text-[13px] outline-none rounded-[29px] h-[57px] mt-[14px] py-2 md:pl-[33px] md:pr-16 pr-12 pl-4 w-full;
.autosize-textarea {
@apply bg-grey-700 text-white leading-6 text-sm outline-none rounded-[29px] h-14 mt-[14px] py-2 md:pl-[33px] md:pr-16 pr-12 pl-4 w-full min-h-14 max-h-40;
}

.prem-chat-input input:-webkit-autofill,
.prem-chat-input input:-webkit-autofill:hover,
.prem-chat-input input:-webkit-autofill:active,
.prem-chat-input input:-webkit-autofill:focus {
.autosize-textarea:empty {
line-height: 38px;
}

.autosize-textarea::placeholder {
line-height: 38px;
}

.autosize-textarea:-webkit-autofill,
.autosize-textarea:-webkit-autofill:hover,
.autosize-textarea:-webkit-autofill:active,
.autosize-textarea:-webkit-autofill:focus {
-webkit-text-fill-color: #302f32;
-webkit-box-shadow: 0 0 0 1000px #302f32 inset;
transition: background-color 5000s ease-in-out 0s;
}

.prem-chat-input img {
.autosize-textarea-container {
@apply relative;
}

.autosize-textarea-container img {
@apply bg-primary-light p-2 w-[35px] h-[35px] rounded-full stroke-white;
}

.prem-chat-input button {
@apply absolute md:right-[21px] right-[12px] top-[25px];
.autosize-textarea-container button {
@apply absolute md:right-[21px] right-[12px] bottom-4;
}

.prem-chat-bottom {
Expand Down
29 changes: 0 additions & 29 deletions src/modules/prem-chat/components/InputBox.tsx

This file was deleted.

47 changes: 29 additions & 18 deletions src/modules/prem-chat/components/PremChatContainer.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import Send from "assets/images/send.svg";
import clsx from "clsx";
import { useEffect, useRef, useState } from "react";
import BotReply from "shared/components/BotReply";
import UserReply from "shared/components/UserReply";
import usePremChatStream from "shared/hooks/usePremChatStream";
import { useMediaQuery, useWindowSize } from "usehooks-ts";

import useAutosizeTextArea from "../../../shared/hooks/useAutosizeTextarea";
import type { Message, PremChatContainerProps } from "../types";

import Header from "./Header";
import InputBox from "./InputBox";
import PremChatSidebar from "./PremChatSidebar";
import RegenerateButton from "./RegenerateButton";
import RightSidebar from "./RightSidebar";
Expand All @@ -23,7 +24,7 @@ const PremChatContainer = ({
const [rightSidebar, setRightSidebar] = useState(false);
const [hamburgerMenuOpen, setHamburgerMenu] = useState<boolean>(true);
const chatMessageListRef = useRef<HTMLDivElement>(null);
const inputRef = useRef<HTMLInputElement>(null);
const textAreaRef = useRef<HTMLTextAreaElement>(null);
const { height } = useWindowSize();
const responsiveMatches = useMediaQuery("(min-width: 768px)");

Expand All @@ -40,15 +41,17 @@ const PremChatContainer = ({
abort,
} = usePremChatStream(serviceId, serviceType, chatId || null);

useAutosizeTextArea(textAreaRef.current, question);

useEffect(() => {
if (chatMessageListRef.current) {
chatMessageListRef.current.scrollTop = chatMessageListRef.current.scrollHeight;
}
}, [chatMessages]);

useEffect(() => {
if (!isLoading && inputRef.current) {
inputRef.current.focus();
if (!isLoading && textAreaRef.current) {
textAreaRef.current.focus();
}
}, [isLoading]);

Expand Down Expand Up @@ -103,20 +106,28 @@ const PremChatContainer = ({
<RegenerateButton onRgenerateClick={onRegenerate} />
</div>
)}
<form className="text-center" onSubmit={onSubmit}>
<InputBox
question={question}
setQuestion={setQuestion}
disabled={isLoading || !model}
ref={inputRef}
placeholder={
isLoading
? "Fetching response..."
: model
? `Type a message or type "/" to select a prompt`
: "Please select a model to get started"
}
/>
<form onSubmit={onSubmit}>
<div className="autosize-textarea-container">
<textarea
autoComplete="off"
className="autosize-textarea"
onChange={(e) => setQuestion(e.target.value)}
placeholder={
isLoading
? "Fetching response..."
: model
? `Type a message or type "/" to select a prompt`
: "Please select a model to get started"
}
ref={textAreaRef}
rows={1}
value={question}
disabled={isLoading || !model}
/>
<button>
<img src={Send} alt="Send" />
</button>
</div>
</form>
</div>
</div>
Expand Down
18 changes: 18 additions & 0 deletions src/shared/hooks/useAutosizeTextarea.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { useEffect } from "react";

// Updates the height of a <textarea> when the value changes.
const useAutosizeTextArea = (textAreaRef: HTMLTextAreaElement | null, value: string) => {
useEffect(() => {
if (textAreaRef) {
// We need to reset the height momentarily to get the correct scrollHeight for the textarea
textAreaRef.style.height = "0px";
const scrollHeight = textAreaRef.scrollHeight;

// We then set the height directly, outside the render loop
// Trying to set this with state or a ref will product an incorrect value.
textAreaRef.style.height = scrollHeight + "px";
}
}, [textAreaRef, value]);
};

export default useAutosizeTextArea;
3 changes: 3 additions & 0 deletions tailwind.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ module.exports = {
fontFamily: {
sans: ["Pretendard", ...defaultTheme.fontFamily.sans],
},
minHeight: {
14: "3.5rem",
},
},
},
};

0 comments on commit 0276260

Please sign in to comment.