diff --git a/web/src/components/ui/inputs/InputTextAreaButton.stories.tsx b/web/src/components/ui/inputs/InputTextAreaButton.stories.tsx index f58f4bd78..84fa3bd91 100644 --- a/web/src/components/ui/inputs/InputTextAreaButton.stories.tsx +++ b/web/src/components/ui/inputs/InputTextAreaButton.stories.tsx @@ -19,7 +19,14 @@ const meta: Meta = { className: { control: 'text' } - } + }, + decorators: [ + (Story) => ( +
+ +
+ ) + ] }; export default meta; diff --git a/web/src/components/ui/inputs/InputTextAreaButton.tsx b/web/src/components/ui/inputs/InputTextAreaButton.tsx index 7f8818b0b..08cb2fa4d 100644 --- a/web/src/components/ui/inputs/InputTextAreaButton.tsx +++ b/web/src/components/ui/inputs/InputTextAreaButton.tsx @@ -1,4 +1,4 @@ -import React, { useMemo, useRef } from 'react'; +import React, { useMemo, useRef, forwardRef } from 'react'; import { InputTextArea, InputTextAreaProps } from './InputTextArea'; import { cn } from '@/lib/classMerge'; import { cva } from 'class-variance-authority'; @@ -9,7 +9,7 @@ import { useMemoizedFn } from 'ahooks'; import { Tooltip } from '../tooltip'; const inputTextAreaButtonVariants = cva( - 'relative flex w-full items-center overflow-hidden rounded-xl border border-border transition-all duration-200', + 'relative flex w-full items-center overflow-visible rounded-xl border border-border transition-all duration-200', { variants: { variant: { @@ -30,66 +30,68 @@ export interface InputTextAreaButtonProps extends Omit = ({ - className, - disabled, - autoResize, - sendIcon = , - loadingIcon = , - loading = false, - onSubmit, - onStop, - variant = 'default', - disabledSubmit, - ...props -}) => { - const textRef = useRef(null); +export const InputTextAreaButton = forwardRef( + ( + { + className, + disabled, + autoResize, + sendIcon = , + loadingIcon = , + loading = false, + onSubmit, + onStop, + variant = 'default', + disabledSubmit, + ...props + }, + textRef + ) => { + const onSubmitPreflight = useMemoizedFn(() => { + if (disabled) return; + const text = (textRef as React.RefObject).current?.value || ''; + onSubmit(text); + }); - const onSubmitPreflight = useMemoizedFn(() => { - if (disabled) return; - const text = textRef.current?.value || ''; - if (text.trim() === '') return; - onSubmit(text); - }); + const onPressMetaEnter = useMemoizedFn(() => { + onSubmitPreflight(); + }); - const onPressMetaEnter = useMemoizedFn(() => { - onSubmitPreflight(); - }); - - return ( -
- - -
- + + +
+ +
-
- ); -}; + ); + } +); const SubmitButton: React.FC<{ loading: boolean; @@ -101,18 +103,19 @@ const SubmitButton: React.FC<{ }> = ({ disabled, sendIcon, loading, loadingIcon, onSubmitPreflight, onStop }) => { const memoizedPrefix = useMemo(() => { return ( - -
-
- {sendIcon} -
-
- {loadingIcon} -
+
+
+ {sendIcon}
- +
+ {loadingIcon} +
+
); }, [loading, sendIcon, loadingIcon]); @@ -123,6 +126,10 @@ const SubmitButton: React.FC<{ prefix={memoizedPrefix} onClick={loading && onStop ? onStop : onSubmitPreflight} disabled={disabled} + className={cn( + 'origin-center transform-gpu transition-all duration-300 ease-out will-change-transform', + !disabled && 'hover:scale-110 active:scale-95' + )} /> ); }; diff --git a/web/src/controllers/HomePage/NewChatInput.tsx b/web/src/controllers/HomePage/NewChatInput.tsx index 44833287c..d63ab1f75 100644 --- a/web/src/controllers/HomePage/NewChatInput.tsx +++ b/web/src/controllers/HomePage/NewChatInput.tsx @@ -1,10 +1,10 @@ 'use client'; -import React from 'react'; +import React, { useRef } from 'react'; import { InputTextAreaButton } from '@/components/ui/inputs/InputTextAreaButton'; import { useBusterChatContextSelector, useBusterNewChatContextSelector } from '@/context/Chats'; import { inputHasText } from '@/lib/text'; -import { useMemoizedFn } from 'ahooks'; +import { useMemoizedFn, useMount } from 'ahooks'; import { ChangeEvent, useMemo, useState } from 'react'; const autoResizeConfig = { @@ -16,6 +16,7 @@ export const NewChatInput: React.FC<{}> = () => { const onStartNewChat = useBusterNewChatContextSelector((state) => state.onStartNewChat); const [inputValue, setInputValue] = useState(''); const [loading, setLoading] = useState(false); + const textAreaRef = useRef(null); const disabledSubmit = useMemo(() => { return !inputHasText(inputValue); @@ -33,12 +34,20 @@ export const NewChatInput: React.FC<{}> = () => { const onStop = useMemoizedFn(() => { setLoading(false); + textAreaRef.current?.focus(); + textAreaRef.current?.select(); }); const onChange = useMemoizedFn((e: ChangeEvent) => { setInputValue(e.target.value); }); + useMount(() => { + if (textAreaRef.current) { + textAreaRef.current.focus(); + } + }); + return ( = () => { loading={loading} disabledSubmit={disabledSubmit} autoFocus + ref={textAreaRef} /> ); }; diff --git a/web/src/styles/styles.scss b/web/src/styles/styles.scss index 659f82a37..5c7a0c338 100644 --- a/web/src/styles/styles.scss +++ b/web/src/styles/styles.scss @@ -6,7 +6,7 @@ @import 'react-data-grid/lib/styles.css'; @import '../components/ui/layouts/AppSplitter/SplitPane/themes/default'; //TODO check if we can remove this -@import 'antd/dist/reset.css'; +// @import 'antd/dist/reset.css'; input { font-family: