fix(FN-2022): correct insights status badge classes and mobile wrapping

- Fix status badge class interpolation in InsightsView so status-specific modifiers render correctly
- Add regression tests that assert generated and confirmed statuses map to the right badge classes
- Improve mobile insights layout by allowing action/meta rows to wrap and preventing title overflow
- Increase mobile icon button touch targets in insight item actions
This commit is contained in:
Fusion
2026-04-17 20:16:23 -07:00
committed by gsxdsm
parent c6377a91d4
commit a0cf637c66
3 changed files with 118 additions and 1 deletions

View File

@@ -216,7 +216,7 @@ export function InsightsView({ projectId, addToast, onClose, onCreateTask }: Ins
<p className="insight-item-content">{insight.content}</p>
)}
<div className="insight-item-meta">
<span className="insight-item-status insight-item-status--{insight.status}">
<span className={`insight-item-status insight-item-status--${insight.status}`}>
{insight.status}
</span>
{insight.createdAt && (

View File

@@ -270,6 +270,108 @@ describe("InsightsView", () => {
expect(screen.getByTestId("insights-empty-architecture")).toBeInTheDocument();
expect(screen.getByTestId("insights-empty-architecture")).toHaveTextContent("No insights in this category");
});
it("should render status badge with correct CSS class for generated status", () => {
const sectionsWithInsight = [
{
category: "features" as const,
label: "Features",
items: [
{
id: "INS-1",
projectId: "test",
title: "Test Insight",
content: "Content",
category: "features" as const,
status: "generated" as const,
fingerprint: "fp1",
provenance: { trigger: "manual" as const },
lastRunId: null,
createdAt: "2024-01-01T00:00:00Z",
updatedAt: "2024-01-01T00:00:00Z",
},
],
isLoading: false,
error: null,
},
...mockSections.slice(1),
];
mockUseInsights.mockReturnValue({
sections: sectionsWithInsight,
loading: false,
error: null,
latestRun: null,
isRunInFlight: false,
runError: null,
refresh: vi.fn(),
runInsights: vi.fn(),
dismiss: vi.fn(),
createTask: vi.fn(),
dismissStates: new Map(),
createTaskStates: new Map(),
totalCount: 1,
dismissedCount: 0,
});
render(<InsightsView {...defaultProps} />);
// Verify the status badge has the correct interpolated CSS class
const statusBadge = screen.getByText("generated").closest("span");
expect(statusBadge).toHaveClass("insight-item-status");
expect(statusBadge).toHaveClass("insight-item-status--generated");
});
it("should render status badge with correct CSS class for confirmed status", () => {
const sectionsWithInsight = [
{
category: "features" as const,
label: "Features",
items: [
{
id: "INS-2",
projectId: "test",
title: "Confirmed Insight",
content: "Content",
category: "features" as const,
status: "confirmed" as const,
fingerprint: "fp2",
provenance: { trigger: "manual" as const },
lastRunId: null,
createdAt: "2024-01-01T00:00:00Z",
updatedAt: "2024-01-01T00:00:00Z",
},
],
isLoading: false,
error: null,
},
...mockSections.slice(1),
];
mockUseInsights.mockReturnValue({
sections: sectionsWithInsight,
loading: false,
error: null,
latestRun: null,
isRunInFlight: false,
runError: null,
refresh: vi.fn(),
runInsights: vi.fn(),
dismiss: vi.fn(),
createTask: vi.fn(),
dismissStates: new Map(),
createTaskStates: new Map(),
totalCount: 1,
dismissedCount: 0,
});
render(<InsightsView {...defaultProps} />);
// Verify the status badge has the correct interpolated CSS class
const statusBadge = screen.getByText("confirmed").closest("span");
expect(statusBadge).toHaveClass("insight-item-status");
expect(statusBadge).toHaveClass("insight-item-status--confirmed");
});
});
describe("actions", () => {

View File

@@ -35503,6 +35503,7 @@ html .column.drag-over * {
.insights-view-actions {
width: 100%;
justify-content: flex-end;
flex-wrap: wrap;
}
.insights-sections {
@@ -35522,15 +35523,29 @@ html .column.drag-over * {
padding: var(--space-sm);
}
.insight-item-title {
word-break: break-word;
}
.insight-item-header {
flex-direction: column;
gap: var(--space-sm);
}
.insight-item-meta {
flex-wrap: wrap;
gap: var(--space-sm);
}
.insight-item-actions {
align-self: flex-end;
}
.insight-item-actions .btn-icon {
min-width: 36px;
min-height: 36px;
}
.post-onboarding-recommendations {
flex-direction: column;
align-items: stretch;