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 public | Clair | Sombre |
|---|---|---|
--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-radius | 10px | 10px |
--legba-space | 8px | 8px |
--legba-target-min | 2.75rem | 2.75rem |
--legba-font-body | -apple-system, "Segoe UI", sans-serif | identique |
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 —
contrastRatioetmeetsContrastAAsont 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-primarydu 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-bordern’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-mindoit 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 par44pxfigerait les cibles et rendrait le réglage sans effet sur elles.--legba-color-focusn’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 fondprimary. Les séparer permet de changer l’accent d’une marque sans dégrader la visibilité du focus.THEME_TOKENSne pose que des variables. L’anneau de focus et la classe.sr-onlyviennent d’une autre feuille, incluse dansLegbaElement.styles: un composant qui compose[THEME_TOKENS, …]au lieu de[LegbaElement.styles, …]reçoit les jetons mais perd ces règles (voirLegbaElement).- Redéfinir
--legba-color-primary(le jeton PUBLIC) sur un ancêtre fonctionne — le jeton n’étant jamais déclaré parTHEME_TOKENSlui-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-themeinconnu (ex. une faute de frappe) ne lève jamais d’erreur et se comporte comme si aucundata-themen’était posé (suitprefers-color-scheme). THEME_TOKENSseul ne suffit pas à rendre un composant thématisable : chaque propriété CSS qui doit varier par thème doit explicitement consommer son jeton viavar(--legba-x, var(--legba-x-default)).