mirror of https://github.com/kortix-ai/suna.git
feat: implement new chat design
This commit is contained in:
parent
b61620c6ca
commit
f7fb080145
|
@ -329,21 +329,28 @@ export function HeroSection() {
|
||||||
|
|
||||||
<div className='flex items-center gap-2'>
|
<div className='flex items-center gap-2'>
|
||||||
<ChatDropdown />
|
<ChatDropdown />
|
||||||
<Button
|
<Tooltip>
|
||||||
type="submit"
|
<TooltipTrigger asChild>
|
||||||
size="sm"
|
<Button
|
||||||
className={cn(
|
type="submit"
|
||||||
'w-8 h-8 flex-shrink-0 self-end rounded-xl',
|
size="sm"
|
||||||
(!inputValue.trim() || isSubmitting) ? 'opacity-50' : '',
|
className={cn(
|
||||||
)}
|
'w-8 h-8 flex-shrink-0 self-end rounded-xl',
|
||||||
disabled={!inputValue.trim() || isSubmitting}
|
(!inputValue.trim() || isSubmitting) ? 'opacity-50' : '',
|
||||||
>
|
)}
|
||||||
{isSubmitting ? (
|
disabled={!inputValue.trim() || isSubmitting}
|
||||||
<Square className="h-5 w-5" />
|
>
|
||||||
) : (
|
{isSubmitting ? (
|
||||||
<ArrowUp className="h-5 w-5" />
|
<Square className="h-5 w-5" />
|
||||||
)}
|
) : (
|
||||||
</Button>
|
<ArrowUp className="h-5 w-5" />
|
||||||
|
)}
|
||||||
|
</Button>
|
||||||
|
</TooltipTrigger>
|
||||||
|
<TooltipContent>
|
||||||
|
<p>Send message</p>
|
||||||
|
</TooltipContent>
|
||||||
|
</Tooltip>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -83,7 +83,7 @@ export function AttachmentGroup({
|
||||||
initial={{ opacity: 0, height: 0 }}
|
initial={{ opacity: 0, height: 0 }}
|
||||||
animate={{ opacity: 1, height: 'auto' }}
|
animate={{ opacity: 1, height: 'auto' }}
|
||||||
exit={{ opacity: 0, height: 0 }}
|
exit={{ opacity: 0, height: 0 }}
|
||||||
className={layout === 'inline' ? "mb-3 py-1 px-0.5" : "mt-4"}
|
className={layout === 'inline' ? "" : "mt-4"}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -277,9 +277,9 @@ export function AttachmentGroup({
|
||||||
} else {
|
} else {
|
||||||
// For inline layout with pre-computed data
|
// For inline layout with pre-computed data
|
||||||
return (
|
return (
|
||||||
<div className={cn("flex flex-wrap gap-3", className)} style={{ maxHeight }}>
|
<div className={cn("flex flex-wrap gap-3", className)}>
|
||||||
{visibleFilesWithMeta.map((item, index) => (
|
{visibleFilesWithMeta.map((item, index) => (
|
||||||
<div key={index} className={cn("relative group", item.wrapperClassName)}>
|
<div key={index} className={cn("relative group h-[54px]", item.wrapperClassName)}>
|
||||||
<FileAttachment
|
<FileAttachment
|
||||||
filepath={item.path}
|
filepath={item.path}
|
||||||
onClick={handleFileClick}
|
onClick={handleFileClick}
|
||||||
|
@ -346,16 +346,18 @@ export function AttachmentGroup({
|
||||||
<AnimatePresence>
|
<AnimatePresence>
|
||||||
<motion.div
|
<motion.div
|
||||||
initial={{ opacity: 0, height: 0 }}
|
initial={{ opacity: 0, height: 0 }}
|
||||||
animate={{ opacity: 1, height: 'auto' }}
|
animate={{
|
||||||
|
opacity: 1, height: 'auto'
|
||||||
|
}}
|
||||||
exit={{ opacity: 0, height: 0 }}
|
exit={{ opacity: 0, height: 0 }}
|
||||||
className={layout === 'inline' ? "mb-3 py-1 px-0.5" : "mt-4"}
|
className={layout === 'inline' ? "pt-1.5 px-1.5 pb-0" : "mt-4"}
|
||||||
>
|
>
|
||||||
{renderContent()}
|
{renderContent()}
|
||||||
</motion.div>
|
</motion.div>
|
||||||
</AnimatePresence>
|
</AnimatePresence >
|
||||||
|
|
||||||
{/* Modal dialog to show all files - conditionally rendered based on isModalOpen state */}
|
{/* Modal dialog to show all files - conditionally rendered based on isModalOpen state */}
|
||||||
<Dialog open={isModalOpen} onOpenChange={setIsModalOpen}>
|
< Dialog open={isModalOpen} onOpenChange={setIsModalOpen} >
|
||||||
<DialogContent className="max-w-3xl max-h-[80vh] overflow-y-auto">
|
<DialogContent className="max-w-3xl max-h-[80vh] overflow-y-auto">
|
||||||
<DialogHeader className="mb-1">
|
<DialogHeader className="mb-1">
|
||||||
<DialogTitle>
|
<DialogTitle>
|
||||||
|
@ -481,7 +483,7 @@ export function AttachmentGroup({
|
||||||
})()}
|
})()}
|
||||||
</div>
|
</div>
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
</Dialog>
|
</Dialog >
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
|
@ -238,12 +238,12 @@ export const ChatInput = forwardRef<ChatInputHandles, ChatInputProps>(
|
||||||
<FloatingToolPreview
|
<FloatingToolPreview
|
||||||
toolCalls={toolCalls}
|
toolCalls={toolCalls}
|
||||||
currentIndex={toolCallIndex}
|
currentIndex={toolCallIndex}
|
||||||
onExpand={onExpandToolPreview || (() => {})}
|
onExpand={onExpandToolPreview || (() => { })}
|
||||||
agentName={agentName}
|
agentName={agentName}
|
||||||
isVisible={showToolPreview}
|
isVisible={showToolPreview}
|
||||||
/>
|
/>
|
||||||
<Card
|
<Card
|
||||||
className="-mb-2 bg-red-400 shadow-none w-full max-w-4xl mx-auto bg-transparent border-none rounded-xl overflow-hidden"
|
className="-mb-2 bg-red-400 shadow-none w-full max-w-4xl mx-auto bg-transparent border-none rounded-3xl overflow-hidden"
|
||||||
onDragOver={handleDragOver}
|
onDragOver={handleDragOver}
|
||||||
onDragLeave={handleDragLeave}
|
onDragLeave={handleDragLeave}
|
||||||
onDrop={(e) => {
|
onDrop={(e) => {
|
||||||
|
@ -265,7 +265,7 @@ export const ChatInput = forwardRef<ChatInputHandles, ChatInputProps>(
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className="w-full text-sm flex flex-col justify-between items-start rounded-lg">
|
<div className="w-full text-sm flex flex-col justify-between items-start rounded-lg">
|
||||||
<CardContent className={`w-full p-1.5 pb-2 ${bgColor} rounded-2xl border`}>
|
<CardContent className={`w-full p-1.5 pb-2 ${bgColor} rounded-3xl border`}>
|
||||||
<AttachmentGroup
|
<AttachmentGroup
|
||||||
files={uploadedFiles || []}
|
files={uploadedFiles || []}
|
||||||
sandboxId={sandboxId}
|
sandboxId={sandboxId}
|
||||||
|
|
|
@ -249,9 +249,9 @@ export const FileUploadHandler = forwardRef<
|
||||||
<Button
|
<Button
|
||||||
type="button"
|
type="button"
|
||||||
onClick={handleFileUpload}
|
onClick={handleFileUpload}
|
||||||
variant="ghost"
|
variant="outline"
|
||||||
size="default"
|
size="sm"
|
||||||
className="h-7 rounded-md text-muted-foreground"
|
className="h-8 px-3 py-2 bg-transparent border border-border rounded-xl text-muted-foreground hover:text-foreground hover:bg-accent/50 flex items-center gap-2"
|
||||||
disabled={
|
disabled={
|
||||||
loading || (disabled && !isAgentRunning) || isUploading
|
loading || (disabled && !isAgentRunning) || isUploading
|
||||||
}
|
}
|
||||||
|
@ -261,6 +261,7 @@ export const FileUploadHandler = forwardRef<
|
||||||
) : (
|
) : (
|
||||||
<Paperclip className="h-4 w-4" />
|
<Paperclip className="h-4 w-4" />
|
||||||
)}
|
)}
|
||||||
|
<span className="text-sm">Attach</span>
|
||||||
</Button>
|
</Button>
|
||||||
</TooltipTrigger>
|
</TooltipTrigger>
|
||||||
<TooltipContent side="top">
|
<TooltipContent side="top">
|
||||||
|
|
|
@ -123,9 +123,9 @@ export const MessageInput = forwardRef<HTMLTextAreaElement, MessageInputProps>(
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="relative flex flex-col w-full h-auto gap-4 justify-between">
|
<div className="relative flex flex-col w-full h-full gap-2 justify-between">
|
||||||
|
|
||||||
<div className="flex flex-col gap-2 items-center px-2">
|
<div className="flex flex-col gap-1 px-2">
|
||||||
<Textarea
|
<Textarea
|
||||||
ref={ref}
|
ref={ref}
|
||||||
value={value}
|
value={value}
|
||||||
|
@ -133,16 +133,16 @@ export const MessageInput = forwardRef<HTMLTextAreaElement, MessageInputProps>(
|
||||||
onKeyDown={handleKeyDown}
|
onKeyDown={handleKeyDown}
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
className={cn(
|
className={cn(
|
||||||
'w-full bg-transparent dark:bg-transparent border-none shadow-none focus-visible:ring-0 px-2 py-1 text-base min-h-[40px] max-h-[200px] overflow-y-auto resize-none',
|
'w-full bg-transparent dark:bg-transparent border-none shadow-none focus-visible:ring-0 px-0.5 pb-6 pt-4 !text-[15px] min-h-[36px] max-h-[200px] overflow-y-auto resize-none',
|
||||||
isDraggingOver ? 'opacity-40' : '',
|
isDraggingOver ? 'opacity-40' : '',
|
||||||
)}
|
)}
|
||||||
disabled={loading || (disabled && !isAgentRunning)}
|
disabled={loading || (disabled && !isAgentRunning)}
|
||||||
rows={2}
|
rows={1}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<div className="flex items-center justify-between mt-1 ml-3 mb-1 pr-2">
|
<div className="flex items-center justify-between mt-0 mb-1 px-2">
|
||||||
<div className="flex items-center gap-3">
|
<div className="flex items-center gap-3">
|
||||||
{!hideAttachments && (
|
{!hideAttachments && (
|
||||||
<FileUploadHandler
|
<FileUploadHandler
|
||||||
|
@ -160,7 +160,7 @@ export const MessageInput = forwardRef<HTMLTextAreaElement, MessageInputProps>(
|
||||||
)}
|
)}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{subscriptionStatus === 'no_subscription' && !isLocalMode() &&
|
{subscriptionStatus === 'no_subscription' && !isLocalMode() &&
|
||||||
<TooltipProvider>
|
<TooltipProvider>
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
|
@ -173,7 +173,7 @@ export const MessageInput = forwardRef<HTMLTextAreaElement, MessageInputProps>(
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</TooltipProvider>
|
</TooltipProvider>
|
||||||
}
|
}
|
||||||
|
|
||||||
<div className='flex items-center gap-2'>
|
<div className='flex items-center gap-2'>
|
||||||
{/* Show model selector inline if custom agents are disabled, otherwise show settings dropdown */}
|
{/* Show model selector inline if custom agents are disabled, otherwise show settings dropdown */}
|
||||||
{!customAgentsEnabled || flagsLoading ? (
|
{!customAgentsEnabled || flagsLoading ? (
|
||||||
|
@ -200,7 +200,7 @@ export const MessageInput = forwardRef<HTMLTextAreaElement, MessageInputProps>(
|
||||||
disabled={loading || (disabled && !isAgentRunning)}
|
disabled={loading || (disabled && !isAgentRunning)}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Billing Modal */}
|
{/* Billing Modal */}
|
||||||
<BillingModal
|
<BillingModal
|
||||||
open={billingModalOpen}
|
open={billingModalOpen}
|
||||||
|
@ -212,14 +212,13 @@ export const MessageInput = forwardRef<HTMLTextAreaElement, MessageInputProps>(
|
||||||
onTranscription={onTranscription}
|
onTranscription={onTranscription}
|
||||||
disabled={loading || (disabled && !isAgentRunning)}
|
disabled={loading || (disabled && !isAgentRunning)}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
type="submit"
|
type="submit"
|
||||||
onClick={isAgentRunning && onStopAgent ? onStopAgent : onSubmit}
|
onClick={isAgentRunning && onStopAgent ? onStopAgent : onSubmit}
|
||||||
size="sm"
|
size="sm"
|
||||||
className={cn(
|
className={cn(
|
||||||
'w-7 h-7 flex-shrink-0 self-end',
|
'w-8 h-8 flex-shrink-0 self-end rounded-xl',
|
||||||
isAgentRunning ? 'bg-red-500 hover:bg-red-600' : '',
|
|
||||||
(!value.trim() && uploadedFiles.length === 0 && !isAgentRunning) ||
|
(!value.trim() && uploadedFiles.length === 0 && !isAgentRunning) ||
|
||||||
loading ||
|
loading ||
|
||||||
(disabled && !isAgentRunning)
|
(disabled && !isAgentRunning)
|
||||||
|
@ -233,11 +232,11 @@ export const MessageInput = forwardRef<HTMLTextAreaElement, MessageInputProps>(
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
{loading ? (
|
{loading ? (
|
||||||
<Loader2 className="h-4 w-4 animate-spin" />
|
<Loader2 className="h-5 w-5 animate-spin" />
|
||||||
) : isAgentRunning ? (
|
) : isAgentRunning ? (
|
||||||
<Square className="h-4 w-4" />
|
<div className="min-h-[14px] min-w-[14px] w-[14px] h-[14px] rounded-sm bg-current" />
|
||||||
) : (
|
) : (
|
||||||
<ArrowUp className="h-4 w-4" />
|
<ArrowUp className="h-5 w-5" />
|
||||||
)}
|
)}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
Loading…
Reference in New Issue