feat: improve theme selector and UI components

- Updated `ThemeSelector` to use a new `ThemePreview` component for better theme visualization.
- Refactored button implementation in `ThemeSelector` to utilize the new `Button` component, enhancing consistency.
- Added a UI showcase section in `GeneralSettingsPageClient` to display available UI components with different themes.
- Enhanced `Badge`, `Button`, and `Input` components with new variants and improved styling for better usability and visual appeal.
- Updated CSS variables in `globals.css` for improved contrast and accessibility across themes.
This commit is contained in:
Julien Froidefond
2025-09-28 21:08:48 +02:00
parent 9ef23dbddc
commit 0e2eaf1052
12 changed files with 694 additions and 202 deletions

View File

@@ -0,0 +1,327 @@
'use client';
import { useState } from 'react';
import { Button } from '@/components/ui/Button';
import { Badge } from '@/components/ui/Badge';
import { Alert, AlertTitle, AlertDescription } from '@/components/ui/Alert';
import { Input } from '@/components/ui/Input';
import { StyledCard } from '@/components/ui/StyledCard';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/Card';
import { ThemeSelector } from '@/components/ThemeSelector';
export function UIShowcaseClient() {
const [inputValue, setInputValue] = useState('');
return (
<div className="min-h-screen bg-[var(--background)] p-8">
<div className="max-w-6xl mx-auto space-y-16">
{/* Header */}
<div className="text-center space-y-6">
<h1 className="text-4xl font-mono font-bold text-[var(--foreground)]">
🎨 UI Components Showcase
</h1>
<p className="text-lg text-[var(--muted-foreground)]">
Démonstration de tous les composants UI disponibles
</p>
</div>
{/* Theme Selector */}
<section className="space-y-8">
<div className="text-center">
<h2 className="text-2xl font-mono font-semibold text-[var(--foreground)] mb-6">
🎨 Sélecteur de Thèmes
</h2>
<p className="text-[var(--muted-foreground)] mb-8">
Changez de thème pour voir comment tous les composants s'adaptent
</p>
</div>
<div className="max-w-4xl mx-auto">
<div className="bg-[var(--card)]/30 border border-[var(--border)]/50 rounded-lg p-6 backdrop-blur-sm">
<ThemeSelector />
</div>
</div>
</section>
{/* Buttons Section */}
<section className="space-y-8">
<h2 className="text-2xl font-mono font-semibold text-[var(--foreground)] border-b border-[var(--border)] pb-3">
Buttons
</h2>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
<div className="space-y-6">
<h3 className="text-lg font-medium text-[var(--foreground)]">Variants</h3>
<div className="space-y-4">
<Button variant="primary">Primary Button</Button>
<Button variant="secondary">Secondary Button</Button>
<Button variant="ghost">Ghost Button</Button>
<Button variant="destructive">Destructive Button</Button>
<Button variant="success">Success Button</Button>
<Button variant="selected">Selected Button</Button>
</div>
</div>
<div className="space-y-6">
<h3 className="text-lg font-medium text-[var(--foreground)]">Sizes</h3>
<div className="space-y-4">
<Button size="sm">Small Button</Button>
<Button size="md">Medium Button</Button>
<Button size="lg">Large Button</Button>
</div>
</div>
<div className="space-y-6">
<h3 className="text-lg font-medium text-[var(--foreground)]">States</h3>
<div className="space-y-4">
<Button>Normal State</Button>
<Button disabled>Disabled State</Button>
<Button className="opacity-50">Loading State</Button>
</div>
</div>
</div>
</section>
{/* Badges Section */}
<section className="space-y-8">
<h2 className="text-2xl font-mono font-semibold text-[var(--foreground)] border-b border-[var(--border)] pb-3">
Badges
</h2>
<div className="space-y-6">
<div className="flex flex-wrap gap-4">
<Badge variant="default">Default Badge</Badge>
<Badge variant="primary">Primary Badge</Badge>
<Badge variant="success">Success Badge</Badge>
<Badge variant="destructive">Destructive Badge</Badge>
<Badge variant="accent">Accent Badge</Badge>
<Badge variant="purple">Purple Badge</Badge>
<Badge variant="yellow">Yellow Badge</Badge>
<Badge variant="green">Green Badge</Badge>
<Badge variant="blue">Blue Badge</Badge>
<Badge variant="gray">Gray Badge</Badge>
</div>
</div>
</section>
{/* Alerts Section */}
<section className="space-y-8">
<h2 className="text-2xl font-mono font-semibold text-[var(--foreground)] border-b border-[var(--border)] pb-3">
Alerts
</h2>
<div className="space-y-6">
<Alert variant="default">
<AlertTitle>Information</AlertTitle>
<AlertDescription>
Ceci est une alerte par défaut avec des informations importantes.
</AlertDescription>
</Alert>
<Alert variant="success">
<AlertTitle>Succès</AlertTitle>
<AlertDescription>
Opération terminée avec succès ! Toutes les données ont été sauvegardées.
</AlertDescription>
</Alert>
<Alert variant="destructive">
<AlertTitle>Erreur</AlertTitle>
<AlertDescription>
Une erreur s'est produite lors du traitement de votre demande.
</AlertDescription>
</Alert>
<Alert variant="warning">
<AlertTitle>Attention</AlertTitle>
<AlertDescription>
Veuillez vérifier vos informations avant de continuer.
</AlertDescription>
</Alert>
<Alert variant="info">
<AlertTitle>Conseil</AlertTitle>
<AlertDescription>
Astuce : Vous pouvez utiliser les raccourcis clavier pour naviguer plus rapidement.
</AlertDescription>
</Alert>
</div>
</section>
{/* Inputs Section */}
<section className="space-y-8">
<h2 className="text-2xl font-mono font-semibold text-[var(--foreground)] border-b border-[var(--border)] pb-3">
Inputs
</h2>
<div className="grid grid-cols-1 md:grid-cols-2 gap-8">
<div className="space-y-6">
<h3 className="text-lg font-medium text-[var(--foreground)]">Types</h3>
<div className="space-y-4">
<Input placeholder="Texte normal" />
<Input type="email" placeholder="Adresse email" />
<Input type="password" placeholder="Mot de passe" />
<Input type="number" placeholder="Nombre" />
<Input type="search" placeholder="Rechercher..." />
</div>
</div>
<div className="space-y-6">
<h3 className="text-lg font-medium text-[var(--foreground)]">États</h3>
<div className="space-y-4">
<Input placeholder="État normal" />
<Input placeholder="État focus" autoFocus />
<Input placeholder="État désactivé" disabled />
<Input variant="error" placeholder="État erreur" />
<Input value={inputValue} onChange={(e) => setInputValue(e.target.value)} placeholder="État avec valeur" />
</div>
</div>
</div>
</section>
{/* Cards Section */}
<section className="space-y-6">
<h2 className="text-2xl font-mono font-semibold text-[var(--foreground)] border-b border-[var(--border)] pb-2">
Cards
</h2>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
{/* Standard Cards */}
<Card>
<CardHeader>
<CardTitle>Card Standard</CardTitle>
</CardHeader>
<CardContent>
<p className="text-[var(--muted-foreground)]">
Ceci est une carte standard avec header et contenu.
</p>
</CardContent>
</Card>
<Card variant="elevated">
<CardHeader>
<CardTitle>Card Élevée</CardTitle>
</CardHeader>
<CardContent>
<p className="text-[var(--muted-foreground)]">
Cette carte a une ombre plus prononcée.
</p>
</CardContent>
</Card>
<Card variant="bordered">
<CardHeader>
<CardTitle>Card Bordée</CardTitle>
</CardHeader>
<CardContent>
<p className="text-[var(--muted-foreground)]">
Cette carte a une bordure colorée.
</p>
</CardContent>
</Card>
{/* Styled Cards */}
<StyledCard color="primary" className="p-4">
<h3 className="font-medium mb-2">Styled Card Primary</h3>
<p className="text-sm opacity-80">
Carte avec couleur primaire et fond subtil.
</p>
</StyledCard>
<StyledCard color="success" className="p-4">
<h3 className="font-medium mb-2">Styled Card Success</h3>
<p className="text-sm opacity-80">
Carte avec couleur de succès.
</p>
</StyledCard>
<StyledCard color="destructive" className="p-4">
<h3 className="font-medium mb-2">Styled Card Destructive</h3>
<p className="text-sm opacity-80">
Carte avec couleur destructive.
</p>
</StyledCard>
</div>
</section>
{/* Interactive Demo */}
<section className="space-y-6">
<h2 className="text-2xl font-mono font-semibold text-[var(--foreground)] border-b border-[var(--border)] pb-2">
Démonstration Interactive
</h2>
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
<Card>
<CardHeader>
<CardTitle>Formulaire d'exemple</CardTitle>
</CardHeader>
<CardContent className="space-y-4">
<div>
<label className="block text-sm font-medium text-[var(--foreground)] mb-2">
Nom d'utilisateur
</label>
<Input placeholder="Entrez votre nom" />
</div>
<div>
<label className="block text-sm font-medium text-[var(--foreground)] mb-2">
Email
</label>
<Input type="email" placeholder="votre@email.com" />
</div>
<div>
<label className="block text-sm font-medium text-[var(--foreground)] mb-2">
Statut
</label>
<div className="flex gap-2">
<Badge variant="success">Actif</Badge>
<Badge variant="gray">En attente</Badge>
</div>
</div>
<div className="flex gap-3 pt-4">
<Button variant="primary">Enregistrer</Button>
<Button variant="secondary">Annuler</Button>
</div>
</CardContent>
</Card>
<Card>
<CardHeader>
<CardTitle>Notifications</CardTitle>
</CardHeader>
<CardContent className="space-y-4">
<Alert variant="success">
<AlertTitle>Bienvenue !</AlertTitle>
<AlertDescription>
Votre compte a é créé avec succès.
</AlertDescription>
</Alert>
<Alert variant="warning">
<AlertTitle>Mise à jour disponible</AlertTitle>
<AlertDescription>
Une nouvelle version de l'application est disponible.
</AlertDescription>
</Alert>
<div className="flex gap-2">
<Button size="sm">Voir les détails</Button>
<Button size="sm" variant="ghost">Ignorer</Button>
</div>
</CardContent>
</Card>
</div>
</section>
{/* Footer */}
<div className="text-center pt-8 border-t border-[var(--border)]">
<p className="text-[var(--muted-foreground)]">
Cette page est accessible via <code className="bg-[var(--card)] px-2 py-1 rounded text-sm">/ui-showcase</code>
</p>
</div>
</div>
</div>
);
}