From ee2d3ed052007967427262a6f45eaf12ea53bc18 Mon Sep 17 00:00:00 2001 From: Alejandro Bailo <59607668+alejandrobailo@users.noreply.github.com> Date: Mon, 10 Nov 2025 09:19:10 +0100 Subject: [PATCH] feat: implement new design system variables across new components and add skeletons (#9193) --- .../components/risk-severity-chart.tsx | 35 ++- .../new-overview/components/status-chart.tsx | 52 ++++- .../new-overview/components/threat-score.tsx | 209 +++++++++--------- ui/app/(prowler)/new-overview/page.tsx | 33 +-- ui/components/graphs/donut-chart.tsx | 10 +- ui/components/graphs/horizontal-bar-chart.tsx | 37 ++-- ui/components/graphs/radial-chart.tsx | 26 +-- ui/components/graphs/shared/constants.ts | 11 +- .../shadcn/card/base-card/base-card.tsx | 36 --- ui/components/shadcn/card/card.tsx | 51 ++++- .../resource-stats-card-container.tsx | 55 ----- .../resource-stats-card-content.tsx | 20 +- .../resource-stats-card-divider.tsx | 59 ----- .../resource-stats-card-header.tsx | 27 +-- .../resource-stats-card.tsx | 16 +- ui/components/shadcn/index.ts | 4 +- ui/components/shadcn/skeleton/skeleton.tsx | 16 ++ ui/styles/globals.css | 61 ++--- 18 files changed, 348 insertions(+), 410 deletions(-) delete mode 100644 ui/components/shadcn/card/base-card/base-card.tsx delete mode 100644 ui/components/shadcn/card/resource-stats-card/resource-stats-card-container.tsx delete mode 100644 ui/components/shadcn/card/resource-stats-card/resource-stats-card-divider.tsx create mode 100644 ui/components/shadcn/skeleton/skeleton.tsx diff --git a/ui/app/(prowler)/new-overview/components/risk-severity-chart.tsx b/ui/app/(prowler)/new-overview/components/risk-severity-chart.tsx index b070a828ba..22f6fbb3b9 100644 --- a/ui/app/(prowler)/new-overview/components/risk-severity-chart.tsx +++ b/ui/app/(prowler)/new-overview/components/risk-severity-chart.tsx @@ -3,10 +3,11 @@ import { HorizontalBarChart } from "@/components/graphs/horizontal-bar-chart"; import { BarDataPoint } from "@/components/graphs/types"; import { - BaseCard, + Card, CardContent, CardHeader, CardTitle, + Skeleton, } from "@/components/shadcn"; import { calculatePercentage } from "@/lib/utils"; @@ -58,7 +59,10 @@ export const RiskSeverityChart = ({ ]; return ( - + Risk Severity @@ -66,6 +70,31 @@ export const RiskSeverityChart = ({ - + ); }; + +export function RiskSeverityChartSkeleton() { + return ( + + + + + + +
+ {/* 5 horizontal bar skeletons */} + {Array.from({ length: 5 }).map((_, index) => ( +
+ + +
+ ))} +
+
+
+ ); +} diff --git a/ui/app/(prowler)/new-overview/components/status-chart.tsx b/ui/app/(prowler)/new-overview/components/status-chart.tsx index 7e773f90e7..1efb406975 100644 --- a/ui/app/(prowler)/new-overview/components/status-chart.tsx +++ b/ui/app/(prowler)/new-overview/components/status-chart.tsx @@ -5,13 +5,13 @@ import { Bell, BellOff, ShieldCheck, TriangleAlert } from "lucide-react"; import { DonutChart } from "@/components/graphs/donut-chart"; import { DonutDataPoint } from "@/components/graphs/types"; import { - BaseCard, + Card, CardContent, CardHeader, CardTitle, CardVariant, ResourceStatsCard, - ResourceStatsCardContainer, + Skeleton, } from "@/components/shadcn"; import { calculatePercentage } from "@/lib/utils"; @@ -60,27 +60,30 @@ export const StatusChart = ({ { name: "Fail Findings", value: failFindingsData.total, - color: "#f43f5e", // Rose-500 + color: "var(--bg-fail-primary)", percentage: Number(failPercentage), change: Number(failChange), }, { name: "Pass Findings", value: passFindingsData.total, - color: "#4ade80", // Green-400 + color: "var(--bg-pass-primary)", percentage: Number(passPercentage), change: Number(passChange), }, ]; return ( - + Check Findings - -
+ +
- +
-
+
- + - + ); }; + +export function StatusChartSkeleton() { + return ( + + + + + + + {/* Circular skeleton for donut chart */} +
+ +
+ + {/* Bottom info box skeleton */} + +
+
+ ); +} diff --git a/ui/app/(prowler)/new-overview/components/threat-score.tsx b/ui/app/(prowler)/new-overview/components/threat-score.tsx index 511f6b9d42..db07e951b8 100644 --- a/ui/app/(prowler)/new-overview/components/threat-score.tsx +++ b/ui/app/(prowler)/new-overview/components/threat-score.tsx @@ -1,7 +1,6 @@ "use client"; import { MessageCircleWarning, ThumbsUp } from "lucide-react"; -import Link from "next/link"; import type { CriticalRequirement, @@ -9,50 +8,33 @@ import type { } from "@/actions/overview/types"; import { RadialChart } from "@/components/graphs/radial-chart"; import { - SEVERITY_COLORS, - STATUS_COLORS, -} from "@/components/graphs/shared/constants"; -import { - BaseCard, + Card, CardContent, CardHeader, CardTitle, + Skeleton, } from "@/components/shadcn"; const THREAT_LEVEL_CONFIG = { - CRITICAL: { + DANGER: { label: "Critical Risk", - color: "text-red-500", - chartColor: SEVERITY_COLORS.Critical, + color: "var(--bg-fail-primary)", + chartColor: "var(--bg-fail-primary)", minScore: 0, - maxScore: 20, + maxScore: 30, }, - HIGH: { - label: "High Risk", - color: "text-orange-500", - chartColor: SEVERITY_COLORS.High, - minScore: 21, - maxScore: 40, - }, - MODERATE: { - label: "Moderately Secure", - color: "text-yellow-500", - chartColor: SEVERITY_COLORS.Medium, - minScore: 41, + WARNING: { + label: "Moderate Risk", + color: "var(--bg-warning-primary)", + chartColor: "var(--bg-warning-primary)", + minScore: 31, maxScore: 60, }, - LOW: { - label: "Low Risk", - color: "text-blue-500", - chartColor: SEVERITY_COLORS.Low, + SUCCESS: { + label: "Secure", + color: "var(--bg-pass-primary)", + chartColor: "var(--bg-pass-primary)", minScore: 61, - maxScore: 80, - }, - SECURE: { - label: "Highly Secure", - color: "text-green-500", - chartColor: STATUS_COLORS.Success, - minScore: 81, maxScore: 100, }, } as const; @@ -74,7 +56,7 @@ function getThreatLevel(score: number): ThreatLevelKey { return key as ThreatLevelKey; } } - return "MODERATE"; + return "WARNING"; } // Convert section scores to tooltip data for the radial chart @@ -84,16 +66,13 @@ function convertSectionScoresToTooltipData( if (!sectionScores) return []; return Object.entries(sectionScores).map(([name, value]) => { - // Determine color based on score value - let color: string = SEVERITY_COLORS.Critical; - if (value >= 80) color = STATUS_COLORS.Success; - else if (value >= 60) color = SEVERITY_COLORS.Low; - else if (value >= 40) color = SEVERITY_COLORS.Medium; - else if (value >= 20) color = SEVERITY_COLORS.High; - // Round to nearest integer const roundedValue = Math.round(value); + // Determine color based on the same ranges as THREAT_LEVEL_CONFIG + const threatLevel = getThreatLevel(roundedValue); + const color = THREAT_LEVEL_CONFIG[threatLevel].chartColor; + return { name, value: roundedValue, color }; }); } @@ -122,22 +101,10 @@ export function ThreatScore({ sectionScores, criticalRequirements, }: ThreatScoreProps) { - if (score === null || score === undefined) { - return ( - - - Prowler Threat Score - - -

- No ThreatScore data available -

-
-
- ); - } + const hasData = score !== null && score !== undefined; + const displayScore = hasData ? score : 0; - const threatLevel = getThreatLevel(score); + const threatLevel = getThreatLevel(displayScore); const config = THREAT_LEVEL_CONFIG[threatLevel]; // Convert section scores to tooltip data @@ -147,20 +114,23 @@ export function ThreatScore({ const gaps = extractTopGaps(criticalRequirements, 2); return ( - + Prowler Threat Score - + {/* Radial Chart */} -
-
+
+
{/* Overlaid Text (centered) */} -
-

- {config.label} -

-
+ {hasData && ( +
+

+ {config.label} +

+
+ )}
- {/* Info Box */} -
-
- {/* Improvement Message */} - {scoreDelta !== undefined && - scoreDelta !== null && - scoreDelta !== 0 && ( -
- + {/* Info Box or Empty State */} + {hasData ? ( + +
+ {/* Improvement Message */} + {scoreDelta !== undefined && + scoreDelta !== null && + scoreDelta !== 0 && ( +
+ +

+ Threat score has{" "} + {scoreDelta > 0 ? "improved" : "decreased"} by{" "} + {Math.abs(scoreDelta)}% +

+
+ )} + + {/* Gaps Message */} + {gaps.length > 0 && ( +
+

- Threat score has {scoreDelta > 0 ? "improved" : "decreased"}{" "} - by {Math.abs(scoreDelta)}% + Major gaps include {gaps.slice(0, 2).join(", ")} + {gaps.length > 2 && ` & ${gaps.length - 2} more...`}

)} - - {/* Gaps Message */} - {gaps.length > 0 && ( -
- -

- Major gaps include {gaps.slice(0, 2).join(", ")} - {gaps.length > 2 && ` & ${gaps.length - 2} more...`} -

-
- )} - - {/* View Remediation Plan Button */} -
- - - View Remediation Plan - -
-
-
+ + ) : ( + +

+ Threat Score Data Unavailable +

+
+ )} - + + ); +} + +export function ThreatScoreSkeleton() { + return ( + + + + + + + {/* Circular skeleton for radial chart */} +
+ +
+ + {/* Bottom info box skeleton */} + +
+
); } diff --git a/ui/app/(prowler)/new-overview/page.tsx b/ui/app/(prowler)/new-overview/page.tsx index d45665be0e..954c668649 100644 --- a/ui/app/(prowler)/new-overview/page.tsx +++ b/ui/app/(prowler)/new-overview/page.tsx @@ -11,9 +11,12 @@ import { SearchParamsProps } from "@/types"; import { AccountsSelector } from "./components/accounts-selector"; import { ProviderTypeSelector } from "./components/provider-type-selector"; -import { RiskSeverityChart } from "./components/risk-severity-chart"; -import { StatusChart } from "./components/status-chart"; -import { ThreatScore } from "./components/threat-score"; +import { + RiskSeverityChart, + RiskSeverityChartSkeleton, +} from "./components/risk-severity-chart"; +import { StatusChart, StatusChartSkeleton } from "./components/status-chart"; +import { ThreatScore, ThreatScoreSkeleton } from "./components/threat-score"; const FILTER_PREFIX = "filter["; @@ -42,33 +45,15 @@ export default async function NewOverviewPage({
- -

Loading...

-
- } - > + }> - -

Loading...

-
- } - > + }> - -

Loading...

-
- } - > + }>
diff --git a/ui/components/graphs/donut-chart.tsx b/ui/components/graphs/donut-chart.tsx index 21fefd058b..e8c1c6e0da 100644 --- a/ui/components/graphs/donut-chart.tsx +++ b/ui/components/graphs/donut-chart.tsx @@ -30,7 +30,7 @@ const CustomTooltip = ({ active, payload }: any) => { const change = entry.payload?.change; return ( -
+
{/* Title with color chip */}
@@ -38,7 +38,7 @@ const CustomTooltip = ({ active, payload }: any) => { className="size-3 shrink-0 rounded" style={{ backgroundColor: color }} /> -

+

{percentage}% {name}

@@ -46,7 +46,7 @@ const CustomTooltip = ({ active, payload }: any) => { {/* Change percentage row */} {change !== undefined && (
-

+

{change > 0 ? "+" : ""} {change}% Since last scan

@@ -171,7 +171,7 @@ export function DonutChart({ { @@ -38,7 +39,7 @@ export function HorizontalBarChart({ data, title }: HorizontalBarChartProps) {

{title}

@@ -50,15 +51,15 @@ export function HorizontalBarChart({ data, title }: HorizontalBarChartProps) { const isHovered = !isEmpty && hoveredIndex === index; const isFaded = !isEmpty && hoveredIndex !== null && !isHovered; const barColor = isEmpty - ? CHART_COLORS.gridLine + ? "var(--bg-neutral-tertiary)" : item.color || getSeverityColorByName(item.name) || - CHART_COLORS.defaultColor; + "var(--bg-neutral-tertiary)"; return (
!isEmpty && setHoveredIndex(index)} onMouseLeave={() => !isEmpty && setHoveredIndex(null)} > @@ -67,18 +68,18 @@ export function HorizontalBarChart({ data, title }: HorizontalBarChartProps) { - {item.name} + {item.name === "Informational" ? "Info" : item.name}
{/* Bar - flexible */}
-
+
{(item.value > 0 || isEmpty) && (
+
{/* Title with color chip */}
@@ -101,8 +102,10 @@ export function HorizontalBarChart({ data, title }: HorizontalBarChartProps) { className="size-3 shrink-0 rounded" style={{ backgroundColor: barColor }} /> -

- {item.value.toLocaleString()} {item.name} Risk +

+ {item.value.toLocaleString()}{" "} + {item.name === "Informational" ? "Info" : item.name}{" "} + Risk

@@ -111,9 +114,9 @@ export function HorizontalBarChart({ data, title }: HorizontalBarChartProps) {
-

+

{item.newFindings} New Findings

@@ -122,7 +125,7 @@ export function HorizontalBarChart({ data, title }: HorizontalBarChartProps) { {/* Change percentage row */} {item.change !== undefined && (
-

+

{item.change > 0 ? "+" : ""} {item.change}% Since last scan

@@ -137,7 +140,7 @@ export function HorizontalBarChart({ data, title }: HorizontalBarChartProps) {
diff --git a/ui/components/graphs/radial-chart.tsx b/ui/components/graphs/radial-chart.tsx index 70b1c3a019..a80613bc59 100644 --- a/ui/components/graphs/radial-chart.tsx +++ b/ui/components/graphs/radial-chart.tsx @@ -8,8 +8,6 @@ import { Tooltip, } from "recharts"; -import { CHART_COLORS } from "./shared/constants"; - export interface TooltipItem { name: string; value: number; @@ -42,18 +40,18 @@ const CustomTooltip = ({ active, payload }: any) => { return null; return ( -
+
{tooltipItems.map((item: TooltipItem, index: number) => (
-

+

{item.name}

-
+

{item.value}% @@ -67,8 +65,8 @@ const CustomTooltip = ({ active, payload }: any) => { export function RadialChart({ percentage, - color = "var(--chart-success-color)", - backgroundColor = CHART_COLORS.tooltipBackground, + color = "var(--bg-pass-primary)", + backgroundColor = "var(--bg-neutral-tertiary)", height = 250, innerRadius = 60, outerRadius = 100, @@ -154,24 +152,18 @@ export function RadialChart({ const y = centerY - middleRadius * Math.sin(currentAngleRad); return ( - + ); })} {percentage}% diff --git a/ui/components/graphs/shared/constants.ts b/ui/components/graphs/shared/constants.ts index 4aadd4aac0..22fc946ff3 100644 --- a/ui/components/graphs/shared/constants.ts +++ b/ui/components/graphs/shared/constants.ts @@ -1,10 +1,9 @@ export const SEVERITY_COLORS = { - Informational: "var(--chart-info)", - Info: "var(--chart-info)", - Low: "var(--chart-warning)", - Medium: "var(--chart-warning-emphasis)", - High: "var(--chart-danger)", - Critical: "var(--chart-danger-emphasis)", + Informational: "var(--bg-data-info)", + Low: "var(--bg-data-low)", + Medium: "var(--bg-data-medium)", + High: "var(--bg-data-high)", + Critical: "var(--bg-data-critical)", } as const; export const PROVIDER_COLORS = { diff --git a/ui/components/shadcn/card/base-card/base-card.tsx b/ui/components/shadcn/card/base-card/base-card.tsx deleted file mode 100644 index 946e0cc184..0000000000 --- a/ui/components/shadcn/card/base-card/base-card.tsx +++ /dev/null @@ -1,36 +0,0 @@ -import { cva, type VariantProps } from "class-variance-authority"; - -import { cn } from "@/lib/utils"; - -import { Card } from "../card"; - -const baseCardVariants = cva("", { - variants: { - variant: { - default: - "border-slate-200 bg-white dark:border-zinc-900 dark:bg-stone-950", - }, - }, - defaultVariants: { - variant: "default", - }, -}); - -interface BaseCardProps - extends React.ComponentProps, - VariantProps {} - -const BaseCard = ({ className, variant, ...props }: BaseCardProps) => { - return ( - - ); -}; - -export { BaseCard }; diff --git a/ui/components/shadcn/card/card.tsx b/ui/components/shadcn/card/card.tsx index 62f4c66865..d57ddf0eb7 100644 --- a/ui/components/shadcn/card/card.tsx +++ b/ui/components/shadcn/card/card.tsx @@ -1,3 +1,5 @@ +import { cva, type VariantProps } from "class-variance-authority"; + import { cn } from "@/lib/utils"; export const CardVariant = { @@ -10,14 +12,44 @@ export const CardVariant = { export type CardVariant = (typeof CardVariant)[keyof typeof CardVariant]; -function Card({ className, ...props }: React.ComponentProps<"div">) { +const cardVariants = cva("flex flex-col gap-6 rounded-xl border", { + variants: { + variant: { + default: "", + base: "border-border-neutral-secondary bg-bg-neutral-secondary px-[18px] pt-3 pb-4", + inner: + "rounded-[12px] backdrop-blur-[46px] border-border-neutral-tertiary bg-bg-neutral-tertiary", + }, + padding: { + default: "", + sm: "px-3 py-2", + md: "px-4 py-3", + lg: "px-5 py-4", + none: "p-0", + }, + }, + compoundVariants: [ + { + variant: "inner", + padding: "default", + className: "px-4 py-3", // md padding by default for inner + }, + ], + defaultVariants: { + variant: "default", + padding: "default", + }, +}); + +interface CardProps + extends React.ComponentProps<"div">, + VariantProps {} + +function Card({ className, variant, padding, ...props }: CardProps) { return (

); @@ -28,7 +60,7 @@ function CardHeader({ className, ...props }: React.ComponentProps<"div">) {
) { return (
); @@ -96,4 +125,6 @@ export { CardFooter, CardHeader, CardTitle, + cardVariants, }; +export type { CardProps }; diff --git a/ui/components/shadcn/card/resource-stats-card/resource-stats-card-container.tsx b/ui/components/shadcn/card/resource-stats-card/resource-stats-card-container.tsx deleted file mode 100644 index de27d052ed..0000000000 --- a/ui/components/shadcn/card/resource-stats-card/resource-stats-card-container.tsx +++ /dev/null @@ -1,55 +0,0 @@ -import { cva, type VariantProps } from "class-variance-authority"; - -import { cn } from "@/lib/utils"; - -const containerVariants = cva( - [ - "flex", - "rounded-[12px]", - "border", - "backdrop-blur-[46px]", - "border-slate-300", - "bg-[#F8FAFC80]", - "dark:border-[rgba(38,38,38,0.70)]", - "dark:bg-[rgba(23,23,23,0.50)]", - ], - { - variants: { - padding: { - sm: "px-3 py-2", - md: "px-[19px] py-[9px]", - lg: "px-6 py-3", - none: "p-0", - }, - }, - defaultVariants: { - padding: "md", - }, - }, -); - -export interface ResourceStatsCardContainerProps - extends React.HTMLAttributes, - VariantProps { - ref?: React.Ref; -} - -export const ResourceStatsCardContainer = ({ - className, - children, - padding, - ref, - ...props -}: ResourceStatsCardContainerProps) => { - return ( -
- {children} -
- ); -}; - -ResourceStatsCardContainer.displayName = "ResourceStatsCardContainer"; diff --git a/ui/components/shadcn/card/resource-stats-card/resource-stats-card-content.tsx b/ui/components/shadcn/card/resource-stats-card/resource-stats-card-content.tsx index e338c5e7b1..be3080143d 100644 --- a/ui/components/shadcn/card/resource-stats-card/resource-stats-card-content.tsx +++ b/ui/components/shadcn/card/resource-stats-card/resource-stats-card-content.tsx @@ -11,11 +11,11 @@ export interface StatItem { } const variantColors = { - default: "#868994", - fail: "#f54280", - pass: "#4ade80", - warning: "#fbbf24", - info: "#60a5fa", + default: "var(--bg-neutral-tertiary)", + fail: "var(--bg-fail-primary)", + pass: "var(--bg-pass-primary)", + warning: "var(--bg-warning-primary)", + info: "var(--bg-data-info)", } as const; type BadgeVariant = keyof typeof variantColors; @@ -26,8 +26,8 @@ const badgeVariants = cva( variants: { variant: { [CardVariant.default]: "bg-slate-100 dark:bg-[#535359]", - [CardVariant.fail]: "bg-red-100 dark:bg-[#432232]", - [CardVariant.pass]: "bg-green-100 dark:bg-[#204237]", + [CardVariant.fail]: "bg-bg-fail-secondary", + [CardVariant.pass]: "bg-bg-pass-secondary", [CardVariant.warning]: "bg-amber-100 dark:bg-[#3d3520]", [CardVariant.info]: "bg-blue-100 dark:bg-[#1e3a5f]", }, @@ -58,7 +58,7 @@ const badgeIconVariants = cva("", { }); const labelTextVariants = cva( - "leading-6 font-semibold text-slate-900 dark:text-zinc-300 whitespace-nowrap", + "leading-6 font-semibold text-text-neutral-secondary whitespace-nowrap", { variants: { size: { @@ -73,7 +73,7 @@ const labelTextVariants = cva( }, ); -const statIconVariants = cva("text-slate-600 dark:text-zinc-300", { +const statIconVariants = cva("text-text-neutral-secondary", { variants: { size: { sm: "h-2.5 w-2.5", @@ -87,7 +87,7 @@ const statIconVariants = cva("text-slate-600 dark:text-zinc-300", { }); const statLabelVariants = cva( - "leading-5 font-medium text-slate-700 dark:text-zinc-300", + "leading-5 font-medium text-text-neutral-secondary", { variants: { size: { diff --git a/ui/components/shadcn/card/resource-stats-card/resource-stats-card-divider.tsx b/ui/components/shadcn/card/resource-stats-card/resource-stats-card-divider.tsx deleted file mode 100644 index 3ec8d57ee4..0000000000 --- a/ui/components/shadcn/card/resource-stats-card/resource-stats-card-divider.tsx +++ /dev/null @@ -1,59 +0,0 @@ -import { cva, type VariantProps } from "class-variance-authority"; - -import { cn } from "@/lib/utils"; - -const dividerVariants = cva("flex items-center justify-center", { - variants: { - spacing: { - sm: "px-2", - md: "px-[23px]", - lg: "px-8", - }, - orientation: { - vertical: "h-full", - horizontal: "w-full", - }, - }, - defaultVariants: { - spacing: "md", - orientation: "vertical", - }, -}); - -const lineVariants = cva("bg-[rgba(39,39,42,1)]", { - variants: { - orientation: { - vertical: "h-full w-px", - horizontal: "w-full h-px", - }, - }, - defaultVariants: { - orientation: "vertical", - }, -}); - -export interface ResourceStatsCardDividerProps - extends React.HTMLAttributes, - VariantProps { - ref?: React.Ref; -} - -export const ResourceStatsCardDivider = ({ - className, - spacing, - orientation, - ref, - ...props -}: ResourceStatsCardDividerProps) => { - return ( -
-
-
- ); -}; - -ResourceStatsCardDivider.displayName = "ResourceStatsCardDivider"; diff --git a/ui/components/shadcn/card/resource-stats-card/resource-stats-card-header.tsx b/ui/components/shadcn/card/resource-stats-card/resource-stats-card-header.tsx index 2a4068e998..c324376a04 100644 --- a/ui/components/shadcn/card/resource-stats-card/resource-stats-card-header.tsx +++ b/ui/components/shadcn/card/resource-stats-card/resource-stats-card-header.tsx @@ -16,7 +16,7 @@ const headerVariants = cva("flex w-full items-center gap-1", { }, }); -const iconVariants = cva("text-zinc-300 dark:text-zinc-300", { +const iconVariants = cva("text-text-neutral-secondary", { variants: { size: { sm: "h-3.5 w-3.5", @@ -30,7 +30,7 @@ const iconVariants = cva("text-zinc-300 dark:text-zinc-300", { }); const titleVariants = cva( - "leading-7 font-semibold text-zinc-300 dark:text-zinc-300", + "leading-7 font-semibold text-text-neutral-secondary", { variants: { size: { @@ -45,21 +45,18 @@ const titleVariants = cva( }, ); -const countVariants = cva( - "leading-4 font-normal text-zinc-300 dark:text-zinc-300", - { - variants: { - size: { - sm: "text-[9px]", - md: "text-[10px]", - lg: "text-xs", - }, - }, - defaultVariants: { - size: "md", +const countVariants = cva("leading-4 font-normal text-text-neutral-secondary", { + variants: { + size: { + sm: "text-[9px]", + md: "text-[10px]", + lg: "text-xs", }, }, -); + defaultVariants: { + size: "md", + }, +}); export interface ResourceStatsCardHeaderProps extends React.HTMLAttributes, diff --git a/ui/components/shadcn/card/resource-stats-card/resource-stats-card.tsx b/ui/components/shadcn/card/resource-stats-card/resource-stats-card.tsx index 99d3e7867d..bb42f4bfff 100644 --- a/ui/components/shadcn/card/resource-stats-card/resource-stats-card.tsx +++ b/ui/components/shadcn/card/resource-stats-card/resource-stats-card.tsx @@ -3,17 +3,12 @@ import { LucideIcon } from "lucide-react"; import { cn } from "@/lib/utils"; -import { CardVariant } from "../card"; -import { ResourceStatsCardContainer } from "./resource-stats-card-container"; +import { Card, CardVariant } from "../card"; import type { StatItem } from "./resource-stats-card-content"; import { ResourceStatsCardContent } from "./resource-stats-card-content"; import { ResourceStatsCardHeader } from "./resource-stats-card-header"; export type { StatItem }; - -// Todo: when the design system is ready, we must use the colors from the design system (semantic colors) -// Variant styles using CVA for type safety and consistency -// Colors are exact HEX values from Figma design system const cardVariants = cva("", { variants: { variant: { @@ -109,7 +104,7 @@ export const ResourceStatsCard = ({ {header && } {emptyState ? (
-

+

{emptyState.message}

@@ -131,15 +126,16 @@ export const ResourceStatsCard = ({ // Otherwise, render with container return ( - {header && } {emptyState ? (
-

+

{emptyState.message}

@@ -155,7 +151,7 @@ export const ResourceStatsCard = ({ /> ) )} -
+ ); }; diff --git a/ui/components/shadcn/index.ts b/ui/components/shadcn/index.ts index 4bb244fb95..8991f1e34d 100644 --- a/ui/components/shadcn/index.ts +++ b/ui/components/shadcn/index.ts @@ -1,14 +1,12 @@ export * from "./badge/badge"; export * from "./button/button"; -export * from "./card/base-card/base-card"; export * from "./card/card"; export * from "./card/resource-stats-card/resource-stats-card"; -export * from "./card/resource-stats-card/resource-stats-card-container"; export * from "./card/resource-stats-card/resource-stats-card-content"; -export * from "./card/resource-stats-card/resource-stats-card-divider"; export * from "./card/resource-stats-card/resource-stats-card-header"; export * from "./dropdown/dropdown"; export * from "./select/select"; export * from "./separator/separator"; +export * from "./skeleton/skeleton"; export * from "./tabs/generic-tabs"; export * from "./tabs/tabs"; diff --git a/ui/components/shadcn/skeleton/skeleton.tsx b/ui/components/shadcn/skeleton/skeleton.tsx new file mode 100644 index 0000000000..34971c0554 --- /dev/null +++ b/ui/components/shadcn/skeleton/skeleton.tsx @@ -0,0 +1,16 @@ +import { cn } from "@/lib/utils"; + +function Skeleton({ className, ...props }: React.ComponentProps<"div">) { + return ( +
+ ); +} + +export { Skeleton }; diff --git a/ui/styles/globals.css b/ui/styles/globals.css index 50272c81a4..d6dfe3ee05 100644 --- a/ui/styles/globals.css +++ b/ui/styles/globals.css @@ -6,11 +6,11 @@ /* ===== LIGHT THEME (ROOT) ===== */ :root { /* ===== LEGACY VARIABLES (CHART COLORS) ===== */ - --chart-info: #3C8DFF; - --chart-warning: #FDFBD4; - --chart-warning-emphasis: #FEC94D; - --chart-danger: #F77852; - --chart-danger-emphasis: #FF006A; + --chart-info: #3c8dff; + --chart-warning: #fdfbd4; + --chart-warning-emphasis: #fec94d; + --chart-danger: #f77852; + --chart-danger-emphasis: #ff006a; --chart-success-color: #16a34a; --chart-fail: #dc2626; --chart-radar-primary: #9d174d; @@ -69,36 +69,40 @@ /* Text Colors */ --text-neutral-primary: var(--color-slate-950); - --text-neutral-secondary: var(--color-zinc-700); + --text-neutral-secondary: var(--color-zinc-800); --text-neutral-tertiary: var(--color-zinc-500); --text-error-primary: var(--color-red-600); /* Background Colors */ - --bg-neutral-primary: #FDFDFD; + --bg-neutral-primary: #fdfdfd; --bg-neutral-secondary: var(--color-white); - --bg-neutral-tertiary: #FBFDFD; + --bg-neutral-tertiary: #fbfdfd; --bg-tag-primary: var(--color-slate-50); --bg-pass-primary: var(--color-emerald-400); --bg-pass-secondary: var(--color-emerald-50); + --bg-warning-primary: var(--color-orange-500); --bg-fail-primary: var(--color-rose-500); --bg-fail-secondary: var(--color-rose-50); /* Severity Colors */ - --bg-data-critical: #FF006A; - --bg-data-high: #F77852; - --bg-data-medium: #FDD34F; - --bg-data-low: #F5F3CE; - --bg-data-info: #3C8DFF; + --bg-data-critical: #ff006a; + --bg-data-high: #f77852; + --bg-data-medium: #fdd34f; + --bg-data-low: #f5f3ce; + --bg-data-info: #3c8dff; + + /* Chart Dots */ + --chart-dots: var(--color-neutral-200); } /* ===== DARK THEME ===== */ .dark { /* ===== LEGACY VARIABLES (CHART COLORS) ===== */ - --chart-info: #3C8DFF; - --chart-warning: #FDFBD4; - --chart-warning-emphasis: #FEC94D; - --chart-danger: #F77852; - --chart-danger-emphasis: #FF006A; + --chart-info: #3c8dff; + --chart-warning: #fdfbd4; + --chart-warning-emphasis: #fec94d; + --chart-danger: #f77852; + --chart-danger-emphasis: #ff006a; --chart-success-color: #86da26; --chart-fail: #db2b49; --chart-radar-primary: #b51c80; @@ -157,26 +161,30 @@ /* Text Colors */ --text-neutral-primary: var(--color-zinc-100); - --text-neutral-secondary: var(--color-zinc-400); + --text-neutral-secondary: var(--color-zinc-300); --text-neutral-tertiary: var(--color-zinc-500); --text-error-primary: var(--color-rose-300); /* Background Colors */ --bg-neutral-primary: var(--color-zinc-950); - --bg-neutral-secondary: var(--color-slate-950); + --bg-neutral-secondary: var(--color-stone-950); --bg-neutral-tertiary: #121110; --bg-tag-primary: var(--color-slate-950); + --bg-warning-primary: var(--color-orange-400); --bg-pass-primary: var(--color-green-400); --bg-pass-secondary: var(--color-emerald-900); --bg-fail-primary: var(--color-rose-500); --bg-fail-secondary: #432232; /* Severity Colors */ - --bg-data-critical: #FF006A; - --bg-data-high: #F77852; - --bg-data-medium: #FEC94D; - --bg-data-low: #FDFBD4; - --bg-data-info: #3C8DFF; + --bg-data-critical: #ff006a; + --bg-data-high: #f77852; + --bg-data-medium: #fec94d; + --bg-data-low: #fdfbd4; + --bg-data-info: #3c8dff; + + /* Chart Dots */ + --chart-dots: var(--text-neutral-primary); } /* ===== TAILWIND THEME MAPPINGS ===== */ @@ -248,6 +256,7 @@ --color-bg-tag: var(--bg-tag-primary); --color-bg-pass: var(--bg-pass-primary); --color-bg-pass-secondary: var(--bg-pass-secondary); + --color-bg-warning: var(--bg-warning-primary); --color-bg-fail: var(--bg-fail-primary); --color-bg-fail-secondary: var(--bg-fail-secondary); } @@ -357,4 +366,4 @@ body { @apply bg-background text-foreground; } -} \ No newline at end of file +}