Design Tokens

Fichier core/css/tokens.css — le seul fichier à modifier pour configurer la charte graphique du client.

Couleurs

Modifiez uniquement les 4 couleurs de base — toutes les variantes (transparent, light, dark) se génèrent automatiquement via color-mix().

color-mix() est une fonction CSS qui mélange automatiquement vos couleurs avec du blanc (pour éclaircir) ou du noir (pour foncer). Vous définissez 4 couleurs de base et obtenez 24+ variantes automatiquement — pas besoin de choisir chaque nuance à la main.

:root {
  --primary: #1a5ed6;   /* À modifier */
  --secondary: #8b5cf6; /* À modifier */
  --tertiary: #ec4899;  /* À modifier */
  --accent: #f59e0b;    /* À modifier */
}

Couleurs de base

--primary
--secondary
--tertiary
--accent

Variantes auto-générées (primary)

Changez --primary et toutes ces variantes se recalculent :

Transparent (t)

--primary-t-1
--primary-t-2
--primary-t-3
--primary-t-4
--primary-t-5
--primary-t-6

Light (l)

--primary-l-1
--primary-l-2
--primary-l-3
--primary-l-4
--primary-l-5
--primary-l-6

Dark (d)

--primary-d-1
--primary-d-2
--primary-d-3
--primary-d-4
--primary-d-5
--primary-d-6

Le même système existe pour --secondary-*, --tertiary-*, --accent-* et --neutral-*.

Sémantique & fond

--success
--error
--warning
--neutral
--black
--white

Nomenclature des variantes

SuffixeTypeExemple
-t-1 à -t-6Transparent (opacité décroissante)var(--primary-t-3)
-l-1 à -l-6Light (mélangé avec blanc)var(--primary-l-4)
-d-1 à -d-6Dark (mélangé avec noir)var(--primary-d-2)

Polices

Le système utilise des polices locales uniquement (RGPD, pas d'appel vers Google Fonts). Les fichiers sont dans assets/fonts/.

Google Fonts = Google sait quels sites visitent vos utilisateurs (car leur navigateur télécharge les polices depuis les serveurs de Google). Polices locales = aucune requête vers Google = aucun tracking = pas besoin de mentionner Google dans votre politique de confidentialité.

Configuration

:root {
  --font-body: 'Inter', system-ui, sans-serif;    /* Texte courant */
  --font-heading: 'Inter', system-ui, sans-serif;  /* Titres h1-h6 */
  --font-mono: 'SF Mono', 'Fira Code', 'Cascadia Code', monospace;  /* Code */
}

--font-body s'applique au body, --font-heading s'applique automatiquement aux titres h1–h6. Vous pouvez utiliser deux polices différentes pour le body et les titres.

Alias : --font-base existe comme alias rétro-compatible de --font-body (--font-base: var(--font-body)). Préférez --font-body dans le nouveau code.

Changer de police

  1. Placez vos fichiers .ttf ou .woff2 dans assets/fonts/
  2. Modifiez les @font-face en haut de tokens.css
  3. Mettez à jour --font-body et/ou --font-heading
/* Exemple : police statique (non-variable) */
@font-face {
  font-family: 'MaPolice';
  src: url('../../assets/fonts/MaPolice-Regular.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'MaPolice';
  src: url('../../assets/fonts/MaPolice-Bold.woff2') format('woff2');
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}

:root {
  --font-body: 'MaPolice', system-ui, sans-serif;
  --font-heading: 'MaPolice', system-ui, sans-serif;
}

Animations Variable Font

Si votre police est variable (comme Inter), vous pouvez animer le poids de la police. Si la police n'est pas variable, l'animation est ignorée silencieusement.

Survolez ce titre (hover)

Apparition au scroll

Boucle infinie

<!-- Poids 400→700 au hover -->
<h2 class="anim-font-weight-hover">Survolez-moi</h2>

<!-- Poids 400→700 au scroll -->
<h2 class="anim-font-weight-scroll">Apparition au scroll</h2>

<!-- Boucle infinie -->
<h2 class="anim-font-weight-loop">Boucle infinie</h2>

Boucle custom 200→900

<!-- Custom : poids et durée personnalisés -->
<h2 class="anim-font-weight-loop"
    data-font-from="200"
    data-font-to="900"
    data-font-duration="3s">
  Boucle custom
</h2>
AttributDéfautDescription
data-font-from400Poids de départ
data-font-to700Poids d'arrivée
data-font-duration0.4s (hover/scroll), 2s (loop)Durée de la transition

Tailles de texte (dynamiques)

Les tailles utilisent clamp() pour s'adapter automatiquement entre mobile et desktop :

:root {
  --text-xs:  clamp(0.7rem, 0.66rem + 0.2vw, 0.75rem);
  --text-sm:  clamp(0.8rem, 0.76rem + 0.2vw, 0.875rem);
  --text-base: clamp(0.9rem, 0.86rem + 0.2vw, 1rem);
  --text-lg:  clamp(1rem, 0.93rem + 0.35vw, 1.125rem);
  --text-xl:  clamp(1.1rem, 1rem + 0.5vw, 1.25rem);
  --text-2xl: clamp(1.25rem, 1.1rem + 0.75vw, 1.5rem);
  --text-3xl: clamp(1.5rem, 1.2rem + 1.5vw, 1.875rem);
  --text-4xl: clamp(1.75rem, 1.35rem + 2vw, 2.25rem);
  --text-5xl: clamp(2rem, 1.4rem + 3vw, 3rem);
}

Border Radius

:root {
  --radius-sm: 0.25rem;    /* 4px  — inputs, badges */
  --radius-md: 0.5rem;     /* 8px  — boutons, cards */
  --radius-lg: 0.75rem;    /* 12px — modals, sections */
  --radius-xl: 1rem;       /* 16px — grandes cards */
  --radius-2xl: 1.5rem;    /* 24px — hero sections */
  --radius-full: 9999px;   /* pills, avatars */
}

Ombres

:root {
  --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05);
  --shadow-md: 0 4px 6px rgba(0, 0, 0, 0.07);
  --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
  --shadow-xl: 0 20px 25px -5px rgba(0, 0, 0, 0.1);
}

Échelle sémantique étendue

Le fichier tokens.css définit des variantes claires (tints) et foncées (shades) pour les couleurs sémantiques, calculées via color-mix() pour s'adapter automatiquement au dark mode.

Success

TokenValeur
--color-success-50color-mix(in srgb, var(--success) 8%, var(--bg))
--color-success-100color-mix(in srgb, var(--success) 15%, var(--bg))
--color-success-300color-mix(in srgb, var(--success) 40%, var(--bg))
--color-success-800color-mix(in srgb, var(--success) 85%, black)
--color-success-darkcolor-mix(in srgb, var(--success) 70%, black)

Warning

TokenValeur
--color-warning-50color-mix(in srgb, var(--warning) 8%, var(--bg))
--color-warning-100color-mix(in srgb, var(--warning) 15%, var(--bg))
--color-warning-200color-mix(in srgb, var(--warning) 25%, var(--bg))
--color-warning-300color-mix(in srgb, var(--warning) 40%, var(--bg))
--color-warning-800color-mix(in srgb, var(--warning) 85%, black)
--color-warning-darkcolor-mix(in srgb, var(--warning) 70%, black)

Error

TokenValeur
--color-errorvar(--error) (alias)
--color-error-50color-mix(in srgb, var(--error) 8%, var(--bg))
--color-error-100color-mix(in srgb, var(--error) 15%, var(--bg))
--color-error-200color-mix(in srgb, var(--error) 25%, var(--bg))
--color-error-300color-mix(in srgb, var(--error) 40%, var(--bg))
--color-error-darkcolor-mix(in srgb, var(--error) 70%, black)

Variantes de couleurs principales

TokenValeur
--color-primary-hovervar(--primary-d-1)
--color-primary-lightvar(--primary-l-4)
--color-secondary-darkvar(--secondary-d-2)
--color-tertiary-darkvar(--tertiary-d-2)
--color-text-lightervar(--border)

Alias de surface / muted

TokenValeur
--color-surfacevar(--bg-alt)
--color-mutedvar(--border)
--color-darkvar(--black)
--color-placeholdervar(--border)
--color-text-muted-inversergba(255, 255, 255, 0.6)

Blocs de code

Tokens dédiés au style des blocs de code (<pre><code>) :

TokenValeurUsage
--code-bg#0f1117Fond du bloc de code
--code-text#e5e7ebCouleur du texte
--code-borderrgba(255, 255, 255, 0.06)Bordure du bloc
--code-btn#9ca3afCouleur du bouton copier
--code-btn-hover#e5e7ebCouleur du bouton copier au survol

Disclaimer / avertissement

Tokens pour les blocs d'avertissement :

TokenValeurUsage
--disclaimer-bg#fff3cdFond du bloc disclaimer
--disclaimer-text#856404Couleur du texte
--disclaimer-border#ffeebaBordure du bloc

Mapping interne

Le bas du fichier tokens.css contient un mapping qui connecte vos variables simples aux noms utilisés par les composants. Ne modifiez pas cette section — elle garantit que tout le système utilise vos valeurs.

/* Mapping interne — Ne pas modifier */
--color-primary: var(--primary);
--color-primary-dark: var(--primary-d-2);
--color-secondary: var(--secondary);
/* ... etc */

Mode sombre (Dark Mode)

Le système de thème sombre fonctionne par surcharge des variables CSS dans tokens.css.

Fonctionnement

Un bloc [data-theme="dark"] à la fin de tokens.css surcharge les variables brutes (--text, --bg, --bg-alt, etc.). Les mappings internes (--color-text, --color-bg...) héritent automatiquement.

Inclure le script

Ajoutez le script en synchrone dans le <head>, avant les CSS, pour éviter un flash de thème :

<script src="core/js/darkmode.js"></script>

Bouton toggle

Le header intègre automatiquement un bouton toggle soleil/lune avec animation. Vous pouvez aussi créer votre propre toggle avec l'attribut data-theme-toggle :

Cliquez pour basculer ←
<!-- Toggle SVG soleil/lune (intégré dans le header) -->
<button class="header__theme-toggle" data-theme-toggle
        aria-label="Basculer le thème">
  <!-- Soleil (visible en light) -->
  <svg class="header__theme-icon header__theme-icon--sun" ...>...</svg>
  <!-- Lune (visible en dark) -->
  <svg class="header__theme-icon header__theme-icon--moon" ...>...</svg>
</button>

<!-- Toggle simple (texte) -->
<button data-theme-toggle>Mode sombre</button>

Comportement

  • Vérifie d'abord localStorage, puis prefers-color-scheme du système
  • Persiste le choix dans localStorage (clé : beely-theme)
  • Si l'utilisateur n'a pas fait de choix, suit la préférence système automatiquement
  • Un choix manuel (clic sur le toggle) prend le dessus sur la préférence système. Tant que la clé beely-theme existe dans localStorage, le système ne suit plus prefers-color-scheme
  • Compatible navigation privée : les 3 accès à localStorage (lecture initiale, écriture au toggle, lecture au changement système) sont protégés par try/catch. En cas d'erreur (quota dépassé, navigation privée), le dark mode fonctionne quand même pour la session en cours, sans persistance
  • Fonction globale : window.toggleTheme()

Personnaliser les couleurs sombres

Modifiez le bloc [data-theme="dark"] en fin de tokens.css :

[data-theme="dark"] {
  --text: #e5e7eb;
  --text-light: #9ca3af;
  --bg: #111827;
  --bg-alt: #1f2937;
  --border: #374151;
  --border-dark: #4b5563;

  --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.3);
  --shadow-md: 0 4px 6px rgba(0, 0, 0, 0.4);
  --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.5);
  --shadow-xl: 0 20px 25px -5px rgba(0, 0, 0, 0.5);
}

Espacements

Utilisés pour les marges, paddings et gaps dans tout le framework :

TokenValeur
--space-00.125rem (2px) — micro-espacement
--space-10.25rem (4px)
--space-20.5rem (8px)
--space-30.75rem (12px)
--space-41rem (16px)
--space-51.25rem (20px)
--space-61.5rem (24px)
--space-82rem (32px)
--space-102.5rem (40px)
--space-123rem (48px)
--space-164rem (64px)
--space-205rem (80px)
--space-246rem (96px)

Font weights

TokenValeur
--font-weight-normal400
--font-weight-medium500
--font-weight-semibold600
--font-weight-bold700

Transitions

Utilisées pour les animations hover, focus et changements d'état :

TokenValeur
--transition-fast150ms ease
--transition-base250ms ease
--transition-slow400ms ease

Breakpoints responsives

Le framework définit 3 breakpoints dans tokens.css :

:root {
  --bp-tablet: 991px;
  --bp-mobile-landscape: 767px;
  --bp-mobile: 478px;
}

Ces valeurs créent 4 paliers :

PalierLargeur
Desktop≥ 992px
Tablette768 – 991px
Mobile paysage479 – 767px
Mobile portrait≤ 478px

Source unique

Modifier les breakpoints dans tokens.css suffit : le framework synchronise automatiquement toutes les media queries (@media) avec vos valeurs — fichiers CSS du core, wireframes copiés, formulaires générés. Aucun autre fichier à modifier.

Fonctionnement technique

Au chargement de la page, site.js :

  1. Lit --bp-tablet, --bp-mobile-landscape et --bp-mobile depuis les custom properties
  2. Compare avec les valeurs par défaut (991px, 767px, 478px)
  3. Si les valeurs diffèrent, réécrit les @media queries dans :
    • Les feuilles de style externes (via CSSOM)
    • Les balises <style> inline (wireframes, form builder)

Les wireframes disposent d'un sync additionnel dans wireframes.js pour les previews iframe.

Exemple

Pour passer le breakpoint tablette à 1024px :

/* tokens.css */
--bp-tablet: 1024px;

Toutes les règles @media (max-width: 991px) deviennent automatiquement @media (max-width: 1024px) sur toutes les pages du site.

Layout

Le framework définit des tokens de conteneur pour contrôler la largeur maximale des différentes zones de contenu. Tous les wireframes utilisent ces tokens pour leur max-width.

Tokens de conteneur

TokenValeur (rem)Équivalent (px)Usage typique
--container-xs30rem480pxFormulaires, modales étroites
--container-sm40rem640pxArticles, contenus centrés
--container-md48rem768pxContenu texte, landing sections
--container-lg64rem1024pxLayouts 2 colonnes
--container-xl75rem1200pxLayout principal (défaut)
--container-2xl90rem1440pxLayouts larges, dashboards
--container-maxvar(--container-xl)Alias — pointe vers --container-xl par défaut
--container-paddingvar(--space-6) (1.5rem / 24px)Padding horizontal du conteneur

--container-max est l’alias utilisé par la classe .container. Pour changer la largeur par défaut du site, il suffit de modifier cette seule variable :

:root {
  --container-max: var(--container-2xl); /* Passer de 1200px à 1440px */
}

Conversion rem ↔ px

Le framework utilise des rem pour tous les tokens d’espacement et de taille. Par défaut dans les navigateurs, 1rem = 16px.

Calcul rapide : multipliez la valeur rem par 16 pour obtenir les pixels. Pour les quarts de rem (0.25, 0.5, 0.75), multipliez par 4 pour obtenir le nombre de « quarts de 16 » (4px, 8px, 12px).

Tokenrempx
--space-00.125rem2px
--space-10.25rem4px
--space-20.5rem8px
--space-30.75rem12px
--space-41rem16px
--space-51.25rem20px
--space-61.5rem24px
--space-82rem32px
--space-102.5rem40px
--space-123rem48px
--space-164rem64px
--space-205rem80px
--space-246rem96px

Le styleguide du configurateur affiche les équivalences en pixels en temps réel.

Problèmes courants

  • Les couleurs ne changent pas : vérifiez que tokens.css est bien chargé avant les autres fichiers CSS.
  • La police ne s'affiche pas : vérifiez que les fichiers .woff2 sont dans assets/fonts/ et que le @font-face dans tokens.css pointe vers le bon chemin.
  • Le dark mode ne fonctionne pas : assurez-vous que darkmode.js est chargé de façon synchrone (sans defer) dans le <head>, avant les CSS.
  • L'animation de poids de police ne fonctionne pas : seules les polices variables supportent cette animation. Vérifiez que votre police est au format variable font.

Voir aussi