From e5364911bbdc50c2c54ee29179a45bd05f38c1ef Mon Sep 17 00:00:00 2001 From: Alan Buscaglia Date: Wed, 22 Oct 2025 10:19:12 +0200 Subject: [PATCH] feat: implement comprehensive light/dark theme support for all chart components - Add CSS variables to all chart tooltips and components for dynamic theme switching - Update AlertPill component to use theme-aware colors (--chart-alert-bg, --chart-alert-text) - Change all alert icons to use red color (--chart-fail) consistently across charts - Add ScatterDataPoint type to centralized types.ts - Fix scatter-plot-with-selection component type definitions and imports - Migrate shadcn Select component to shared folder structure - Update ThreatMap to use shadcn Select instead of native select element - Ensure all graph components dynamically update colors when theme toggles This enables seamless light/dark theme support across: - ChartTooltip and MultiSeriesChartTooltip - LineChart, RadarChart, ScatterPlot custom tooltips - AlertPill and icon coloring - All form elements now use shadcn components --- ui/app/(prowler)/page.tsx | 749 ------------------ ui/components/graphs/donut-chart.tsx | 5 +- ui/components/graphs/horizontal-bar-chart.tsx | 2 +- ui/components/graphs/line-chart.tsx | 20 +- ui/components/graphs/radar-chart.tsx | 4 +- ui/components/graphs/radial-chart.tsx | 5 +- ui/components/graphs/sankey-chart.tsx | 5 +- ui/components/graphs/scatter-plot.tsx | 9 +- ui/components/graphs/shared/alert-pill.tsx | 13 +- ui/components/graphs/shared/chart-tooltip.tsx | 65 +- ui/components/graphs/threat-map.tsx | 48 +- ui/components/graphs/types.ts | 8 + .../overview/radar-chart-with-selection.tsx | 38 - .../overview/scatter-plot-with-selection.tsx | 40 - ui/components/shared/shadcn/index.tsx | 1 + .../{ui => shared/shadcn}/select/Select.tsx | 0 ui/components/shared/shadcn/select/index.ts | 12 + ui/components/ui/index.ts | 1 - .../ui/table/data-table-pagination.tsx | 7 +- 19 files changed, 141 insertions(+), 891 deletions(-) delete mode 100644 ui/components/overview/radar-chart-with-selection.tsx delete mode 100644 ui/components/overview/scatter-plot-with-selection.tsx create mode 100644 ui/components/shared/shadcn/index.tsx rename ui/components/{ui => shared/shadcn}/select/Select.tsx (100%) create mode 100644 ui/components/shared/shadcn/select/index.ts diff --git a/ui/app/(prowler)/page.tsx b/ui/app/(prowler)/page.tsx index 857251c08f..29ebeb06bf 100644 --- a/ui/app/(prowler)/page.tsx +++ b/ui/app/(prowler)/page.tsx @@ -8,24 +8,12 @@ import { getProvidersOverview, } from "@/actions/overview/overview"; import { FilterControls } from "@/components/filters"; -import { - DonutChart, - HorizontalBarChart, - LineChart, - RadarChart, - RadialChart, - SankeyChart, - ScatterPlot, - ThreatMap, -} from "@/components/graphs"; import { LighthouseBanner } from "@/components/lighthouse"; import { FindingsBySeverityChart, FindingsByStatusChart, LinkToFindings, ProvidersOverview, - RadarChartWithSelection, - ScatterPlotWithSelection, SkeletonFindingsBySeverityChart, SkeletonFindingsByStatusChart, SkeletonProvidersOverview, @@ -39,659 +27,6 @@ import { FindingProps, SearchParamsProps } from "@/types"; const FILTER_PREFIX = "filter["; -// Sample data for ThreatMap component -const RISK_LEVELS = { - LOW_HIGH: "low-high", - HIGH: "high", - CRITICAL: "critical", -} as const; - -const sampleThreatMapData = { - regions: ["US East", "US West", "Europe", "Asia Pacific", "South America"], - locations: [ - { - id: "us-east-1", - name: "US East-1", - region: "US East", - coordinates: [-77.4875, 39.0438] as [number, number], - totalFindings: 455, - riskLevel: RISK_LEVELS.LOW_HIGH, - change: 21, - severityData: [ - { name: "Info", value: 10, percentage: 3, color: "var(--chart-info)" }, - { - name: "Low", - value: 543, - percentage: 25, - color: "var(--chart-warning)", - }, - { - name: "Medium", - value: 221, - percentage: 18, - color: "var(--chart-warning-emphasis)", - }, - { - name: "High", - value: 1232, - percentage: 32, - color: "var(--chart-danger)", - }, - { - name: "Critical", - value: 432, - percentage: 22, - color: "var(--chart-danger-emphasis)", - }, - ], - }, - { - id: "us-west-2", - name: "US West-2", - region: "US West", - coordinates: [-121.7269, 45.6387] as [number, number], - totalFindings: 324, - riskLevel: RISK_LEVELS.HIGH, - severityData: [ - { name: "Info", value: 8, percentage: 2, color: "var(--chart-info)" }, - { - name: "Low", - value: 89, - percentage: 15, - color: "var(--chart-warning)", - }, - { - name: "Medium", - value: 156, - percentage: 28, - color: "var(--chart-warning-emphasis)", - }, - { - name: "High", - value: 187, - percentage: 35, - color: "var(--chart-danger)", - }, - { - name: "Critical", - value: 124, - percentage: 20, - color: "var(--chart-danger-emphasis)", - }, - ], - }, - { - id: "eu-west-1", - name: "EU West-1", - region: "Europe", - coordinates: [-6.2603, 53.3498] as [number, number], - totalFindings: 567, - riskLevel: RISK_LEVELS.CRITICAL, - change: 15, - severityData: [ - { name: "Info", value: 12, percentage: 2, color: "var(--chart-info)" }, - { - name: "Low", - value: 98, - percentage: 10, - color: "var(--chart-warning)", - }, - { - name: "Medium", - value: 203, - percentage: 22, - color: "var(--chart-warning-emphasis)", - }, - { - name: "High", - value: 354, - percentage: 38, - color: "var(--chart-danger)", - }, - { - name: "Critical", - value: 267, - percentage: 28, - color: "var(--chart-danger-emphasis)", - }, - ], - }, - { - id: "eu-central-1", - name: "EU Central-1", - region: "Europe", - coordinates: [8.6821, 50.1109] as [number, number], - totalFindings: 289, - riskLevel: RISK_LEVELS.LOW_HIGH, - severityData: [ - { name: "Info", value: 15, percentage: 5, color: "var(--chart-info)" }, - { - name: "Low", - value: 134, - percentage: 32, - color: "var(--chart-warning)", - }, - { - name: "Medium", - value: 87, - percentage: 22, - color: "var(--chart-warning-emphasis)", - }, - { - name: "High", - value: 103, - percentage: 28, - color: "var(--chart-danger)", - }, - { - name: "Critical", - value: 43, - percentage: 13, - color: "var(--chart-danger-emphasis)", - }, - ], - }, - { - id: "ap-northeast-1", - name: "AP Northeast-1", - region: "Asia Pacific", - coordinates: [139.6917, 35.6895] as [number, number], - totalFindings: 412, - riskLevel: RISK_LEVELS.HIGH, - severityData: [ - { name: "Info", value: 9, percentage: 2, color: "var(--chart-info)" }, - { - name: "Low", - value: 87, - percentage: 18, - color: "var(--chart-warning)", - }, - { - name: "Medium", - value: 145, - percentage: 26, - color: "var(--chart-warning-emphasis)", - }, - { - name: "High", - value: 198, - percentage: 34, - color: "var(--chart-danger)", - }, - { - name: "Critical", - value: 112, - percentage: 20, - color: "var(--chart-danger-emphasis)", - }, - ], - }, - { - id: "ap-southeast-1", - name: "AP Southeast-1", - region: "Asia Pacific", - coordinates: [103.8198, 1.3521] as [number, number], - totalFindings: 378, - riskLevel: RISK_LEVELS.HIGH, - severityData: [ - { name: "Info", value: 11, percentage: 3, color: "var(--chart-info)" }, - { - name: "Low", - value: 76, - percentage: 16, - color: "var(--chart-warning)", - }, - { - name: "Medium", - value: 132, - percentage: 25, - color: "var(--chart-warning-emphasis)", - }, - { - name: "High", - value: 187, - percentage: 36, - color: "var(--chart-danger)", - }, - { - name: "Critical", - value: 94, - percentage: 20, - color: "var(--chart-danger-emphasis)", - }, - ], - }, - { - id: "ap-south-1", - name: "AP South-1", - region: "Asia Pacific", - coordinates: [72.8777, 19.076] as [number, number], - totalFindings: 234, - riskLevel: RISK_LEVELS.LOW_HIGH, - change: -8, - severityData: [ - { name: "Info", value: 7, percentage: 3, color: "var(--chart-info)" }, - { - name: "Low", - value: 98, - percentage: 28, - color: "var(--chart-warning)", - }, - { - name: "Medium", - value: 76, - percentage: 24, - color: "var(--chart-warning-emphasis)", - }, - { - name: "High", - value: 89, - percentage: 30, - color: "var(--chart-danger)", - }, - { - name: "Critical", - value: 43, - percentage: 15, - color: "var(--chart-danger-emphasis)", - }, - ], - }, - { - id: "sa-east-1", - name: "SA East-1", - region: "South America", - coordinates: [-46.6333, -23.5505] as [number, number], - totalFindings: 189, - riskLevel: RISK_LEVELS.LOW_HIGH, - severityData: [ - { name: "Info", value: 6, percentage: 3, color: "var(--chart-info)" }, - { - name: "Low", - value: 87, - percentage: 30, - color: "var(--chart-warning)", - }, - { - name: "Medium", - value: 54, - percentage: 22, - color: "var(--chart-warning-emphasis)", - }, - { - name: "High", - value: 67, - percentage: 28, - color: "var(--chart-danger)", - }, - { - name: "Critical", - value: 32, - percentage: 17, - color: "var(--chart-danger-emphasis)", - }, - ], - }, - { - id: "ca-central-1", - name: "CA Central-1", - region: "US East", - coordinates: [-73.5673, 45.5017] as [number, number], - totalFindings: 267, - riskLevel: RISK_LEVELS.LOW_HIGH, - severityData: [ - { name: "Info", value: 8, percentage: 3, color: "var(--chart-info)" }, - { - name: "Low", - value: 112, - percentage: 27, - color: "var(--chart-warning)", - }, - { - name: "Medium", - value: 87, - percentage: 23, - color: "var(--chart-warning-emphasis)", - }, - { - name: "High", - value: 98, - percentage: 30, - color: "var(--chart-danger)", - }, - { - name: "Critical", - value: 54, - percentage: 17, - color: "var(--chart-danger-emphasis)", - }, - ], - }, - { - id: "ap-southeast-2", - name: "AP Southeast-2", - region: "Asia Pacific", - coordinates: [151.2093, -33.8688] as [number, number], - totalFindings: 345, - riskLevel: RISK_LEVELS.HIGH, - severityData: [ - { name: "Info", value: 10, percentage: 3, color: "var(--chart-info)" }, - { - name: "Low", - value: 78, - percentage: 17, - color: "var(--chart-warning)", - }, - { - name: "Medium", - value: 121, - percentage: 25, - color: "var(--chart-warning-emphasis)", - }, - { - name: "High", - value: 167, - percentage: 35, - color: "var(--chart-danger)", - }, - { - name: "Critical", - value: 89, - percentage: 20, - color: "var(--chart-danger-emphasis)", - }, - ], - }, - { - id: "eu-west-2", - name: "EU West-2", - region: "Europe", - coordinates: [-0.1278, 51.5074] as [number, number], - totalFindings: 423, - riskLevel: RISK_LEVELS.HIGH, - severityData: [ - { name: "Info", value: 11, percentage: 3, color: "var(--chart-info)" }, - { - name: "Low", - value: 98, - percentage: 19, - color: "var(--chart-warning)", - }, - { - name: "Medium", - value: 154, - percentage: 26, - color: "var(--chart-warning-emphasis)", - }, - { - name: "High", - value: 189, - percentage: 32, - color: "var(--chart-danger)", - }, - { - name: "Critical", - value: 112, - percentage: 20, - color: "var(--chart-danger-emphasis)", - }, - ], - }, - { - id: "us-east-2", - name: "US East-2", - region: "US East", - coordinates: [-82.9988, 39.9612] as [number, number], - totalFindings: 298, - riskLevel: RISK_LEVELS.LOW_HIGH, - severityData: [ - { name: "Info", value: 9, percentage: 3, color: "var(--chart-info)" }, - { - name: "Low", - value: 123, - percentage: 28, - color: "var(--chart-warning)", - }, - { - name: "Medium", - value: 89, - percentage: 23, - color: "var(--chart-warning-emphasis)", - }, - { - name: "High", - value: 101, - percentage: 29, - color: "var(--chart-danger)", - }, - { - name: "Critical", - value: 54, - percentage: 17, - color: "var(--chart-danger-emphasis)", - }, - ], - }, - { - id: "us-west-1", - name: "US West-1", - region: "US West", - coordinates: [-121.8863, 37.3382] as [number, number], - totalFindings: 389, - riskLevel: RISK_LEVELS.HIGH, - severityData: [ - { name: "Info", value: 10, percentage: 3, color: "var(--chart-info)" }, - { - name: "Low", - value: 87, - percentage: 18, - color: "var(--chart-warning)", - }, - { - name: "Medium", - value: 143, - percentage: 26, - color: "var(--chart-warning-emphasis)", - }, - { - name: "High", - value: 176, - percentage: 33, - color: "var(--chart-danger)", - }, - { - name: "Critical", - value: 98, - percentage: 20, - color: "var(--chart-danger-emphasis)", - }, - ], - }, - { - id: "eu-north-1", - name: "EU North-1", - region: "Europe", - coordinates: [18.0686, 59.3293] as [number, number], - totalFindings: 213, - riskLevel: RISK_LEVELS.LOW_HIGH, - severityData: [ - { name: "Info", value: 7, percentage: 3, color: "var(--chart-info)" }, - { - name: "Low", - value: 89, - percentage: 29, - color: "var(--chart-warning)", - }, - { - name: "Medium", - value: 67, - percentage: 23, - color: "var(--chart-warning-emphasis)", - }, - { - name: "High", - value: 76, - percentage: 28, - color: "var(--chart-danger)", - }, - { - name: "Critical", - value: 43, - percentage: 17, - color: "var(--chart-danger-emphasis)", - }, - ], - }, - ], -}; - -// Sample data for DonutChart (Findings by Severity) -const sampleDonutChartData = [ - { - name: "Critical", - value: 432, - percentage: 22, - color: "var(--chart-danger-emphasis)", - change: 5, - }, - { - name: "High", - value: 1232, - percentage: 32, - color: "var(--chart-danger)", - change: 8, - }, - { - name: "Medium", - value: 925, - percentage: 28, - color: "var(--chart-warning-emphasis)", - change: -3, - }, - { - name: "Low", - value: 543, - percentage: 15, - color: "var(--chart-warning)", - change: -2, - }, - { - name: "Info", - value: 108, - percentage: 3, - color: "var(--chart-info)", - change: 0, - }, -]; - -// Sample data for LineChart -const sampleLineChartData = [ - { date: "Jan", critical: 385, high: 1100, medium: 820, low: 450 }, - { date: "Feb", critical: 398, high: 1150, medium: 870, low: 480 }, - { date: "Mar", critical: 410, high: 1180, medium: 890, low: 510 }, - { date: "Apr", critical: 425, high: 1210, medium: 915, low: 530 }, - { date: "May", critical: 418, high: 1195, medium: 905, low: 520 }, - { date: "Jun", critical: 432, high: 1232, medium: 925, low: 543 }, -]; - -const sampleLineConfig = [ - { - dataKey: "critical", - color: "var(--chart-danger-emphasis)", - label: "Critical", - }, - { dataKey: "high", color: "var(--chart-danger)", label: "High" }, - { - dataKey: "medium", - color: "var(--chart-warning-emphasis)", - label: "Medium", - }, - { dataKey: "low", color: "var(--chart-warning)", label: "Low" }, -]; - -// Sample data for HorizontalBarChart (Severity Distribution) -const sampleHorizontalBarData = [ - { - name: "Critical", - value: 432, - percentage: 22, - newFindings: 15, - change: 5, - }, - { name: "High", value: 1232, percentage: 32, newFindings: 45, change: 8 }, - { - name: "Medium", - value: 925, - percentage: 28, - newFindings: 32, - change: -3, - }, - { name: "Low", value: 543, percentage: 15, newFindings: 18, change: -2 }, - { name: "Info", value: 108, percentage: 3, newFindings: 5, change: 0 }, -]; - -// Sample data for SankeyChart -const sampleSankeyData = { - nodes: [ - { name: "Success" }, - { name: "Fail" }, - { name: "AWS" }, - { name: "Azure" }, - { name: "Google" }, - { name: "Critical", newFindings: 5, change: 15 }, - { name: "High", newFindings: 12, change: 8 }, - { name: "Medium", newFindings: 28, change: -3 }, - { name: "Low", newFindings: 45, change: -8 }, - { name: "Info", newFindings: 18, change: 2 }, - ], - links: [ - // Success to Providers - { source: 0, target: 2, value: 300 }, // Success -> AWS - { source: 0, target: 3, value: 283 }, // Success -> Azure - { source: 0, target: 4, value: 300 }, // Success -> Google - - // Fail to Providers - { source: 1, target: 2, value: 200 }, // Fail -> AWS - { source: 1, target: 3, value: 300 }, // Fail -> Azure - { source: 1, target: 4, value: 500 }, // Fail -> Google - - // AWS to Severities (Critical to Info order) - { source: 2, target: 5, value: 8 }, // AWS -> Critical - { source: 2, target: 6, value: 25 }, // AWS -> High - { source: 2, target: 7, value: 67 }, // AWS -> Medium - { source: 2, target: 8, value: 80 }, // AWS -> Low - { source: 2, target: 9, value: 20 }, // AWS -> Info - - // Azure to Severities - { source: 3, target: 5, value: 10 }, // Azure -> Critical - { source: 3, target: 6, value: 35 }, // Azure -> High - { source: 3, target: 7, value: 95 }, // Azure -> Medium - { source: 3, target: 8, value: 130 }, // Azure -> Low - { source: 3, target: 9, value: 30 }, // Azure -> Info - - // Google to Severities - { source: 4, target: 5, value: 7 }, // Google -> Critical - { source: 4, target: 6, value: 40 }, // Google -> High - { source: 4, target: 7, value: 163 }, // Google -> Medium - { source: 4, target: 8, value: 190 }, // Google -> Low - { source: 4, target: 9, value: 100 }, // Google -> Info - ], -}; - -// Sample data for ScatterPlot -const sampleScatterPlotData = [ - { x: 8.2, y: 45, provider: "AWS", name: "S3 Buckets", size: 120 }, - { x: 7.5, y: 62, provider: "AWS", name: "EC2 Instances", size: 95 }, - { x: 6.8, y: 78, provider: "Azure", name: "Storage Accounts", size: 85 }, - { x: 9.1, y: 32, provider: "AWS", name: "RDS Databases", size: 110 }, - { x: 5.4, y: 88, provider: "Google", name: "Cloud Storage", size: 75 }, - { x: 7.9, y: 55, provider: "Azure", name: "Virtual Machines", size: 90 }, - { x: 8.5, y: 48, provider: "AWS", name: "Lambda Functions", size: 105 }, - { x: 6.2, y: 82, provider: "Google", name: "Compute Engine", size: 80 }, - { x: 7.2, y: 68, provider: "Azure", name: "SQL Databases", size: 88 }, - { x: 8.8, y: 41, provider: "AWS", name: "IAM Users", size: 115 }, -]; - // Extract only query params that start with "filter[" for API calls function pickFilterParams( params: SearchParamsProps | undefined | null, @@ -741,90 +76,6 @@ export default async function Home({ - -
- -

- Security Categories -

- -
- -
- -

Threat Map

- -
- -
- -

- Findings by Severity -

- -
- -
- -

- Severity Distribution -

- -
- -
- -

- Findings Trend Over Time -

- -
- -
- -

- Provider to Severity Flow -

- -
- -
- -

Compliance Score

- -
- -
- -

- Risk Score vs Compliance by Service -

- -
); diff --git a/ui/components/graphs/donut-chart.tsx b/ui/components/graphs/donut-chart.tsx index 9c212fe84e..ea5ff49e5f 100644 --- a/ui/components/graphs/donut-chart.tsx +++ b/ui/components/graphs/donut-chart.tsx @@ -44,7 +44,10 @@ const CustomTooltip = ({ active, payload }: any) => { {data.change !== undefined && ( -

+

{data.change > 0 ? "+" : ""} {data.change}% diff --git a/ui/components/graphs/horizontal-bar-chart.tsx b/ui/components/graphs/horizontal-bar-chart.tsx index 7af8556b65..c792d60d38 100644 --- a/ui/components/graphs/horizontal-bar-chart.tsx +++ b/ui/components/graphs/horizontal-bar-chart.tsx @@ -99,7 +99,7 @@ export function HorizontalBarChart({ data, title }: HorizontalBarChartProps) {

-

+

{label}

@@ -75,13 +78,19 @@ const CustomLineTooltip = ({ className="h-2 w-2 rounded-full" style={{ backgroundColor: item.stroke }} /> - + {item.value}
{newFindings !== undefined && (
- + )} {change !== undefined && typeof change === "number" && ( -

+

{change > 0 ? "+" : ""} {change}% diff --git a/ui/components/graphs/radar-chart.tsx b/ui/components/graphs/radar-chart.tsx index b0fb6936c2..ab3a43e6da 100644 --- a/ui/components/graphs/radar-chart.tsx +++ b/ui/components/graphs/radar-chart.tsx @@ -96,7 +96,9 @@ const CustomDot = (props: any) => { cx={cx} cy={cy} r={isSelected ? 9 : 6} - fill={isSelected ? "var(--chart-success-color)" : "var(--chart-radar-primary)"} + fill={ + isSelected ? "var(--chart-success-color)" : "var(--chart-radar-primary)" + } fillOpacity={1} className={isSelected ? "drop-shadow-[0_0_8px_#86da26]" : ""} style={{ diff --git a/ui/components/graphs/radial-chart.tsx b/ui/components/graphs/radial-chart.tsx index 3fcb0ee2a0..ad9374d856 100644 --- a/ui/components/graphs/radial-chart.tsx +++ b/ui/components/graphs/radial-chart.tsx @@ -68,7 +68,10 @@ export function RadialChart({ y="50%" textAnchor="middle" dominantBaseline="middle" - className="fill-white text-4xl font-bold" + className="text-4xl font-bold" + style={{ + fill: "var(--chart-text-primary)", + }} > {percentage}% diff --git a/ui/components/graphs/sankey-chart.tsx b/ui/components/graphs/sankey-chart.tsx index 2208b69576..58179aadf6 100644 --- a/ui/components/graphs/sankey-chart.tsx +++ b/ui/components/graphs/sankey-chart.tsx @@ -3,8 +3,8 @@ import { useState } from "react"; import { Rectangle, ResponsiveContainer, Sankey, Tooltip } from "recharts"; -import { CHART_COLORS } from "./shared/constants"; import { ChartTooltip } from "./shared/chart-tooltip"; +import { CHART_COLORS } from "./shared/constants"; interface SankeyNode { name: string; @@ -193,8 +193,7 @@ const CustomLink = (props: any) => { const color = COLORS[sourceName] || CHART_COLORS.defaultColor; const isHidden = targetName === ""; - const isHovered = - props.hoveredLink !== null && props.hoveredLink === index; + const isHovered = props.hoveredLink !== null && props.hoveredLink === index; const hasHoveredLink = props.hoveredLink !== null; const pathD = ` diff --git a/ui/components/graphs/scatter-plot.tsx b/ui/components/graphs/scatter-plot.tsx index 0b8cf7b8fd..a0725f0dc5 100644 --- a/ui/components/graphs/scatter-plot.tsx +++ b/ui/components/graphs/scatter-plot.tsx @@ -15,14 +15,7 @@ import { AlertPill } from "./shared/alert-pill"; import { ChartLegend } from "./shared/chart-legend"; import { CHART_COLORS } from "./shared/constants"; import { getSeverityColorByRiskScore } from "./shared/utils"; - -interface ScatterDataPoint { - x: number; - y: number; - provider: string; - name: string; - size?: number; -} +import type { ScatterDataPoint } from "./types"; interface ScatterPlotProps { data: ScatterDataPoint[]; diff --git a/ui/components/graphs/shared/alert-pill.tsx b/ui/components/graphs/shared/alert-pill.tsx index f611b27766..8fcba831e6 100644 --- a/ui/components/graphs/shared/alert-pill.tsx +++ b/ui/components/graphs/shared/alert-pill.tsx @@ -17,13 +17,14 @@ export function AlertPill({ }: AlertPillProps) { return (

-
- +
+ {value} diff --git a/ui/components/graphs/shared/chart-tooltip.tsx b/ui/components/graphs/shared/chart-tooltip.tsx index 6b4bde27bc..95af794d89 100644 --- a/ui/components/graphs/shared/chart-tooltip.tsx +++ b/ui/components/graphs/shared/chart-tooltip.tsx @@ -3,6 +3,7 @@ import { Bell, VolumeX } from "lucide-react"; import { cn } from "@/lib/utils"; import { TooltipData } from "../types"; +import { CHART_COLORS } from "./constants"; interface ChartTooltipProps { active?: boolean; @@ -27,7 +28,13 @@ export function ChartTooltip({ const color = payload[0].color || data.color; return ( -
+
{showColorIndicator && color && (
)} -

{label || data.name}

+

+ {label || data.name} +

-

+

{typeof data.value === "number" ? data.value.toLocaleString() : data.value} @@ -50,8 +65,8 @@ export function ChartTooltip({ {data.newFindings !== undefined && data.newFindings > 0 && (

- - + + {data.newFindings} New Findings
@@ -59,20 +74,24 @@ export function ChartTooltip({ {data.new !== undefined && data.new > 0 && (
- - {data.new} New + + + {data.new} New +
)} {data.muted !== undefined && data.muted > 0 && (
- - {data.muted} Muted + + + {data.muted} Muted +
)} {data.change !== undefined && ( -

+

{data.change > 0 ? "+" : ""} {data.change}% @@ -97,8 +116,19 @@ export function MultiSeriesChartTooltip({ } return ( -

-

{label}

+
+

+ {label} +

{payload.map((entry: any, index: number) => (
@@ -106,12 +136,17 @@ export function MultiSeriesChartTooltip({ className="h-2 w-2 rounded-full" style={{ backgroundColor: entry.color }} /> - {entry.name}: - + + {entry.name}: + + {entry.value} {entry.payload[`${entry.dataKey}_change`] && ( - + ({entry.payload[`${entry.dataKey}_change`] > 0 ? "+" : ""} {entry.payload[`${entry.dataKey}_change`]}%) diff --git a/ui/components/graphs/threat-map.tsx b/ui/components/graphs/threat-map.tsx index 571bba221c..5ab2a62f66 100644 --- a/ui/components/graphs/threat-map.tsx +++ b/ui/components/graphs/threat-map.tsx @@ -7,7 +7,7 @@ import type { GeoJsonProperties, Geometry, } from "geojson"; -import { AlertTriangle, ChevronDown, Info, MapPin } from "lucide-react"; +import { AlertTriangle, Info, MapPin } from "lucide-react"; import { useEffect, useRef, useState } from "react"; import { feature } from "topojson-client"; import type { @@ -16,6 +16,14 @@ import type { Topology, } from "topojson-specification"; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from "@/components/shared/shadcn"; + import { HorizontalBarChart } from "./horizontal-bar-chart"; import { BarDataPoint } from "./types"; @@ -152,7 +160,10 @@ function MapTooltip({
{location.change !== undefined && ( -

+

{location.change > 0 ? "+" : ""} {location.change}% @@ -180,7 +191,11 @@ function EmptyState() { }} >

- +

Select a location on the map to view details

@@ -398,30 +413,26 @@ export function ThreatMap({ > Threat Map -
- + - + + + + All Regions {data.regions.map((region) => ( - + ))} - - -
+ +
); } - diff --git a/ui/components/graphs/types.ts b/ui/components/graphs/types.ts index 0961a32105..f7a9b02542 100644 --- a/ui/components/graphs/types.ts +++ b/ui/components/graphs/types.ts @@ -36,6 +36,14 @@ export interface RadarDataPoint { change?: number; } +export interface ScatterDataPoint { + x: number; + y: number; + provider: string; + name: string; + size?: number; +} + export interface LineConfig { dataKey: string; color: string; diff --git a/ui/components/overview/radar-chart-with-selection.tsx b/ui/components/overview/radar-chart-with-selection.tsx deleted file mode 100644 index d90beeb69a..0000000000 --- a/ui/components/overview/radar-chart-with-selection.tsx +++ /dev/null @@ -1,38 +0,0 @@ -"use client"; - -import { useState } from "react"; - -import { RadarChart } from "@/components/graphs"; -import type { RadarDataPoint } from "@/components/graphs/types"; - -interface RadarChartWithSelectionProps { - data?: RadarDataPoint[]; - height?: number; -} - -const sampleRadarData: RadarDataPoint[] = [ - { category: "IAM", value: 85, change: 5 }, - { category: "Storage", value: 72, change: -2 }, - { category: "Network", value: 88, change: 8 }, - { category: "Compute", value: 76, change: 3 }, - { category: "Database", value: 82, change: -1 }, - { category: "Encryption", value: 91, change: 6 }, -]; - -export function RadarChartWithSelection({ - data = sampleRadarData, - height = 400, -}: RadarChartWithSelectionProps) { - const [selectedPoint, setSelectedPoint] = useState( - null, - ); - - return ( - - ); -} diff --git a/ui/components/overview/scatter-plot-with-selection.tsx b/ui/components/overview/scatter-plot-with-selection.tsx deleted file mode 100644 index ad9a0b6b17..0000000000 --- a/ui/components/overview/scatter-plot-with-selection.tsx +++ /dev/null @@ -1,40 +0,0 @@ -"use client"; - -import { useState } from "react"; - -import { ScatterPlot } from "@/components/graphs"; - -interface DataPoint { - x: number; - y: number; - provider: string; - name: string; - size: number; -} - -interface ScatterPlotWithSelectionProps { - data: DataPoint[]; - height?: number; - xLabel?: string; - yLabel?: string; -} - -export function ScatterPlotWithSelection({ - data, - height = 400, - xLabel = "Risk Score", - yLabel = "Compliance %", -}: ScatterPlotWithSelectionProps) { - const [selectedPoint, setSelectedPoint] = useState(null); - - return ( - - ); -} diff --git a/ui/components/shared/shadcn/index.tsx b/ui/components/shared/shadcn/index.tsx new file mode 100644 index 0000000000..9268fdeeb5 --- /dev/null +++ b/ui/components/shared/shadcn/index.tsx @@ -0,0 +1 @@ +export * from "./select/Select"; diff --git a/ui/components/ui/select/Select.tsx b/ui/components/shared/shadcn/select/Select.tsx similarity index 100% rename from ui/components/ui/select/Select.tsx rename to ui/components/shared/shadcn/select/Select.tsx diff --git a/ui/components/shared/shadcn/select/index.ts b/ui/components/shared/shadcn/select/index.ts new file mode 100644 index 0000000000..730dd10551 --- /dev/null +++ b/ui/components/shared/shadcn/select/index.ts @@ -0,0 +1,12 @@ +export { + Select, + SelectContent, + SelectGroup, + SelectItem, + SelectLabel, + SelectScrollDownButton, + SelectScrollUpButton, + SelectSeparator, + SelectTrigger, + SelectValue, +} from "./Select"; diff --git a/ui/components/ui/index.ts b/ui/components/ui/index.ts index 205ec7fd50..9099a7caa0 100644 --- a/ui/components/ui/index.ts +++ b/ui/components/ui/index.ts @@ -12,6 +12,5 @@ export * from "./feedback-banner/feedback-banner"; export * from "./headers/navigation-header"; export * from "./label/Label"; export * from "./main-layout/main-layout"; -export * from "./select/Select"; export * from "./sidebar"; export * from "./toast"; diff --git a/ui/components/ui/table/data-table-pagination.tsx b/ui/components/ui/table/data-table-pagination.tsx index 965c066efd..280844cec5 100644 --- a/ui/components/ui/table/data-table-pagination.tsx +++ b/ui/components/ui/table/data-table-pagination.tsx @@ -10,16 +10,15 @@ import Link from "next/link"; import { usePathname, useRouter, useSearchParams } from "next/navigation"; import { useState } from "react"; -import { getPaginationInfo } from "@/lib"; -import { MetaDataProps } from "@/types"; - import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, -} from "../select/Select"; +} from "@/components/shared/shadcn"; +import { getPaginationInfo } from "@/lib"; +import { MetaDataProps } from "@/types"; interface DataTablePaginationProps { metadata?: MetaDataProps;