import { ChevronDown, Copy, Download, FileWarning, Info, TriangleAlert, } from "lucide-react"; import type { CategoryTab, ExportPayload, LighthouseIssue, LighthouseMetrics, LighthouseScores, } from "./types"; import { LighthouseIssueRow } from "./LighthouseIssueRow"; import { LighthouseIssuesSummary } from "./LighthouseIssuesSummary"; import { categoryLabel } from "./utils"; import { categoryTabs } from "./types"; export function LighthouseIssuesHeader({ backLabel, onBack, scannedAt, finalUrl, scores, metrics, severityCounts, }: { backLabel: string; onBack: () => void; scannedAt?: string; finalUrl?: string; scores?: LighthouseScores | null; metrics?: LighthouseMetrics | null; severityCounts: { critical: number; warning: number; info: number }; }) { return ( <>
{scannedAt ? `Scanned ${new Date(scannedAt).toLocaleString()}` : "Reading latest issues..."}

Lighthouse Issues

{finalUrl ?? "Loading URL..."}

Critical {severityCounts.critical} Warning {severityCounts.warning} Info {severityCounts.info}
); } export function LighthouseIssuesToolbar({ category, categoryCounts, selectedCategoryLabel, isBusy, visibleIssues, allIssues, onCategoryChange, onCopy, onExport, onExportCsv, }: { category: CategoryTab; categoryCounts: Record; selectedCategoryLabel: string; isBusy: boolean; visibleIssues: LighthouseIssue[]; allIssues: LighthouseIssue[]; onCategoryChange: (next: CategoryTab) => void; onCopy: (data: ExportPayload, toastMessage: string) => void; onExport: (data: ExportPayload) => void; onExportCsv: (issues: LighthouseIssue[], variant: "all" | "current") => void; }) { const exportCurrentCategory: ExportPayload = category === "all" ? { mode: "issues" } : { mode: "category", category }; const categoryLabelLower = selectedCategoryLabel.toLowerCase(); return (
); } function CategoryTabs({ category, categoryCounts, onCategoryChange, }: { category: CategoryTab; categoryCounts: Record; onCategoryChange: (next: CategoryTab) => void; }) { return (
{categoryTabs.map((tab) => ( ))}
); } function ExportMenu({ allIssues, categoryLabelLower, exportCurrentCategory, isBusy, onCopy, onExport, onExportCsv, visibleIssues, }: { allIssues: LighthouseIssue[]; categoryLabelLower: string; exportCurrentCategory: ExportPayload; isBusy: boolean; onCopy: (data: ExportPayload, toastMessage: string) => void; onExport: (data: ExportPayload) => void; onExportCsv: (issues: LighthouseIssue[], variant: "all" | "current") => void; visibleIssues: LighthouseIssue[]; }) { return (
Export
  • Copy
  • Download JSON
  • Download CSV
); } export function LighthouseIssueList({ issues, isLoading, emptyMessage, }: { issues: LighthouseIssue[]; isLoading: boolean; emptyMessage?: string; }) { if (isLoading) { return

Loading issues...

; } if (!issues.length) { return (

{emptyMessage ?? "No actionable issues for this category."}

); } return ( {issues.map((issue, issueIndex) => ( ))}
Severity Issue Category Impact Score
); }