suppoer multiple line input using textarea instead

This commit is contained in:
Faisal Amir 2023-11-11 17:22:54 +07:00
parent 45abf10424
commit ef3d89f33e
6 changed files with 65 additions and 16 deletions

View File

@ -9,3 +9,4 @@ export * from './badge'
export * from './tooltip'
export * from './modal'
export * from './command'
export * from './textarea'

View File

@ -13,6 +13,7 @@
@import './tooltip/styles.scss';
@import './modal/styles.scss';
@import './command/styles.scss';
@import './textarea/styles.scss';
.animate-spin {
animation: spin 1s linear infinite;

View File

@ -0,0 +1,21 @@
import * as React from 'react'
import { twMerge } from 'tailwind-merge'
export interface TextareaProps
extends React.TextareaHTMLAttributes<HTMLTextAreaElement> {}
const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(
({ className, ...props }, ref) => {
return (
<textarea
className={twMerge('textarea-input', className)}
ref={ref}
{...props}
/>
)
}
)
Textarea.displayName = 'Textarea'
export { Textarea }

View File

@ -0,0 +1,6 @@
.textarea-input {
@apply border-border placeholder:text-muted-foreground flex w-full rounded-md border bg-transparent px-3 py-2 transition-colors;
@apply disabled:cursor-not-allowed disabled:opacity-50;
@apply focus-visible:ring-secondary focus-visible:outline-none focus-visible:ring-1;
@apply file:border-0 file:bg-transparent file:font-medium;
}

View File

@ -80,8 +80,11 @@ const SimpleTextMessage: React.FC<Props> = ({
<BubbleLoader />
) : (
<>
<span
className={'message text-[15px] font-normal leading-relaxed'}
<div
className={twMerge(
'message flex flex-grow flex-col gap-y-2 text-[15px] font-normal leading-relaxed',
isUser && 'whitespace-pre-wrap break-words'
)}
// eslint-disable-next-line @typescript-eslint/naming-convention
dangerouslySetInnerHTML={{ __html: parsedText }}
/>

View File

@ -1,7 +1,7 @@
import { Fragment, useEffect } from 'react'
import { Fragment, useEffect, useRef } from 'react'
import { Model } from '@janhq/core/lib/types'
import { Input, Button, Badge } from '@janhq/uikit'
import { Button, Badge, Textarea } from '@janhq/uikit'
import { useAtom, useAtomValue } from 'jotai'
import { Trash2Icon } from 'lucide-react'
@ -54,13 +54,15 @@ const ChatScreen = () => {
const conversations = useAtomValue(userConversationsAtom)
const isEnableChat = (currentConvo && activeModel) || conversations.length > 0
const textareaRef = useRef<HTMLTextAreaElement>(null)
useEffect(() => {
getUserConversations()
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [])
const handleMessageChange = (value: string) => {
setCurrentPrompt(value)
const handleMessageChange = (e: React.ChangeEvent<HTMLTextAreaElement>) => {
setCurrentPrompt(e.target.value)
}
const handleSendMessage = async () => {
@ -71,6 +73,7 @@ const ChatScreen = () => {
await requestCreateConvo(activeModel as Model)
}
}
useEffect(() => {
if (isWaitingToSend && activeConversationId) {
setIsWaitingToSend(false)
@ -79,12 +82,24 @@ const ChatScreen = () => {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [waitingToSendMessage, activeConversationId])
const handleKeyDown = async (
event: React.KeyboardEvent<HTMLInputElement>
) => {
if (event.key === 'Enter') {
if (!event.shiftKey) {
event.preventDefault()
useEffect(() => {
if (textareaRef.current !== null) {
const scrollHeight = textareaRef.current.scrollHeight
if (currentPrompt.length === 0) {
textareaRef.current.style.height = '40px'
} else {
textareaRef.current.style.height = `${
scrollHeight < 40 ? 40 : scrollHeight
}px`
}
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [currentPrompt])
const handleKeyDown = async (e: React.KeyboardEvent<HTMLTextAreaElement>) => {
if (e.key === 'Enter') {
if (!e.shiftKey) {
e.preventDefault()
handleSendMessage()
}
}
@ -162,9 +177,9 @@ const ChatScreen = () => {
</div>
)}
<div className="mx-auto flex w-full flex-shrink-0 items-center justify-center space-x-4 p-4 lg:w-3/4">
<Input
type="text"
className="h-10"
<Textarea
className="min-h-10 h-10 max-h-16 resize-none pr-20"
ref={textareaRef}
onKeyDown={(e) => handleKeyDown(e)}
placeholder="Type your message ..."
disabled={
@ -173,7 +188,9 @@ const ChatScreen = () => {
activeModel._id !== currentConvo?.modelId
}
value={currentPrompt}
onChange={(e) => handleMessageChange(e.target.value)}
onChange={(e) => {
handleMessageChange(e)
}}
/>
<Button
size="lg"