# Thèmes Documentation [Tailwind CSS v4](https://tailwindcss.com/docs) SmartMaker utilise **TailwindCSS v4** pour la stylisation. Cette version introduit une nouvelle syntaxe CSS-first avec ''@theme'' et ''@layer''. ## Configuration TailwindCSS 4 ### Installation TailwindCSS 4 est intégré via le plugin Vite : ``` // vite.config.js import { defineConfig } from "vite"; import react from "@vitejs/plugin-react"; import tailwindcss from "@tailwindcss/vite"; export default defineConfig({ plugins: [ react(), tailwindcss(), ], }); ``` ### Point d'entrée CSS ``` /* src/assets/styles/style.css */ @import "tailwindcss"; @layer theme, base, components; @import "./theme.css" layer(theme); @import "./base.css" layer(base); ``` ## Définir un thème ### Variables CSS avec @theme ``` /* src/assets/styles/theme.css */ @theme { /* Couleurs principales */ --color-primary: #5fbabf; --color-primary-light: #8cd4d8; --color-primary-dark: #4a9599; --color-secondary: #fc8c8c; --color-secondary-light: #fdb5b5; --color-secondary-dark: #e67070; /* Couleurs sémantiques */ --color-success: #22c55e; --color-warning: #f59e0b; --color-error: #ef4444; --color-info: #3b82f6; /* Couleurs de fond */ --color-background: #ffffff; --color-surface: #f8fafc; --color-muted: #f1f5f9; /* Couleurs de texte */ --color-foreground: #0f172a; --color-foreground-muted: #64748b; /* Espacements customs */ --spacing-page: 1rem; --spacing-card: 1.5rem; /* Rayons de bordure */ --radius-sm: 0.375rem; --radius-md: 0.5rem; --radius-lg: 1rem; --radius-full: 9999px; /* Ombres */ --shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.05); --shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1); --shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1); /* Typographie */ --font-sans: 'Inter', system-ui, sans-serif; --font-mono: 'Fira Code', monospace; } ``` ### Utilisation dans les composants Les variables ''@theme'' génèrent automatiquement des classes Tailwind : ```
Fond primaire
Texte atténué
Carte avec espacement
``` ## Styles de base ### Reset et règles globales ``` /* src/assets/styles/base.css */ @layer base { * { @apply box-border p-0 m-0; -webkit-tap-highlight-color: transparent; } *::-webkit-scrollbar { display: none; } html { @apply scroll-smooth antialiased; } body { @apply bg-background text-foreground font-sans; } /* Focus visible pour accessibilité */ :focus-visible { @apply outline-2 outline-offset-2 outline-primary; } /* Liens */ a { @apply text-primary hover:text-primary-dark transition-colors; } /* Inputs */ input, textarea, select { @apply bg-surface border border-gray-200 rounded-md; @apply focus:border-primary focus:ring-1 focus:ring-primary; } } ``` ## Créer des thèmes multiples ### Structure des fichiers ``` src/assets/ ├── styles/ │ ├── style.css # Point d'entrée │ ├── theme.css # Variables par défaut │ └── base.css # Règles globales └── themes/ ├── light.css # Thème clair └── dark.css # Thème sombre ``` ### Thème clair (défaut) ``` /* src/assets/themes/light.css */ @theme { --color-background: #ffffff; --color-surface: #f8fafc; --color-foreground: #0f172a; --color-foreground-muted: #64748b; } ``` ### Thème sombre ``` /* src/assets/themes/dark.css */ @theme { --color-background: #0f172a; --color-surface: #1e293b; --color-foreground: #f8fafc; --color-foreground-muted: #94a3b8; } ``` ### Chargement dynamique ``` // src/main.jsx import { StrictMode } from "react"; import { createRoot } from "react-dom/client"; import "./assets/styles/style.css"; // Charger le thème depuis les settings const theme = localStorage.getItem('theme') || 'light'; import(`./assets/themes/${theme}.css`); import { App } from "./App"; createRoot(document.getElementById("root")).render( ); ``` ### Hook useTheme ``` import { useGlobalStates } from '@cap-rel/smartcommon'; import { useEffect } from 'react'; export const useTheme = () => { const [theme, setTheme] = useGlobalStates('settings.theme'); useEffect(() => { // Appliquer le thème au document document.documentElement.setAttribute('data-theme', theme); // Charger le CSS du thème const link = document.createElement('link'); link.rel = 'stylesheet'; link.href = `/themes/${theme}.css`; document.head.appendChild(link); return () => { document.head.removeChild(link); }; }, [theme]); const toggleTheme = () => { setTheme(theme === 'light' ? 'dark' : 'light'); }; return { theme, setTheme, toggleTheme }; }; ``` ### Composant ThemeToggle ``` import { useTheme } from '../hooks/useTheme'; const ThemeToggle = () => { const { theme, toggleTheme } = useTheme(); return ( ); }; ``` ## Variantes de composants ### Avec SmartCommon SmartCommon permet de définir des variantes pour les composants : ``` // appConfig.js export const config = { components: { variants: { Button: { default: "bg-primary text-white rounded-md px-4 py-2", secondary: "bg-secondary text-white rounded-md px-4 py-2", outline: "border-2 border-primary text-primary rounded-md px-4 py-2", ghost: "text-primary hover:bg-primary/10 rounded-md px-4 py-2", }, Input: { default: "bg-surface border border-gray-200 rounded-md p-3", filled: "bg-muted border-0 rounded-md p-3", underline: "border-b-2 border-gray-200 rounded-none p-3", }, }, }, }; ``` ### Utilisation ``` import { Button, Input } from '@cap-rel/smartcommon'; const MyForm = () => { return (
); }; ``` ## Classes utilitaires personnalisées ### Avec @layer components ``` /* src/assets/styles/components.css */ @layer components { .card { @apply bg-surface rounded-lg shadow-md p-card; } .btn { @apply inline-flex items-center justify-center; @apply px-4 py-2 rounded-md font-medium; @apply transition-all duration-200; @apply focus:outline-none focus:ring-2 focus:ring-offset-2; } .btn-primary { @apply btn bg-primary text-white; @apply hover:bg-primary-dark; @apply focus:ring-primary; } .btn-secondary { @apply btn bg-secondary text-white; @apply hover:bg-secondary-dark; @apply focus:ring-secondary; } .input { @apply w-full px-4 py-3 rounded-md; @apply bg-surface border border-gray-200; @apply focus:border-primary focus:ring-1 focus:ring-primary; @apply placeholder:text-foreground-muted; } } ``` ## Dark mode automatique ### Avec prefers-color-scheme ``` /* src/assets/styles/theme.css */ @theme { --color-background: #ffffff; --color-foreground: #0f172a; } @media (prefers-color-scheme: dark) { @theme { --color-background: #0f172a; --color-foreground: #f8fafc; } } ``` ### Avec classe CSS ``` /* Thème par défaut (clair) */ @theme { --color-background: #ffffff; --color-foreground: #0f172a; } /* Thème sombre via classe */ .dark { --color-background: #0f172a; --color-foreground: #f8fafc; } ``` ``` // Toggle dark mode document.documentElement.classList.toggle('dark'); ``` ## Conseils ### Performance * Utilisez ''@theme'' pour les variables réutilisées * Évitez les classes Tailwind dynamiques (''bg-${color}'') * Préférez les variantes de composants ### Organisation * Un fichier pour les variables (''theme.css'') * Un fichier pour les règles de base (''base.css'') * Un fichier par thème additionnel ### Accessibilité * Respectez les contrastes WCAG * Testez avec ''prefers-reduced-motion'' * Utilisez ''focus-visible'' pour le focus ## Voir aussi * [[configuration|Configuration]] - Variantes de composants * [[smartcommon|SmartCommon]] - Composants disponibles * [[animations|Animations]] - Transitions de pages