From 1548ce4b0d9a2649bb5a2e7550bc43967c26ef76 Mon Sep 17 00:00:00 2001 From: Julien Froidefond Date: Sun, 7 Dec 2025 17:25:58 +0100 Subject: [PATCH] feat: update global styles and component designs for enhanced aesthetics and responsiveness, including new gradients, shadows, and transitions --- app/globals.css | 270 ++++++++++++++---------- components/accounts/account-card.tsx | 80 ++++--- components/dashboard/overview-cards.tsx | 15 +- components/ui/button.tsx | 12 +- components/ui/card.tsx | 7 +- components/ui/dropdown-menu.tsx | 5 +- components/ui/input.tsx | 9 +- components/ui/textarea.tsx | 8 +- 8 files changed, 243 insertions(+), 163 deletions(-) diff --git a/app/globals.css b/app/globals.css index fed63f2..548a878 100644 --- a/app/globals.css +++ b/app/globals.css @@ -4,74 +4,117 @@ @custom-variant dark (&:is(.dark *)); :root { - --background: oklch(1 0 0); - --foreground: oklch(0.145 0 0); - --card: oklch(1 0 0); - --card-foreground: oklch(0.145 0 0); - --popover: oklch(1 0 0); - --popover-foreground: oklch(0.145 0 0); - --primary: oklch(0.205 0 0); - --primary-foreground: oklch(0.985 0 0); - --secondary: oklch(0.97 0 0); - --secondary-foreground: oklch(0.205 0 0); - --muted: oklch(0.97 0 0); - --muted-foreground: oklch(0.556 0 0); - --accent: oklch(0.97 0 0); - --accent-foreground: oklch(0.205 0 0); - --destructive: oklch(0.577 0.245 27.325); - --destructive-foreground: oklch(0.577 0.245 27.325); - --border: oklch(0.922 0 0); - --input: oklch(0.922 0 0); - --ring: oklch(0.708 0 0); - --chart-1: oklch(0.646 0.222 41.116); - --chart-2: oklch(0.6 0.118 184.704); - --chart-3: oklch(0.398 0.07 227.392); - --chart-4: oklch(0.828 0.189 84.429); - --chart-5: oklch(0.769 0.188 70.08); - --radius: 0.625rem; - --sidebar: oklch(0.985 0 0); - --sidebar-foreground: oklch(0.145 0 0); - --sidebar-primary: oklch(0.205 0 0); - --sidebar-primary-foreground: oklch(0.985 0 0); - --sidebar-accent: oklch(0.97 0 0); - --sidebar-accent-foreground: oklch(0.205 0 0); - --sidebar-border: oklch(0.922 0 0); - --sidebar-ring: oklch(0.708 0 0); + /* Background moderne avec légère teinte */ + --background: oklch(0.99 0.002 270); + --foreground: oklch(0.15 0.01 270); + + /* Cards avec glassmorphism subtil */ + --card: oklch(1 0 0 / 0.8); + --card-foreground: oklch(0.15 0.01 270); + + /* Popover avec backdrop blur */ + --popover: oklch(1 0 0 / 0.95); + --popover-foreground: oklch(0.15 0.01 270); + + /* Primary: Bleu/violet fintech moderne */ + --primary: oklch(0.55 0.18 260); + --primary-foreground: oklch(0.99 0 0); + + /* Secondary avec teinte subtile */ + --secondary: oklch(0.97 0.005 270); + --secondary-foreground: oklch(0.25 0.01 270); + + /* Muted plus doux */ + --muted: oklch(0.96 0.003 270); + --muted-foreground: oklch(0.5 0.008 270); + + /* Accent avec couleur vibrante */ + --accent: oklch(0.95 0.01 260); + --accent-foreground: oklch(0.55 0.18 260); + + /* Destructive moderne */ + --destructive: oklch(0.55 0.22 25); + --destructive-foreground: oklch(0.99 0 0); + + /* Bordures fines et subtiles */ + --border: oklch(0.92 0.005 270 / 0.6); + --input: oklch(0.96 0.003 270); + --ring: oklch(0.55 0.18 260 / 0.3); + + /* Chart colors modernes et vibrantes */ + --chart-1: oklch(0.6 0.2 260); + --chart-2: oklch(0.65 0.18 180); + --chart-3: oklch(0.7 0.15 120); + --chart-4: oklch(0.65 0.2 320); + --chart-5: oklch(0.6 0.18 40); + + --radius: 0.75rem; + + /* Sidebar moderne */ + --sidebar: oklch(0.98 0.003 270); + --sidebar-foreground: oklch(0.2 0.01 270); + --sidebar-primary: oklch(0.55 0.18 260); + --sidebar-primary-foreground: oklch(0.99 0 0); + --sidebar-accent: oklch(0.95 0.01 260); + --sidebar-accent-foreground: oklch(0.25 0.01 270); + --sidebar-border: oklch(0.92 0.005 270 / 0.5); + --sidebar-ring: oklch(0.55 0.18 260 / 0.2); } .dark { - --background: oklch(0.145 0 0); - --foreground: oklch(0.985 0 0); - --card: oklch(0.145 0 0); - --card-foreground: oklch(0.985 0 0); - --popover: oklch(0.145 0 0); - --popover-foreground: oklch(0.985 0 0); - --primary: oklch(0.985 0 0); - --primary-foreground: oklch(0.205 0 0); - --secondary: oklch(0.269 0 0); - --secondary-foreground: oklch(0.985 0 0); - --muted: oklch(0.269 0 0); - --muted-foreground: oklch(0.708 0 0); - --accent: oklch(0.269 0 0); - --accent-foreground: oklch(0.985 0 0); - --destructive: oklch(0.396 0.141 25.723); - --destructive-foreground: oklch(0.637 0.237 25.331); - --border: oklch(0.269 0 0); - --input: oklch(0.269 0 0); - --ring: oklch(0.439 0 0); - --chart-1: oklch(0.488 0.243 264.376); - --chart-2: oklch(0.696 0.17 162.48); - --chart-3: oklch(0.769 0.188 70.08); - --chart-4: oklch(0.627 0.265 303.9); - --chart-5: oklch(0.645 0.246 16.439); - --sidebar: oklch(0.205 0 0); - --sidebar-foreground: oklch(0.985 0 0); - --sidebar-primary: oklch(0.488 0.243 264.376); - --sidebar-primary-foreground: oklch(0.985 0 0); - --sidebar-accent: oklch(0.269 0 0); - --sidebar-accent-foreground: oklch(0.985 0 0); - --sidebar-border: oklch(0.269 0 0); - --sidebar-ring: oklch(0.439 0 0); + /* Background sombre avec teinte subtile */ + --background: oklch(0.12 0.01 270); + --foreground: oklch(0.98 0.002 270); + + /* Cards avec effet glassmorphism sombre */ + --card: oklch(0.15 0.01 270 / 0.7); + --card-foreground: oklch(0.98 0.002 270); + + /* Popover avec backdrop blur */ + --popover: oklch(0.15 0.01 270 / 0.95); + --popover-foreground: oklch(0.98 0.002 270); + + /* Primary: Bleu/violet brillant pour dark mode */ + --primary: oklch(0.65 0.2 260); + --primary-foreground: oklch(0.12 0.01 270); + + /* Secondary avec plus de contraste */ + --secondary: oklch(0.22 0.01 270); + --secondary-foreground: oklch(0.95 0.002 270); + + /* Muted plus visible */ + --muted: oklch(0.22 0.01 270); + --muted-foreground: oklch(0.65 0.008 270); + + /* Accent vibrant */ + --accent: oklch(0.25 0.015 260); + --accent-foreground: oklch(0.65 0.2 260); + + /* Destructive moderne */ + --destructive: oklch(0.6 0.22 25); + --destructive-foreground: oklch(0.98 0 0); + + /* Bordures subtiles */ + --border: oklch(0.25 0.01 270 / 0.5); + --input: oklch(0.22 0.01 270); + --ring: oklch(0.65 0.2 260 / 0.4); + + /* Chart colors vibrantes pour dark */ + --chart-1: oklch(0.7 0.22 260); + --chart-2: oklch(0.75 0.2 180); + --chart-3: oklch(0.8 0.18 120); + --chart-4: oklch(0.75 0.22 320); + --chart-5: oklch(0.7 0.2 40); + + /* Sidebar dark moderne */ + --sidebar: oklch(0.14 0.01 270); + --sidebar-foreground: oklch(0.95 0.002 270); + --sidebar-primary: oklch(0.65 0.2 260); + --sidebar-primary-foreground: oklch(0.12 0.01 270); + --sidebar-accent: oklch(0.25 0.015 260); + --sidebar-accent-foreground: oklch(0.95 0.002 270); + --sidebar-border: oklch(0.25 0.01 270 / 0.4); + --sidebar-ring: oklch(0.65 0.2 260 / 0.3); } @theme inline { @@ -121,9 +164,45 @@ } body { @apply bg-background text-foreground; + font-feature-settings: "rlig" 1, "calt" 1; } - /* Background avec beau dégradé */ + /* Animations fintech modernes */ + @keyframes fade-in { + from { + opacity: 0; + transform: translateY(4px); + } + to { + opacity: 1; + transform: translateY(0); + } + } + + @keyframes slide-in { + from { + opacity: 0; + transform: translateX(-8px); + } + to { + opacity: 1; + transform: translateX(0); + } + } + + /* Smooth scrolling */ + html { + scroll-behavior: smooth; + } + + /* Amélioration des transitions globales */ + * { + transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform; + transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + transition-duration: 150ms; + } + + /* Background fintech moderne avec dégradés subtils */ .page-background { position: relative; background: var(--background); @@ -138,58 +217,37 @@ bottom: 0; z-index: 0; background: - radial-gradient(ellipse 80% 50% at 50% -20%, - color-mix(in srgb, var(--chart-1) 25%, transparent) 0%, - transparent 50% + radial-gradient(ellipse 100% 60% at 0% 0%, + color-mix(in srgb, var(--primary) 8%, transparent) 0%, + transparent 60% ), - radial-gradient(ellipse 60% 80% at -10% 50%, - color-mix(in srgb, var(--chart-2) 20%, transparent) 0%, - transparent 50% + radial-gradient(ellipse 80% 50% at 100% 100%, + color-mix(in srgb, var(--chart-2) 6%, transparent) 0%, + transparent 60% ), - radial-gradient(ellipse 60% 80% at 110% 50%, - color-mix(in srgb, var(--chart-3) 20%, transparent) 0%, - transparent 50% - ), - radial-gradient(ellipse 80% 50% at 50% 120%, - color-mix(in srgb, var(--chart-4) 25%, transparent) 0%, - transparent 50% - ), - linear-gradient( - 135deg, - color-mix(in srgb, var(--chart-1) 8%, transparent) 0%, - transparent 25%, - transparent 75%, - color-mix(in srgb, var(--chart-2) 8%, transparent) 100% + radial-gradient(ellipse 60% 40% at 50% 50%, + color-mix(in srgb, var(--chart-3) 4%, transparent) 0%, + transparent 70% ); background-size: 100% 100%; pointer-events: none; opacity: 1; + transition: opacity 0.3s ease; } .dark .page-background::before { background: - radial-gradient(ellipse 80% 50% at 50% -20%, - color-mix(in srgb, var(--chart-1) 35%, transparent) 0%, - transparent 50% + radial-gradient(ellipse 100% 60% at 0% 0%, + color-mix(in srgb, var(--primary) 12%, transparent) 0%, + transparent 60% ), - radial-gradient(ellipse 60% 80% at -10% 50%, - color-mix(in srgb, var(--chart-2) 30%, transparent) 0%, - transparent 50% + radial-gradient(ellipse 80% 50% at 100% 100%, + color-mix(in srgb, var(--chart-2) 10%, transparent) 0%, + transparent 60% ), - radial-gradient(ellipse 60% 80% at 110% 50%, - color-mix(in srgb, var(--chart-3) 30%, transparent) 0%, - transparent 50% - ), - radial-gradient(ellipse 80% 50% at 50% 120%, - color-mix(in srgb, var(--chart-4) 35%, transparent) 0%, - transparent 50% - ), - linear-gradient( - 135deg, - color-mix(in srgb, var(--chart-1) 12%, transparent) 0%, - transparent 25%, - transparent 75%, - color-mix(in srgb, var(--chart-2) 12%, transparent) 100% + radial-gradient(ellipse 60% 40% at 50% 50%, + color-mix(in srgb, var(--chart-3) 8%, transparent) 0%, + transparent 70% ); opacity: 1; } diff --git a/components/accounts/account-card.tsx b/components/accounts/account-card.tsx index ce356c8..bcc8ef8 100644 --- a/components/accounts/account-card.tsx +++ b/components/accounts/account-card.tsx @@ -79,9 +79,10 @@ export function AccountCard({ const cardContent = ( @@ -107,20 +108,23 @@ export function AccountCard({ className="shrink-0" /> )} -
- +
+
- + {account.name} {!compact && !isMobile && ( @@ -139,13 +143,14 @@ export function AccountCard({
- @@ -164,19 +169,22 @@ export function AccountCard({
- +
= 0 ? "text-emerald-600" : "text-red-600", + realBalance >= 0 ? "text-emerald-600" : "text-red-600" )} > {formatCurrency(realBalance)} @@ -195,11 +203,13 @@ export function AccountCard({
{!compact && ( <> -
+
- = 0 - ? "from-emerald-50/50 to-card dark:from-emerald-950/20 dark:to-card" - : "from-red-50/50 to-card dark:from-red-950/20 dark:to-card" - )} - > + Solde Total @@ -77,7 +70,7 @@ export function OverviewCards({ data }: OverviewCardsProps) { - + Revenus du mois @@ -99,7 +92,7 @@ export function OverviewCards({ data }: OverviewCardsProps) { - + Dépenses du mois @@ -121,7 +114,7 @@ export function OverviewCards({ data }: OverviewCardsProps) { - + Pointage diff --git a/components/ui/button.tsx b/components/ui/button.tsx index 1dd187c..38a6381 100644 --- a/components/ui/button.tsx +++ b/components/ui/button.tsx @@ -5,19 +5,19 @@ import { cva, type VariantProps } from "class-variance-authority"; import { cn } from "@/lib/utils"; const buttonVariants = cva( - "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive", + "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-lg text-sm font-medium transition-all duration-200 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive", { variants: { variant: { - default: "bg-primary text-primary-foreground hover:bg-primary/90", + default: "bg-primary text-primary-foreground hover:bg-primary/90 hover:shadow-lg hover:shadow-primary/25 active:scale-[0.98]", destructive: - "bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60", + "bg-destructive text-white hover:bg-destructive/90 hover:shadow-lg hover:shadow-destructive/25 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60 active:scale-[0.98]", outline: - "border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50", + "border bg-background/80 backdrop-blur-sm shadow-sm hover:bg-accent hover:text-accent-foreground hover:border-primary/30 hover:shadow-md dark:bg-input/30 dark:border-input dark:hover:bg-input/50 active:scale-[0.98]", secondary: - "bg-secondary text-secondary-foreground hover:bg-secondary/80", + "bg-secondary text-secondary-foreground hover:bg-secondary/80 hover:shadow-sm active:scale-[0.98]", ghost: - "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50", + "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50 active:scale-[0.98]", link: "text-primary underline-offset-4 hover:underline", }, size: { diff --git a/components/ui/card.tsx b/components/ui/card.tsx index 9d8e279..850e7dd 100644 --- a/components/ui/card.tsx +++ b/components/ui/card.tsx @@ -7,7 +7,12 @@ function Card({ className, ...props }: React.ComponentProps<"div">) {
) { type={type} data-slot="input" className={cn( - "file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm", - "focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]", + "file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground", + "dark:bg-input/40 border-input h-9 w-full min-w-0 rounded-lg border bg-background/50 backdrop-blur-sm px-3 py-1 text-base", + "shadow-sm transition-all duration-200 outline-none", + "file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium", + "disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm", + "focus-visible:border-primary/50 focus-visible:ring-primary/20 focus-visible:ring-[3px] focus-visible:shadow-md focus-visible:shadow-primary/10", + "hover:border-primary/30 hover:shadow-sm", "aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive", className, )} diff --git a/components/ui/textarea.tsx b/components/ui/textarea.tsx index 0735a8c..5f32808 100644 --- a/components/ui/textarea.tsx +++ b/components/ui/textarea.tsx @@ -7,7 +7,13 @@ function Textarea({ className, ...props }: React.ComponentProps<"textarea">) {