Skip to content

Commit

Permalink
Make StyledTextArea grow-able
Browse files Browse the repository at this point in the history
  • Loading branch information
m-rgba committed Nov 23, 2024
1 parent 469961c commit f2dd7d1
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ export const PlaygroundChat = ({
</PlaygroundContext.Provider>
)}
</div>
<div className="h-[125px] w-full" />
</Tailwind>
</Box>
<Box
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,27 @@ export const PlaygroundChatInput: React.FC<PlaygroundChatInputProps> = ({
const [addMessageRole, setAddMessageRole] = useState<'assistant' | 'user'>(
'user'
);
const [shouldReset, setShouldReset] = useState(false);

const handleReset = () => {
setShouldReset(true);
setTimeout(() => setShouldReset(false), 0);
};

const handleSend = (role: 'assistant' | 'user') => {
onSend(role);
handleReset();
};

const handleAdd = (role: 'assistant' | 'user', text: string) => {
onAdd(role, text);
handleReset();
};

const handleKeyDown = (event: React.KeyboardEvent<HTMLTextAreaElement>) => {
if (event.key === 'Enter' && (event.metaKey || event.ctrlKey)) {
event.preventDefault(); // Prevent default to avoid newline in textarea
onSend(addMessageRole);
event.preventDefault();
handleSend(addMessageRole);
}
};

Expand All @@ -47,6 +63,7 @@ export const PlaygroundChatInput: React.FC<PlaygroundChatInputProps> = ({
paddingTop: '8px',
backgroundColor: 'white',
width: settingsTab !== null ? 'calc(100% - 58px - 320px)' : 'calc(100% - 58px)',
zIndex: 100,
}}>
<Box
sx={{
Expand All @@ -66,6 +83,10 @@ export const PlaygroundChatInput: React.FC<PlaygroundChatInputProps> = ({
onChange={e => setChatText(e.target.value)}
value={chatText}
onKeyDown={handleKeyDown}
placeholder="Type your message here..."
autoGrow
maxHeight={160}
reset={shouldReset}
/>
<Box sx={{display: 'flex', justifyContent: 'space-between'}}>
<Box sx={{display: 'flex', gap: '8px'}}>
Expand Down Expand Up @@ -102,13 +123,13 @@ export const PlaygroundChatInput: React.FC<PlaygroundChatInputProps> = ({
variant="secondary"
size="medium"
startIcon="add-new"
onClick={() => onAdd(addMessageRole, chatText)}>
onClick={() => handleAdd(addMessageRole, chatText)}>
Add
</Button>
<Divider orientation="vertical" flexItem sx={{bgcolor: MOON_250}} />
<Button
size="medium"
onClick={() => onSend(addMessageRole)}
onClick={() => handleSend(addMessageRole)}
disabled={isLoading || chatText.trim() === ''}
startIcon={isLoading ? 'loading' : undefined}>
{isLoading ? 'Sending...' : 'Send'}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,63 @@ import {Tailwind} from '@wandb/weave/components/Tailwind';
import classNames from 'classnames';
import React, {forwardRef} from 'react';

type TextAreaProps = React.TextareaHTMLAttributes<HTMLTextAreaElement>;
type TextAreaProps = React.TextareaHTMLAttributes<HTMLTextAreaElement> & {
autoGrow?: boolean;
maxHeight?: string | number;
reset?: boolean;
};

export const StyledTextArea = forwardRef<HTMLTextAreaElement, TextAreaProps>(
({className, ...props}, ref) => {
({className, autoGrow, maxHeight, reset, ...props}, ref) => {
const textareaRef = React.useRef<HTMLTextAreaElement>(null);

React.useEffect(() => {
if (!autoGrow || !textareaRef.current) return;

const adjustHeight = () => {
const textarea = textareaRef.current;
if (!textarea) return;

// Disable resize when autoGrow is true
textarea.style.resize = 'none';

if (reset || textarea.value === '') {
textarea.style.height = 'auto';
return;
}

// Reset height to allow shrinking
textarea.style.height = 'auto';
const newHeight = textarea.scrollHeight;

// Apply max height if specified
if (maxHeight) {
textarea.style.height = `${Math.min(newHeight, typeof maxHeight === 'string' ? parseInt(maxHeight) : maxHeight)}px`;
textarea.style.overflowY = newHeight > (typeof maxHeight === 'string' ? parseInt(maxHeight) : maxHeight) ? 'auto' : 'hidden';
} else {
textarea.style.height = `${newHeight}px`;
textarea.style.overflowY = 'hidden';
}
};

const textarea = textareaRef.current;
textarea.addEventListener('input', adjustHeight);
adjustHeight(); // Initial adjustment

return () => textarea.removeEventListener('input', adjustHeight);
}, [autoGrow, maxHeight, reset]);

return (
<Tailwind style={{display: 'contents'}}>
<textarea
ref={ref}
ref={(element) => {
if (typeof ref === 'function') {
ref(element);
} else if (ref) {
ref.current = element;
}
textareaRef.current = element;
}}
className={classNames(
'h-full w-full',
'p-8 leading-6',
Expand Down

0 comments on commit f2dd7d1

Please sign in to comment.