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:
@@ -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 };
|
||||
|
||||
Reference in New Issue
Block a user