From 9906dd4e2a97e7085c76c87191e3b981d33ff83b Mon Sep 17 00:00:00 2001 From: Aliyan Ishfaq Date: Thu, 31 Jul 2025 11:55:39 -0700 Subject: [PATCH] feat: dark mode & general web app improvements (#615) * feat: viewability improvements * chore: code formatting * fix: code fixes * fix: merge changes lost from main * fix: attached doc styling * chore: attachments logo * fix: remove attachments button * fix: text visibility & tooltip mardown * fix: auth state change * feat conflict with main resolved * fix: feat conflicts with main * fix: conversation summary consistency with theme * fix: conversation summary * chore: removed text * cr --------- Co-authored-by: bracesproul --- apps/web/src/app/(v2)/chat/threads/page.tsx | 19 ++-- apps/web/src/app/globals.css | 54 ++++----- .../web/src/components/gen-ui/action-step.tsx | 107 +++++++++++++----- .../components/gen-ui/code-review-started.tsx | 28 +++-- .../gen-ui/conversation-summary.tsx | 33 ++++-- .../components/gen-ui/pull-request-opened.tsx | 49 ++++---- .../src/components/gen-ui/push-changes.tsx | 6 +- .../src/components/gen-ui/replanning-step.tsx | 10 +- .../web/src/components/gen-ui/task-review.tsx | 12 +- .../src/components/gen-ui/task-summary.tsx | 73 ++++++++---- .../web/src/components/github/auth-status.tsx | 3 +- .../github/repo-branch-selectors/index.tsx | 4 +- apps/web/src/components/icons/openswe.tsx | 28 +++++ apps/web/src/components/plan/plan-viewer.tsx | 9 +- .../web/src/components/plan/proposed-plan.tsx | 43 ++++--- apps/web/src/components/tasks/index.tsx | 38 ++++--- .../web/src/components/tasks/progress-bar.tsx | 23 ++-- .../thread/ContentBlocksPreview.tsx | 2 +- .../components/thread/MultimodalPreview.tsx | 27 +++-- .../src/components/thread/markdown-text.tsx | 13 ++- .../components/thread/messages/tool-calls.tsx | 22 ++-- apps/web/src/components/v2/default-view.tsx | 43 ++----- .../components/v2/diagnose-error-action.tsx | 42 +++++-- apps/web/src/components/v2/manager-chat.tsx | 61 +++++----- apps/web/src/components/v2/quick-actions.tsx | 4 +- apps/web/src/components/v2/terminal-input.tsx | 18 ++- apps/web/src/components/v2/thread-card.tsx | 44 ++++--- .../web/src/components/v2/thread-switcher.tsx | 10 +- .../src/components/v2/thread-view-loading.tsx | 70 ++++++------ apps/web/src/components/v2/thread-view.tsx | 7 +- 30 files changed, 528 insertions(+), 374 deletions(-) create mode 100644 apps/web/src/components/icons/openswe.tsx diff --git a/apps/web/src/app/(v2)/chat/threads/page.tsx b/apps/web/src/app/(v2)/chat/threads/page.tsx index b632b3f0..84566c10 100644 --- a/apps/web/src/app/(v2)/chat/threads/page.tsx +++ b/apps/web/src/app/(v2)/chat/threads/page.tsx @@ -16,6 +16,7 @@ import { MANAGER_GRAPH_ID } from "@open-swe/shared/constants"; import { useThreadsStatus } from "@/hooks/useThreadsStatus"; import { cn } from "@/lib/utils"; import { threadsToMetadata } from "@/lib/thread-utils"; +import { OpenSWELogoSVG } from "@/components/icons/openswe"; type FilterStatus = | "all" @@ -109,10 +110,10 @@ function AllThreadsPageContent() {
-
- - All Threads - +
@@ -129,7 +130,7 @@ function AllThreadsPageContent() {
{/* Search and Filters */} -
+
@@ -137,7 +138,7 @@ function AllThreadsPageContent() { placeholder="Search threads..." value={searchQuery} onChange={(e) => setSearchQuery(e.target.value)} - className="border-border bg-background text-foreground placeholder:text-muted-foreground pl-10 dark:bg-gray-900" + className="border-border bg-background text-foreground placeholder:text-muted-foreground pl-10" />
@@ -162,7 +163,7 @@ function AllThreadsPageContent() { className={cn( "h-7 text-xs", statusFilter === status - ? "bg-muted text-foreground dark:bg-gray-700" + ? "bg-muted text-foreground" : "text-muted-foreground hover:bg-muted hover:text-foreground", )} onClick={() => setStatusFilter(status)} @@ -172,7 +173,7 @@ function AllThreadsPageContent() { : status.charAt(0).toUpperCase() + status.slice(1)} {statusCounts[status]} @@ -197,7 +198,7 @@ function AllThreadsPageContent() { {threads.length} diff --git a/apps/web/src/app/globals.css b/apps/web/src/app/globals.css index e06aab7c..bcf8fb66 100644 --- a/apps/web/src/app/globals.css +++ b/apps/web/src/app/globals.css @@ -41,38 +41,38 @@ } .dark { - --background: oklch(0.145 0 0); - --foreground: oklch(0.985 0 0); - --card: oklch(0.145 0 0); - --card-foreground: oklch(0.985 0 0); - --popover: oklch(0.145 0 0); - --popover-foreground: oklch(0.985 0 0); - --primary: oklch(0.985 0 0); - --primary-foreground: oklch(0.205 0 0); - --secondary: oklch(0.269 0 0); - --secondary-foreground: oklch(0.985 0 0); - --muted: oklch(0.269 0 0); - --muted-foreground: oklch(0.708 0 0); - --accent: oklch(0.269 0 0); - --accent-foreground: oklch(0.985 0 0); - --destructive: oklch(0.396 0.141 25.723); - --destructive-foreground: oklch(0.637 0.237 25.331); - --border: oklch(0.269 0 0); - --input: oklch(0.269 0 0); - --ring: oklch(0.439 0 0); + --background: oklch(0.29 0.005 280); + --foreground: oklch(0.92 0.01 280); + --card: oklch(0.32 0.005 280); + --card-foreground: oklch(0.92 0.01 280); + --popover: oklch(0.32 0.005 280); + --popover-foreground: oklch(0.92 0.01 280); + --primary: oklch(0.92 0.01 280); + --primary-foreground: oklch(0.24 0.005 280); + --secondary: oklch(0.38 0.005 280); + --secondary-foreground: oklch(0.92 0.01 280); + --muted: oklch(0.35 0.005 280); + --muted-foreground: oklch(0.65 0.01 280); + --accent: oklch(0.38 0.005 280); + --accent-foreground: oklch(0.92 0.01 280); + --destructive: oklch(0.55 0.15 20); + --destructive-foreground: oklch(0.95 0.01 280); + --border: oklch(0.42 0.005 280); + --input: oklch(0.42 0.005 280); + --ring: oklch(0.5 0.01 280); --chart-1: oklch(0.488 0.243 264.376); --chart-2: oklch(0.696 0.17 162.48); --chart-3: oklch(0.769 0.188 70.08); --chart-4: oklch(0.627 0.265 303.9); --chart-5: oklch(0.645 0.246 16.439); - --sidebar: oklch(0.205 0 0); - --sidebar-foreground: oklch(0.985 0 0); + --sidebar: oklch(0.3 0.005 280); + --sidebar-foreground: oklch(0.92 0.01 280); --sidebar-primary: oklch(0.488 0.243 264.376); - --sidebar-primary-foreground: oklch(0.985 0 0); - --sidebar-accent: oklch(0.269 0 0); - --sidebar-accent-foreground: oklch(0.985 0 0); - --sidebar-border: oklch(0.269 0 0); - --sidebar-ring: oklch(0.439 0 0); + --sidebar-primary-foreground: oklch(0.92 0.01 280); + --sidebar-accent: oklch(0.38 0.005 280); + --sidebar-accent-foreground: oklch(0.92 0.01 280); + --sidebar-border: oklch(0.42 0.005 280); + --sidebar-ring: oklch(0.5 0.01 280); } @theme inline { @@ -167,6 +167,6 @@ } .dark .scrollbar-pretty-auto::-webkit-scrollbar-thumb { - background-color: rgb(75 85 99); + background-color: rgb(95 105 119); } } diff --git a/apps/web/src/components/gen-ui/action-step.tsx b/apps/web/src/components/gen-ui/action-step.tsx index 57c45b5e..45bb1789 100644 --- a/apps/web/src/components/gen-ui/action-step.tsx +++ b/apps/web/src/components/gen-ui/action-step.tsx @@ -1,6 +1,7 @@ "use client"; import { JSX, useState } from "react"; +import { AnimatePresence, motion } from "framer-motion"; import { Terminal, FileText, @@ -165,7 +166,7 @@ function MatchCaseIcon({ matchCase }: { matchCase: boolean }) { "rounded-sm border border-gray-300 px-1 py-[2px] text-xs dark:border-gray-600", matchCase ? "border-blue-500 bg-blue-500/80 text-white" - : "bg-gray-100 text-gray-800 dark:bg-gray-800 dark:text-gray-200", + : "dark:bg-muted dark:text-muted-foreground bg-muted text-gray-800", )} >

Aa

@@ -554,7 +555,7 @@ function ActionItem(props: ActionItemProps) { props.output ) { return ( -
+
             {props.output}
           
@@ -577,7 +578,7 @@ function ActionItem(props: ActionItemProps) { } return ( -
+
{hasArgs && (
@@ -623,7 +624,7 @@ function ActionItem(props: ActionItemProps) { ); } else if (props.actionType === "get_url_content" && props.output) { return ( -
+
             {props.output}
           
@@ -631,7 +632,7 @@ function ActionItem(props: ActionItemProps) { ); } else if (props.actionType === "apply-patch" && props.diff) { return ( -
+
 0
     ) {
       return (
-        
+
    {props.scratchpad.map((note, i) => (
  • -
    +
    {renderHeaderIcon()} {renderHeaderContent()}
    @@ -707,15 +708,24 @@ function ActionItem(props: ActionItemProps) {
    - {renderContent()} + + {expanded && ( + + {renderContent()} + + )} +
    ); } export function ActionStep(props: ActionStepProps) { - const [showReasoning, setShowReasoning] = useState(true); - const [showSummary, setShowSummary] = useState(true); - const reasoningText = "reasoningText" in props ? props.reasoningText : undefined; const summaryText = "summaryText" in props ? props.summaryText : undefined; @@ -724,21 +734,41 @@ export function ActionStep(props: ActionStepProps) { (action: ActionItemProps) => action.status === "done", ); + const [showReasoning, setShowReasoning] = useState(!!reasoningText); + const [showSummary, setShowSummary] = useState(!!summaryText); + return ( -
    -
    +
    +
    - {showReasoning && ( - - {reasoningText || "No reasoning provided."} - - )} + + {showReasoning && ( + +
    + + {reasoningText || "No reasoning provided."} + +
    +
    + )} +
    @@ -751,19 +781,36 @@ export function ActionStep(props: ActionStepProps) {
    {summaryText && anyActionDone && ( -
    +
    - {showSummary && ( - - {summaryText} - - )} + + {showSummary && ( + +
    + + {summaryText} + +
    +
    + )} +
    )}
    diff --git a/apps/web/src/components/gen-ui/code-review-started.tsx b/apps/web/src/components/gen-ui/code-review-started.tsx index 7ea91f5b..2b71a13b 100644 --- a/apps/web/src/components/gen-ui/code-review-started.tsx +++ b/apps/web/src/components/gen-ui/code-review-started.tsx @@ -1,8 +1,8 @@ "use client"; -import { Sparkles } from "lucide-react"; +import { FileSearch } from "lucide-react"; import { Badge } from "../ui/badge"; -import { Check } from "lucide-react"; +import { Clock } from "lucide-react"; import { cn } from "@/lib/utils"; type CodeReviewStartedProps = { @@ -13,36 +13,34 @@ export function CodeReviewStarted({ status = "done" }: CodeReviewStartedProps) { return (
    {/* Header */}
    -
    - +
    +
    -

    - Code review started -

    +

    Code review

    - - In Progress + + In progress
    -

    - Analyzing code for best practices and potential improvements +

    + Analyzing code quality

    diff --git a/apps/web/src/components/gen-ui/conversation-summary.tsx b/apps/web/src/components/gen-ui/conversation-summary.tsx index dd9e4427..4a5302c7 100644 --- a/apps/web/src/components/gen-ui/conversation-summary.tsx +++ b/apps/web/src/components/gen-ui/conversation-summary.tsx @@ -1,5 +1,6 @@ import { FileText, ChevronDown, Check } from "lucide-react"; import { useState } from "react"; +import { AnimatePresence, motion } from "framer-motion"; import { MarkdownText } from "../thread/markdown-text"; import { cn } from "@/lib/utils"; import { Button } from "../ui/button"; @@ -15,18 +16,18 @@ export function ConversationHistorySummary({ summary }: { summary: string }) { return (
    {/* Header */}
    -
    +
    @@ -37,7 +38,7 @@ export function ConversationHistorySummary({ summary }: { summary: string }) { Complete @@ -64,13 +65,23 @@ export function ConversationHistorySummary({ summary }: { summary: string }) {
    {/* Content */} - {expanded && ( -
    -
    - {summary} -
    -
    - )} + + {expanded && ( + +
    +
    + {summary} +
    +
    +
    + )} +
    ); } diff --git a/apps/web/src/components/gen-ui/pull-request-opened.tsx b/apps/web/src/components/gen-ui/pull-request-opened.tsx index f9458174..9fd34322 100644 --- a/apps/web/src/components/gen-ui/pull-request-opened.tsx +++ b/apps/web/src/components/gen-ui/pull-request-opened.tsx @@ -1,6 +1,7 @@ "use client"; import { useState } from "react"; +import { AnimatePresence, motion } from "framer-motion"; import { GitPullRequest, Loader2, @@ -43,7 +44,7 @@ export function PullRequestOpened({ return ( Preparing @@ -53,7 +54,7 @@ export function PullRequestOpened({ return ( Opening @@ -64,7 +65,7 @@ export function PullRequestOpened({ return ( Draft @@ -74,7 +75,7 @@ export function PullRequestOpened({ return ( Opened @@ -110,18 +111,18 @@ export function PullRequestOpened({ return (
    {/* Header */}
    -
    +
    {isDraft ? ( ) : ( @@ -178,18 +179,28 @@ export function PullRequestOpened({
    {/* Content */} - {expanded && description && status === "done" && ( -
    -
    -

    - Description -

    -
    -              {description}
    -            
    -
    -
    - )} + + {expanded && description && status === "done" && ( + +
    +
    +

    + Description +

    +
    +                  {description}
    +                
    +
    +
    +
    + )} +
    ); } diff --git a/apps/web/src/components/gen-ui/push-changes.tsx b/apps/web/src/components/gen-ui/push-changes.tsx index 7c7d7fc6..366b17f7 100644 --- a/apps/web/src/components/gen-ui/push-changes.tsx +++ b/apps/web/src/components/gen-ui/push-changes.tsx @@ -72,16 +72,16 @@ export function PushChanges({ return (
    {reasoningText && ( -
    +
    {showReasoning && ( - + {reasoningText} )} diff --git a/apps/web/src/components/gen-ui/replanning-step.tsx b/apps/web/src/components/gen-ui/replanning-step.tsx index 0af524ec..ca8a315f 100644 --- a/apps/web/src/components/gen-ui/replanning-step.tsx +++ b/apps/web/src/components/gen-ui/replanning-step.tsx @@ -34,7 +34,9 @@ export function ReplanningStep({ case "generating": return ; case "done": - return ; + return ( + + ); } }; @@ -52,16 +54,16 @@ export function ReplanningStep({ return (
    {reasoningText && ( -
    +
    {showReasoning && ( - + {reasoningText} )} diff --git a/apps/web/src/components/gen-ui/task-review.tsx b/apps/web/src/components/gen-ui/task-review.tsx index 4be30231..a0eb5426 100644 --- a/apps/web/src/components/gen-ui/task-review.tsx +++ b/apps/web/src/components/gen-ui/task-review.tsx @@ -42,7 +42,7 @@ export function MarkTaskCompleted({ ); case "done": return ( - + ); } }; @@ -61,16 +61,16 @@ export function MarkTaskCompleted({ return (
    {reasoningText && ( -
    +
    {showReasoning && ( - + {reasoningText} )} @@ -185,10 +185,10 @@ export function MarkTaskIncomplete({ return (
    {reasoningText && ( -
    +
    - {showSummary && ( - - {summaryText} - - )} + /> + {showSummary ? "Hide reflection" : "Show reflection"} + + + {showSummary && ( + +
    + + {summaryText} + +
    +
    + )} +
    )}
    diff --git a/apps/web/src/components/github/auth-status.tsx b/apps/web/src/components/github/auth-status.tsx index 2640f1cd..fd561a94 100644 --- a/apps/web/src/components/github/auth-status.tsx +++ b/apps/web/src/components/github/auth-status.tsx @@ -72,7 +72,7 @@ function AuthStatusContent() { if (!showGetStarted && !showInstallApp && !showLoading) { router.push("/chat"); } - }, [showGetStarted, showInstallApp, showLoading]); + }, [showGetStarted, showInstallApp, showLoading, router]); if (showGetStarted) { return ( @@ -172,6 +172,7 @@ function AuthStatusContent() {
    ); } + return null; } export default function AuthStatus() { diff --git a/apps/web/src/components/github/repo-branch-selectors/index.tsx b/apps/web/src/components/github/repo-branch-selectors/index.tsx index 134bf6a4..aeb8afea 100644 --- a/apps/web/src/components/github/repo-branch-selectors/index.tsx +++ b/apps/web/src/components/github/repo-branch-selectors/index.tsx @@ -6,9 +6,9 @@ export function RepositoryBranchSelectors() { const [threadId] = useQueryState("threadId"); const chatStarted = !!threadId; const defaultButtonStyles = - "bg-inherit border-none text-muted-foreground hover:text-muted-foreground/70 text-xs p-0 px-0 py-0 !p-0 !px-0 !py-0 h-fit hover:bg-inherit shadow-none"; + "bg-inherit border-none text-foreground hover:text-foreground/80 text-xs p-0 px-0 py-0 !p-0 !px-0 !py-0 h-fit hover:bg-inherit shadow-none"; const defaultStylesChatStarted = - "hover:bg-inherit cursor-default hover:cursor-default text-muted-foreground hover:border-gray-300 hover:ring-inherit shadow-none p-0 px-0 py-0 !p-0 !px-0 !py-0"; + "hover:bg-inherit cursor-default hover:cursor-default text-foreground hover:border-gray-300 hover:ring-inherit shadow-none p-0 px-0 py-0 !p-0 !px-0 !py-0"; return (
    diff --git a/apps/web/src/components/icons/openswe.tsx b/apps/web/src/components/icons/openswe.tsx new file mode 100644 index 00000000..2efc4469 --- /dev/null +++ b/apps/web/src/components/icons/openswe.tsx @@ -0,0 +1,28 @@ +export function OpenSWELogoSVG({ + className, + width = 130, + height = 20, + style, +}: { + width?: number; + height?: number; + className?: string; + style?: React.CSSProperties; +}) { + return ( + + + + ); +} diff --git a/apps/web/src/components/plan/plan-viewer.tsx b/apps/web/src/components/plan/plan-viewer.tsx index 989414e8..8098c6c8 100644 --- a/apps/web/src/components/plan/plan-viewer.tsx +++ b/apps/web/src/components/plan/plan-viewer.tsx @@ -5,6 +5,7 @@ import { TooltipIconButton } from "../ui/tooltip-icon-button"; import { Dispatch, SetStateAction, useState } from "react"; import { Textarea } from "../ui/textarea"; import { Button } from "../ui/button"; +import { MarkdownText } from "../thread/markdown-text"; interface PlanViewerProps { planItems: PlanItem[]; @@ -166,7 +167,7 @@ export function PlanViewer({ className="text-foreground" /> ) : ( -

    {planItems[item.index].plan} -

    + )} {/* Summary for completed tasks */} @@ -184,9 +185,9 @@ export function PlanViewer({

    Summary:

    -

    + {item.summary} -

    +
    )}
    diff --git a/apps/web/src/components/plan/proposed-plan.tsx b/apps/web/src/components/plan/proposed-plan.tsx index bedb6577..f361e860 100644 --- a/apps/web/src/components/plan/proposed-plan.tsx +++ b/apps/web/src/components/plan/proposed-plan.tsx @@ -1,8 +1,8 @@ import { PlanViewer } from "./plan-viewer"; -import { Button } from "../ui/button"; import { useProposedPlan } from "../thread/agent-inbox/hooks/useProposedPlan"; import { PlanItem } from "@open-swe/shared/open-swe/types"; import { useStream } from "@langchain/langgraph-sdk/react"; +import { X, ArrowDown } from "lucide-react"; export function ProposedPlan({ originalPlanItems, @@ -28,21 +28,32 @@ export function ProposedPlan({ setPlanItems={setPlanItems} isProposedPlan={true} /> -
    - - +
    +
    + + + +
    ); diff --git a/apps/web/src/components/tasks/index.tsx b/apps/web/src/components/tasks/index.tsx index b5397126..ca6bd19b 100644 --- a/apps/web/src/components/tasks/index.tsx +++ b/apps/web/src/components/tasks/index.tsx @@ -102,10 +102,12 @@ export function TasksSidebar({ switch (state) { case "completed": return ( - + ); case "current": - return ; + return ( + + ); default: return ; } @@ -140,7 +142,7 @@ export function TasksSidebar({ return (
    @@ -161,7 +163,7 @@ export function TasksSidebar({ variant="ghost" size="sm" onClick={onClose} - className="h-8 w-8 p-0 hover:bg-gray-100 dark:hover:bg-gray-800" + className="h-8 w-8 p-0 hover:bg-gray-100 dark:hover:bg-gray-700/50" > @@ -174,7 +176,7 @@ export function TasksSidebar({ Task
    @@ -340,11 +342,11 @@ export function TasksSidebar({ className={cn( "rounded-full px-2 py-1 text-xs", state === "completed" && - "bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-400", + "bg-green-100/70 text-green-600 dark:bg-green-900/20 dark:text-green-300/90", state === "current" && - "bg-blue-100 text-blue-700 dark:bg-blue-900/30 dark:text-blue-400", + "bg-orange-100 text-orange-700 dark:bg-orange-900/30 dark:text-orange-300", state === "remaining" && - "bg-gray-100 text-gray-700 dark:bg-gray-700 dark:text-gray-300", + "bg-muted dark:bg-muted text-gray-700 dark:text-gray-300", )} > {state === "completed" @@ -373,7 +375,7 @@ export function TasksSidebar({ -
    +
    {item.summary} @@ -412,7 +414,7 @@ export function TaskPlanView({ taskPlan, onTaskChange }: TaskPlanViewProps) { if (taskPlan.tasks.length === 0) { return ( -
    +
    No tasks available
    diff --git a/apps/web/src/components/tasks/progress-bar.tsx b/apps/web/src/components/tasks/progress-bar.tsx index 041437ea..2b55b157 100644 --- a/apps/web/src/components/tasks/progress-bar.tsx +++ b/apps/web/src/components/tasks/progress-bar.tsx @@ -20,7 +20,7 @@ import { HoverCardContent, HoverCardTrigger, } from "@/components/ui/hover-card"; -import { InlineMarkdownText } from "../thread/markdown-text"; +import { InlineMarkdownText } from "@/components/thread/markdown-text"; interface ProgressBarProps { taskPlan?: TaskPlan; @@ -39,7 +39,7 @@ export function ProgressBar({ return (
    @@ -73,7 +73,7 @@ export function ProgressBar({ return (
    @@ -105,7 +105,7 @@ export function ProgressBar({ const getSegmentColor = (state: string) => { switch (state) { case "completed": - return "bg-green-400 dark:bg-green-500"; + return "bg-green-500/90 dark:bg-green-400/80"; case "current": return "bg-blue-400 dark:bg-blue-500"; default: @@ -116,7 +116,7 @@ export function ProgressBar({ return (
    @@ -140,11 +140,12 @@ export function ProgressBar({
    -

    Plan Progress

    -

    +

    Plan Progress

    +

    Shows the current progress of the AI agent's plan execution.

    @@ -165,7 +166,7 @@ export function ProgressBar({ variant="outline" size="sm" onClick={onOpenSidebar} - className="h-6 border-blue-200 text-xs hover:bg-blue-50 dark:border-blue-700 dark:hover:bg-blue-900/20" + className="hover:bg-muted/80 hover:border-muted-foreground/50 h-6 text-xs" > Tasks @@ -176,9 +177,9 @@ export function ProgressBar({
    {showLegend && ( -
    +
    -
    +
    Completed
    diff --git a/apps/web/src/components/thread/ContentBlocksPreview.tsx b/apps/web/src/components/thread/ContentBlocksPreview.tsx index 14fe4aa1..d6068442 100644 --- a/apps/web/src/components/thread/ContentBlocksPreview.tsx +++ b/apps/web/src/components/thread/ContentBlocksPreview.tsx @@ -22,7 +22,7 @@ export const ContentBlocksPreview: React.FC = ({ }) => { if (!blocks.length) return null; return ( -
    +
    {blocks.map((block, idx) => ( = ({ block.mime_type.startsWith("image/") ) { const url = `data:${block.mime_type};base64,${block.data}`; - let imgClass: string = "rounded-md object-cover h-16 w-16 text-lg"; - if (size === "sm") imgClass = "rounded-md object-cover h-10 w-10 text-base"; - if (size === "lg") imgClass = "rounded-md object-cover h-24 w-24 text-xl"; + let imgClass: string = + "rounded-md object-cover h-16 w-16 text-lg shadow-sm ring-1 ring-border"; + if (size === "sm") + imgClass = + "rounded-md object-cover h-10 w-10 text-base shadow-sm ring-1 ring-border"; + if (size === "lg") + imgClass = + "rounded-md object-cover h-24 w-24 text-xl shadow-sm ring-1 ring-border"; return (
    = ({ {removable && ( )}
    @@ -63,20 +68,20 @@ export const MultimodalPreview: React.FC = ({ return (
    {String(filename)} @@ -84,7 +89,7 @@ export const MultimodalPreview: React.FC = ({ {removable && ( - {showReasoning && ( - - {reasoningText} - - )} + + {showReasoning && ( + +
    + + {reasoningText} + +
    +
    + )} +
    )} diff --git a/apps/web/src/components/v2/manager-chat.tsx b/apps/web/src/components/v2/manager-chat.tsx index 84895ae5..f856d217 100644 --- a/apps/web/src/components/v2/manager-chat.tsx +++ b/apps/web/src/components/v2/manager-chat.tsx @@ -5,15 +5,7 @@ import { useState } from "react"; import { StickToBottom } from "use-stick-to-bottom"; import { TooltipIconButton } from "../ui/tooltip-icon-button"; import { AnimatePresence, motion } from "framer-motion"; -import { - Bot, - Copy, - CopyCheck, - Send, - User, - Loader2, - AlertCircle, -} from "lucide-react"; +import { Bot, Copy, CopyCheck, ArrowUp, User, AlertCircle } from "lucide-react"; import { Textarea } from "../ui/textarea"; import { Button } from "../ui/button"; import { cn } from "@/lib/utils"; @@ -21,6 +13,7 @@ import { isAIMessageSDK } from "@/lib/langchain-messages"; import { BasicMarkdownText } from "../thread/markdown-text"; import { ErrorState } from "./types"; import { CollapsibleAlert } from "./collapsible-alert"; +import { Loader2 } from "lucide-react"; function MessageCopyButton({ content }: { content: string }) { const [copied, setCopied] = useState(false); @@ -102,7 +95,7 @@ export function ManagerChat({ errorState, }: ManagerChatProps) { return ( -
    +
    {message.type === "human" ? ( -
    +
    ) : ( -
    - +
    +
    )}
    @@ -166,13 +159,13 @@ export function ManagerChat({
    -
    +