@zevra/ui 0.1.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.
Files changed (77) hide show
  1. package/DECISIONS.md +150 -0
  2. package/README.md +177 -0
  3. package/logos/index.json +599 -0
  4. package/logos/png/campus-glyph-ink.png +0 -0
  5. package/logos/png/campus-glyph-orig.png +0 -0
  6. package/logos/png/campus-glyph-white.png +0 -0
  7. package/logos/png/campus-lockup.png +0 -0
  8. package/logos/png/lexform-glyph-ink.png +0 -0
  9. package/logos/png/lexform-glyph-orig.png +0 -0
  10. package/logos/png/lexform-glyph-white.png +0 -0
  11. package/logos/png/lexform-lockup.png +0 -0
  12. package/logos/png/mcp-glyph-ink.png +0 -0
  13. package/logos/png/mcp-glyph-orig.png +0 -0
  14. package/logos/png/mcp-glyph-white.png +0 -0
  15. package/logos/png/mcp-lockup.png +0 -0
  16. package/logos/png/memoire-dark.png +0 -0
  17. package/logos/png/memoire-glyph-ink.png +0 -0
  18. package/logos/png/memoire-glyph-orig.png +0 -0
  19. package/logos/png/memoire-glyph-white.png +0 -0
  20. package/logos/png/memoire-lockup.png +0 -0
  21. package/logos/png/zevra-lockup-ink.png +0 -0
  22. package/logos/png/zevra-lockup-white.png +0 -0
  23. package/logos/png/zevra-lockup.png +0 -0
  24. package/logos/png/zevra-mark-ink.png +0 -0
  25. package/logos/png/zevra-mark-orig.png +0 -0
  26. package/logos/png/zevra-mark-white.png +0 -0
  27. package/logos/png/zevra-mark.png +0 -0
  28. package/logos/svg/campus-glyph-ink.svg +1 -0
  29. package/logos/svg/campus-glyph-navy.svg +1 -0
  30. package/logos/svg/campus-glyph-orig.svg +1 -0
  31. package/logos/svg/campus-glyph-white.svg +1 -0
  32. package/logos/svg/campus-lockup-ink.svg +1 -0
  33. package/logos/svg/campus-lockup-navy.svg +1 -0
  34. package/logos/svg/campus-lockup-orig.svg +1 -0
  35. package/logos/svg/campus-lockup-white.svg +1 -0
  36. package/logos/svg/lexform-glyph-ink.svg +1 -0
  37. package/logos/svg/lexform-glyph-navy.svg +1 -0
  38. package/logos/svg/lexform-glyph-orig.svg +1 -0
  39. package/logos/svg/lexform-glyph-white.svg +1 -0
  40. package/logos/svg/lexform-lockup-ink.svg +1 -0
  41. package/logos/svg/lexform-lockup-navy.svg +1 -0
  42. package/logos/svg/lexform-lockup-orig.svg +1 -0
  43. package/logos/svg/lexform-lockup-white.svg +1 -0
  44. package/logos/svg/mcp-glyph-ink.svg +1 -0
  45. package/logos/svg/mcp-glyph-navy.svg +1 -0
  46. package/logos/svg/mcp-glyph-orig.svg +1 -0
  47. package/logos/svg/mcp-glyph-white.svg +1 -0
  48. package/logos/svg/mcp-lockup-ink.svg +1 -0
  49. package/logos/svg/mcp-lockup-navy.svg +1 -0
  50. package/logos/svg/mcp-lockup-orig.svg +1 -0
  51. package/logos/svg/mcp-lockup-white.svg +1 -0
  52. package/logos/svg/memoire-glyph-ink.svg +1 -0
  53. package/logos/svg/memoire-glyph-navy.svg +1 -0
  54. package/logos/svg/memoire-glyph-orig.svg +1 -0
  55. package/logos/svg/memoire-glyph-white.svg +1 -0
  56. package/logos/svg/memoire-lockup-ink.svg +1 -0
  57. package/logos/svg/memoire-lockup-navy.svg +1 -0
  58. package/logos/svg/memoire-lockup-orig.svg +1 -0
  59. package/logos/svg/memoire-lockup-white.svg +1 -0
  60. package/logos/svg/zevra-lockup-ink.svg +1 -0
  61. package/logos/svg/zevra-lockup-navy.svg +1 -0
  62. package/logos/svg/zevra-lockup-orig.svg +1 -0
  63. package/logos/svg/zevra-lockup-white.svg +1 -0
  64. package/logos/svg/zevra-mark-ink.svg +1 -0
  65. package/logos/svg/zevra-mark-navy.svg +1 -0
  66. package/logos/svg/zevra-mark-orig.svg +1 -0
  67. package/logos/svg/zevra-mark-white.svg +1 -0
  68. package/package.json +52 -0
  69. package/src/base.css +367 -0
  70. package/src/components.css +553 -0
  71. package/src/fonts.css +16 -0
  72. package/src/index.css +11 -0
  73. package/src/layout.css +542 -0
  74. package/src/motion.css +248 -0
  75. package/src/surfaces.css +235 -0
  76. package/src/tokens.css +76 -0
  77. package/tokens/index.js +91 -0
package/DECISIONS.md ADDED
@@ -0,0 +1,150 @@
1
+ # Arbitrages de relevé
2
+
3
+ Les cinq maquettes de la passation ne s'accordent pas toujours. Ce fichier
4
+ liste chaque désaccord, la valeur retenue et pourquoi — pour qu'aucun écart ne
5
+ soit tranché en silence, et que la DA puisse rejuger sur pièces.
6
+
7
+ Sources : les dix planches de `reference/maquettes/` et
8
+ `reference/prototype/experience.html`, à jour de la passation du 23/08/2026
9
+ au soir (« handoff 3 »), qui ajoute `Blocks.html`, `Motion.html` et les trois
10
+ landings.
11
+
12
+ ---
13
+
14
+ ## Tranchés par la passation suivante
15
+
16
+ Les deux questions laissées ouvertes à la première livraison sont **closes**,
17
+ et dans le sens qui avait été retenu. Les cinq planches ajoutées le
18
+ confirment à l'unanimité.
19
+
20
+ ### 1. Le sens du dégradé de signature — clos
21
+
22
+ | Source | Valeur |
23
+ |---|---|
24
+ | Main, DesignSystem, Mobile (1re passation) | `iris → violet 50% → cyan` |
25
+ | Logos, prototype, token `--spectre` | `violet → bleu 55% → cyan` |
26
+ | **Blocks, Motion, les 3 landings** | **`violet → bleu 55% → cyan`** |
27
+
28
+ Les cinq nouvelles planches posent toutes `linear-gradient(90deg, #8a3af8,
29
+ #2f6ef8 55%, #14c2f8)`, c'est-à-dire exactement `--spectre`. La valeur du
30
+ token est donc la bonne ; les trois planches historiques sont en retard, pas
31
+ en désaccord.
32
+
33
+ ### 2. Le rayon des cartes — clos
34
+
35
+ Les cinq nouvelles planches codent `border-radius: 16px` sur `.panel`, soit
36
+ `--r-card`. Le `14px` de DesignSystem et Logos et le `12px` du prototype
37
+ appartiennent à l'état antérieur.
38
+
39
+ ---
40
+
41
+ ## Tranché sans ambiguïté
42
+
43
+ **Hauteur des boutons — 48px.** Main, Mobile et le prototype s'accordent ;
44
+ DesignSystem est seule à 46px.
45
+
46
+ **Icône du lien fléché — 15×15.** Quatre occurrences dans Main contre une à
47
+ 16px dans DesignSystem.
48
+
49
+ **Pastille — 28px de haut, 10px de texte, 0.18em.** Main et le prototype
50
+ s'accordent ; DesignSystem est plus grande (30/11), Mobile plus petite
51
+ (26/0.16em — repris dans la déclinaison mobile).
52
+
53
+ **Puce de source — `--accent-deep`.** Main et le prototype ; DesignSystem pose
54
+ `--accent`.
55
+
56
+ **Entité pseudonymisée — 10px, `1px 6px`.** Main et DesignSystem ; le
57
+ prototype est plus grand (11px, `2px 7px`).
58
+
59
+ **Les deux encarts ne sont pas le même composant.** `.zv-inset` (blanc,
60
+ `--line`, 13px/1.6, `--muted`) vient de DesignSystem ; `.zv-inset--quiet`
61
+ (`--panel`, `--hairline`, 12px/1.9, `--ink`) vient de Main. Les fusionner
62
+ donnait une chimère qui n'existe dans aucune maquette.
63
+
64
+ ---
65
+
66
+ ## Apports de la passation « handoff 3 »
67
+
68
+ **Le mouvement est spécifié.** `Motion.html` nomme neuf animations, leurs
69
+ plages de défilement et leurs règles : une seule courbe
70
+ (`cubic-bezier(.2,.7,.2,1)`), un seul type de mouvement par scène, des
71
+ entrées toujours vers le haut, aucun mouvement sur la typographie posée.
72
+ Elles vivent dans `motion.css` sous le préfixe `zv-anim-`.
73
+
74
+ Deux choix d'implémentation méritent d'être dits :
75
+
76
+ - les entrées ne sont déclarées QUE dans `@supports (animation-timeline:
77
+ view())`. Un navigateur sans support affiche la page complète, jamais un
78
+ écran vide en attente d'une animation qui ne viendra pas ;
79
+ - les deux boucles animent les propriétés `translate` et `scale`
80
+ indépendantes, jamais `transform` — le halo est centré par
81
+ `translateX(-50%)`, qu'une animation sur `transform` écraserait. La
82
+ maquette contournait le problème en recopiant le `translateX(-50%)` dans
83
+ chaque image-clé ; la propriété indépendante compose proprement.
84
+
85
+ **Six blocs de plus.** Citation, carte de tarif, FAQ, aperçu d'interface,
86
+ bande de preuve sociale, pied de page réduit — relevés dans `Blocks.html`,
87
+ qui liste les composants du site. Deux d'entre eux portent une règle
88
+ éditoriale que le CSS ne peut pas faire respecter et qui est donc écrite en
89
+ commentaire : **jamais de fausse citation**, et **jamais de lorem dans un
90
+ aperçu d'interface** — c'est ce bloc qui porte la crédibilité de la page.
91
+
92
+ **Un palier typographique et une accroche.** `.zv-note` (12,5px) et
93
+ `.zv-tagline`, la phrase d'accroche posée sous le nom d'un glyphe, moins
94
+ interlettrée que le label qu'elle suit.
95
+
96
+ **Un titre de section plus court.** `.zv-h2--sm` (48px) pour les landings
97
+ produit, à côté du 56px de la home et du 64px des CTA.
98
+
99
+ `Blocks.html` s'intitule « Quinze blocs » mais n'en étiquette que quatorze :
100
+ le bloc de hero, présent dans les trois landings, n'a pas d'étiquette. Rien
101
+ n'a été inventé pour combler l'écart.
102
+
103
+ ---
104
+
105
+ ## Ajouts assumés, hors relevé
106
+
107
+ **Le point de rupture à 768px.** Les cinq maquettes sont à largeur fixe, sans
108
+ une seule media query — Mobile.html est un rendu figé à 390px. Le seuil vient
109
+ de la convention `md` du projet ; les valeurs mobiles, elles, sont toutes
110
+ relevées dans Mobile.html. Un test vérifie qu'il reste unique.
111
+
112
+ **Les conteneurs sont fluides.** `.zv-page` est plafonnée à 1440px, pas figée :
113
+ la reproduire à l'identique garantissait un débordement horizontal sur
114
+ téléphone.
115
+
116
+ **Le focus clavier.** Aucune maquette ne déclare d'état de focus. Un système
117
+ livré sans focus visible est inutilisable au clavier : `:focus-visible` est
118
+ posé avec `--accent`, sans introduire de valeur nouvelle.
119
+
120
+ **`prefers-reduced-motion`.** Neutralise les deux animations.
121
+
122
+ **L'état désactivé des boutons.** Absent du relevé. Traitement neutre
123
+ (opacité), plutôt qu'une couleur inventée.
124
+
125
+ **Le liseré interne du bouton plein.** `0 1px 0 rgba(255,255,255,0.18) inset`
126
+ est bien dans Main.html, mais absent de `--shadow-btn`. Il est recomposé dans
127
+ le composant plutôt qu'ajouté au token.
128
+
129
+ ---
130
+
131
+ ## Écarté du paquet
132
+
133
+ Ce que le relevé recense mais que le paquet ne livre pas, faute d'usage hors
134
+ des planches de documentation : nuanciers, damier de transparence, cotations
135
+ de zone de protection, échelle de tailles minimales, grille de lockups,
136
+ nomenclature de fichiers, scènes de constellation et motifs d'animation liés
137
+ au défilement (`animation-timeline`, encore mal supporté).
138
+
139
+ Ces éléments restent consultables dans `reference/`.
140
+
141
+ ---
142
+
143
+ ## Asymétries connues, laissées telles quelles
144
+
145
+ `--ok-line` existe, `--err-line` non : la carte en erreur code `#efc9cd` en
146
+ dur. Même chose pour `#8fd3a8` / `#f0a5ad`, les états sur fond sombre.
147
+
148
+ Trois rayons de surface pour un seul token : `--r-card` (16), la puce de
149
+ source (4px) et le rayon 18px de la carte verre de DesignSystem — ce dernier
150
+ ramené à `--r-card`, comme le fait Mobile.html.
package/README.md ADDED
@@ -0,0 +1,177 @@
1
+ # Zevra UI — design system « Encre & Papier »
2
+
3
+ Tokens, CSS des composants et logos officiels de la plateforme Zevra.
4
+ Source de vérité pour tout ce qui touche à l'identité visuelle : une app qui
5
+ recopie un hexadécimal au lieu de lire une variable d'ici finira par diverger.
6
+
7
+ Issu de la passation DA du 23/08/2026. L'atelier où la direction évolue reste
8
+ le canvas Claude Design « Zevra DA Encre et Papier » ; **ce dépôt est ce qui en
9
+ sort**, versionné et consommable.
10
+
11
+ ---
12
+
13
+ ## Installer
14
+
15
+ ```bash
16
+ pnpm add @zevra/ui
17
+ ```
18
+
19
+ ## Utiliser
20
+
21
+ ### Le CSS
22
+
23
+ ```css
24
+ /* tout d'un coup */
25
+ @import "@zevra/ui/css";
26
+
27
+ /* ou à la carte */
28
+ @import "@zevra/ui/tokens.css"; /* les variables, indispensable */
29
+ @import "@zevra/ui/base.css"; /* reset, typographie, kicker, liens */
30
+ @import "@zevra/ui/components.css"; /* boutons, badges, cartes, encarts */
31
+ @import "@zevra/ui/layout.css"; /* conteneurs, grilles, sections, chrome */
32
+ @import "@zevra/ui/surfaces.css"; /* halos, sols, voiles, manifeste */
33
+ @import "@zevra/ui/motion.css"; /* les neuf animations autorisées */
34
+ ```
35
+
36
+ L'ordre compte : les tokens d'abord, le socle ensuite. Toutes les classes sont
37
+ préfixées `zv-`. Aucune dépendance, aucun préprocesseur : le paquet fonctionne
38
+ à l'identique en React, en Astro, en HTML brut et dans un canvas de design.
39
+
40
+ Le CSS est **fluide et responsive** là où les maquettes étaient figées à
41
+ 1440px : `.zv-page` est plafonnée, pas verrouillée, et un point de rupture
42
+ unique à 768px reprend les valeurs mobiles du relevé.
43
+
44
+ Chaque valeur vient des maquettes de la passation. Là où deux planches se
45
+ contredisaient, l'arbitrage est écrit dans [DECISIONS.md](DECISIONS.md).
46
+
47
+ ## Le mouvement
48
+
49
+ Neuf animations, pas une de plus, sous le préfixe `zv-anim-`. Sept sont
50
+ pilotées par le défilement, deux tournent en continu :
51
+
52
+ ```html
53
+ <span class="zv-halo zv-halo--hero zv-anim-breathe"></span>
54
+ <h2 class="zv-h2 zv-anim-rise">…</h2>
55
+ <img class="zv-glyph zv-anim-drift" style="--zv-delay: .8s">
56
+ ```
57
+
58
+ Les règles de la passation : une seule courbe, un seul type de mouvement par
59
+ scène, des entrées toujours vers le haut, et **aucun mouvement sur la
60
+ typographie une fois posée**.
61
+
62
+ Les entrées ne sont déclarées que dans un bloc `@supports` : sans
63
+ `animation-timeline`, la page s'affiche complète plutôt que vide. Un seul
64
+ media query neutralise les neuf pour `prefers-reduced-motion`.
65
+
66
+ ### Les tokens en JavaScript
67
+
68
+ Pour ce qui ne peut pas lire une variable CSS — graphes, images générées,
69
+ gabarits d'e-mail :
70
+
71
+ ```js
72
+ import { couleurs, serieGraphique, polices } from '@zevra/ui'
73
+
74
+ couleurs.accent // '#2a2aa8'
75
+ serieGraphique // palette ordonnée, dérivée du spectre
76
+ ```
77
+
78
+ C'est un **miroir** de `tokens.css`, pas une seconde source. Un test échoue si
79
+ les deux divergent.
80
+
81
+ ### Les logos
82
+
83
+ `logos/index.json` décrit les 40 fichiers : produit, forme, nuance, et surtout
84
+ **sur quel fond chacun se pose**.
85
+
86
+ ```js
87
+ import index from '@zevra/ui/logos/index.json'
88
+ ```
89
+
90
+ Nommage : `<produit>-<forme>-<nuance>.svg` — par exemple
91
+ `campus-lockup-navy.svg`. Produits : `zevra`, `campus`, `lexform`, `mcp`,
92
+ `memoire`. Formes : `glyph`, `lockup`, `mark` (Zevra). Nuances : `ink`, `navy`,
93
+ `white`, `orig`.
94
+
95
+ Les SVG sont **autonomes** (aucune ressource externe, ~4 Ko) : ils s'inlinent
96
+ partout, y compris là où les images distantes sont interdites.
97
+
98
+ ## Polices
99
+
100
+ Trois familles Google : **Outfit** (titres), **Public Sans** (texte),
101
+ **Space Grotesk** (labels capitales).
102
+
103
+ En production, chargez-les par balise — une `@import` CSS bloque le rendu :
104
+
105
+ ```html
106
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
107
+ <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Outfit:wght@200;300;400;500;600&family=Public+Sans:wght@400;600&family=Space+Grotesk:wght@500;600;700&display=swap">
108
+ ```
109
+
110
+ `@import "@zevra/ui/fonts.css"` existe pour les prototypes et les
111
+ maquettes, où la simplicité prime.
112
+
113
+ ---
114
+
115
+ ## Les règles qui ne se négocient pas
116
+
117
+ Elles viennent de la passation. Les ignorer produit du « presque Zevra », qui
118
+ coûte plus cher à corriger qu'à respecter.
119
+
120
+ **Un seul bouton plein par écran.** L'indigo porte l'action. Pas de bouton en
121
+ dégradé, pas de rayon 999.
122
+
123
+ **Jamais de fausse citation, jamais de lorem.** Le bloc `.zv-quote` reste en
124
+ réserve tant qu'un verbatim client n'a pas été recueilli ; `.zv-ui-preview`
125
+ montre de vraies données réalistes — c'est lui qui porte la crédibilité de la
126
+ page.
127
+
128
+ **Trois cartes de tarif par page au maximum, cinq questions de FAQ, une seule
129
+ ligne de preuve sociale.** Au-delà, la preuve se dilue au lieu de s'accumuler.
130
+
131
+ **Le spectre ne sert qu'à trois choses** : le filet de section (56×2 px devant
132
+ un kicker), la barre de progression, les points de la méthode. Jamais en fond,
133
+ jamais en texte.
134
+
135
+ **Les logos ne se retouchent pas** : ni recoloration, ni resaturation, ni
136
+ inclinaison. Sur navy, utiliser les versions blanches. Sous 24 px, passer en
137
+ mono. Zone de protection X/2 ; hauteur de capitale du wordmark = 0,30 × glyphe.
138
+
139
+ **Le système est clair par nature.** Une surface sombre se fait avec
140
+ `--manifeste` et `--accent-on-dark`, pas en inversant les neutres : les
141
+ contrastes ont été réglés dans ce sens-là.
142
+
143
+ ---
144
+
145
+ ## Dans un canvas Claude Design
146
+
147
+ Un canvas interdit les ressources distantes : ni feuille de style externe, ni
148
+ image par URL. Pour y travailler dans la charte :
149
+
150
+ 1. coller le bloc `:root { … }` de `src/tokens.css` en tête de l'artboard ;
151
+ 2. coller les SVG de logo **en ligne** plutôt que de les référencer.
152
+
153
+ L'admin Zevra propose les deux au presse-papier (page *Plateforme → Design
154
+ system*), c'est le chemin le plus court.
155
+
156
+ Les polices Google, elles, sont autorisées dans un canvas : la balise `<link>`
157
+ ci-dessus fonctionne telle quelle.
158
+
159
+ ---
160
+
161
+ ## Faire évoluer
162
+
163
+ 1. La décision visuelle se prend dans le canvas Claude Design, avec Pierre.
164
+ 2. Elle atterrit ici : `src/tokens.css` d'abord, puis son miroir
165
+ `tokens/index.js`, puis les modules CSS concernés.
166
+ 3. `pnpm test` doit rester vert. Les tests ne jugent pas l'esthétique : ils
167
+ attrapent le token appelé mais inexistant, la classe définie dans deux
168
+ modules (où c'est l'ordre de chargement qui tranche à la place de la DA),
169
+ le second point de rupture glissé au fil de l'eau, et le spectre écrit à
170
+ la main hors de ses trois emplois autorisés.
171
+ 4. Après ajout de logos : `node scripts/build-logo-index.mjs`, et committer
172
+ l'index régénéré.
173
+ 5. Publier une version : `npm version <patch|minor|major>` puis `npm publish`.
174
+
175
+ `reference/` conserve les maquettes HTML, le prototype animé et les fichiers
176
+ d'origine de la passation. Ce dossier n'est **pas publié** dans le paquet : il
177
+ sert d'archive et de référence visuelle, pas de dépendance.