Refine selected-agent chat header layout

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
DottaandPaperclip committed 2026-06-16 17:35:36 +00:00
1 parent e913431cf2
commit bc43558c58
2 files changed
+98 -45

No files matched your search

@@ -91,6 +91,10 @@ describe("SelectedAgentChatView", () => {
flushSync(() => root.render(node));
}
function countText(text: string, needle: string): number {
return text.split(needle).length - 1;
}
it("renders the real selected-agent identity in the header", () => {
render(
<SelectedAgentChatView
@@ -106,6 +110,46 @@ describe("SelectedAgentChatView", () => {
expect(container.textContent?.toLowerCase()).not.toContain("concierge");
});
it("uses the left-side selector as the selected-agent identity without repeating the role", () => {
render(
<SelectedAgentChatView
agents={[ceo, eng]}
targetAgentId={ceo.id}
comments={[]}
onSend={async () => {}}
onTargetAgentChange={() => {}}
/>,
);
const header = container.querySelector(
'[data-testid="selected-agent-chat-header"]',
) as HTMLDivElement | null;
const switcher = header?.querySelector('[aria-label="Choose chat agent"]');
expect(switcher).not.toBeNull();
expect(switcher?.textContent).toContain("Sarah");
expect(countText(switcher?.textContent ?? "", "CEO")).toBe(1);
expect(header?.textContent).toBe(switcher?.textContent);
});
it("pads the chat body to align with the selected-agent header", () => {
render(
<SelectedAgentChatView
agents={[ceo]}
targetAgentId={ceo.id}
comments={[]}
onSend={async () => {}}
/>,
);
const body = container.querySelector(
'[data-testid="selected-agent-chat-body"]',
) as HTMLDivElement | null;
expect(body).not.toBeNull();
expect(body?.className).toContain("px-4");
expect(body?.className).toContain("pt-3");
expect(body?.className).toContain("pb-4");
});
it("shows a loading indicator while the first fetch is in flight", () => {
render(
<SelectedAgentChatView agents={[ceo]} targetAgentId={ceo.id} comments={[]} loading onSend={async () => {}} />,
+54 -45
View File
@@ -184,28 +184,14 @@ export function SelectedAgentChatView({
return (
<div className={cn("flex min-h-0 min-w-0 flex-1 flex-col", className)}>
{/* Identity header — real selected agent (no board-concierge persona). */}
<div className="relative flex shrink-0 items-center justify-between gap-2 px-4 py-3">
<div
data-testid="selected-agent-chat-header"
className="relative flex shrink-0 items-center gap-2 px-4 py-3"
>
<div
className="pointer-events-none absolute bottom-0 left-0 right-0 h-px bg-border"
aria-hidden
/>
<div className="flex min-w-0 items-center gap-2">
<Avatar size="sm" className="shrink-0">
<AvatarFallback>
{targetAgent?.icon ? (
<AgentIcon icon={targetAgent.icon} className="h-3.5 w-3.5" />
) : (
agentInitials(targetName)
)}
</AvatarFallback>
</Avatar>
<div className="min-w-0">
<div className="truncate text-sm font-semibold text-foreground">{targetName}</div>
{targetRole ? (
<div className="truncate text-xs text-muted-foreground">{targetRole}</div>
) : null}
</div>
</div>
{canSwitch ? (
<Select
value={targetAgentId ?? undefined}
@@ -213,12 +199,12 @@ export function SelectedAgentChatView({
>
<SelectTrigger
size="sm"
className="w-auto min-w-[9rem] gap-2"
className="h-auto w-auto min-w-0 max-w-full gap-2 px-2 py-1.5"
aria-label="Choose chat agent"
>
<SelectValue placeholder="Choose agent" />
</SelectTrigger>
<SelectContent align="end">
<SelectContent align="start">
{invokableAgents.map((a) => (
<SelectItem key={a.id} value={a.id}>
<span className="flex items-center gap-2">
@@ -232,7 +218,25 @@ export function SelectedAgentChatView({
))}
</SelectContent>
</Select>
) : null}
) : (
<div className="flex min-w-0 items-center gap-2">
<Avatar size="sm" className="shrink-0">
<AvatarFallback>
{targetAgent?.icon ? (
<AgentIcon icon={targetAgent.icon} className="h-3.5 w-3.5" />
) : (
agentInitials(targetName)
)}
</AvatarFallback>
</Avatar>
<div className="min-w-0">
<div className="truncate text-sm font-semibold text-foreground">{targetName}</div>
{targetRole ? (
<div className="truncate text-xs text-muted-foreground">{targetRole}</div>
) : null}
</div>
</div>
)}
</div>
{errorText ? (
@@ -266,30 +270,35 @@ export function SelectedAgentChatView({
<Loader2 className="h-5 w-5 animate-spin" aria-label="Loading conversation" />
</div>
) : (
<IssueChatThread
variant="full"
comments={comments}
interactions={interactions}
liveRuns={liveRuns}
activeRun={activeRun}
feedbackVotes={feedbackVotes}
issueId={issueId}
companyId={companyId}
projectId={projectId}
agentMap={agentMap}
currentUserId={currentUserId}
mentions={mentions}
emptyMessage={
emptyMessage ?? `Send ${targetName} a message to start the conversation.`
}
onAdd={handleAdd}
onStopRun={onStopRun}
onVote={onVote}
onAcceptInteraction={onAcceptInteraction}
onRejectInteraction={onRejectInteraction}
onSubmitInteractionAnswers={onSubmitInteractionAnswers}
onCancelInteraction={onCancelInteraction}
/>
<div
data-testid="selected-agent-chat-body"
className="min-w-0 px-4 pb-4 pt-3"
>
<IssueChatThread
variant="full"
comments={comments}
interactions={interactions}
liveRuns={liveRuns}
activeRun={activeRun}
feedbackVotes={feedbackVotes}
issueId={issueId}
companyId={companyId}
projectId={projectId}
agentMap={agentMap}
currentUserId={currentUserId}
mentions={mentions}
emptyMessage={
emptyMessage ?? `Send ${targetName} a message to start the conversation.`
}
onAdd={handleAdd}
onStopRun={onStopRun}
onVote={onVote}
onAcceptInteraction={onAcceptInteraction}
onRejectInteraction={onRejectInteraction}
onSubmitInteractionAnswers={onSubmitInteractionAnswers}
onCancelInteraction={onCancelInteraction}
/>
</div>
)}
</div>
);