Skip to content

Commit 6291fe1

Browse files
committed
fix status page link
2 parents 812b81e + cebb598 commit 6291fe1

File tree

10 files changed

+371
-242
lines changed

10 files changed

+371
-242
lines changed

components/ai-elements/code-block.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,15 +41,15 @@ export const CodeBlock = ({
4141
margin: 0,
4242
padding: '1rem',
4343
fontSize: '0.875rem',
44-
background: 'hsl(var(--background))',
44+
background: 'hsl(var(--muted) / 0.02)',
4545
color: 'hsl(var(--foreground))',
4646
}
4747

4848
return (
4949
<CodeBlockContext.Provider value={{ code }}>
5050
<div
5151
className={cn(
52-
'relative w-full overflow-hidden rounded-md border bg-background text-foreground',
52+
'relative w-full overflow-hidden rounded-md bg-muted/30 text-foreground',
5353
className,
5454
)}
5555
{...props}

components/ai-elements/prompt-input.tsx

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import type {
66
HTMLAttributes,
77
KeyboardEventHandler,
88
} from "react";
9-
import { Children } from "react";
9+
import { Children, forwardRef } from "react";
1010
import { Button } from "@/components/ui/button";
1111
import {
1212
Select,
@@ -36,14 +36,17 @@ export type PromptInputTextareaProps = ComponentProps<typeof Textarea> & {
3636
maxHeight?: number;
3737
};
3838

39-
export const PromptInputTextarea = ({
39+
export const PromptInputTextarea = forwardRef<
40+
HTMLTextAreaElement,
41+
PromptInputTextareaProps
42+
>(({
4043
onChange,
4144
className,
4245
placeholder = "What would you like to know?",
4346
minHeight = 48,
4447
maxHeight = 164,
4548
...props
46-
}: PromptInputTextareaProps) => {
49+
}, ref) => {
4750
const handleKeyDown: KeyboardEventHandler<HTMLTextAreaElement> = (e) => {
4851
if (e.key === "Enter") {
4952
if (e.shiftKey) {
@@ -62,6 +65,7 @@ export const PromptInputTextarea = ({
6265

6366
return (
6467
<Textarea
68+
ref={ref}
6569
className={cn(
6670
"w-full resize-none rounded-none border-none p-3 shadow-none outline-none ring-0",
6771
"bg-transparent dark:bg-transparent field-sizing-content max-h-[6lh]",
@@ -77,7 +81,8 @@ export const PromptInputTextarea = ({
7781
{...props}
7882
/>
7983
);
80-
};
84+
});
85+
PromptInputTextarea.displayName = "PromptInputTextarea";
8186

8287
export type PromptInputToolbarProps = HTMLAttributes<HTMLDivElement>;
8388

components/ai-elements/reasoning.tsx

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -73,11 +73,10 @@ export const Reasoning = memo(
7373
}
7474
}, [isStreaming, startTime, setDuration]);
7575

76-
// Auto-open when streaming starts, auto-close when streaming ends (once only)
76+
// Keep collapsed by default - don't auto-open when streaming
77+
// Auto-close when streaming ends (once only) if it was opened
7778
useEffect(() => {
78-
if (isStreaming && !isOpen) {
79-
setIsOpen(true);
80-
} else if (!isStreaming && isOpen && !defaultOpen && !hasAutoClosedRef) {
79+
if (!isStreaming && isOpen && !defaultOpen && !hasAutoClosedRef) {
8180
// Add a small delay before closing to allow user to see the content
8281
const timer = setTimeout(() => {
8382
setIsOpen(false);
@@ -122,6 +121,30 @@ export const ReasoningTrigger = memo(
122121
...props
123122
}: ReasoningTriggerProps) => {
124123
const { isStreaming, isOpen, duration } = useReasoning();
124+
const [dots, setDots] = useState("");
125+
126+
useEffect(() => {
127+
if (!isStreaming) {
128+
setDots("");
129+
return;
130+
}
131+
132+
let interval: NodeJS.Timeout;
133+
let dotCount = 0;
134+
135+
const animateDots = () => {
136+
dotCount = (dotCount % 3) + 1;
137+
setDots(".".repeat(dotCount));
138+
};
139+
140+
// Start immediately
141+
animateDots();
142+
interval = setInterval(animateDots, 500);
143+
144+
return () => {
145+
if (interval) clearInterval(interval);
146+
};
147+
}, [isStreaming]);
125148

126149
return (
127150
<CollapsibleTrigger
@@ -135,7 +158,10 @@ export const ReasoningTrigger = memo(
135158
<>
136159
<BrainIcon className="size-4" />
137160
{isStreaming || duration === 0 ? (
138-
<p>Thinking...</p>
161+
<p className="flex items-center">
162+
<span>Thinking</span>
163+
<span className="w-4 inline-block">{dots}</span>
164+
</p>
139165
) : (
140166
<p>Thought for {duration} seconds</p>
141167
)}
@@ -168,7 +194,7 @@ export const ReasoningContent = memo(
168194
)}
169195
{...props}
170196
>
171-
<Response className="grid gap-2">{children}</Response>
197+
<Response className="grid gap-2 text-muted-foreground italic">{children}</Response>
172198
</CollapsibleContent>
173199
)
174200
);

components/ai-elements/response.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ const components: Options["components"] = {
204204
),
205205
a: ({ node, children, className, ...props }) => (
206206
<a
207-
className={cn("font-medium text-primary underline", className)}
207+
className={cn("font-medium text-blue-600 hover:text-blue-800 dark:text-blue-400 dark:hover:text-blue-300 underline", className)}
208208
rel="noreferrer"
209209
target="_blank"
210210
{...props}

components/ai-elements/tool.tsx

Lines changed: 7 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import {
99
XCircleIcon,
1010
} from "lucide-react";
1111
import type { ComponentProps, ReactNode } from "react";
12-
import { Badge } from "@/components/ui/badge";
1312
import {
1413
Collapsible,
1514
CollapsibleContent,
@@ -23,7 +22,7 @@ export type ToolProps = ComponentProps<typeof Collapsible>;
2322

2423
export const Tool = ({ className, ...props }: ToolProps) => (
2524
<Collapsible
26-
className={cn("not-prose mb-4 w-full rounded-md border", className)}
25+
className={cn("not-prose mb-4 w-full rounded-md", className)}
2726
{...props}
2827
/>
2928
);
@@ -34,27 +33,15 @@ export type ToolHeaderProps = {
3433
className?: string;
3534
};
3635

37-
const getStatusBadge = (status: ToolUIPart["state"]) => {
38-
const labels = {
39-
"input-streaming": "Pending",
40-
"input-available": "Running",
41-
"output-available": "Completed",
42-
"output-error": "Error",
43-
} as const;
44-
36+
const getStatusIcon = (status: ToolUIPart["state"]) => {
4537
const icons = {
4638
"input-streaming": <CircleIcon className="size-4" />,
4739
"input-available": <ClockIcon className="size-4 animate-pulse" />,
4840
"output-available": <CheckCircleIcon className="size-4 text-green-600" />,
4941
"output-error": <XCircleIcon className="size-4 text-red-600" />,
5042
} as const;
5143

52-
return (
53-
<Badge className="rounded-full text-xs gap-2" variant="secondary">
54-
{icons[status]}
55-
{labels[status]}
56-
</Badge>
57-
);
44+
return icons[status];
5845
};
5946

6047
export const ToolHeader = ({
@@ -64,15 +51,15 @@ export const ToolHeader = ({
6451
...props
6552
}: ToolHeaderProps) => (
6653
<CollapsibleTrigger
67-
className={cn("flex w-full items-center justify-between gap-4", className)}
54+
className={cn("flex w-full items-center gap-4", className)}
6855
{...props}
6956
>
7057
<div className="flex items-center gap-2">
7158
<WrenchIcon className="size-4 text-muted-foreground" />
72-
<span className="font-medium text-sm">{type}</span>
73-
{getStatusBadge(state)}
59+
<span className="font-medium text-sm text-muted-foreground">{type}</span>
60+
{getStatusIcon(state)}
61+
<ChevronDownIcon className="size-4 text-muted-foreground transition-transform group-data-[state=open]:rotate-180" />
7462
</div>
75-
<ChevronDownIcon className="size-4 text-muted-foreground transition-transform group-data-[state=open]:rotate-180" />
7663
</CollapsibleTrigger>
7764
);
7865

0 commit comments

Comments
 (0)