SmarMaker - Documentation
Docs» 03_front:themes

Thèmes

Documentation Tailwind CSS v4

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 :

<div className="bg-primary text-white">
  Fond primaire
</div>

<div className="text-foreground-muted">
  Texte atténué
</div>

<div className="rounded-lg shadow-md p-card">
  Carte avec espacement
</div>

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(
  <StrictMode>
    <App />
  </StrictMode>
);

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 (
    <button
      onClick={toggleTheme}
      className="p-2 rounded-full bg-surface"
    >
      {theme === 'light' ? '🌙' : '☀️'}
    </button>
  );
};

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 (
    <form>
      <Input name="email" variant="filled" />
      <Button variant="secondary">Envoyer</Button>
      <Button variant="ghost">Annuler</Button>
    </form>
  );
};

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 - Variantes de composants
  • SmartCommon - Composants disponibles
  • Animations - Transitions de pages
Previous Next

Made with ❤ by CAP-REL · SmartMaker · GNU AGPL v3+
Code source · Faire un don
SmarMaker - Documentation
Traductions de cette page:
  • Français
  • Deutsch
  • English
  • Español
  • Italiano
  • Nederlands

Table of Contents

Table des matières

  • Thèmes
    • Configuration TailwindCSS 4
      • Installation
      • Point d'entrée CSS
    • Définir un thème
      • Variables CSS avec @theme
      • Utilisation dans les composants
    • Styles de base
      • Reset et règles globales
    • Créer des thèmes multiples
      • Structure des fichiers
      • Thème clair (défaut)
      • Thème sombre
      • Chargement dynamique
      • Hook useTheme
      • Composant ThemeToggle
    • Variantes de composants
      • Avec SmartCommon
      • Utilisation
    • Classes utilitaires personnalisées
      • Avec @layer components
    • Dark mode automatique
      • Avec prefers-color-scheme
      • Avec classe CSS
    • Conseils
      • Performance
      • Organisation
      • Accessibilité
    • Voir aussi
  • SmartAuth
  • SmartMaker - Back (PHP)
    • Mapping Dolibarr - React
  • SmartMaker - Front (React)
    • Animations de pages
    • Architecture
    • Astuces
    • Calendar
    • Composants et pages
    • Configuration du Provider
    • Debug et Logs
    • Hooks SmartCommon
    • PWA (Progressive Web App)
    • Requêtes API
    • Routage
    • SmartCommon
    • Stockage de données
    • Thèmes
    • Traductions
  • HowTo - Pas à pas - Votre première application
    • Développement PHP (back)
    • Développement React (front)
    • Première étape : Module Builder Dolibarr
    • SmartAuth
    • SmartBoot : Un "squelette" quasiment prêt à l'emploi
  • Formation SmartMaker
    • Module 1 : Fondamentaux JavaScript ES6+
      • Chapitre 1 : Variables et Scope
      • Chapitre 2 : Fonctions
      • Chapitre 3 : Programmation Asynchrone
      • Chapitre 4 : Modules ES6
    • Module 2 : Introduction à React
      • Chapitre 1 : Philosophie React
      • Chapitre 2 : JSX
      • Chapitre 3 : Composants
    • Module 3 : Hooks React Fondamentaux
      • Chapitre 1 : useState
      • Chapitre 2 : useEffect
      • Chapitre 3 : useRef
      • Chapitre 4 : useContext
    • Module 4 : React Avancé
      • Chapitre 1 : useCallback et useMemo
      • Chapitre 2 : Custom Hooks
      • Chapitre 3 : Redux et Redux Toolkit
    • Module 5 : Architecture SmartMaker
      • Chapitre 1 : Structure du projet
      • Chapitre 2 : Configuration
      • Chapitre 3 : Flux de données
    • Module 6 : SmartCommon - Composants
      • Chapitre 1 : Mise en page
      • Chapitre 2 : Navigation
      • Chapitre 3 : Formulaires
      • Chapitre 4 : Affichage
    • Module 7 : SmartCommon - Hooks
      • Chapitre 1 : useApi
      • Chapitre 2 : Gestion d'état
      • Chapitre 3 : Hooks utilitaires
    • Module 8 : Backend API (PHP)
      • Chapitre 1 : Routage
      • Chapitre 2 : Controllers
      • Chapitre 3 : Mappers
      • Extrafields et formulaires dynamiques
    • Module 9 : Intégration complète
      • Chapitre 1 : Backend
      • Chapitre 2 : Frontend
      • Chapitre 3 : Déploiement
    • Module 10 : Fonctionnalités avancées
      • Chapitre 1 : Mode offline
      • Chapitre 2 : Internationalisation (i18n)
      • Chapitre 3 : Autres fonctionnalités
    • Module 11 : Bonnes pratiques
  • Démonstration
  • Start
  • Composants et pages
  • Afficher le texte source
  • Anciennes révisions
  • Liens de retour
  • Haut de page