Update SubmitButton.tsx

This commit is contained in:
Nate Kelley 2025-02-04 22:10:39 -07:00
parent 3977d7bb34
commit bc93d18f7e
No known key found for this signature in database
GPG Key ID: FD90372AB8D98B4F
4 changed files with 63 additions and 36 deletions

View File

@ -25,7 +25,8 @@ export const ChatInput: React.FC<{}> = React.memo(({}) => {
const { onSubmitPreflight } = useChatInputFlow({ const { onSubmitPreflight } = useChatInputFlow({
disableSendButton, disableSendButton,
inputValue inputValue,
setInputValue
}); });
const onPressEnter = useMemoizedFn((e: React.KeyboardEvent<HTMLTextAreaElement>) => { const onPressEnter = useMemoizedFn((e: React.KeyboardEvent<HTMLTextAreaElement>) => {

View File

@ -13,30 +13,36 @@ interface SubmitButtonProps {
const animationIcon = { const animationIcon = {
initial: { opacity: 0, scale: 0.8 }, initial: { opacity: 0, scale: 0.8 },
animate: { opacity: 1, scale: 1 }, animate: { opacity: 1, scale: 1 },
exit: { opacity: 0, scale: 0.8 } exit: { opacity: 0, scale: 0.8 },
transition: { duration: 0.2, ease: [0.4, 0, 0.2, 1] }
};
const buttonAnimation = {
whileHover: { scale: 1.085 },
whileTap: { scale: 0.9 },
transition: { duration: 0.24, ease: 'easeInOut' }
}; };
export const SubmitButton: React.FC<SubmitButtonProps> = React.memo( export const SubmitButton: React.FC<SubmitButtonProps> = React.memo(
({ disableSendButton, onSubmitPreflight }) => { ({ disableSendButton, loading, onSubmitPreflight }) => {
const { styles } = useStyles(); const { styles } = useStyles();
const [loading, setLoading] = useState(false);
const onTest = () => {
setLoading(!loading);
};
const tooltipText = loading ? 'Stop' : 'Send message'; const tooltipText = loading ? 'Stop' : 'Send message';
const tooltipShortcuts = loading ? [] : ['⌘', '↵']; const tooltipShortcuts = loading ? [] : ['⌘', '↵'];
return ( return (
<AppTooltip title={tooltipText} shortcuts={tooltipShortcuts} mouseEnterDelay={1}> <AppTooltip
<button title={tooltipText}
onClick={onTest} shortcuts={tooltipShortcuts}
mouseEnterDelay={1.75}
mouseLeaveDelay={0}>
<motion.button
onClick={onSubmitPreflight}
disabled={disableSendButton} disabled={disableSendButton}
className={`${styles.button} ${loading ? styles.loading : ''} ${ className={`${styles.button} ${loading ? styles.loading : ''} ${
disableSendButton ? styles.disabled : '' disableSendButton ? styles.disabled : ''
}`}> }`}
{...(!disableSendButton && buttonAnimation)}>
<AnimatePresence mode="wait"> <AnimatePresence mode="wait">
{loading ? ( {loading ? (
<motion.div key="loading" {...animationIcon} className={styles.iconWrapper}> <motion.div key="loading" {...animationIcon} className={styles.iconWrapper}>
@ -48,7 +54,7 @@ export const SubmitButton: React.FC<SubmitButtonProps> = React.memo(
</motion.div> </motion.div>
)} )}
</AnimatePresence> </AnimatePresence>
</button> </motion.button>
</AppTooltip> </AppTooltip>
); );
} }
@ -65,26 +71,17 @@ const useStyles = createStyles(({ token, css }) => ({
align-items: center; align-items: center;
justify-content: center; justify-content: center;
cursor: pointer; cursor: pointer;
transition: all 0.2s ease;
background: ${token.colorBgContainer}; background: ${token.colorBgContainer};
border: 0.5px solid ${token.colorBorder}; border: 0.5px solid ${token.colorBorder};
padding: 0; padding: 0;
outline: none; outline: none;
transition: all 0.2s ease-in-out;
.material-symbols {
transition: color 0.2s ease;
}
&:not(:disabled):hover { &:not(:disabled):hover {
border-color: ${token.colorPrimary}; border-color: ${token.colorPrimary};
transform: scale(1.075);
box-shadow: ${token.boxShadowTertiary}; box-shadow: ${token.boxShadowTertiary};
} }
&:not(:disabled):active {
transform: scale(0.95);
}
&:disabled { &:disabled {
cursor: not-allowed; cursor: not-allowed;
} }
@ -98,12 +95,12 @@ const useStyles = createStyles(({ token, css }) => ({
} }
`, `,
loading: css` loading: css`
background: ${token.colorText}; background: ${token.colorText} !important;
border: 0.5px solid ${token.colorBorder}; border: 0.5px solid ${token.colorText} !important;
color: ${token.colorBgLayout}; color: ${token.colorBgLayout};
&:hover { &:hover {
background: ${token.colorTextSecondary}; background: ${token.colorTextSecondary} !important;
border-color: ${token.colorTextSecondary} !important; border-color: ${token.colorTextSecondary} !important;
} }

View File

@ -7,10 +7,12 @@ type FlowType = 'followup-chat' | 'followup-metric' | 'followup-dashboard' | 'ne
export const useChatInputFlow = ({ export const useChatInputFlow = ({
disableSendButton, disableSendButton,
inputValue inputValue,
setInputValue
}: { }: {
disableSendButton: boolean; disableSendButton: boolean;
inputValue: string; inputValue: string;
setInputValue: (value: string) => void;
}) => { }) => {
const hasChat = useChatContextSelector((x) => x.hasChat); const hasChat = useChatContextSelector((x) => x.hasChat);
const selectedFileType = useChatContextSelector((x) => x.selectedFileType); const selectedFileType = useChatContextSelector((x) => x.selectedFileType);
@ -32,29 +34,34 @@ export const useChatInputFlow = ({
switch (flow) { switch (flow) {
case 'followup-chat': case 'followup-chat':
return onFollowUpChat({ prompt: inputValue, messageId: currentMessageId! }); await onFollowUpChat({ prompt: inputValue, messageId: currentMessageId! });
break;
case 'followup-metric': case 'followup-metric':
return onStartChatFromFile({ await onStartChatFromFile({
prompt: inputValue, prompt: inputValue,
fileId: selectedFileId!, fileId: selectedFileId!,
fileType: 'metric' fileType: 'metric'
}); });
break;
case 'followup-dashboard': case 'followup-dashboard':
return onStartChatFromFile({ await onStartChatFromFile({
prompt: inputValue, prompt: inputValue,
fileId: selectedFileId!, fileId: selectedFileId!,
fileType: 'dashboard' fileType: 'dashboard'
}); });
break;
case 'new': case 'new':
return onStartNewChat(inputValue); await onStartNewChat(inputValue);
break;
default: default:
const _exhaustiveCheck: never = flow; const _exhaustiveCheck: never = flow;
return _exhaustiveCheck; return _exhaustiveCheck;
} }
setInputValue('');
}); });
return { onSubmitPreflight }; return { onSubmitPreflight };

View File

@ -17,28 +17,50 @@ export const useBusterNewChat = () => {
setPrompt(prompt); setPrompt(prompt);
}); });
const onSelectSearchAsset = useMemoizedFn((asset: BusterSearchResult) => {}); const onSelectSearchAsset = useMemoizedFn(async (asset: BusterSearchResult) => {
setLoadingNewChat(true);
console.log('select search asset');
await new Promise((resolve) => setTimeout(resolve, 1000));
setLoadingNewChat(false);
onSetPrompt('');
});
const onStartNewChat = useMemoizedFn(async (prompt: string) => { const onStartNewChat = useMemoizedFn(async (prompt: string) => {
setLoadingNewChat(true); setLoadingNewChat(true);
console.log('start new chat');
await new Promise((resolve) => setTimeout(resolve, 1000)); await new Promise((resolve) => setTimeout(resolve, 1000));
setLoadingNewChat(false); setLoadingNewChat(false);
onSetPrompt('');
}); });
const onStartChatFromFile = useMemoizedFn( const onStartChatFromFile = useMemoizedFn(
async ({}: { prompt: string; fileId: string; fileType: FileType }) => {} async ({}: { prompt: string; fileId: string; fileType: FileType }) => {
setLoadingNewChat(true);
console.log('start chat from file');
await new Promise((resolve) => setTimeout(resolve, 1000));
setLoadingNewChat(false);
onSetPrompt('');
}
); );
const onFollowUpChat = useMemoizedFn( const onFollowUpChat = useMemoizedFn(
async ({ prompt, messageId }: { prompt: string; messageId: string }) => { async ({ prompt, messageId }: { prompt: string; messageId: string }) => {
setLoadingNewChat(true); setLoadingNewChat(true);
console.log('follow up chat');
await new Promise((resolve) => setTimeout(resolve, 1000)); await new Promise((resolve) => setTimeout(resolve, 1000));
setLoadingNewChat(false); setLoadingNewChat(false);
onSetPrompt('');
} }
); );
const onReplaceMessageInChat = useMemoizedFn( const onReplaceMessageInChat = useMemoizedFn(
async ({ prompt, messageId }: { prompt: string; messageId: string }) => {} async ({ prompt, messageId }: { prompt: string; messageId: string }) => {
setLoadingNewChat(true);
console.log('replace message in chat');
await new Promise((resolve) => setTimeout(resolve, 1000));
setLoadingNewChat(false);
onSetPrompt('');
}
); );
const onSetSelectedChatDataSource = useMemoizedFn((dataSource: BusterDatasetListItem | null) => { const onSetSelectedChatDataSource = useMemoizedFn((dataSource: BusterDatasetListItem | null) => {