feat: refine card styles and interactions across the dashboard; adjust glassmorphism effects, enhance texture for statistic cards, and improve layout for account filter component

This commit is contained in:
Julien Froidefond
2025-12-21 13:33:23 +01:00
parent c4707e5511
commit 6f78dca1f0
4 changed files with 84 additions and 41 deletions

View File

@@ -10,9 +10,9 @@
--foreground: oklch(0.1 0.015 280); --foreground: oklch(0.1 0.015 280);
/* Cards avec glassmorphism très prononcé */ /* Cards avec glassmorphism très prononcé */
--card: oklch(1 0 0 / 0.6); --card: oklch(1 0 0 / 0.5);
--card-foreground: oklch(0.1 0.015 280); --card-foreground: oklch(0.1 0.015 280);
--card-hover: oklch(1 0 0 / 0.75); --card-hover: oklch(1 0 0 / 0.65);
/* Popover avec backdrop blur très fort */ /* Popover avec backdrop blur très fort */
--popover: oklch(1 0 0 / 0.95); --popover: oklch(1 0 0 / 0.95);
@@ -82,9 +82,9 @@
--foreground: oklch(0.97 0.005 280); --foreground: oklch(0.97 0.005 280);
/* Cards avec effet glassmorphism sombre très prononcé */ /* Cards avec effet glassmorphism sombre très prononcé */
--card: oklch(0.15 0.015 280 / 0.6); --card: oklch(0.15 0.015 280 / 0.5);
--card-foreground: oklch(0.97 0.005 280); --card-foreground: oklch(0.97 0.005 280);
--card-hover: oklch(0.18 0.015 280 / 0.75); --card-hover: oklch(0.18 0.015 280 / 0.65);
/* Popover avec backdrop blur très fort */ /* Popover avec backdrop blur très fort */
--popover: oklch(0.15 0.015 280 / 0.95); --popover: oklch(0.15 0.015 280 / 0.95);
@@ -459,18 +459,19 @@
z-index: 1; z-index: 1;
} }
/* Fintech card styles avec design moderne et élégant */ /* Fintech card styles avec effet glassmorphism prononcé */
.fintech-card { .fintech-card {
background: var(--card); background: color-mix(in srgb, var(--card) 70%, transparent);
backdrop-filter: blur(40px) saturate(180%); backdrop-filter: blur(60px) saturate(200%) brightness(1.05);
-webkit-backdrop-filter: blur(40px) saturate(180%); -webkit-backdrop-filter: blur(60px) saturate(200%) brightness(1.05);
border: 1px solid color-mix(in srgb, var(--border) 60%, transparent); border: none;
border-radius: calc(var(--radius) + 0.25rem); border-radius: calc(var(--radius) + 0.25rem);
box-shadow: box-shadow:
0 1px 3px 0 color-mix(in srgb, var(--foreground) 4%, transparent), 0 2px 8px 0 color-mix(in srgb, var(--foreground) 6%, transparent),
0 4px 12px -2px color-mix(in srgb, var(--primary) 6%, transparent), 0 8px 24px -4px color-mix(in srgb, var(--primary) 8%, transparent),
0 8px 24px -4px color-mix(in srgb, var(--foreground) 2%, transparent), 0 16px 48px -8px color-mix(in srgb, var(--foreground) 3%, transparent),
inset 0 1px 0 0 color-mix(in srgb, white 30%, transparent); inset 0 1px 0 0 color-mix(in srgb, white 40%, transparent),
inset 0 -1px 0 0 color-mix(in srgb, var(--foreground) 2%, transparent);
position: relative; position: relative;
overflow: hidden; overflow: hidden;
} }
@@ -494,13 +495,47 @@
opacity: 0.1; opacity: 0.1;
} }
/* Texture plus prononcée pour les cards de statistiques */
.stat-card-textured::before {
background-image:
radial-gradient(circle at 1px 1px, color-mix(in srgb, var(--foreground) 3%, transparent) 1px, transparent 0),
radial-gradient(circle at 11px 11px, color-mix(in srgb, var(--foreground) 1.5%, transparent) 1px, transparent 0);
background-size: 16px 16px, 24px 24px;
opacity: 0.2;
z-index: 1;
}
.dark .stat-card-textured::before {
background-image:
radial-gradient(circle at 1px 1px, color-mix(in srgb, white 4%, transparent) 1px, transparent 0),
radial-gradient(circle at 11px 11px, color-mix(in srgb, white 2%, transparent) 1px, transparent 0);
opacity: 0.15;
}
/* Effet glass renforcé pour les cards de contenu */
.fintech-card.card-hover {
background: color-mix(in srgb, var(--card) 60%, transparent);
backdrop-filter: blur(80px) saturate(220%) brightness(1.08);
-webkit-backdrop-filter: blur(80px) saturate(220%) brightness(1.08);
}
.dark .fintech-card.card-hover {
background: color-mix(in srgb, var(--card) 55%, transparent);
backdrop-filter: blur(80px) saturate(220%) brightness(0.92);
-webkit-backdrop-filter: blur(80px) saturate(220%) brightness(0.92);
}
.dark .fintech-card { .dark .fintech-card {
border-color: color-mix(in srgb, var(--border) 40%, transparent); background: color-mix(in srgb, var(--card) 65%, transparent);
backdrop-filter: blur(60px) saturate(200%) brightness(0.95);
-webkit-backdrop-filter: blur(60px) saturate(200%) brightness(0.95);
border: none;
box-shadow: box-shadow:
0 1px 3px 0 color-mix(in srgb, var(--foreground) 8%, transparent), 0 2px 8px 0 color-mix(in srgb, var(--foreground) 12%, transparent),
0 4px 12px -2px color-mix(in srgb, var(--primary) 8%, transparent), 0 8px 24px -4px color-mix(in srgb, var(--primary) 12%, transparent),
0 8px 24px -4px color-mix(in srgb, black 40%, transparent), 0 16px 48px -8px color-mix(in srgb, black 50%, transparent),
inset 0 1px 0 0 color-mix(in srgb, white 8%, transparent); inset 0 1px 0 0 color-mix(in srgb, white 12%, transparent),
inset 0 -1px 0 0 color-mix(in srgb, var(--foreground) 4%, transparent);
} }
.fintech-card::after { .fintech-card::after {
@@ -509,19 +544,29 @@
top: 0; top: 0;
left: 0; left: 0;
right: 0; right: 0;
height: 1px; height: 2px;
background: linear-gradient( background: linear-gradient(
90deg, 90deg,
transparent 0%, transparent 0%,
color-mix(in srgb, white 50%, transparent) 50%, color-mix(in srgb, white 60%, transparent) 20%,
color-mix(in srgb, white 80%, transparent) 50%,
color-mix(in srgb, white 60%, transparent) 80%,
transparent 100% transparent 100%
); );
opacity: 0.6; opacity: 0.7;
z-index: 2; z-index: 2;
} }
.dark .fintech-card::after { .dark .fintech-card::after {
opacity: 0.2; opacity: 0.25;
background: linear-gradient(
90deg,
transparent 0%,
color-mix(in srgb, white 30%, transparent) 20%,
color-mix(in srgb, white 40%, transparent) 50%,
color-mix(in srgb, white 30%, transparent) 80%,
transparent 100%
);
} }
/* Gradient backgrounds for stat cards - design moderne et subtil */ /* Gradient backgrounds for stat cards - design moderne et subtil */

View File

@@ -60,18 +60,16 @@ export default function DashboardPage() {
} }
/> />
<Card className="mb-6 card-hover"> <div className="mb-6">
<CardContent className="px-5 py-5 sm:px-6 sm:py-6"> <AccountFilterCombobox
<AccountFilterCombobox accounts={data.accounts}
accounts={data.accounts} folders={data.folders}
folders={data.folders} value={selectedAccounts}
value={selectedAccounts} onChange={setSelectedAccounts}
onChange={setSelectedAccounts} className="w-full md:w-[320px]"
className="w-full md:w-[320px]" filteredTransactions={data.transactions}
filteredTransactions={data.transactions} />
/> </div>
</CardContent>
</Card>
<OverviewCards data={filteredData} /> <OverviewCards data={filteredData} />

View File

@@ -61,13 +61,13 @@ export function RecentTransactions({ data }: RecentTransactionsProps) {
} }
return ( return (
<Card className="card-hover"> <Card className="card-hover relative overflow-hidden">
<CardHeader className="pb-5"> <CardHeader className="pb-5 relative z-10">
<CardTitle className="text-lg md:text-xl font-black tracking-tight"> <CardTitle className="text-lg md:text-xl font-black tracking-tight">
Transactions récentes Transactions récentes
</CardTitle> </CardTitle>
</CardHeader> </CardHeader>
<CardContent className="px-5 md:px-6"> <CardContent className="px-5 md:px-6 relative z-10">
<div className="space-y-3"> <div className="space-y-3">
{recentTransactions.map((transaction) => { {recentTransactions.map((transaction) => {
const category = getCategory(transaction.categoryId); const category = getCategory(transaction.categoryId);

View File

@@ -21,7 +21,7 @@ export function StatsSummaryCards({
return ( return (
<div className="grid gap-3 md:gap-4 grid-cols-2 md:grid-cols-4"> <div className="grid gap-3 md:gap-4 grid-cols-2 md:grid-cols-4">
<Card className="relative overflow-hidden"> <Card className="stat-card-textured relative overflow-hidden">
{/* Icône en arrière-plan */} {/* Icône en arrière-plan */}
<div className="absolute bottom-2 right-2 opacity-[0.04] dark:opacity-[0.03] z-0 pointer-events-none"> <div className="absolute bottom-2 right-2 opacity-[0.04] dark:opacity-[0.03] z-0 pointer-events-none">
<TrendingUp className="h-16 w-16 md:h-20 md:w-20 text-emerald-600 dark:text-emerald-400" strokeWidth={1} /> <TrendingUp className="h-16 w-16 md:h-20 md:w-20 text-emerald-600 dark:text-emerald-400" strokeWidth={1} />
@@ -38,7 +38,7 @@ export function StatsSummaryCards({
</CardContent> </CardContent>
</Card> </Card>
<Card className="relative overflow-hidden"> <Card className="stat-card-textured relative overflow-hidden">
{/* Icône en arrière-plan */} {/* Icône en arrière-plan */}
<div className="absolute bottom-2 right-2 opacity-[0.04] dark:opacity-[0.03] z-0 pointer-events-none"> <div className="absolute bottom-2 right-2 opacity-[0.04] dark:opacity-[0.03] z-0 pointer-events-none">
<TrendingDown className="h-16 w-16 md:h-20 md:w-20 text-red-600 dark:text-red-400" strokeWidth={1} /> <TrendingDown className="h-16 w-16 md:h-20 md:w-20 text-red-600 dark:text-red-400" strokeWidth={1} />
@@ -55,7 +55,7 @@ export function StatsSummaryCards({
</CardContent> </CardContent>
</Card> </Card>
<Card className="relative overflow-hidden"> <Card className="stat-card-textured relative overflow-hidden">
{/* Icône en arrière-plan */} {/* Icône en arrière-plan */}
<div className="absolute bottom-2 right-2 opacity-[0.04] dark:opacity-[0.03] z-0 pointer-events-none"> <div className="absolute bottom-2 right-2 opacity-[0.04] dark:opacity-[0.03] z-0 pointer-events-none">
<ArrowRight className="h-16 w-16 md:h-20 md:w-20 text-muted-foreground/40" strokeWidth={1} /> <ArrowRight className="h-16 w-16 md:h-20 md:w-20 text-muted-foreground/40" strokeWidth={1} />
@@ -72,7 +72,7 @@ export function StatsSummaryCards({
</CardContent> </CardContent>
</Card> </Card>
<Card className="relative overflow-hidden"> <Card className="stat-card-textured relative overflow-hidden">
{/* Icône en arrière-plan */} {/* Icône en arrière-plan */}
<div className="absolute bottom-2 right-2 opacity-[0.04] dark:opacity-[0.03] z-0 pointer-events-none"> <div className="absolute bottom-2 right-2 opacity-[0.04] dark:opacity-[0.03] z-0 pointer-events-none">
<div className={cn( <div className={cn(