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:
@@ -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 && (
|
||||
|
||||
@@ -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", () => {
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user