@zevra/ui 0.26.0 → 0.27.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/react/email.ts CHANGED
@@ -23,6 +23,11 @@
23
23
  // stylées.
24
24
 
25
25
  import { COULEURS, POLICES as PILES } from './email-tokens.js'
26
+ // Les URL publiques des glyphes — sept chaînes, aucune image inlinée : un
27
+ // client de messagerie ne résout pas une data-URI (Gmail les bloque), il lui
28
+ // faut une adresse absolue.
29
+ import { LOGOS_PRODUITS } from './glyph-urls.js'
30
+ export { BASE_RESSOURCES, LOGOS_PRODUITS } from './glyph-urls.js'
26
31
 
27
32
  /** ⚠️ Les piles de polices du paquet contiennent des GUILLEMETS DOUBLES
28
33
  * (`"Public Sans", …`), et tout ici s'écrit dans un attribut `style="…"`
@@ -144,6 +149,10 @@ export interface EmailOptions {
144
149
  /** L'URL ABSOLUE du logo — une image d'e-mail ne se résout pas depuis un
145
150
  * chemin relatif, et les data-URI sont bloquées par Gmail. */
146
151
  logo?: { src: string; hauteur?: number }
152
+ /** Raccourci : le glyphe d'un produit Zevra, à son URL publiée avec la
153
+ * planche. Écrase `logo`.
154
+ * ⚠️ Ne dispense PAS de `marque` : une image sur deux est bloquée. */
155
+ produit?: keyof typeof LOGOS_PRODUITS
147
156
  /** Les blocs, concaténés. */
148
157
  contenu: string
149
158
  /** Sous la carte : mentions légales, désinscription. */
@@ -167,12 +176,17 @@ export function email({
167
176
  preheader,
168
177
  marque,
169
178
  logo,
179
+ produit,
170
180
  contenu,
171
181
  pied,
172
182
  lang = 'fr',
173
183
  }: EmailOptions): string {
174
- const enTete = logo
175
- ? `<img src="${echappe(logo.src)}" height="${logo.hauteur ?? 28}" alt="${echappe(marque)}" style="display:block;border:0;height:${logo.hauteur ?? 28}px;width:auto;">`
184
+ const source = produit ? LOGOS_PRODUITS[produit] : logo?.src
185
+ // 34px : la hauteur du logo de la barre de vitrine sous le seuil. Un
186
+ // e-mail se lit surtout au téléphone.
187
+ const hauteur = logo?.hauteur ?? 34
188
+ const enTete = source
189
+ ? `<img src="${echappe(source)}" height="${hauteur}" alt="${echappe(marque)}" style="display:block;border:0;height:${hauteur}px;width:auto;">`
176
190
  : `<span style="font-family:${POLICES.display};font-weight:600;font-size:20px;letter-spacing:-0.02em;color:${COULEURS.ink};">${echappe(marque)}</span>`
177
191
 
178
192
  return `<!doctype html>
@@ -0,0 +1,16 @@
1
+ // GÉNÉRÉ par scripts/build-glyph-data.mjs — ne pas éditer à la main.
2
+
3
+ /** Où la planche publie les glyphes (staticDirs de .storybook/main.ts). */
4
+ export const BASE_RESSOURCES = 'https://design.zevra.tech'
5
+
6
+ /** L'URL PUBLIQUE de chaque glyphe. Absolue, parce qu'un e-mail ne résout
7
+ * ni un chemin relatif ni une data-URI. */
8
+ export const LOGOS_PRODUITS = {
9
+ 'campus': `${BASE_RESSOURCES}/logos/glyphes/campus.png`,
10
+ 'lexform': `${BASE_RESSOURCES}/logos/glyphes/lexform.png`,
11
+ 'mcp': `${BASE_RESSOURCES}/logos/glyphes/mcp.png`,
12
+ 'memoire': `${BASE_RESSOURCES}/logos/glyphes/memoire.png`,
13
+ 'plume': `${BASE_RESSOURCES}/logos/glyphes/plume.png`,
14
+ 'supernovia': `${BASE_RESSOURCES}/logos/glyphes/supernovia.png`,
15
+ 'zevra': `${BASE_RESSOURCES}/logos/glyphes/zevra.png`,
16
+ } as const
package/src/surfaces.css CHANGED
@@ -173,13 +173,39 @@
173
173
  background: radial-gradient(closest-side, rgba(32, 160, 240, 0.5), rgba(32, 160, 240, 0) 70%);
174
174
  }
175
175
 
176
- /* Texte courant sur fond sombre : ni blanc pur, ni le gris du mode clair. */
177
- .zv-band .zv-body,
178
- .zv-band .zv-rule,
176
+ /* ─── Texte sur fond sombre ─────────────────────────────────────────────
177
+ * Ni blanc pur, ni le gris du mode clair.
178
+ *
179
+ * ⚠️ POURQUOI CETTE RÈGLE EXISTE, ET POURQUOI ELLE COUVRE TOUT. Les classes
180
+ * de texte du paquet posent leur PROPRE couleur (.zv-body, .zv-lead,
181
+ * .zv-note et .zv-rule sont en --muted ; .zv-h1 en --ink). Cette couleur
182
+ * l'emporte sur celle héritée de la surface : poser un paragraphe dans un
183
+ * panneau navy donnait du gris de mode clair sur du bleu nuit, et un titre
184
+ * h1 y devenait carrément invisible.
185
+ *
186
+ * La règle ne visait que `.zv-band` et deux classes. Les autres surfaces
187
+ * sombres du système — le panneau navy, l'enveloppe .zv-text-on-dark, la
188
+ * planche sociale — n'étaient pas couvertes, et les trois autres paliers de
189
+ * texte non plus. Corrigé le 27/08/2026 : une seule liste, toutes les
190
+ * surfaces, tous les paliers.
191
+ *
192
+ * Ce qui reste EXPLICITE et ne s'adapte pas tout seul : les labels mono
193
+ * (`Mono ton="on-dark"`) et la mise en valeur (`Em surSombre`). Ceux-là
194
+ * changent de RÔLE sur fond sombre, pas seulement de clarté — c'est une
195
+ * décision de rédaction, elle se pose à la main. */
196
+ :is(.zv-band, .zv-panel-navy, .zv-text-on-dark, .zv-social--manifeste)
197
+ :is(.zv-body, .zv-lead, .zv-rule, .zv-note),
179
198
  .zv-text-on-dark {
180
199
  color: #c7cde0;
181
200
  }
182
201
 
202
+ /* Les titres, eux, reprennent le blanc : sur une surface sombre ils portent
203
+ * la même hiérarchie que l'encre sur le papier. */
204
+ :is(.zv-band, .zv-panel-navy, .zv-text-on-dark, .zv-social--manifeste)
205
+ :is(.zv-h1, .zv-h2, .zv-h3, .zv-card-title, .zv-display) {
206
+ color: var(--white);
207
+ }
208
+
183
209
  /* Panneau navy compact (planches de logos). */
184
210
  .zv-panel-navy {
185
211
  background: linear-gradient(135deg, #06063a 0%, #0b0b5e 40%, var(--accent-deep) 100%);