feat(dashboard): Complete "Mission Control" UI redesign

Overhaul the GuruRMM dashboard with a dark cyberpunk aesthetic featuring
glassmorphism effects, cyan accent lighting, and smooth animations.

Visual Changes:
- Dark theme with CSS variables for consistent theming
- Glassmorphism card effects with colored glow variants
- Grid pattern backgrounds and floating geometric shapes
- JetBrains Mono + Inter font pairing for tech aesthetic
- Cyan, green, amber, and rose accent colors with glow effects

Component Updates:
- index.css: Complete CSS overhaul with utility classes, animations,
  and glassmorphism foundations (1300+ lines added)
- Login.tsx: Glassmorphism login card with gradient logo and
  floating background shapes
- Layout.tsx: Dark sidebar with cyan nav highlights, grid pattern
  main area, animated user profile section
- Dashboard.tsx: Animated stat cards with staggered entrances,
  live status indicator with pulse animation, relative timestamps
- Card.tsx: Added glow variants (cyan/green/amber/rose) with
  hover lift effects
- Button.tsx: Gradient backgrounds, glow-on-hover, scale animations
- Input.tsx: Dark styling with cyan focus glow, added Textarea component

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-21 06:23:59 -07:00
parent bc103bd888
commit 666d06af1b
7 changed files with 2258 additions and 241 deletions

View File

@@ -1,12 +1,52 @@
import { HTMLAttributes, forwardRef } from "react";
import { cn } from "../lib/utils";
const Card = forwardRef<HTMLDivElement, HTMLAttributes<HTMLDivElement>>(
({ className, ...props }, ref) => (
/**
* Mission Control Card Component
* Glassmorphism design with optional glow variants
*/
export type CardVariant = "default" | "glow-cyan" | "glow-green" | "glow-amber" | "glow-rose";
export interface CardProps extends HTMLAttributes<HTMLDivElement> {
variant?: CardVariant;
}
const cardVariants: Record<CardVariant, string> = {
default: "border-slate-700/50",
"glow-cyan": "border-cyan-500/50 shadow-[0_0_15px_rgba(6,182,212,0.15)]",
"glow-green": "border-emerald-500/50 shadow-[0_0_15px_rgba(16,185,129,0.15)]",
"glow-amber": "border-amber-500/50 shadow-[0_0_15px_rgba(245,158,11,0.15)]",
"glow-rose": "border-rose-500/50 shadow-[0_0_15px_rgba(244,63,94,0.15)]",
};
const cardHoverVariants: Record<CardVariant, string> = {
default: "hover:border-slate-600/70 hover:shadow-lg hover:shadow-slate-900/50",
"glow-cyan": "hover:border-cyan-400/70 hover:shadow-[0_0_25px_rgba(6,182,212,0.25)]",
"glow-green": "hover:border-emerald-400/70 hover:shadow-[0_0_25px_rgba(16,185,129,0.25)]",
"glow-amber": "hover:border-amber-400/70 hover:shadow-[0_0_25px_rgba(245,158,11,0.25)]",
"glow-rose": "hover:border-rose-400/70 hover:shadow-[0_0_25px_rgba(244,63,94,0.25)]",
};
const Card = forwardRef<HTMLDivElement, CardProps>(
({ className, variant = "default", ...props }, ref) => (
<div
ref={ref}
className={cn(
"rounded-xl border border-[hsl(var(--border))] bg-[hsl(var(--card))] text-[hsl(var(--card-foreground))] shadow",
// Base glassmorphism
"rounded-xl bg-slate-900/60 backdrop-blur-xl",
// Border
"border",
cardVariants[variant],
// Inner shadow for depth
"shadow-[inset_0_1px_0_0_rgba(148,163,184,0.1)]",
// Text color
"text-slate-100",
// Transition for hover effects
"transition-all duration-300 ease-out",
// Hover: subtle lift
"hover:-translate-y-0.5",
cardHoverVariants[variant],
className
)}
{...props}
@@ -17,16 +57,42 @@ Card.displayName = "Card";
const CardHeader = forwardRef<HTMLDivElement, HTMLAttributes<HTMLDivElement>>(
({ className, ...props }, ref) => (
<div ref={ref} className={cn("flex flex-col space-y-1.5 p-6", className)} {...props} />
<div
ref={ref}
className={cn(
"flex flex-col space-y-1.5 p-6",
// Bottom border separator
"border-b border-slate-700/50",
className
)}
{...props}
/>
)
);
CardHeader.displayName = "CardHeader";
const CardTitle = forwardRef<HTMLParagraphElement, HTMLAttributes<HTMLHeadingElement>>(
({ className, ...props }, ref) => (
export interface CardTitleProps extends HTMLAttributes<HTMLHeadingElement> {
gradient?: boolean;
gradientFrom?: string;
gradientTo?: string;
}
const CardTitle = forwardRef<HTMLParagraphElement, CardTitleProps>(
({ className, gradient = false, gradientFrom = "cyan-400", gradientTo = "blue-500", ...props }, ref) => (
<h3
ref={ref}
className={cn("font-semibold leading-none tracking-tight", className)}
className={cn(
// Monospace/bold styling
"font-mono font-bold leading-none tracking-tight text-lg",
// Gradient text option
gradient && [
"bg-clip-text text-transparent",
`bg-gradient-to-r from-${gradientFrom} to-${gradientTo}`,
],
// Default text color when not gradient
!gradient && "text-slate-100",
className
)}
{...props}
/>
)
@@ -35,16 +101,41 @@ CardTitle.displayName = "CardTitle";
const CardDescription = forwardRef<HTMLParagraphElement, HTMLAttributes<HTMLParagraphElement>>(
({ className, ...props }, ref) => (
<p ref={ref} className={cn("text-sm text-[hsl(var(--muted-foreground))]", className)} {...props} />
<p
ref={ref}
className={cn(
"text-sm text-slate-400",
className
)}
{...props}
/>
)
);
CardDescription.displayName = "CardDescription";
const CardContent = forwardRef<HTMLDivElement, HTMLAttributes<HTMLDivElement>>(
({ className, ...props }, ref) => (
<div ref={ref} className={cn("p-6 pt-0", className)} {...props} />
<div
ref={ref}
className={cn("p-6 pt-0", className)}
{...props}
/>
)
);
CardContent.displayName = "CardContent";
export { Card, CardHeader, CardTitle, CardDescription, CardContent };
const CardFooter = forwardRef<HTMLDivElement, HTMLAttributes<HTMLDivElement>>(
({ className, ...props }, ref) => (
<div
ref={ref}
className={cn(
"flex items-center p-6 pt-0",
className
)}
{...props}
/>
)
);
CardFooter.displayName = "CardFooter";
export { Card, CardHeader, CardTitle, CardDescription, CardContent, CardFooter };