Skip to content

Commit 709a375

Browse files
ismoilovdevmlclaude
andcommitted
Apply gradient design system across all pages
- Updated StatsCard component with theme-aware gradients - Added support for 6 color variants (blue, green, red, yellow, purple, orange) - Applied consistent light/dark theme gradient backgrounds - Enhanced all statistics cards with hover animations - Unified design system across Overview, Pipelines, Runners, and Insights pages - Light theme: Soft pastel gradients (50-100 range) - Dark theme: Subtle glow gradients (10-20 opacity) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
1 parent f45755d commit 709a375

File tree

1 file changed

+61
-13
lines changed

1 file changed

+61
-13
lines changed

src/components/StatsCard.tsx

Lines changed: 61 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import { LucideIcon } from 'lucide-react';
44
import { cn } from '@/lib/utils';
5+
import { useTheme } from '@/hooks/useTheme';
56

67
interface StatsCardProps {
78
title: string;
@@ -11,39 +12,86 @@ interface StatsCardProps {
1112
value: number;
1213
isPositive: boolean;
1314
};
14-
color?: 'blue' | 'green' | 'red' | 'yellow' | 'purple';
15+
color?: 'blue' | 'green' | 'red' | 'yellow' | 'purple' | 'orange';
1516
}
1617

1718
export default function StatsCard({ title, value, icon: Icon, trend, color = 'blue' }: StatsCardProps) {
18-
const colorClasses = {
19-
blue: 'from-blue-500/10 to-blue-600/10 border-blue-500/20 text-blue-500',
20-
green: 'from-green-500/10 to-green-600/10 border-green-500/20 text-green-500',
21-
red: 'from-red-500/10 to-red-600/10 border-red-500/20 text-red-500',
22-
yellow: 'from-yellow-500/10 to-yellow-600/10 border-yellow-500/20 text-yellow-500',
23-
purple: 'from-purple-500/10 to-purple-600/10 border-purple-500/20 text-purple-500',
19+
const { theme, textPrimary, textSecondary } = useTheme();
20+
21+
const getColorClasses = () => {
22+
const colors = {
23+
blue: {
24+
light: 'from-blue-50 to-blue-100 border-blue-200 hover:from-blue-100 hover:to-blue-200',
25+
dark: 'from-blue-500/10 to-blue-600/20 border-blue-500/30 hover:from-blue-500/20 hover:to-blue-600/30',
26+
icon: 'bg-blue-500/20',
27+
iconDark: 'bg-blue-500/10',
28+
text: theme === 'light' ? 'text-blue-700' : 'text-blue-400',
29+
},
30+
green: {
31+
light: 'from-green-50 to-green-100 border-green-200 hover:from-green-100 hover:to-green-200',
32+
dark: 'from-green-500/10 to-green-600/20 border-green-500/30 hover:from-green-500/20 hover:to-green-600/30',
33+
icon: 'bg-green-500/20',
34+
iconDark: 'bg-green-500/10',
35+
text: theme === 'light' ? 'text-green-700' : 'text-green-400',
36+
},
37+
red: {
38+
light: 'from-red-50 to-red-100 border-red-200 hover:from-red-100 hover:to-red-200',
39+
dark: 'from-red-500/10 to-red-600/20 border-red-500/30 hover:from-red-500/20 hover:to-red-600/30',
40+
icon: 'bg-red-500/20',
41+
iconDark: 'bg-red-500/10',
42+
text: theme === 'light' ? 'text-red-700' : 'text-red-400',
43+
},
44+
yellow: {
45+
light: 'from-yellow-50 to-yellow-100 border-yellow-200 hover:from-yellow-100 hover:to-yellow-200',
46+
dark: 'from-yellow-500/10 to-yellow-600/20 border-yellow-500/30 hover:from-yellow-500/20 hover:to-yellow-600/30',
47+
icon: 'bg-yellow-500/20',
48+
iconDark: 'bg-yellow-500/10',
49+
text: theme === 'light' ? 'text-yellow-700' : 'text-yellow-400',
50+
},
51+
purple: {
52+
light: 'from-purple-50 to-purple-100 border-purple-200 hover:from-purple-100 hover:to-purple-200',
53+
dark: 'from-purple-500/10 to-purple-600/20 border-purple-500/30 hover:from-purple-500/20 hover:to-purple-600/30',
54+
icon: 'bg-purple-500/20',
55+
iconDark: 'bg-purple-500/10',
56+
text: theme === 'light' ? 'text-purple-700' : 'text-purple-400',
57+
},
58+
orange: {
59+
light: 'from-orange-50 to-orange-100 border-orange-200 hover:from-orange-100 hover:to-orange-200',
60+
dark: 'from-orange-500/10 to-orange-600/20 border-orange-500/30 hover:from-orange-500/20 hover:to-orange-600/30',
61+
icon: 'bg-orange-500/20',
62+
iconDark: 'bg-orange-500/10',
63+
text: theme === 'light' ? 'text-orange-700' : 'text-orange-400',
64+
},
65+
};
66+
return colors[color];
2467
};
2568

69+
const colorClasses = getColorClasses();
70+
2671
return (
2772
<div className={cn(
2873
'bg-gradient-to-br border rounded-xl p-6 transition-all hover:scale-105',
29-
colorClasses[color]
74+
theme === 'light' ? `${colorClasses.light} shadow-sm hover:shadow-md` : colorClasses.dark
3075
)}>
3176
<div className="flex items-start justify-between">
3277
<div>
33-
<p className="text-zinc-400 text-sm font-medium mb-2">{title}</p>
34-
<p className="text-3xl font-bold text-white mb-1">{value}</p>
78+
<p className={`text-sm font-medium mb-2 ${colorClasses.text}`}>{title}</p>
79+
<p className={`text-3xl font-bold mb-1 ${textPrimary}`}>{value}</p>
3580
{trend && (
3681
<div className={cn(
3782
'text-xs font-medium flex items-center gap-1',
38-
trend.isPositive ? 'text-green-400' : 'text-red-400'
83+
trend.isPositive ? 'text-green-500' : 'text-red-500'
3984
)}>
4085
<span>{trend.isPositive ? '↗' : '↘'}</span>
4186
<span>{Math.abs(trend.value)}%</span>
4287
</div>
4388
)}
4489
</div>
45-
<div className={cn('p-3 rounded-lg', colorClasses[color])}>
46-
<Icon className="w-6 h-6" />
90+
<div className={cn(
91+
'p-3 rounded-lg',
92+
theme === 'light' ? colorClasses.icon : colorClasses.iconDark
93+
)}>
94+
<Icon className={`w-6 h-6 ${colorClasses.text.replace('text-', 'text-')}`} />
4795
</div>
4896
</div>
4997
</div>

0 commit comments

Comments
 (0)