feat(phase-27): add advanced ATT&CK Navigator-style heatmap with layers, filters and export (T-221 to T-223)
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
interface HeatmapLegendProps {
|
||||
layerType: "coverage" | "threat-actor" | "detection-rules" | "campaign";
|
||||
}
|
||||
|
||||
const LEGENDS: Record<
|
||||
string,
|
||||
{ label: string; colors: { color: string; label: string }[] }
|
||||
> = {
|
||||
coverage: {
|
||||
label: "Coverage Status",
|
||||
colors: [
|
||||
{ color: "#d3d3d3", label: "Not Evaluated (0)" },
|
||||
{ color: "#ff6666", label: "Not Covered (10)" },
|
||||
{ color: "#ff9933", label: "In Progress (30)" },
|
||||
{ color: "#ffff66", label: "Partial (60)" },
|
||||
{ color: "#66ff66", label: "Validated (100)" },
|
||||
],
|
||||
},
|
||||
"threat-actor": {
|
||||
label: "Threat Actor Coverage",
|
||||
colors: [
|
||||
{ color: "#d3d3d3", label: "Not Used by Actor" },
|
||||
{ color: "#ff6666", label: "Not Covered (10)" },
|
||||
{ color: "#ff9933", label: "In Progress (30)" },
|
||||
{ color: "#ffff66", label: "Partial (60)" },
|
||||
{ color: "#66ff66", label: "Covered (100)" },
|
||||
],
|
||||
},
|
||||
"detection-rules": {
|
||||
label: "Detection Rules Coverage",
|
||||
colors: [
|
||||
{ color: "#d3d3d3", label: "No Rules (0)" },
|
||||
{ color: "#ff6666", label: "Few Rules (<25)" },
|
||||
{ color: "#ff9933", label: "Some Rules (25-50)" },
|
||||
{ color: "#ffff66", label: "Good Coverage (50-75)" },
|
||||
{ color: "#66ff66", label: "Full Coverage (75-100)" },
|
||||
],
|
||||
},
|
||||
campaign: {
|
||||
label: "Campaign Progress",
|
||||
colors: [
|
||||
{ color: "#ff6666", label: "Draft / Rejected" },
|
||||
{ color: "#ff9933", label: "Red Executing (30)" },
|
||||
{ color: "#ffff66", label: "Blue Evaluating (50)" },
|
||||
{ color: "#66ff66", label: "Validated (100)" },
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
export default function HeatmapLegend({ layerType }: HeatmapLegendProps) {
|
||||
const legend = LEGENDS[layerType] || LEGENDS.coverage;
|
||||
|
||||
return (
|
||||
<div className="flex flex-wrap items-center gap-4 rounded-xl border border-gray-800 bg-gray-900 p-4">
|
||||
<span className="text-sm font-medium text-gray-400">{legend.label}:</span>
|
||||
|
||||
{/* Gradient bar */}
|
||||
<div className="flex items-center gap-1">
|
||||
<div
|
||||
className="h-3 w-40 rounded"
|
||||
style={{
|
||||
background: `linear-gradient(to right, ${legend.colors.map((c) => c.color).join(", ")})`,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Individual labels */}
|
||||
{legend.colors.map((item) => (
|
||||
<div key={item.label} className="flex items-center gap-1.5">
|
||||
<div
|
||||
className="h-3 w-3 rounded border border-gray-700"
|
||||
style={{ backgroundColor: item.color }}
|
||||
/>
|
||||
<span className="text-xs text-gray-400">{item.label}</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user