THEME_TOKENS

expérimentaldepuis 0.1.0@legba-core/ui

THEME_TOKENS

Ce que ça fait

Feuille de styles Lit (CSSResult) posée par LegbaElement sur :host. Elle ne déclare que des variables --legba-*-default (jamais les jetons publics --legba-* eux-mêmes) et gère la résolution clair/sombre/marque à 3 états : data-theme explicite si posé, sinon prefers-color-scheme du système.

Signature

const THEME_TOKENS: CSSResult

Paramètres

N/A — une constante.

Retour

N/A — une constante.

Jetons posés

Chaque ligne donne le nom du jeton PUBLIC à redéfinir, et la valeur de repli interne (<nom>-default) dans chaque thème.

Jeton publicClairSombre
--legba-color-bg#f4f2ec#14120f
--legba-color-surface#ffffff#1c1914
--legba-color-text#1d1a14#f1ece0
--legba-color-text-dim#6b6555#a89f8a
--legba-color-border#87795a#87755a
--legba-color-primary#8a4e12#e0a24a
--legba-color-focus#8a4e12#e0a24a
--legba-radius10px10px
--legba-space8px8px
--legba-target-min2.75rem2.75rem
--legba-font-body-apple-system, "Segoe UI", sans-serifidentique

Erreurs

N/A.

Exemple minimal

import { css } from "lit";
import { THEME_TOKENS } from "@legba-core/ui";

const monComposantStyles = [
  THEME_TOKENS,
  css`
    .surface {
      background: var(--legba-color-bg, var(--legba-color-bg-default));
    }
  `,
];

Exemple complet

import { html, css } from "lit";
import { customElement } from "lit/decorators.js";
import { LegbaElement, THEME_TOKENS } from "@legba-core/ui";

@customElement("legba-card")
class LegbaCard extends LegbaElement {
  // Équivalent à `static styles = LegbaElement.styles` (déjà [THEME_TOKENS]),
  // mais explicite pour un composant qui préfère composer directement.
  static styles = [
    THEME_TOKENS,
    css`
      .card {
        background: var(--legba-color-surface, var(--legba-color-surface-default));
        color: var(--legba-color-text, var(--legba-color-text-default));
        border: 1px solid var(--legba-color-border, var(--legba-color-border-default));
        border-radius: var(--legba-radius, var(--legba-radius-default));
      }
    `,
  ];

  render() {
    return html`<div class="card" part="card"><slot></slot></div>`;
  }
}

Pièges

  • Redéfinir une couleur, c’est reprendre à sa charge sa conformité WCAG. Les valeurs par défaut du tableau ci-dessus sont vérifiées à chaque exécution des tests : chaque couple texte/fond atteint AA dans les deux thèmes, y compris en mode « system ». Aucune de ces vérifications ne s’applique à une valeur posée par un intégrateur — contrastRatio et meetsContrastAA sont exportés pour lui permettre de faire la même vérification dans ses propres tests. Repère concret : #b3661a, l’ancienne valeur de --legba-color-primary du thème clair, ne donnait que 3,88:1 sur le fond clair et a dû être corrigée par LGB-035 ; l’erreur est facile à refaire.
  • --legba-color-border n’est soumis à 3:1 (WCAG 1.4.11) que quand il délimite un composant d’interface ou un objet graphique porteur de sens — c’est le cas de chaque usage du jeton dans ce paquet (bouton, champ de saisie, bulle de message, avatar, tuile vidéo…) : sans cette bordure, rien d’autre ne délimite le contrôle. Un séparateur purement décoratif (qui ne délimite rien) n’y serait pas soumis. Historique (LGB-057) : #ddd8cc (clair) et #362f24 (sombre) ne donnaient respectivement que 1,27:1/1,42:1 et 1,41:1/1,33:1 sur le fond et la surface de leur thème — le constat d’origine ne citait que le thème clair, le sombre était tout aussi non conforme. #87795a (clair) et #87755a (sombre) corrigent les deux.
  • --legba-target-min doit rester une longueur relative. Sa valeur par défaut, 2.75rem, vaut 44 px à la taille de police par défaut ET grandit avec le réglage « taille de police » du navigateur. La remplacer par 44px figerait les cibles et rendrait le réglage sans effet sur elles.
  • --legba-color-focus n’est pas un doublon de --legba-color-primary, même quand les deux valeurs coïncident. L’un porte du texte (seuil AA 4,5:1), l’autre est un indicateur non textuel (WCAG 1.4.11, seuil 3:1) qui doit contraster avec ce qui ENTOURE le contrôle focalisé — y compris quand ce contrôle a lui-même un fond primary. Les séparer permet de changer l’accent d’une marque sans dégrader la visibilité du focus.
  • THEME_TOKENS ne pose que des variables. L’anneau de focus et la classe .sr-only viennent d’une autre feuille, incluse dans LegbaElement.styles : un composant qui compose [THEME_TOKENS, …] au lieu de [LegbaElement.styles, …] reçoit les jetons mais perd ces règles (voir LegbaElement).
  • Redéfinir --legba-color-primary (le jeton PUBLIC) sur un ancêtre fonctionne — le jeton n’étant jamais déclaré par THEME_TOKENS lui-même, l’héritage CSS normal s’applique sans concurrence. Redéfinir --legba-color-primary-default (la variable INTERNE) n’a d’effet que sur les composants qui n’ont reçu aucune redéfinition du jeton public — usage déconseillé, préférer toujours le jeton public.
  • Un data-theme inconnu (ex. une faute de frappe) ne lève jamais d’erreur et se comporte comme si aucun data-theme n’était posé (suit prefers-color-scheme).
  • THEME_TOKENS seul ne suffit pas à rendre un composant thématisable : chaque propriété CSS qui doit varier par thème doit explicitement consommer son jeton via var(--legba-x, var(--legba-x-default)).

Voir aussi