feat(ui/overview): add click navigation for charts and threat score improvements (#9281)

This commit is contained in:
Alan Buscaglia
2025-11-20 18:47:42 +01:00
committed by GitHub
parent 46bfe02ee8
commit 58bb66ff27
10 changed files with 226 additions and 61 deletions

View File

@@ -18,6 +18,7 @@ interface DonutChartProps {
value: string | number;
label: string;
};
onSegmentClick?: (dataPoint: DonutDataPoint, index: number) => void;
}
const CustomTooltip = ({ active, payload }: any) => {
@@ -72,6 +73,7 @@ export function DonutChart({
outerRadius = 86,
showLegend = true,
centerLabel,
onSegmentClick,
}: DonutChartProps) {
const [hoveredIndex, setHoveredIndex] = useState<number | null>(null);
@@ -137,14 +139,23 @@ export function DonutChart({
{(isEmpty ? emptyData : chartData).map((entry, index) => {
const opacity =
hoveredIndex === null ? 1 : hoveredIndex === index ? 1 : 0.5;
const isClickable = !isEmpty && onSegmentClick;
return (
<Cell
key={`cell-${index}`}
fill={entry.fill}
opacity={opacity}
style={{ transition: "opacity 0.2s" }}
style={{
transition: "opacity 0.2s",
cursor: isClickable ? "pointer" : "default",
}}
onMouseEnter={() => setHoveredIndex(index)}
onMouseLeave={() => setHoveredIndex(null)}
onClick={() => {
if (isClickable) {
onSegmentClick(data[index], index);
}
}}
/>
);
})}

View File

@@ -12,12 +12,14 @@ interface HorizontalBarChartProps {
height?: number;
title?: string;
labelWidth?: string;
onBarClick?: (dataPoint: BarDataPoint, index: number) => void;
}
export function HorizontalBarChart({
data,
title,
labelWidth = "w-20",
onBarClick,
}: HorizontalBarChartProps) {
const [hoveredIndex, setHoveredIndex] = useState<number | null>(null);
@@ -58,12 +60,33 @@ export function HorizontalBarChart({
getSeverityColorByName(item.name) ||
"var(--bg-neutral-tertiary)";
const isClickable = !isEmpty && onBarClick;
return (
<div
key={item.name}
className="flex items-center gap-10"
style={{ cursor: isClickable ? "pointer" : "default" }}
role={isClickable ? "button" : undefined}
tabIndex={isClickable ? 0 : undefined}
onMouseEnter={() => !isEmpty && setHoveredIndex(index)}
onMouseLeave={() => !isEmpty && setHoveredIndex(null)}
onClick={() => {
if (isClickable) {
const originalIndex = data.findIndex(
(d) => d.name === item.name,
);
onBarClick(data[originalIndex], originalIndex);
}
}}
onKeyDown={(e) => {
if (isClickable && (e.key === "Enter" || e.key === " ")) {
e.preventDefault();
const originalIndex = data.findIndex(
(d) => d.name === item.name,
);
onBarClick(data[originalIndex], originalIndex);
}
}}
>
{/* Label */}
<div className={`w-20 md:${labelWidth} shrink-0`}>