Skip to content

Commit ae7090c

Browse files
chore: properly show agents description (#2534)
1 parent bbe2d1e commit ae7090c

File tree

3 files changed

+127
-31
lines changed

3 files changed

+127
-31
lines changed

platform/frontend/src/components/agent-dialog.tsx

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import {
3636
DialogHeader,
3737
DialogTitle,
3838
} from "@/components/ui/dialog";
39+
import { ExpandableText } from "@/components/ui/expandable-text";
3940
import { Input } from "@/components/ui/input";
4041
import { Label } from "@/components/ui/label";
4142
import { MultiSelectCombobox } from "@/components/ui/multi-select-combobox";
@@ -137,10 +138,12 @@ function SubagentPill({ agent, isSelected, onToggle }: SubagentPillProps) {
137138
<div className="p-4 border-b flex items-start justify-between gap-2">
138139
<div className="flex-1 min-w-0">
139140
<h4 className="font-semibold truncate">{agent.name}</h4>
140-
{(agent.description || agent.systemPrompt) && (
141-
<p className="text-sm text-muted-foreground mt-1 line-clamp-2">
142-
{agent.description || agent.systemPrompt}
143-
</p>
141+
{agent.description && (
142+
<ExpandableText
143+
text={agent.description}
144+
maxLines={2}
145+
className="text-sm text-muted-foreground mt-1"
146+
/>
144147
)}
145148
</div>
146149
<Button

platform/frontend/src/components/chat/agent-tools-display.tsx

Lines changed: 23 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
import { Bot, Wrench } from "lucide-react";
44
import { type ReactNode, useCallback, useEffect, useState } from "react";
55
import { Button } from "@/components/ui/button";
6+
import { Checkbox } from "@/components/ui/checkbox";
7+
import { ExpandableText } from "@/components/ui/expandable-text";
68
import {
79
HoverCard,
810
HoverCardContent,
@@ -153,35 +155,29 @@ export function AgentToolsDisplay({
153155
<span>{delegatedAgent.name}</span>
154156
</Button>
155157
</HoverCardTrigger>
156-
<HoverCardContent
157-
className="w-80 cursor-pointer"
158-
align="start"
159-
onClick={() => handleToggle(delegatedAgent.id)}
160-
>
161-
<div className="space-y-2">
162-
<div className="flex items-center justify-between">
163-
<h4 className="text-sm font-semibold">
164-
{delegatedAgent.name}
165-
</h4>
166-
<span
167-
className={cn(
168-
"text-xs px-2 py-0.5 rounded",
169-
enabled
170-
? "bg-green-100 text-green-700"
171-
: "bg-red-100 text-red-700",
172-
)}
173-
>
174-
{enabled ? "Enabled" : "Disabled"}
175-
</span>
176-
</div>
158+
<HoverCardContent className="w-80" align="start">
159+
<div className="space-y-3">
160+
<h4 className="text-sm font-semibold">{delegatedAgent.name}</h4>
177161
{delegatedAgent.description && (
178-
<p className="text-xs text-muted-foreground">
179-
{delegatedAgent.description}
180-
</p>
162+
<ExpandableText
163+
text={delegatedAgent.description}
164+
maxLines={2}
165+
className="text-xs text-muted-foreground"
166+
/>
181167
)}
182-
<p className="text-xs text-muted-foreground">
183-
Click to {enabled ? "disable" : "enable"} this agent
184-
</p>
168+
<label
169+
htmlFor={`chat-subagent-toggle-${delegatedAgent.id}`}
170+
className="flex items-center gap-3 cursor-pointer"
171+
>
172+
<Checkbox
173+
id={`chat-subagent-toggle-${delegatedAgent.id}`}
174+
checked={enabled}
175+
onCheckedChange={() => handleToggle(delegatedAgent.id)}
176+
/>
177+
<span className="text-sm font-medium">
178+
{enabled ? "Enabled" : "Enable"}
179+
</span>
180+
</label>
185181
<AgentToolsList agentId={delegatedAgent.id} />
186182
</div>
187183
</HoverCardContent>
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
"use client";
2+
3+
import { useEffect, useRef, useState } from "react";
4+
import { cn } from "@/lib/utils";
5+
6+
interface ExpandableTextProps {
7+
text: string;
8+
maxLines?: number;
9+
className?: string;
10+
}
11+
12+
export function ExpandableText({
13+
text,
14+
maxLines = 2,
15+
className,
16+
}: ExpandableTextProps) {
17+
const [isExpanded, setIsExpanded] = useState(false);
18+
const [isTruncated, setIsTruncated] = useState(false);
19+
const containerRef = useRef<HTMLDivElement>(null);
20+
const measureRef = useRef<HTMLParagraphElement>(null);
21+
const clampedRef = useRef<HTMLParagraphElement>(null);
22+
23+
// Check truncation by comparing heights (only when collapsed)
24+
// biome-ignore lint/correctness/useExhaustiveDependencies: intentionally re-run when text/maxLines props change
25+
useEffect(() => {
26+
// Skip truncation check when expanded - both elements have same height when expanded
27+
if (isExpanded) return;
28+
29+
const checkTruncation = () => {
30+
const measureEl = measureRef.current;
31+
const clampedEl = clampedRef.current;
32+
if (!measureEl || !clampedEl) return;
33+
34+
// Compare unclamped height to clamped height
35+
const fullHeight = measureEl.offsetHeight;
36+
const clampedHeight = clampedEl.offsetHeight;
37+
38+
setIsTruncated(fullHeight > clampedHeight + 2); // 2px tolerance
39+
};
40+
41+
// Small delay to ensure DOM is updated
42+
const timeoutId = setTimeout(checkTruncation, 0);
43+
44+
// Also check on resize
45+
const container = containerRef.current;
46+
if (!container) return () => clearTimeout(timeoutId);
47+
48+
const resizeObserver = new ResizeObserver(checkTruncation);
49+
resizeObserver.observe(container);
50+
51+
return () => {
52+
clearTimeout(timeoutId);
53+
resizeObserver.disconnect();
54+
};
55+
}, [text, maxLines, isExpanded]);
56+
57+
return (
58+
<div ref={containerRef} className={cn("relative", className)}>
59+
{/* Hidden element for measuring full text height */}
60+
<p
61+
ref={measureRef}
62+
aria-hidden="true"
63+
className="invisible absolute top-0 left-0 right-0 pointer-events-none break-words"
64+
>
65+
{text}
66+
</p>
67+
68+
{/* Visible clamped text */}
69+
<p
70+
ref={clampedRef}
71+
className={cn("break-words", !isExpanded && `line-clamp-${maxLines}`)}
72+
style={
73+
!isExpanded
74+
? {
75+
display: "-webkit-box",
76+
WebkitLineClamp: maxLines,
77+
WebkitBoxOrient: "vertical",
78+
overflow: "hidden",
79+
}
80+
: undefined
81+
}
82+
>
83+
{text}
84+
</p>
85+
86+
{isTruncated && (
87+
<button
88+
type="button"
89+
onClick={() => setIsExpanded(!isExpanded)}
90+
className="text-primary hover:underline text-inherit mt-1"
91+
>
92+
{isExpanded ? "Show less" : "Show more"}
93+
</button>
94+
)}
95+
</div>
96+
);
97+
}

0 commit comments

Comments
 (0)