From ccbfead519639f995cc3f66195e65d8df0477e63 Mon Sep 17 00:00:00 2001 From: Philip Langer Date: Mon, 11 Nov 2024 17:14:08 +0100 Subject: [PATCH] fix(ai): adjust chat input height dynamically So far the height of the chat input field only was increased with Ctrl+Enter, but not when the lines broke due to their length, or when the view was resized. With this change, we adapt the height of the input also during normal typing when the content wraps into a new line. Moreover, we add a short transition when adjusting the height to make it look smoother. --- .../src/browser/chat-input-widget.tsx | 55 ++++++++++++------- .../ai-chat-ui/src/browser/style/index.css | 1 + 2 files changed, 36 insertions(+), 20 deletions(-) diff --git a/packages/ai-chat-ui/src/browser/chat-input-widget.tsx b/packages/ai-chat-ui/src/browser/chat-input-widget.tsx index 332c5b3b04232..242c4180cebf9 100644 --- a/packages/ai-chat-ui/src/browser/chat-input-widget.tsx +++ b/packages/ai-chat-ui/src/browser/chat-input-widget.tsx @@ -126,6 +126,9 @@ const ChatInput: React.FunctionComponent = (props: ChatInpu const lastRequest = allRequests.length === 0 ? undefined : allRequests[allRequests.length - 1]; const createInputElement = async () => { + const padding = 8; + const lineHeight = 20; + const maxHeight = 240; const resource = await props.untitledResourceResolver.createUntitledResource('', CHAT_VIEW_LANGUAGE_EXTENSION); const editor = await props.editorProvider.createInline(resource.uri, editorContainerRef.current!, { language: CHAT_VIEW_LANGUAGE_EXTENSION, @@ -133,7 +136,7 @@ const ChatInput: React.FunctionComponent = (props: ChatInpu codeLens: false, inlayHints: { enabled: 'off' }, hover: { enabled: false }, - autoSizing: true, + autoSizing: false, // we handle the sizing ourselves scrollBeyondLastLine: false, scrollBeyondLastColumn: 0, minHeight: 1, @@ -144,8 +147,8 @@ const ChatInput: React.FunctionComponent = (props: ChatInpu scrollbar: { horizontal: 'hidden' }, automaticLayout: true, lineNumbers: 'off', - lineHeight: 20, - padding: { top: 8 }, + lineHeight, + padding: { top: padding }, suggest: { showIcons: true, showSnippets: false, @@ -158,8 +161,23 @@ const ChatInput: React.FunctionComponent = (props: ChatInpu stickyScroll: { enabled: false }, }); - editor.getControl().onDidChangeModelContent(() => { - layout(); + if (editorContainerRef.current) { + editorContainerRef.current.style.height = (lineHeight + (2 * padding)) + 'px'; + } + + const updateEditorHeight = () => { + if (editorContainerRef.current) { + const contentHeight = editor.getControl().getContentHeight() + padding; + editorContainerRef.current.style.height = `${Math.min(contentHeight, maxHeight)}px`; + } + }; + editor.getControl().onDidChangeModelContent(updateEditorHeight); + const resizeObserver = new ResizeObserver(updateEditorHeight); + if (editorContainerRef.current) { + resizeObserver.observe(editorContainerRef.current); + } + editor.getControl().onDidDispose(() => { + resizeObserver.disconnect(); }); editor.getControl().onContextMenu(e => @@ -193,19 +211,6 @@ const ChatInput: React.FunctionComponent = (props: ChatInpu if (editorRef.current) { editorRef.current.document.textEditorModel.setValue(''); } - }; - - function layout(): void { - if (editorRef.current === undefined) { - return; - } - const hiddenClass = 'hidden'; - const editor = editorRef.current; - if (editor.document.textEditorModel.getValue().length > 0) { - placeholderRef.current?.classList.add(hiddenClass); - } else { - placeholderRef.current?.classList.remove(hiddenClass); - } } const onKeyDown = React.useCallback((event: React.KeyboardEvent) => { @@ -218,10 +223,20 @@ const ChatInput: React.FunctionComponent = (props: ChatInpu } }, [props.isEnabled]); + const handleInputFocus = () => { + placeholderRef.current?.classList.add('hidden'); + }; + + const handleInputBlur = () => { + if (!editorRef.current?.getControl().getValue()) { + placeholderRef.current?.classList.remove('hidden'); + } + }; + return
-
-
Enter your question
+
+
Ask a question
diff --git a/packages/ai-chat-ui/src/browser/style/index.css b/packages/ai-chat-ui/src/browser/style/index.css index a6eb67a4d91b0..4c86cfe272689 100644 --- a/packages/ai-chat-ui/src/browser/style/index.css +++ b/packages/ai-chat-ui/src/browser/style/index.css @@ -163,6 +163,7 @@ div:last-child > .theia-ChatNode { display: flex; flex-direction: column-reverse; overflow: hidden; + transition: height 0.05s ease-in-out; } .theia-ChatInput-Editor:has(.monaco-editor.focused) {