diff --git a/packages/dashboard/app/components/AgentsView.css b/packages/dashboard/app/components/AgentsView.css
index c7d306c698..fd77e6d5d8 100644
--- a/packages/dashboard/app/components/AgentsView.css
+++ b/packages/dashboard/app/components/AgentsView.css
@@ -608,10 +608,16 @@ FN-6774 removes the saturated left-edge status stripe from split-sidebar agent c
box-shadow: inset 0 0 0 calc(var(--space-xs) / 4) var(--todo);
}
+/*
+FNXC:AgentsView 2026-07-23-12:26:
+Agent-card identity and every visible status badge must remain in separate layout allocations at desktop, split-sidebar, and mobile widths. Let both regions shrink and wrap, while identity text breaks inside its own allocation, so long names or populated health/role/skill badges never paint over one another.
+*/
.agent-card-header {
display: flex;
justify-content: space-between;
align-items: flex-start;
+ flex-wrap: wrap;
+ gap: var(--space-sm);
margin-bottom: var(--space-md);
}
@@ -619,6 +625,8 @@ FN-6774 removes the saturated left-edge status stripe from split-sidebar agent c
display: flex;
align-items: center;
gap: var(--space-md);
+ flex: 1 1 auto;
+ min-width: 0;
}
.agent-info--clickable {
@@ -680,6 +688,7 @@ FN-6774 removes the saturated left-edge status stripe from split-sidebar agent c
.agent-meta {
display: flex;
flex-direction: column;
+ min-width: 0;
}
.agent-name {
@@ -692,14 +701,29 @@ FN-6774 removes the saturated left-edge status stripe from split-sidebar agent c
font-family: var(--font-mono);
}
+.agent-name,
+.agent-id {
+ min-width: 0;
+ max-width: 100%;
+ overflow-wrap: anywhere;
+}
+
.agent-badges {
display: flex;
+ flex: 0 1 auto;
gap: var(--space-sm);
flex-wrap: wrap;
min-width: 0;
+ max-width: 100%;
justify-content: flex-end;
}
+.agent-badges .badge {
+ max-width: 100%;
+ white-space: normal;
+ overflow-wrap: anywhere;
+}
+
.agent-approval-badge {
display: inline-flex;
align-items: center;
@@ -712,6 +736,7 @@ FN-6774 removes the saturated left-edge status stripe from split-sidebar agent c
max-width: min(100%, calc(var(--space-2xl) * 6));
overflow: hidden;
text-overflow: ellipsis;
+ white-space: nowrap;
}
.agent-card-chevron {
@@ -1582,4 +1607,17 @@ AgentsView uses the measured SVG overlay as the single connector system so paren
overscroll-behavior: contain;
padding: var(--space-md) var(--space-md) calc(var(--space-md) + env(safe-area-inset-bottom, 0px) + var(--standalone-bottom-gap));
}
+
+ .agents-view .agent-card-header {
+ flex-direction: column;
+ align-items: stretch;
+ }
+
+ .agents-view .agent-info {
+ min-width: 0;
+ }
+
+ .agents-view .agent-badges {
+ justify-content: flex-start;
+ }
}
diff --git a/packages/dashboard/app/components/__tests__/AgentsView.test.tsx b/packages/dashboard/app/components/__tests__/AgentsView.test.tsx
index 5bdcc9575d..7fedde9290 100644
--- a/packages/dashboard/app/components/__tests__/AgentsView.test.tsx
+++ b/packages/dashboard/app/components/__tests__/AgentsView.test.tsx
@@ -910,6 +910,45 @@ describe("AgentsView", () => {
expect(css).toContain(".agents-split-sidebar .agent-card-actions .agent-card-action-label {\n display: none;\n }");
});
+ it("keeps long agent identities and populated health badges readable in split-sidebar cards", async () => {
+ const collisionAgent: Agent = {
+ ...mockAgents[1],
+ id: "agent-marketing-manager",
+ name: "Marketing Manager",
+ role: "custom",
+ state: "active",
+ runtimeConfig: { enabled: false },
+ metadata: {
+ skills: ["auto::skills/../../.agents/skills/brand-strategy/SKILL.md", "auto::skills/../../.agents/skills/campaign-analytics/SKILL.md"],
+ },
+ };
+ mockFetchAgents.mockResolvedValueOnce([collisionAgent]);
+ mockFetchAgentStats.mockResolvedValueOnce({ total: 1, byState: { active: 1 }, byRole: { custom: 1 } });
+
+ const { container } = renderView();
+
+ const card = await waitFor(() => {
+ const renderedCard = container.querySelector(".agents-split-sidebar .agent-card");
+ expect(renderedCard).toBeTruthy();
+ return renderedCard!;
+ });
+
+ expect(within(card).getByText("Marketing Manager")).toBeInTheDocument();
+ expect(within(card).getByText("agent-marketing-manager")).toBeInTheDocument();
+ expect(within(card).getByText("active")).toBeInTheDocument();
+ expect(within(card).getByText("Heartbeat Disabled")).toBeInTheDocument();
+ expect(within(card).getByText("Custom")).toBeInTheDocument();
+ expect(within(card).getByText("brand-strategy")).toBeInTheDocument();
+ expect(within(card).getByText("campaign-analytics")).toBeInTheDocument();
+
+ const css = loadAllAppCss();
+ expect(css).toMatch(/\.agent-card-header\s*\{[^}]*flex-wrap:\s*wrap;[^}]*gap:\s*var\(--space-sm\);[^}]*\}/);
+ expect(css).toMatch(/\.agent-info\s*\{[^}]*flex:\s*1 1 auto;[^}]*min-width:\s*0;[^}]*\}/);
+ expect(css).toMatch(/\.agent-meta\s*\{[^}]*min-width:\s*0;[^}]*\}/);
+ expect(css).toMatch(/\.agent-name,\s*\.agent-id\s*\{[^}]*overflow-wrap:\s*anywhere;[^}]*\}/);
+ expect(css).toMatch(/\.agent-badges\s*\{[^}]*flex:\s*0 1 auto;[^}]*flex-wrap:\s*wrap;[^}]*min-width:\s*0;[^}]*\}/);
+ });
+
it("opens matching detail view when clicking View Details button", async () => {
renderView();
diff --git a/packages/dashboard/app/components/__tests__/agents-view-mobile.test.tsx b/packages/dashboard/app/components/__tests__/agents-view-mobile.test.tsx
index 71d75d8642..81eee4067b 100644
--- a/packages/dashboard/app/components/__tests__/agents-view-mobile.test.tsx
+++ b/packages/dashboard/app/components/__tests__/agents-view-mobile.test.tsx
@@ -314,6 +314,18 @@ describe("agents-view mobile CSS", () => {
expect(block).toContain("flex-wrap: wrap");
});
+ it("stacks card identity and populated badges on narrow mobile cards", () => {
+ const headerBlock = extractRuleBlock(mobileMediaBlock, ".agents-view .agent-card-header");
+ expect(headerBlock).toContain("flex-direction: column");
+ expect(headerBlock).toContain("align-items: stretch");
+
+ const infoBlock = extractRuleBlock(mobileMediaBlock, ".agents-view .agent-info");
+ expect(infoBlock).toContain("min-width: 0");
+
+ const badgesBlock = extractRuleBlock(mobileMediaBlock, ".agents-view .agent-badges");
+ expect(badgesBlock).toContain("justify-content: flex-start");
+ });
+
it("defines mobile org chart sizing and pan/zoom controls rules", () => {
expect(extractRuleBlock(mobileMediaBlock, ".agent-org-chart-controls")).toContain("display: flex");
expect(extractRuleBlock(mobileMediaBlock, ".agent-org-chart-controls")).toContain("gap: var(--space-sm)");