chore: more frontend nice ui changes

This commit is contained in:
Lluis Agusti
2025-12-16 16:54:48 +01:00
parent 22298c24fd
commit 0b576d4d48
11 changed files with 164 additions and 52 deletions

View File

@@ -150,6 +150,43 @@
}
}
@keyframes l3 {
25% {
background-position:
0 0,
100% 100%,
100% calc(100% - 5px);
}
50% {
background-position:
0 100%,
100% 100%,
0 calc(100% - 5px);
}
75% {
background-position:
0 100%,
100% 0,
100% 5px;
}
}
.loader {
width: 80px;
height: 70px;
border: 5px solid rgb(241 245 249);
padding: 0 8px;
box-sizing: border-box;
background:
linear-gradient(rgb(15 23 42) 0 0) 0 0/8px 20px,
linear-gradient(rgb(15 23 42) 0 0) 100% 0/8px 20px,
radial-gradient(farthest-side, rgb(15 23 42) 90%, #0000) 0 5px/8px 8px
content-box,
transparent;
background-repeat: no-repeat;
animation: l3 2s infinite linear;
}
input[type="number"]::-webkit-outer-spin-button,
input[type="number"]::-webkit-inner-spin-button {
-webkit-appearance: none;

View File

@@ -1,5 +1,7 @@
"use client";
import { Button } from "@/components/atoms/Button/Button";
import { Text } from "@/components/atoms/Text/Text";
import { cn } from "@/lib/utils";
import React from "react";
import { ChatContainer } from "./components/ChatContainer/ChatContainer";
@@ -19,7 +21,7 @@ export interface ChatProps {
export function Chat({
className,
headerTitle = "Chat",
headerTitle = "AutoGPT Copilot",
showHeader = true,
showSessionInfo = true,
showNewChatButton = true,
@@ -46,26 +48,37 @@ export function Chat({
<div className={cn("flex h-full flex-col", className)}>
{/* Header */}
{showHeader && (
<header className="shrink-0 border-b border-zinc-200 bg-white p-4">
<header className="shrink-0 border-b border-zinc-200 bg-white p-3">
<div className="flex items-center justify-between">
{typeof headerTitle === "string" ? (
<h2 className="text-xl font-semibold">{headerTitle}</h2>
<Text variant="h2" className="text-lg font-semibold">
{headerTitle}
</Text>
) : (
headerTitle
)}
<div className="flex items-center gap-4">
<div className="flex items-center gap-3">
{showSessionInfo && sessionId && (
<>
<span className="text-sm text-zinc-600">
Session: {sessionId.slice(0, 8)}...
</span>
<Text variant="body">
<span
className="inline-block bg-gradient-to-r from-indigo-500 via-purple-500 to-indigo-500 bg-clip-text text-transparent"
style={{
backgroundSize: "200% 100%",
animation: "shimmer 2s ease-in-out infinite",
}}
>
Session: {sessionId.slice(0, 8)}...
</span>
</Text>
{showNewChatButton && (
<button
<Button
variant="outline"
size="small"
onClick={handleNewChat}
className="text-sm text-zinc-600 hover:text-zinc-900"
>
New Chat
</button>
</Button>
)}
</>
)}

View File

@@ -1,6 +1,5 @@
"use client";
import { Button } from "@/components/__legacy__/ui/button";
import { scrollbarStyles } from "@/components/styles/scrollbars";
import { cn } from "@/lib/utils";
import { Flag, useGetFlag } from "@/services/feature-flags/use-get-flag";
@@ -57,19 +56,14 @@ export function ChatDrawer({ blurBackground = true }: ChatDrawerProps) {
>
<Chat
headerTitle={
<Drawer.Title className="text-xl font-semibold">
Chat
<Drawer.Title className="text-lg font-semibold">
AutoGPT Copilot
</Drawer.Title>
}
headerActions={
<Button
variant="link"
aria-label="Close"
onClick={close}
className="!focus-visible:ring-0 p-0"
>
<X width="1.5rem" />
</Button>
<button aria-label="Close" onClick={close} className="size-8">
<X width="1.25rem" height="1.25rem" />
</button>
}
/>
</Drawer.Content>

View File

@@ -45,11 +45,20 @@ export function ChatContainer({
];
return (
<div className={cn("flex h-full flex-col", className)}>
<div
className={cn("flex h-full flex-col", className)}
style={{
backgroundColor: "#ffffff",
backgroundImage:
"radial-gradient(#e5e5e5 0.5px, transparent 0.5px), radial-gradient(#e5e5e5 0.5px, #ffffff 0.5px)",
backgroundSize: "20px 20px",
backgroundPosition: "0 0, 10px 10px",
}}
>
{/* Messages or Welcome Screen */}
{messages.length === 0 ? (
<QuickActionsWelcome
title="Welcome to AutoGPT Chat"
title="Welcome to AutoGPT Copilot"
description="Start a conversation to discover and run AI agents."
actions={quickActions}
onActionClick={sendMessageWithContext}

View File

@@ -165,8 +165,8 @@ export function ChatMessage({
<div className="flex w-full max-w-3xl gap-3">
{!isUser && (
<div className="flex-shrink-0">
<div className="flex h-7 w-7 items-center justify-center rounded-lg bg-neutral-200">
<RobotIcon className="h-4 w-4 text-neutral-600" />
<div className="flex h-7 w-7 items-center justify-center rounded-lg bg-indigo-500">
<RobotIcon className="h-4 w-4 text-indigo-50" />
</div>
</div>
)}

View File

@@ -12,16 +12,45 @@ export function MessageBubble({
variant,
className,
}: MessageBubbleProps) {
const userTheme = {
bg: "bg-slate-900",
border: "border-slate-800",
gradient: "from-slate-900/30 via-slate-800/20 to-transparent",
text: "text-slate-50",
};
const assistantTheme = {
bg: "bg-slate-50/20",
border: "border-slate-100",
gradient: "from-slate-200/20 via-slate-300/10 to-transparent",
text: "text-slate-900",
};
const theme = variant === "user" ? userTheme : assistantTheme;
return (
<div
className={cn(
"min-w-20 rounded-[20px] px-6 py-2.5 text-sm leading-relaxed",
variant === "user" && "bg-zinc-700 text-right text-neutral-50",
variant === "assistant" && "bg-zinc-100 text-left text-neutral-900",
"group relative min-w-20 overflow-hidden rounded-xl border px-6 py-2.5 text-sm leading-relaxed backdrop-blur-xl transition-all duration-500 ease-in-out",
theme.bg,
theme.border,
variant === "user" && "text-right",
variant === "assistant" && "text-left",
className,
)}
>
{children}
{/* Gradient flare background */}
<div
className={cn("absolute inset-0 bg-gradient-to-br", theme.gradient)}
/>
<div
className={cn(
"relative z-10 transition-all duration-500 ease-in-out",
theme.text,
)}
>
{children}
</div>
</div>
);
}

View File

@@ -31,7 +31,7 @@ export function MessageList({
<div
ref={messagesContainerRef}
className={cn(
"flex-1 overflow-y-auto bg-white",
"flex-1 overflow-y-auto",
"scrollbar-thin scrollbar-track-transparent scrollbar-thumb-zinc-300",
className,
)}

View File

@@ -38,11 +38,11 @@ export function QuickActionsWelcome({
{actions.map((action) => {
// Use slate theme for all cards
const theme = {
bg: "bg-slate-50/30",
border: "border-slate-200",
hoverBg: "hover:bg-slate-100",
bg: "bg-slate-50/10",
border: "border-slate-100",
hoverBg: "hover:bg-slate-50/20",
hoverBorder: "hover:border-slate-200",
gradient: "from-slate-300/20 via-slate-400/10 to-transparent",
gradient: "from-slate-200/20 via-slate-300/10 to-transparent",
text: "text-slate-900",
hoverText: "group-hover:text-slate-900",
};

View File

@@ -1,5 +1,5 @@
import { cn } from "@/lib/utils";
import { Robot } from "@phosphor-icons/react";
import { RobotIcon } from "@phosphor-icons/react";
import { MarkdownContent } from "../MarkdownContent/MarkdownContent";
import { MessageBubble } from "../MessageBubble/MessageBubble";
import { useStreamingMessage } from "./useStreamingMessage";
@@ -26,8 +26,8 @@ export function StreamingMessage({
>
<div className="flex w-full max-w-3xl gap-3">
<div className="flex-shrink-0">
<div className="flex h-7 w-7 items-center justify-center rounded-lg bg-neutral-200">
<Robot className="h-4 w-4 text-neutral-600" />
<div className="flex h-7 w-7 items-center justify-center rounded-lg bg-indigo-600">
<RobotIcon className="h-4 w-4 text-indigo-50" />
</div>
</div>

View File

@@ -1,5 +1,6 @@
import { cn } from "@/lib/utils";
import { Robot } from "@phosphor-icons/react";
import { RobotIcon } from "@phosphor-icons/react";
import { useEffect, useRef, useState } from "react";
import { MessageBubble } from "../MessageBubble/MessageBubble";
export interface ThinkingMessageProps {
@@ -7,6 +8,24 @@ export interface ThinkingMessageProps {
}
export function ThinkingMessage({ className }: ThinkingMessageProps) {
const [showSlowLoader, setShowSlowLoader] = useState(false);
const timerRef = useRef<NodeJS.Timeout | null>(null);
useEffect(() => {
if (timerRef.current === null) {
timerRef.current = setTimeout(() => {
setShowSlowLoader(true);
}, 8000);
}
return () => {
if (timerRef.current) {
clearTimeout(timerRef.current);
timerRef.current = null;
}
};
}, []);
return (
<div
className={cn(
@@ -16,22 +35,33 @@ export function ThinkingMessage({ className }: ThinkingMessageProps) {
>
<div className="flex w-full max-w-3xl gap-3">
<div className="flex-shrink-0">
<div className="flex h-7 w-7 items-center justify-center rounded-lg bg-neutral-200">
<Robot className="h-4 w-4 text-neutral-600" />
<div className="flex h-7 w-7 items-center justify-center rounded-lg bg-indigo-500">
<RobotIcon className="h-4 w-4 text-indigo-50" />
</div>
</div>
<div className="flex min-w-0 flex-1 flex-col">
<MessageBubble variant="assistant">
<span
className="inline-block bg-gradient-to-r from-neutral-400 via-neutral-600 to-neutral-400 bg-clip-text text-transparent"
style={{
backgroundSize: "200% 100%",
animation: "shimmer 2s ease-in-out infinite",
}}
>
Thinking...
</span>
<div className="transition-all duration-500 ease-in-out">
{showSlowLoader ? (
<div className="flex flex-col items-center gap-3 py-2">
<div className="loader" style={{ flexShrink: 0 }} />
<p className="text-sm text-slate-700">
Taking a bit longer to think, wait a moment please
</p>
</div>
) : (
<span
className="inline-block bg-gradient-to-r from-neutral-400 via-neutral-600 to-neutral-400 bg-clip-text text-transparent"
style={{
backgroundSize: "200% 100%",
animation: "shimmer 2s ease-in-out infinite",
}}
>
Thinking...
</span>
)}
</div>
</MessageBubble>
</div>
</div>

View File

@@ -44,7 +44,7 @@ export function NavbarView({ isLoggedIn, previewBranchName }: NavbarViewProps) {
const { open: openChatDrawer } = useChatDrawer();
const linksWithChat = useMemo(() => {
const chatLink = { name: "Chat", href: "/chat" };
const chatLink = { name: "Copilot", href: "/chat" };
return isChatEnabled ? [...loggedInLinks, chatLink] : loggedInLinks;
}, [isChatEnabled]);
@@ -124,7 +124,7 @@ export function NavbarView({ isLoggedIn, previewBranchName }: NavbarViewProps) {
? IconType.Library
: link.name === "Build"
? IconType.Builder
: link.name === "Chat"
: link.name === "Copilot"
? IconType.Chat
: link.name === "Monitor"
? IconType.Library
@@ -132,7 +132,7 @@ export function NavbarView({ isLoggedIn, previewBranchName }: NavbarViewProps) {
text: link.name,
href: link.href,
onClick:
link.name === "Chat" && isChatEnabled
link.name === "Copilot" && isChatEnabled
? openChatDrawer
: undefined,
})),