Autogrow the textarea

This commit is contained in:
Justin 2022-08-30 11:22:36 -04:00
parent 3939e27827
commit 7535862a40
2 changed files with 62 additions and 18 deletions

View File

@ -1,9 +1,15 @@
import classNames from 'clsx'; import classNames from 'clsx';
import React from 'react'; import React, { useState } from 'react';
interface ITextarea extends Pick<React.TextareaHTMLAttributes<HTMLTextAreaElement>, 'maxLength' | 'onChange' | 'onKeyDown' | 'required' | 'disabled' | 'rows' | 'readOnly'> { interface ITextarea extends Pick<React.TextareaHTMLAttributes<HTMLTextAreaElement>, 'maxLength' | 'onChange' | 'onKeyDown' | 'required' | 'disabled' | 'rows' | 'readOnly'> {
/** Put the cursor into the input on mount. */ /** Put the cursor into the input on mount. */
autoFocus?: boolean, autoFocus?: boolean,
/** Allows the textarea height to grow while typing */
autoGrow?: boolean,
/** Used with "autoGrow". Sets a max number of rows. */
maxRows?: number,
/** Used with "autoGrow". Sets a min number of rows. */
minRows?: number,
/** The initial text in the input. */ /** The initial text in the input. */
defaultValue?: string, defaultValue?: string,
/** Internal input name. */ /** Internal input name. */
@ -23,12 +29,49 @@ interface ITextarea extends Pick<React.TextareaHTMLAttributes<HTMLTextAreaElemen
} }
/** Textarea with custom styles. */ /** Textarea with custom styles. */
const Textarea = React.forwardRef( const Textarea = React.forwardRef(({
({ isCodeEditor = false, hasError = false, isResizeable = true, ...props }: ITextarea, ref: React.ForwardedRef<HTMLTextAreaElement>) => { isCodeEditor = false,
hasError = false,
isResizeable = true,
onChange,
autoGrow = false,
maxRows = 10,
minRows = 1,
...props
}: ITextarea, ref: React.ForwardedRef<HTMLTextAreaElement>) => {
const [rows, setRows] = useState<number>(autoGrow ? 1 : 4);
const handleChange = (event: React.ChangeEvent<HTMLTextAreaElement>) => {
if (autoGrow) {
const textareaLineHeight = 20;
const previousRows = event.target.rows;
event.target.rows = minRows;
const currentRows = ~~(event.target.scrollHeight / textareaLineHeight);
if (currentRows === previousRows) {
event.target.rows = currentRows;
}
if (currentRows >= maxRows) {
event.target.rows = maxRows;
event.target.scrollTop = event.target.scrollHeight;
}
setRows(currentRows < maxRows ? currentRows : maxRows);
}
if (onChange) {
onChange(event);
}
};
return ( return (
<textarea <textarea
{...props} {...props}
ref={ref} ref={ref}
rows={rows}
onChange={handleChange}
className={classNames({ className={classNames({
'bg-white dark:bg-transparent shadow-sm block w-full sm:text-sm rounded-md text-gray-900 dark:text-gray-100 placeholder:text-gray-600 dark:placeholder:text-gray-600 border-gray-400 dark:border-gray-800 dark:ring-1 dark:ring-gray-800 focus:ring-primary-500 focus:border-primary-500 dark:focus:ring-primary-500 dark:focus:border-primary-500': 'bg-white dark:bg-transparent shadow-sm block w-full sm:text-sm rounded-md text-gray-900 dark:text-gray-100 placeholder:text-gray-600 dark:placeholder:text-gray-600 border-gray-400 dark:border-gray-800 dark:ring-1 dark:ring-gray-800 focus:ring-primary-500 focus:border-primary-500 dark:focus:ring-primary-500 dark:focus:border-primary-500':
true, true,

View File

@ -219,7 +219,6 @@ const ChatBox: React.FC<IChatBox> = ({ chat, onSetInputRef, autosize, inputRef }
<HStack alignItems='center' justifyContent='between' space={4}> <HStack alignItems='center' justifyContent='between' space={4}>
<div className='flex-grow'> <div className='flex-grow'>
<Textarea <Textarea
rows={1}
autoFocus autoFocus
ref={inputRef} ref={inputRef}
placeholder={intl.formatMessage(messages.placeholder)} placeholder={intl.formatMessage(messages.placeholder)}
@ -227,6 +226,8 @@ const ChatBox: React.FC<IChatBox> = ({ chat, onSetInputRef, autosize, inputRef }
value={content} value={content}
onChange={handleContentChange} onChange={handleContentChange}
isResizeable={false} isResizeable={false}
autoGrow
maxRows={5}
/> />
</div> </div>