@zevra/ui 0.8.0 → 0.9.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 (65) hide show
  1. package/DECISIONS.md +227 -0
  2. package/dist/actions.d.ts +13 -3
  3. package/dist/actions.d.ts.map +1 -1
  4. package/dist/actions.js +9 -2
  5. package/dist/actions.js.map +1 -1
  6. package/dist/catalogue.d.ts.map +1 -1
  7. package/dist/catalogue.js +160 -11
  8. package/dist/catalogue.js.map +1 -1
  9. package/dist/css-inline.d.ts.map +1 -1
  10. package/dist/css-inline.js +1 -1
  11. package/dist/css-inline.js.map +1 -1
  12. package/dist/data.d.ts +34 -1
  13. package/dist/data.d.ts.map +1 -1
  14. package/dist/data.js +27 -0
  15. package/dist/data.js.map +1 -1
  16. package/dist/feedback.d.ts +49 -0
  17. package/dist/feedback.d.ts.map +1 -1
  18. package/dist/feedback.js +24 -0
  19. package/dist/feedback.js.map +1 -1
  20. package/dist/forms.d.ts +36 -0
  21. package/dist/forms.d.ts.map +1 -1
  22. package/dist/forms.js +24 -0
  23. package/dist/forms.js.map +1 -1
  24. package/dist/icon-data.d.ts +1 -1
  25. package/dist/icon-data.d.ts.map +1 -1
  26. package/dist/icon-data.js +42 -0
  27. package/dist/icon-data.js.map +1 -1
  28. package/dist/icon.d.ts +1 -1
  29. package/dist/icon.js +1 -1
  30. package/dist/layout.d.ts +21 -0
  31. package/dist/layout.d.ts.map +1 -1
  32. package/dist/layout.js +18 -0
  33. package/dist/layout.js.map +1 -1
  34. package/dist/navigation.d.ts +45 -7
  35. package/dist/navigation.d.ts.map +1 -1
  36. package/dist/navigation.js +54 -7
  37. package/dist/navigation.js.map +1 -1
  38. package/dist/surfaces.d.ts +18 -0
  39. package/dist/surfaces.d.ts.map +1 -1
  40. package/dist/surfaces.js +6 -0
  41. package/dist/surfaces.js.map +1 -1
  42. package/icons/index.json +126 -0
  43. package/icons/sprite.svg +21 -0
  44. package/package.json +4 -3
  45. package/react/actions.tsx +28 -2
  46. package/react/catalogue.tsx +343 -17
  47. package/react/css-inline.ts +1 -1
  48. package/react/data.tsx +87 -1
  49. package/react/feedback.tsx +98 -0
  50. package/react/forms.tsx +90 -0
  51. package/react/icon-data.ts +63 -0
  52. package/react/icon.tsx +2 -2
  53. package/react/layout.tsx +39 -0
  54. package/react/navigation.tsx +108 -6
  55. package/react/surfaces.tsx +45 -0
  56. package/src/base.css +16 -0
  57. package/src/components.css +135 -3
  58. package/src/data.css +143 -1
  59. package/src/feedback.css +196 -37
  60. package/src/forms.css +137 -1
  61. package/src/layout.css +72 -0
  62. package/src/navigation.css +207 -12
  63. package/src/surfaces.css +76 -7
  64. package/src/tokens.css +6 -0
  65. package/tokens/index.js +2 -0
package/icons/sprite.svg CHANGED
@@ -1,28 +1,45 @@
1
1
  <svg xmlns="http://www.w3.org/2000/svg" style="display:none" aria-hidden="true">
2
2
  <symbol id="zv-accueil" viewBox="0 0 24 24"><path d="M4 10.67 L12 4 L20 10.67 V20 H4 Z" /><path d="M9.33 20 V13.33 H14.67 V20" /></symbol>
3
3
  <symbol id="zv-activite" viewBox="0 0 24 24"><path d="M3.33 12 H8 L10.67 5.33 L14 18.67 L16 12 H20.67" /></symbol>
4
+ <symbol id="zv-aide" viewBox="0 0 24 24"><circle cx="12" cy="12" r="8.67" /><path d="M9.33 9.33 A2.67 2.67 0 0 1 14.53 10.13 C14.53 11.87 12 12.27 12 14" /><circle cx="12" cy="17.07" r="0.8" fill="currentColor" stroke="none" /></symbol>
4
5
  <symbol id="zv-app-couches" viewBox="0 0 24 24"><path d="M12 2.67 L20 6.67 L12 10.67 L4 6.67 Z" /><path d="M4 12 L12 16 L20 12" /><path d="M4 17.33 L12 21.33 L20 17.33" /></symbol>
5
6
  <symbol id="zv-archiver" viewBox="0 0 24 24"><rect x="3.33" y="4" width="17.33" height="4.67" rx="1.07" /><path d="M5.33 8.67 V18.93 A1.07 1.07 0 0 0 6.4 20 H17.6 A1.07 1.07 0 0 0 18.67 18.93 V8.67" /><path d="M9.33 12.67 H14.67" /></symbol>
7
+ <symbol id="zv-attention" viewBox="0 0 24 24"><path d="M10.67 3.87 L2.53 17.87 A1.55 1.55 0 0 0 3.87 20.19 H20.13 A1.55 1.55 0 0 0 21.47 17.87 L13.33 3.87 A1.54 1.54 0 0 0 10.67 3.87 Z" /><path d="M12 9.33 V13.33" /><circle cx="12" cy="16.53" r="0.8" fill="currentColor" stroke="none" /></symbol>
8
+ <symbol id="zv-balance" viewBox="0 0 24 24"><path d="M12 3.33 V20.67" /><path d="M8.67 20.67 H15.33" /><path d="M5.33 6 H18.67" /><path d="M6.67 6 L3.33 13.33" /><path d="M6.67 6 L10 13.33" /><path d="M3.33 13.33 A3.33 3.33 0 0 0 10 13.33" /><path d="M17.33 6 L14 13.33" /><path d="M17.33 6 L20.67 13.33" /><path d="M14 13.33 A3.33 3.33 0 0 0 20.67 13.33" /></symbol>
6
9
  <symbol id="zv-base-de-donnees" viewBox="0 0 24 24"><ellipse cx="12" cy="6" rx="7.33" ry="2.67" /><path d="M4.67 6 V12 C4.67 13.47 7.87 14.67 12 14.67 C16.13 14.67 19.33 13.47 19.33 12 V6" /><path d="M4.67 12 V18 C4.67 19.47 7.87 20.67 12 20.67 C16.13 20.67 19.33 19.47 19.33 18 V12" /></symbol>
7
10
  <symbol id="zv-bouclier-verifie" viewBox="0 0 24 24"><path d="M12 2.67 L20 6 V12 C20 16.67 16.67 19.73 12 21.33 C7.33 19.73 4 16.67 4 12 V6 Z" /><path d="M8.67 12 L11.07 14.4 L15.33 10" /></symbol>
8
11
  <symbol id="zv-cadenas" viewBox="0 0 24 24"><rect x="4.67" y="10.67" width="14.67" height="9.33" rx="1.6" /><path d="M8 10.67 V7.33 A4 4 0 0 1 16 7.33 V10.67" /><circle cx="12" cy="15.33" r="1.33" /></symbol>
9
12
  <symbol id="zv-cadrer" viewBox="0 0 24 24"><path d="M4 8 V4 H8" /><path d="M20 8 V4 H16" /><path d="M4 16 V20 H8" /><path d="M20 16 V20 H16" /></symbol>
13
+ <symbol id="zv-calendrier" viewBox="0 0 24 24"><rect x="3.33" y="4.67" width="17.33" height="16" rx="1.33" /><path d="M3.33 9.33 H20.67" /><path d="M8 2.67 V6.67" /><path d="M16 2.67 V6.67" /></symbol>
10
14
  <symbol id="zv-chevron-bas" viewBox="0 0 24 24"><path d="M6.67 9.33 L12 14.67 L17.33 9.33" /></symbol>
11
15
  <symbol id="zv-chevron-droit" viewBox="0 0 24 24"><path d="M9.33 4 L17.33 12 L9.33 20" /></symbol>
12
16
  <symbol id="zv-chevron-gauche" viewBox="0 0 24 24"><path d="M14.67 4 L6.67 12 L14.67 20" /></symbol>
17
+ <symbol id="zv-chevron-haut" viewBox="0 0 24 24"><path d="M6.67 14.67 L12 9.33 L17.33 14.67" /></symbol>
13
18
  <symbol id="zv-coche" viewBox="0 0 24 24"><path d="M5 12.4 L9.4 16.8 L19 6.8" /></symbol>
14
19
  <symbol id="zv-copier" viewBox="0 0 24 24"><rect x="4" y="4" width="12" height="12" rx="1.6" /><path d="M8 16 V18.93 A1.07 1.07 0 0 0 9.07 20 H18.93 A1.07 1.07 0 0 0 20 18.93 V9.07 A1.07 1.07 0 0 0 18.93 8 H16" /></symbol>
15
20
  <symbol id="zv-corbeille" viewBox="0 0 24 24"><path d="M4 6.67 H20" /><path d="M9.33 6.67 V4.67 A1.33 1.33 0 0 1 10.67 3.33 H13.33 A1.33 1.33 0 0 1 14.67 4.67 V6.67" /><path d="M6 6.67 L6.93 18.93 A1.33 1.33 0 0 0 8.27 20 H15.73 A1.33 1.33 0 0 0 17.07 18.93 L18 6.67" /><path d="M10 10.67 V16.67" /><path d="M14 10.67 V16.67" /></symbol>
21
+ <symbol id="zv-courriel" viewBox="0 0 24 24"><rect x="2.67" y="5.33" width="18.67" height="13.33" rx="1.33" /><path d="M2.67 7.33 L12 13.33 L21.33 7.33" /></symbol>
16
22
  <symbol id="zv-cube" viewBox="0 0 24 24"><path d="M3.33 8 L12 4 L20.67 8 V16 L12 20 L3.33 16 Z" /><path d="M3.33 8 L12 12 L20.67 8" /><path d="M12 12 V20" /></symbol>
17
23
  <symbol id="zv-deconnexion" viewBox="0 0 24 24"><path d="M14.67 4 H5.33 V20 H14.67" /><path d="M10.67 12 H20" /><path d="M16.67 8 L20.67 12 L16.67 16" /></symbol>
18
24
  <symbol id="zv-depot-fichier" viewBox="0 0 24 24"><path d="M12 3.2 V14.4" /><polyline points="7.6,10 12,14.4 16.4,10" /><path d="M4 16.8 v2.4 a1.6 1.6 0 0 0 1.6 1.6 h12.8 a1.6 1.6 0 0 0 1.6-1.6 v-2.4" /></symbol>
25
+ <symbol id="zv-diplome" viewBox="0 0 24 24"><path d="M2.67 9.33 L12 4.67 L21.33 9.33 L12 14 Z" /><path d="M6.67 11.6 V16 C6.67 17.47 9.07 18.67 12 18.67 C14.93 18.67 17.33 17.47 17.33 16 V11.6" /><path d="M21.33 9.33 V14.67" /></symbol>
19
26
  <symbol id="zv-dossier" viewBox="0 0 24 24"><path d="M1.41 6.64a1.69 1.69 0 0 1 1.69-1.69h4.8l2.12 2.4h10.87a1.69 1.69 0 0 1 1.69 1.69v9.88a1.69 1.69 0 0 1-1.69 1.69H3.11A1.69 1.69 0 0 1 1.41 20.33V6.64Z" /></symbol>
20
27
  <symbol id="zv-eclair" viewBox="0 0 24 24"><path d="M13.33 2.67 L5.33 13.33 H12 L10.67 21.33 L18.67 10.67 H12 Z" /></symbol>
28
+ <symbol id="zv-envoyer" viewBox="0 0 24 24"><path d="M21.33 2.67 L10.67 13.33" /><path d="M21.33 2.67 L14.67 21.33 L10.67 13.33 L2.67 9.33 Z" /></symbol>
29
+ <symbol id="zv-epingle" viewBox="0 0 24 24"><path d="M12 21.33 C7.56 16.89 5.33 13.42 5.33 10.67 A6.67 6.67 0 0 1 18.67 10.67 C18.67 13.42 16.44 16.89 12 21.33 Z" /><circle cx="12" cy="10.67" r="2.4" /></symbol>
21
30
  <symbol id="zv-equipe" viewBox="0 0 24 24"><circle cx="9.33" cy="8" r="3.33" /><path d="M3.33 20 C3.33 15.33 6 13.33 9.33 13.33 C12.67 13.33 15.33 15.33 15.33 20" /><path d="M16 5.33 A2.93 2.93 0 0 1 16 11.07" /><path d="M17.33 13.6 C19.73 14.27 20.67 16.4 20.67 20" /></symbol>
22
31
  <symbol id="zv-etincelles" viewBox="0 0 24 24"><path d="M12 2.67 L13.87 8.8 L20 10.67 L13.87 12.53 L12 18.67 L10.13 12.53 L4 10.67 L10.13 8.8 Z" /><path d="M19.33 16.67 L20 18.67 L22 19.33 L20 20 L19.33 22 L18.67 20 L16.67 19.33 L18.67 18.67 Z" /></symbol>
32
+ <symbol id="zv-etoile" viewBox="0 0 24 24"><path d="M12 3.33 L14.67 8.53 L20.4 9.37 L16.2 13.4 L17.2 19.07 L12 16.4 L6.8 19.07 L7.8 13.4 L3.6 9.37 L9.33 8.53 Z" /></symbol>
23
33
  <symbol id="zv-fermer" viewBox="0 0 24 24"><path d="M5.33 5.33 L18.67 18.67" /><path d="M18.67 5.33 L5.33 18.67" /></symbol>
34
+ <symbol id="zv-fichier" viewBox="0 0 24 24"><path d="M13.33 2.67 H6.67 A1.33 1.33 0 0 0 5.33 4 V20 A1.33 1.33 0 0 0 6.67 21.33 H17.33 A1.33 1.33 0 0 0 18.67 20 V8 Z" /><path d="M13.33 2.67 V8 H18.67" /></symbol>
35
+ <symbol id="zv-filtre" viewBox="0 0 24 24"><path d="M2.67 4 H21.33 L14.67 12.27 V18.67 L9.33 21.33 V12.27 Z" /></symbol>
36
+ <symbol id="zv-globe" viewBox="0 0 24 24"><circle cx="12" cy="12" r="8.67" /><path d="M3.33 12 H20.67" /><path d="M12 3.33 C14.22 5.64 15.47 8.71 15.47 12 C15.47 15.29 14.22 18.36 12 20.67 C9.78 18.36 8.53 15.29 8.53 12 C8.53 8.71 9.78 5.64 12 3.33 Z" /></symbol>
37
+ <symbol id="zv-graphique" viewBox="0 0 24 24"><path d="M4 4 V20 H20" /><path d="M8.67 20 V12.67" /><path d="M12.67 20 V8" /><path d="M16.67 20 V15.33" /></symbol>
24
38
  <symbol id="zv-horloge" viewBox="0 0 24 24"><circle cx="12" cy="12" r="8" /><path d="M12 6.67 V12 L15.33 14" /></symbol>
39
+ <symbol id="zv-imprimante" viewBox="0 0 24 24"><path d="M6.67 8 V3.33 H17.33 V8" /><path d="M6.67 17.33 H4.67 A1.33 1.33 0 0 1 3.33 16 V10.67 A1.33 1.33 0 0 1 4.67 9.33 H19.33 A1.33 1.33 0 0 1 20.67 10.67 V16 A1.33 1.33 0 0 1 19.33 17.33 H17.33" /><rect x="6.67" y="13.33" width="10.67" height="7.33" rx="0.8" /></symbol>
40
+ <symbol id="zv-info" viewBox="0 0 24 24"><circle cx="12" cy="12" r="8.67" /><path d="M12 11.33 V16" /><circle cx="12" cy="8" r="0.8" fill="currentColor" stroke="none" /></symbol>
25
41
  <symbol id="zv-lien-externe" viewBox="0 0 24 24"><path d="M10.67 4 H4 V20 H20 V13.33" /><path d="M14.67 4 H20 V9.33" /><path d="M20 4 L12 12" /></symbol>
42
+ <symbol id="zv-livre-ouvert" viewBox="0 0 24 24"><path d="M2.67 5.33 C5.33 4.67 7.78 4.89 12 6.67 C16.22 4.89 18.67 4.67 21.33 5.33 V18 C18.67 17.33 16.22 17.56 12 19.33 C7.78 17.56 5.33 17.33 2.67 18 Z" /><path d="M12 6.67 V19.33" /></symbol>
26
43
  <symbol id="zv-menu" viewBox="0 0 24 24"><path d="M0 5.33 H24" /><path d="M0 12 H24" /><path d="M0 18.67 H24" /></symbol>
27
44
  <symbol id="zv-moins" viewBox="0 0 24 24"><path d="M4 12 H20" /></symbol>
28
45
  <symbol id="zv-oeil" viewBox="0 0 24 24"><path d="M2 12 C5.33 6.67 8.67 4.67 12 4.67 C15.33 4.67 18.67 6.67 22 12 C18.67 17.33 15.33 19.33 12 19.33 C8.67 19.33 5.33 17.33 2 12 Z" /><circle cx="12" cy="12" r="2.67" /></symbol>
@@ -32,5 +49,9 @@
32
49
  <symbol id="zv-reglages" viewBox="0 0 24 24"><circle cx="12" cy="12" r="2.93" /><path d="M12 2 V4.67 M12 19.33 V22 M2 12 H4.67 M19.33 12 H22 M4.8 4.8 L6.67 6.67 M17.33 17.33 L19.2 19.2 M19.2 4.8 L17.33 6.67 M6.67 17.33 L4.8 19.2" /></symbol>
33
50
  <symbol id="zv-reseau" viewBox="0 0 24 24"><circle cx="12" cy="12" r="8" /><path d="M4 12 H20" /><path d="M12 4 C14.67 8 14.67 16 12 20" /><path d="M12 4 C9.33 8 9.33 16 12 20" /></symbol>
34
51
  <symbol id="zv-taches" viewBox="0 0 24 24"><path d="M4.67 6.67 L6.67 8.67 L10 5.33" /><path d="M4.67 16 L6.67 18 L10 14.67" /><path d="M13.33 7.33 H20" /><path d="M13.33 16.67 H20" /></symbol>
52
+ <symbol id="zv-telecharger" viewBox="0 0 24 24"><path d="M12 3.33 V15.33" /><polyline points="6.67,10 12,15.33 17.33,10" /><path d="M4.67 20.67 H19.33" /></symbol>
53
+ <symbol id="zv-telephone" viewBox="0 0 24 24"><path d="M20.67 16.93 V19.33 A1.6 1.6 0 0 1 18.93 20.93 C16.13 20.67 13.47 19.67 11.2 18.13 C9.09 16.71 7.29 14.91 5.87 12.8 C4.33 10.52 3.33 7.85 3.07 5.05 A1.6 1.6 0 0 1 4.67 3.33 H7.07 A1.6 1.6 0 0 1 8.67 4.71 C8.79 5.83 9.04 6.93 9.4 7.97 A1.6 1.6 0 0 1 9.04 9.65 L8 10.69 C9.32 13.01 11.03 14.71 13.33 16 L14.37 14.96 A1.6 1.6 0 0 1 16.05 14.6 C17.09 14.96 18.19 15.21 19.31 15.33 A1.6 1.6 0 0 1 20.67 16.93 Z" /></symbol>
54
+ <symbol id="zv-tri" viewBox="0 0 24 24"><path d="M8 4 V20" /><path d="M4.67 7.33 L8 4 L11.33 7.33" /><path d="M16 20 V4" /><path d="M12.67 16.67 L16 20 L19.33 16.67" /></symbol>
35
55
  <symbol id="zv-trois-points" viewBox="0 0 24 24"><circle cx="5.33" cy="12" r="1.33" fill="currentColor" stroke="none" /><circle cx="12" cy="12" r="1.33" fill="currentColor" stroke="none" /><circle cx="18.67" cy="12" r="1.33" fill="currentColor" stroke="none" /></symbol>
56
+ <symbol id="zv-utilisateur" viewBox="0 0 24 24"><circle cx="12" cy="8" r="3.33" /><path d="M5.33 20 C5.33 15.33 8.33 13.33 12 13.33 C15.67 13.33 18.67 15.33 18.67 20" /></symbol>
36
57
  </svg>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zevra/ui",
3
- "version": "0.8.0",
3
+ "version": "0.9.0",
4
4
  "description": "Design system Zevra « Encre & Papier » — tokens, CSS des composants et logos officiels.",
5
5
  "license": "UNLICENSED",
6
6
  "private": false,
@@ -76,6 +76,7 @@
76
76
  },
77
77
  "devDependencies": {
78
78
  "@storybook/addon-docs": "^10.5.10",
79
+ "@storybook/addon-mcp": "^0.7.0",
79
80
  "@storybook/react-vite": "^10.5.10",
80
81
  "@tanstack/react-table": "^8.21.3",
81
82
  "@types/react": "^19.2.18",
@@ -95,8 +96,8 @@
95
96
  "components"
96
97
  ],
97
98
  "peerDependencies": {
98
- "react": ">=18",
99
- "@tanstack/react-table": ">=8"
99
+ "@tanstack/react-table": ">=8",
100
+ "react": ">=18"
100
101
  },
101
102
  "peerDependenciesMeta": {
102
103
  "react": {
package/react/actions.tsx CHANGED
@@ -12,13 +12,18 @@ import type {
12
12
  } from 'react'
13
13
  import { cx } from './cx.js'
14
14
 
15
- /** Variantes de bouton. Une seule pleine par écran — c'est la règle de charte. */
16
- export type BoutonVariante = 'plein' | 'fantome' | 'encre'
15
+ /** Variantes de bouton. Une seule pleine par écran — c'est la règle de
16
+ * charte, et « danger » COMPTE comme la pleine : la règle compte les
17
+ * aplats, pas les couleurs. « danger » est réservée à l'action destructive
18
+ * (la confirmation d'une modale de suppression), jamais à une action
19
+ * simplement importante. */
20
+ export type BoutonVariante = 'plein' | 'fantome' | 'encre' | 'danger'
17
21
 
18
22
  const VARIANTE_BOUTON: Record<BoutonVariante, string> = {
19
23
  plein: 'zv-btn',
20
24
  fantome: 'zv-btn--ghost',
21
25
  encre: 'zv-btn--ink',
26
+ danger: 'zv-btn--danger',
22
27
  }
23
28
 
24
29
  export interface ButtonProps
@@ -28,6 +33,12 @@ export interface ButtonProps
28
33
  compact?: boolean
29
34
  /** Pleine largeur — l'appel à l'action d'un écran mobile. */
30
35
  bloc?: boolean
36
+ /** Attente pendant l'action : pose aria-busy et aria-disabled, et AVALE
37
+ * le clic — sans poser `disabled`, qui sortirait le bouton du parcours
38
+ * clavier au moment précis où l'attente doit s'annoncer.
39
+ * ⚠️ Le LIBELLÉ doit changer avec elle (« Connexion… ») — c'est le motif
40
+ * relevé de Mémoire : l'estompement seul ne dit pas ce qu'on attend. */
41
+ occupe?: boolean
31
42
  /** Échappatoire assumée. À employer pour un ajustement de position, jamais
32
43
  * pour redéfinir une couleur ou une taille : c'est par là que les apps
33
44
  * recommencent à écrire leur propre charte. */
@@ -39,13 +50,28 @@ export function Button({
39
50
  variante = 'plein',
40
51
  compact,
41
52
  bloc,
53
+ occupe,
42
54
  className,
43
55
  type = 'button',
56
+ disabled,
57
+ onClick,
44
58
  ...reste
45
59
  }: ButtonProps) {
46
60
  return (
47
61
  <button
48
62
  type={type}
63
+ aria-busy={occupe || undefined}
64
+ aria-disabled={occupe || undefined}
65
+ disabled={disabled}
66
+ onClick={
67
+ occupe
68
+ ? (e) => {
69
+ // Le clic est avalé, pas interdit : un `disabled` sortirait le
70
+ // bouton du parcours clavier pendant l'annonce de l'attente.
71
+ e.preventDefault()
72
+ }
73
+ : onClick
74
+ }
49
75
  className={cx(
50
76
  VARIANTE_BOUTON[variante],
51
77
  compact && 'zv-btn--sm',
@@ -22,31 +22,34 @@ import {
22
22
  Quote, Rows, RowsItem, Src, SrcRow, StatCard, Tag, UiPreview,
23
23
  } from './content.js'
24
24
  import {
25
- Avatar, Break, Cell, Chip, ChipRow, Cite, CiteRow, FileType, KV, KVRow,
26
- List, ListMain, ListName, ListRow, Meta, MetaRow, Row, Table, TableHead,
27
- Trunc, Unwrap,
25
+ Avatar, Break, Cell, Chip, ChipRow, Cite, CiteRow, Code, CodeBlock,
26
+ FileType, Fold, KV, KVRow, Kbd, List, ListMain, ListName, ListRow, Meta,
27
+ MetaRow, Row, Table, TableHead, Trunc, Unwrap,
28
28
  } from './data.js'
29
29
  import {
30
- Alert, Badge, Caret, Dot, Empty, Loading, Progress, Status,
30
+ Alert, Badge, Caret, Dot, Empty, Loading, Progress, Skeleton, Spinner,
31
+ Status, Tooltip,
31
32
  } from './feedback.js'
32
33
  import {
33
- Checkbox, Drop, Field, Input, Radio, Search, Seg, SegGroup, Select,
34
- SelectAnchor, SelectTrigger, Switch, Textarea,
34
+ Checkbox, Drop, Field, Input, InputAffix, Radio, Range, Search, Seg,
35
+ SegGroup, Select, SelectAnchor, SelectTrigger, Switch, Textarea,
35
36
  } from './forms.js'
36
37
  import { ICONES, Icon, IconButton, NOMS_ICONES } from './icon.js'
37
38
  import {
38
- CTA, Col, Footer, FooterMini, Grid, Grid12, Gutter, Hero, Nav, NavLink,
39
- NavLinks, NavLogo, ProofBar, SectionHead, SectionRule, SheetSection, Stat,
40
- Stats, Step, Steps,
39
+ Banner, CTA, Carousel, CarouselItem, Col, Footer, FooterMini, Grid, Grid12,
40
+ Gutter, Hero, Nav, NavLink, NavLinks, NavLogo, ProofBar, SectionHead,
41
+ SectionRule, SheetSection, Stat, Stats, Step, Steps,
41
42
  } from './layout.js'
42
43
  import {
43
44
  ChromeButton, CitePanel, Crumbs, Menu, MenuItem, Pager, PagerArrow,
44
- PagerRank, PagerStep, Scroll, SideGroup, SideLink, Sidebar, SidebarFoot,
45
- SidebarHead, Tabs, Topbar, TopbarTitle,
45
+ PagerRank, PagerStep, Popover, Scroll, SideGroup, SideLink, Sidebar,
46
+ SidebarFoot, SidebarHead, Tabs, Topbar, TopbarTitle,
46
47
  } from './navigation.js'
47
48
  import { Drawer, Modal, Toast, Toasts } from './overlays.js'
48
49
  import { SelectMenu } from './select-menu.js'
49
- import { Band, Fade, Glyph, GridFloor, Halo, PanelNavy, TextOnDark, anim } from './surfaces.js'
50
+ import {
51
+ Band, Fade, Glyph, GridFloor, Halo, PanelNavy, SocialFrame, TextOnDark, anim,
52
+ } from './surfaces.js'
50
53
  import {
51
54
  Body, CardTitle, Display, Em, H1, H2, H3, Heading, Kicker, Lead, Link, Mono, Note,
52
55
  Rule, Spec, Tagline,
@@ -248,6 +251,66 @@ function DemoDrop() {
248
251
  )
249
252
  }
250
253
 
254
+ function DemoRange() {
255
+ const [sources, setSources] = useState(12)
256
+ return (
257
+ <div style={{ maxWidth: 320 }}>
258
+ <Field
259
+ label="SOURCES INTERROGÉES"
260
+ htmlFor="ex-range"
261
+ help={`${sources} sources sur 17`}
262
+ >
263
+ <Range
264
+ id="ex-range"
265
+ min={1}
266
+ max={17}
267
+ value={sources}
268
+ onChange={(e) => setSources(Number(e.currentTarget.value))}
269
+ />
270
+ </Field>
271
+ </div>
272
+ )
273
+ }
274
+
275
+ function DemoTabsLine() {
276
+ const [actif, setActif] = useState<'apercu' | 'sources' | 'journal'>('apercu')
277
+ return (
278
+ <Tabs
279
+ variante="soulignes"
280
+ actif={actif}
281
+ onChange={setActif}
282
+ onglets={[
283
+ { id: 'apercu', label: 'Aperçu' },
284
+ { id: 'sources', label: 'Sources', compte: 12 },
285
+ { id: 'journal', label: 'Journal' },
286
+ ]}
287
+ />
288
+ )
289
+ }
290
+
291
+ function DemoPopover() {
292
+ const [ouvert, setOuvert] = useState(false)
293
+ return (
294
+ <SelectAnchor>
295
+ <Button variante="fantome" compact aria-expanded={ouvert} onClick={() => setOuvert(!ouvert)}>
296
+ Colonnes affichées
297
+ </Button>
298
+ {ouvert && (
299
+ <Popover>
300
+ <div style={{ display: 'grid', gap: 8 }}>
301
+ {['Nom', 'Taille', 'Statut'].map((c) => (
302
+ <label key={c} style={{ display: 'flex', gap: 8, alignItems: 'center' }}>
303
+ <Checkbox defaultChecked={c !== 'Taille'} />
304
+ <span className="zv-body zv-body--dense">{c}</span>
305
+ </label>
306
+ ))}
307
+ </div>
308
+ </Popover>
309
+ )}
310
+ </SelectAnchor>
311
+ )
312
+ }
313
+
251
314
  /* ── Le catalogue ─────────────────────────────────────────────────── */
252
315
 
253
316
  export const CATALOGUE: GroupeCatalogue[] = [
@@ -368,7 +431,7 @@ export const CATALOGUE: GroupeCatalogue[] = [
368
431
  couche: 'commun',
369
432
  css: 'components.css',
370
433
  resume:
371
- "Trois variantes, et UNE SEULE pleine par page : c'est ce qui fait que l'action principale se voit. Un écran à deux boutons pleins n'en a plus aucun.",
434
+ "Quatre variantes, et UNE SEULE pleine par page — « danger » comprise, la règle compte les aplats, pas les couleurs : c'est ce qui fait que l'action principale se voit. Un écran à deux boutons pleins n'en a plus aucun.",
372
435
  exemples: [
373
436
  {
374
437
  id: 'boutons',
@@ -408,6 +471,24 @@ export const CATALOGUE: GroupeCatalogue[] = [
408
471
  </div>
409
472
  ),
410
473
  },
474
+ {
475
+ id: 'etats',
476
+ nom: 'États',
477
+ resume:
478
+ '« danger » COMPTE comme le bouton plein de la page — la règle compte les aplats, pas les couleurs ; à réserver à la confirmation destructive. « occupe » pose aria-busy et aria-disabled et AVALE le clic sans sortir le bouton du parcours clavier : le LIBELLÉ doit changer avec lui, l’estompement seul ne dit pas ce qu’on attend. Survol et appui sont dans le CSS, rien à câbler.',
479
+ code: `<Button variante="danger">Supprimer définitivement</Button>
480
+ <Button occupe>Connexion…</Button>
481
+ <Button variante="fantome" disabled>Envoyer</Button>`,
482
+ rendu: (
483
+ <ButtonRow>
484
+ <Button variante="danger">Supprimer définitivement</Button>
485
+ <Button occupe>Connexion…</Button>
486
+ <Button variante="fantome" disabled>
487
+ Envoyer
488
+ </Button>
489
+ </ButtonRow>
490
+ ),
491
+ },
411
492
  {
412
493
  id: 'lien-fleche',
413
494
  nom: 'Lien fléché',
@@ -560,6 +641,54 @@ export const CATALOGUE: GroupeCatalogue[] = [
560
641
  </div>
561
642
  ),
562
643
  },
644
+ {
645
+ id: 'affixe',
646
+ nom: 'Champ à affixe',
647
+ resume:
648
+ '« 30 », seul dans un champ, ne dit pas s’il s’agit de jours ou d’euros. Le champ intérieur est un <Input nu> : c’est le CADRE qui fait le champ. Les identifiants d’affixe (idAvant/idApres) se citent en aria-describedby sur le champ, sinon l’unité reste muette au lecteur d’écran. À ne pas employer quand l’unité est déjà dans l’intitulé.',
649
+ code: `<Field label="HONORAIRES" htmlFor="hono">
650
+ <InputAffix avant="€" apres="HT" idAvant="hono-avant" idApres="hono-apres">
651
+ <Input nu id="hono" type="number" defaultValue={1200}
652
+ aria-describedby="hono-avant hono-apres" />
653
+ </InputAffix>
654
+ </Field>`,
655
+ rendu: (
656
+ <div style={{ display: 'grid', gap: 16, maxWidth: 320 }}>
657
+ <Field label="DÉLAI DE RÉPONSE" htmlFor="ex-delai">
658
+ <InputAffix apres="JOURS" idApres="ex-delai-apres">
659
+ <Input
660
+ nu
661
+ id="ex-delai"
662
+ type="number"
663
+ defaultValue={30}
664
+ aria-describedby="ex-delai-apres"
665
+ />
666
+ </InputAffix>
667
+ </Field>
668
+ <Field label="HONORAIRES" htmlFor="ex-hono">
669
+ <InputAffix avant="€" apres="HT" idAvant="ex-hono-avant" idApres="ex-hono-apres">
670
+ <Input
671
+ nu
672
+ id="ex-hono"
673
+ type="number"
674
+ defaultValue={1200}
675
+ aria-describedby="ex-hono-avant ex-hono-apres"
676
+ />
677
+ </InputAffix>
678
+ </Field>
679
+ </div>
680
+ ),
681
+ },
682
+ {
683
+ id: 'curseur',
684
+ nom: 'Curseur',
685
+ resume:
686
+ 'Natif habillé : clavier, bornes et annonce viennent du navigateur ; le remplissage suit la valeur en contrôlé. Toujours un intitulé ET la valeur affichée en clair — un curseur seul ne dit ni ce qu’il règle, ni sur combien. Pas de spectre sur la piste : ce n’est pas une barre de progression.',
687
+ code: `<Field label="SOURCES INTERROGÉES" htmlFor="prof" help={\`\${sources} sources sur 17\`}>
688
+ <Range id="prof" min={1} max={17} value={sources} onChange={…} />
689
+ </Field>`,
690
+ rendu: <DemoRange />,
691
+ },
563
692
  {
564
693
  id: 'puces',
565
694
  nom: 'Puces de filtre',
@@ -589,7 +718,7 @@ export const CATALOGUE: GroupeCatalogue[] = [
589
718
  couche: 'applicatif',
590
719
  css: 'feedback.css',
591
720
  resume:
592
- "Rien n'est interactif ici. ⚠️ Ni roue, ni squelette, ni infobulle : le CSS n'en a aucun, parce que le relevé de production n'en contenait aucun. Le travail en cours se dit par « Loading », qui nomme ce qu'on attend.",
721
+ "Rien n'y crie : le bandeau porte le ton, la pastille l'état, la phrase le travail. La roue, le squelette et l'infobulle — longtemps refusés faute de relevé — sont arbitrés depuis le 25/08/2026 (DECISIONS.md), chacun avec son périmètre écrit ; « Loading », qui nomme ce qu'on attend, reste le motif d'attente par défaut.",
593
722
  exemples: [
594
723
  {
595
724
  id: 'alertes',
@@ -682,6 +811,56 @@ export const CATALOGUE: GroupeCatalogue[] = [
682
811
  </div>
683
812
  ),
684
813
  },
814
+ {
815
+ id: 'roue',
816
+ nom: 'Roue',
817
+ resume:
818
+ 'Attente COURTE et LOCALE : un bouton, une cellule, un panneau sans la place d’une phrase. Pour l’attente d’un écran, « Loading » reste le motif — la phrase dit sur quoi et sur combien. Sans label, la roue est décorative et masquée aux lecteurs d’écran.',
819
+ code: `<Spinner label="Vérification du dépôt…" />
820
+ <Spinner grand />`,
821
+ rendu: (
822
+ <div style={{ display: 'flex', gap: 16, alignItems: 'center' }}>
823
+ <Spinner label="Vérification du dépôt…" />
824
+ <Spinner grand />
825
+ </div>
826
+ ),
827
+ },
828
+ {
829
+ id: 'squelette',
830
+ nom: 'Squelette',
831
+ resume:
832
+ 'Il ANNONCE une structure connue — la carte, la ligne qui va venir ; pour un contenu de forme inconnue, c’est « Loading ». La géométrie vient de l’appelant : un squelette qui invente ses dimensions ne ressemble jamais au contenu. C’est la zone qui charge qui porte aria-busy, pas chaque os.',
833
+ code: `<div aria-busy="true">
834
+ <Skeleton texte largeur="60%" />
835
+ <Skeleton texte />
836
+ <Skeleton hauteur={96} />
837
+ </div>`,
838
+ rendu: (
839
+ <div aria-busy="true" style={{ display: 'grid', gap: 10, maxWidth: 380 }}>
840
+ <Skeleton texte largeur="60%" />
841
+ <Skeleton texte />
842
+ <Skeleton hauteur={96} />
843
+ </div>
844
+ ),
845
+ },
846
+ {
847
+ id: 'infobulle',
848
+ nom: 'Infobulle',
849
+ resume:
850
+ 'Un COMPLÉMENT dispensable — un raccourci, une date exacte, une unité : une commande n’a pas le droit d’y cacher son nom, et le tactile ne survole pas. Liage aria-describedby EXPLICITE (id), comme le htmlFor de Field — pas de useId, le rendu serveur reste possible. Apparition retardée de 300 ms, disparition immédiate, Échap la ferme.',
851
+ code: `<Tooltip id="th-date" contenu="Déposé le 12/08/2026 à 14 h 02">
852
+ <Button variante="fantome" compact aria-describedby="th-date">12 août</Button>
853
+ </Tooltip>`,
854
+ rendu: (
855
+ <div style={{ paddingTop: 44 }}>
856
+ <Tooltip id="ex-th-date" contenu="Déposé le 12/08/2026 à 14 h 02">
857
+ <Button variante="fantome" compact aria-describedby="ex-th-date">
858
+ 12 août
859
+ </Button>
860
+ </Tooltip>
861
+ </div>
862
+ ),
863
+ },
685
864
  ],
686
865
  },
687
866
 
@@ -1089,6 +1268,45 @@ export const CATALOGUE: GroupeCatalogue[] = [
1089
1268
  </div>
1090
1269
  ),
1091
1270
  },
1271
+ {
1272
+ id: 'depliant',
1273
+ nom: 'Rangée dépliante',
1274
+ resume:
1275
+ '<details> NATIF : clavier, annonce et état viennent du navigateur, aucun JavaScript. Le pliage APPLICATIF — options avancées, détail d’une ligne de journal ; la FAQ (contenu) reste celui de la vitrine. Plusieurs rangées se posent bord à bord, le filet mitoyen tombe seul.',
1276
+ code: `<Fold titre="Options avancées">…</Fold>
1277
+ <Fold titre="Journal d'indexation" ouvert>…</Fold>`,
1278
+ rendu: (
1279
+ <div style={{ maxWidth: 420 }}>
1280
+ <Fold titre="Options avancées">
1281
+ Périmètre, profondeur et sources exclues se règlent par dossier, jamais
1282
+ par requête.
1283
+ </Fold>
1284
+ <Fold titre="Journal d’indexation" ouvert>
1285
+ Reçu, OCR, indexation : chaque étape est datée, et l’échec d’une page
1286
+ n’interrompt pas les suivantes.
1287
+ </Fold>
1288
+ </div>
1289
+ ),
1290
+ },
1291
+ {
1292
+ id: 'code',
1293
+ nom: 'Code et raccourcis',
1294
+ resume:
1295
+ 'La chasse fixe RÉELLE (--font-code) : --font-mono est proportionnelle et n’aligne pas du code, tabular-nums n’aligne que les chiffres. Aucune coloration syntaxique — elle imposerait une palette que la charte n’a pas. « ⌘K » fait DEUX touches, donc deux Kbd.',
1296
+ code: `<Body>Lancer <Code>pnpm build</Code>, puis <Kbd>⌘</Kbd> <Kbd>K</Kbd>.</Body>
1297
+ <CodeBlock>claude mcp add --transport http zevra-design …</CodeBlock>`,
1298
+ rendu: (
1299
+ <div style={{ display: 'grid', gap: 12, maxWidth: 520 }}>
1300
+ <Body taille="dense">
1301
+ Lancer <Code>pnpm build</Code>, puis ouvrir la recherche avec <Kbd>⌘</Kbd>{' '}
1302
+ <Kbd>K</Kbd>.
1303
+ </Body>
1304
+ <CodeBlock>
1305
+ {'claude mcp add --transport http zevra-design \\\n https://mcp.design.zevra.tech/mcp --scope user'}
1306
+ </CodeBlock>
1307
+ </div>
1308
+ ),
1309
+ },
1092
1310
  ],
1093
1311
  },
1094
1312
 
@@ -1160,15 +1378,37 @@ export const CATALOGUE: GroupeCatalogue[] = [
1160
1378
  },
1161
1379
  {
1162
1380
  id: 'onglets',
1163
- nom: 'Onglets',
1381
+ nom: 'Onglets en puces',
1164
1382
  resume:
1165
- '⚠️ Il n’existe AUCUNE classe d’onglet dans le CSS : une rangée d’onglets EST une rangée de puces. Ce composant n’ajoute que l’ARIA, pas un style de plus. L’onglet souligné reste à arbitrer avec la DA.',
1383
+ 'La rangée de puces, grammaire d’état de Seg — le motif des FILTRES, qui restreignent une collection. Ce composant n’ajoute que l’ARIA. Pour les VUES d’un même objet, prendre la variante soulignée.',
1166
1384
  code: `<Tabs actif={actif} onChange={setActif} onglets={[
1167
1385
  { id: 'apercu', label: 'Aperçu' },
1168
1386
  { id: 'sources', label: 'Sources', compte: 12 },
1169
1387
  ]} />`,
1170
1388
  rendu: <DemoTabs />,
1171
1389
  },
1390
+ {
1391
+ id: 'onglets-soulignes',
1392
+ nom: 'Onglets soulignés',
1393
+ resume:
1394
+ 'L’arbitrage longtemps en attente, tranché le 25/08/2026 : trait actif de 2 px — l’épaisseur des filets dessinés du système — en accent, PAS en spectre (un quatrième emploi n’existe pas). Pour les VUES d’un même objet (Aperçu / Sources) ; pour filtrer, les puces.',
1395
+ code: `<Tabs variante="soulignes" actif={actif} onChange={setActif} onglets={[
1396
+ { id: 'apercu', label: 'Aperçu' },
1397
+ { id: 'sources', label: 'Sources', compte: 12 },
1398
+ ]} />`,
1399
+ rendu: <DemoTabsLine />,
1400
+ },
1401
+ {
1402
+ id: 'popover',
1403
+ nom: 'Popover',
1404
+ resume:
1405
+ 'Surface ancrée LIBRE — aide contextuelle, mini-formulaire de filtre — dans la même ancre que le menu (SelectAnchor). Ce n’est PAS une infobulle : le popover s’ouvre au CLIC et peut porter de l’interactif. Fermeture par clic extérieur et Échap : à l’appelant, comme pour le menu.',
1406
+ code: `<SelectAnchor>
1407
+ <Button variante="fantome" compact aria-expanded={ouvert} onClick={…}>Colonnes affichées</Button>
1408
+ {ouvert && <Popover>…</Popover>}
1409
+ </SelectAnchor>`,
1410
+ rendu: <DemoPopover />,
1411
+ },
1172
1412
  {
1173
1413
  id: 'pagination',
1174
1414
  nom: 'Pagination',
@@ -1297,7 +1537,7 @@ export const CATALOGUE: GroupeCatalogue[] = [
1297
1537
  couche: 'commun',
1298
1538
  css: 'icons.css',
1299
1539
  resume:
1300
- "34 icônes TRACÉES, jamais pleines : trait 2, bouts arrondis, grille de 24. Elles héritent de la couleur du texte — c'est ce qui leur permet de fonctionner sur papier comme sur la bande manifeste sans déclinaison. Le tracé est inliné : rien à résoudre côté bundler, rien à autoriser côté CSP.",
1540
+ "55 icônes TRACÉES, jamais pleines : trait 2, bouts arrondis, grille de 24. Elles héritent de la couleur du texte — c'est ce qui leur permet de fonctionner sur papier comme sur la bande manifeste sans déclinaison. Le tracé est inliné : rien à résoudre côté bundler, rien à autoriser côté CSP.",
1301
1541
  exemples: [
1302
1542
  {
1303
1543
  id: 'jeu',
@@ -1660,6 +1900,57 @@ export const CATALOGUE: GroupeCatalogue[] = [
1660
1900
  </div>
1661
1901
  ),
1662
1902
  },
1903
+ {
1904
+ id: 'bandeau',
1905
+ nom: 'Bandeau d’annonce',
1906
+ resume:
1907
+ 'La bande AU-DESSUS de la barre de navigation : annonce de version, information réglementaire. UN SEUL par page, et jamais pour du marketing permanent — un bandeau qui ne part pas devient un bourrelet de chrome. Le lien s’y souligne : sur un fond déjà indigo, la couleur seule ne le distingue plus.',
1908
+ code: `<Banner>
1909
+ La charte 0.8 est en ligne — angles vifs sur tout le système.{' '}
1910
+ <a href="/journal">Ce qui change</a>
1911
+ </Banner>`,
1912
+ rendu: (
1913
+ <Banner>
1914
+ La charte 0.8 est en ligne — angles vifs sur tout le système.{' '}
1915
+ <a href="#">Ce qui change</a>
1916
+ </Banner>
1917
+ ),
1918
+ },
1919
+ {
1920
+ id: 'carrousel',
1921
+ nom: 'Carrousel',
1922
+ resume:
1923
+ 'Défilement natif scroll-snap, AUCUN JavaScript : pas de flèches, pas de points ; le conteneur prend le focus, et son label est OBLIGATOIRE — une région qui défile sans nom est une énigme au lecteur d’écran. Un carrousel reste un aveu d’espace : la règle de variété lui préfère une grille tant que le contenu tient.',
1924
+ code: `<Carousel label="La suite Zevra">
1925
+ <CarouselItem style={{ width: 260 }}>
1926
+ <Card>…</Card>
1927
+ </CarouselItem>
1928
+ …
1929
+ </Carousel>`,
1930
+ rendu: (
1931
+ <div style={{ maxWidth: 560 }}>
1932
+ <Carousel label="La suite Zevra">
1933
+ {(
1934
+ [
1935
+ ['Mémoire', 'Votre savoir, interrogeable en une phrase.'],
1936
+ ['Lexform', 'Vos actes, anonymisés à la volée.'],
1937
+ ['Campus', 'La profession qui se rééquipe se forme.'],
1938
+ ['MCP juridique', 'Vos sources, branchées sur vos agents.'],
1939
+ ] as const
1940
+ ).map(([nom, phrase]) => (
1941
+ <CarouselItem key={nom} style={{ width: 240 }}>
1942
+ <Card>
1943
+ <div style={{ display: 'grid', gap: 8 }}>
1944
+ <CardTitle>{nom}</CardTitle>
1945
+ <Body taille="dense">{phrase}</Body>
1946
+ </div>
1947
+ </Card>
1948
+ </CarouselItem>
1949
+ ))}
1950
+ </Carousel>
1951
+ </div>
1952
+ ),
1953
+ },
1663
1954
  ],
1664
1955
  },
1665
1956
 
@@ -1774,6 +2065,41 @@ export const CATALOGUE: GroupeCatalogue[] = [
1774
2065
  </div>
1775
2066
  ),
1776
2067
  },
2068
+ {
2069
+ id: 'format-social',
2070
+ nom: 'Formats sociaux',
2071
+ resume:
2072
+ 'Planches d’EXPORT — paysage 1200×630 (OpenGraph, lien LinkedIn), carré 1080 (post), story 1080×1920 — FIGÉES en pixels : on les capture, on ne les publie pas en HTML, et elles ignorent le point de rupture. Un visuel social EST une publication : jamais de faux chiffre ni de fausse citation. Rendue ici à l’échelle 0,35.',
2073
+ code: `<SocialFrame manifeste pied={<><Mono ton="on-dark">ZEVRA</Mono><Mono ton="on-dark">zevra.tech</Mono></>}>
2074
+ <Kicker surSombre><Mono ton="on-dark">Manifeste · Article 1ᵉʳ</Mono></Kicker>
2075
+ <Heading taille="h2" as="p">
2076
+ Émanciper les avocats et les juristes des outils qu'on leur <Em surSombre>impose</Em>.
2077
+ </Heading>
2078
+ </SocialFrame>`,
2079
+ rendu: (
2080
+ <div style={{ width: 421, height: 221, overflow: 'hidden' }}>
2081
+ <div style={{ transform: 'scale(0.35)', transformOrigin: 'top left' }}>
2082
+ <SocialFrame
2083
+ manifeste
2084
+ pied={
2085
+ <>
2086
+ <Mono ton="on-dark">ZEVRA</Mono>
2087
+ <Mono ton="on-dark">zevra.tech</Mono>
2088
+ </>
2089
+ }
2090
+ >
2091
+ <Kicker surSombre>
2092
+ <Mono ton="on-dark">Manifeste · Article 1ᵉʳ</Mono>
2093
+ </Kicker>
2094
+ <Heading taille="h2" as="p">
2095
+ Émanciper les avocats et les juristes des outils qu’on leur{' '}
2096
+ <Em surSombre>impose</Em>.
2097
+ </Heading>
2098
+ </SocialFrame>
2099
+ </div>
2100
+ </div>
2101
+ ),
2102
+ },
1777
2103
  ],
1778
2104
  },
1779
2105
  ]