@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.
- package/DECISIONS.md +227 -0
- package/dist/actions.d.ts +13 -3
- package/dist/actions.d.ts.map +1 -1
- package/dist/actions.js +9 -2
- package/dist/actions.js.map +1 -1
- package/dist/catalogue.d.ts.map +1 -1
- package/dist/catalogue.js +160 -11
- package/dist/catalogue.js.map +1 -1
- package/dist/css-inline.d.ts.map +1 -1
- package/dist/css-inline.js +1 -1
- package/dist/css-inline.js.map +1 -1
- package/dist/data.d.ts +34 -1
- package/dist/data.d.ts.map +1 -1
- package/dist/data.js +27 -0
- package/dist/data.js.map +1 -1
- package/dist/feedback.d.ts +49 -0
- package/dist/feedback.d.ts.map +1 -1
- package/dist/feedback.js +24 -0
- package/dist/feedback.js.map +1 -1
- package/dist/forms.d.ts +36 -0
- package/dist/forms.d.ts.map +1 -1
- package/dist/forms.js +24 -0
- package/dist/forms.js.map +1 -1
- package/dist/icon-data.d.ts +1 -1
- package/dist/icon-data.d.ts.map +1 -1
- package/dist/icon-data.js +42 -0
- package/dist/icon-data.js.map +1 -1
- package/dist/icon.d.ts +1 -1
- package/dist/icon.js +1 -1
- package/dist/layout.d.ts +21 -0
- package/dist/layout.d.ts.map +1 -1
- package/dist/layout.js +18 -0
- package/dist/layout.js.map +1 -1
- package/dist/navigation.d.ts +45 -7
- package/dist/navigation.d.ts.map +1 -1
- package/dist/navigation.js +54 -7
- package/dist/navigation.js.map +1 -1
- package/dist/surfaces.d.ts +18 -0
- package/dist/surfaces.d.ts.map +1 -1
- package/dist/surfaces.js +6 -0
- package/dist/surfaces.js.map +1 -1
- package/icons/index.json +126 -0
- package/icons/sprite.svg +21 -0
- package/package.json +4 -3
- package/react/actions.tsx +28 -2
- package/react/catalogue.tsx +343 -17
- package/react/css-inline.ts +1 -1
- package/react/data.tsx +87 -1
- package/react/feedback.tsx +98 -0
- package/react/forms.tsx +90 -0
- package/react/icon-data.ts +63 -0
- package/react/icon.tsx +2 -2
- package/react/layout.tsx +39 -0
- package/react/navigation.tsx +108 -6
- package/react/surfaces.tsx +45 -0
- package/src/base.css +16 -0
- package/src/components.css +135 -3
- package/src/data.css +143 -1
- package/src/feedback.css +196 -37
- package/src/forms.css +137 -1
- package/src/layout.css +72 -0
- package/src/navigation.css +207 -12
- package/src/surfaces.css +76 -7
- package/src/tokens.css +6 -0
- package/tokens/index.js +2 -0
package/DECISIONS.md
CHANGED
|
@@ -279,3 +279,230 @@ prototype `experience.html` compose toutes ses scènes produit en `span 5`
|
|
|
279
279
|
(glyphe) + `span 7` (discours), et c'est cette répartition qui équilibre
|
|
280
280
|
l'air entre le visuel et le texte. `zv-col-5` et `zv-col-7` complètent donc
|
|
281
281
|
le relevé ; en 4+8, le texte nage et le glyphe s'exile au bord.
|
|
282
|
+
|
|
283
|
+
---
|
|
284
|
+
|
|
285
|
+
## L'angle vif (25/08/2026)
|
|
286
|
+
|
|
287
|
+
« Très carré, ça fait pro et inspire confiance » — arbitrage DA rendu sur
|
|
288
|
+
pièces. Les quatre tokens de rayon (`--r-btn`, `--r-pill`, `--r-panel`,
|
|
289
|
+
`--r-card`) sont ramenés à `0` et RESTENT nommés : rendre de la rondeur à
|
|
290
|
+
l'une des quatre intentions doit rester une ligne à changer, pas une chasse
|
|
291
|
+
dans douze fichiers. Seul survit le rond de FORME — pastille d'état, radio,
|
|
292
|
+
halo, bouton d'interrupteur exclu (passé au carré), roue incluse — parce
|
|
293
|
+
qu'il porte du sens là où le rayon ne portait que du style.
|
|
294
|
+
|
|
295
|
+
Cet arbitrage SUCCÈDE au « rayon des cartes — clos » ci-dessus : la
|
|
296
|
+
question tranchée là était la fidélité au relevé (16px contre 14 et 12),
|
|
297
|
+
celle-ci est une décision de DA qui lui passe devant.
|
|
298
|
+
|
|
299
|
+
---
|
|
300
|
+
|
|
301
|
+
## Compléments du 25/08/2026 (0.9.0) — les manques comblés, hors relevé
|
|
302
|
+
|
|
303
|
+
La demande : compléter le système au niveau d'une bibliothèque de référence
|
|
304
|
+
(états d'interaction, contrôles absents, formats), en restant dans la charte.
|
|
305
|
+
Tout ce qui suit est **HORS RELEVÉ** — dessiné dans les tokens existants,
|
|
306
|
+
chaque écart dit — et se rejuge sur pièces avec la DA. Un seul token entre
|
|
307
|
+
(`--font-code`, voir « Bloc de code ») ; aucune couleur nouvelle.
|
|
308
|
+
|
|
309
|
+
### Les états de survol et d'appui des boutons
|
|
310
|
+
|
|
311
|
+
Aucune maquette ne donne d'état `:hover` ni `:active` aux trois boutons —
|
|
312
|
+
elles sont figées. Un bouton sans réaction se lit comme un décor (l'argument
|
|
313
|
+
qui a déjà tranché pour `.zv-chrome-btn`). Arbitrages :
|
|
314
|
+
|
|
315
|
+
- **le survol assombrit, l'appui assombrit davantage et rassoit** : les
|
|
316
|
+
teintes sont dérivées par `color-mix` (l'idiome que le voile emploie
|
|
317
|
+
déjà) des couleurs que le bouton porte déjà — le sommet de dégradé relevé
|
|
318
|
+
(`--zv-btn-haut`, #2b2bb4, sans token) et `--accent-deep`. Aucune teinte
|
|
319
|
+
nouvelle n'entre ;
|
|
320
|
+
- à l'appui, l'ombre TOMBE et le liseré s'éteint : le bouton se rassoit sur
|
|
321
|
+
la page au lieu de flotter — aucun déplacement, c'est la lumière qui dit
|
|
322
|
+
l'enfoncement ;
|
|
323
|
+
- le fantôme prend le filet `--accent` et l'appui pose `--accent-soft` en
|
|
324
|
+
fond ; l'encre s'éclaircit d'un cran (un aplat sombre ne peut pas
|
|
325
|
+
s'assombrir visiblement) ;
|
|
326
|
+
- une seule transition, la courbe maison, 160 ms — coupée par
|
|
327
|
+
`prefers-reduced-motion` (base.css) ;
|
|
328
|
+
- **aucun déplacement** : pas de translateY. Les entrées du système montent
|
|
329
|
+
au défilement ; un bouton qui saute au survol raconterait autre chose.
|
|
330
|
+
|
|
331
|
+
### Le bouton destructif
|
|
332
|
+
|
|
333
|
+
La modale destructive porte son filet `--err`, mais son action de
|
|
334
|
+
confirmation restait un plein indigo : « Supprimer » s'y lisait comme
|
|
335
|
+
n'importe quelle action. `zv-btn--danger` pose l'aplat `--err`, sans
|
|
336
|
+
dégradé ni ombre indigo. **Il compte comme LE bouton plein de l'écran** — la
|
|
337
|
+
règle « un seul plein par page » ne distingue pas les couleurs, elle compte
|
|
338
|
+
les aplats.
|
|
339
|
+
|
|
340
|
+
### L'attente d'un bouton
|
|
341
|
+
|
|
342
|
+
Relevé de Mémoire, cette fois (le motif de balisage documenté dans
|
|
343
|
+
feedback.css) : pendant l'action, le libellé change (« Connexion… ») et le
|
|
344
|
+
bouton passe en `cursor-wait; opacity: .7` — valeurs reprises telles
|
|
345
|
+
quelles. Le paquet le code sur `[aria-busy="true"]` — l'attribut qui rend
|
|
346
|
+
l'attente audible ne coûte alors rien — et la façade React l'expose en prop
|
|
347
|
+
`occupe`, qui pose `aria-disabled` et AVALE le clic plutôt que de poser
|
|
348
|
+
`disabled` : un `disabled` sortirait le bouton du parcours clavier au
|
|
349
|
+
moment précis où l'attente doit s'annoncer. Mémoire, elle, désactive ; cet
|
|
350
|
+
écart-là est assumé.
|
|
351
|
+
|
|
352
|
+
### L'onglet souligné — l'arbitrage attendu
|
|
353
|
+
|
|
354
|
+
La question ouverte depuis le relevé Mémoire est tranchée ainsi :
|
|
355
|
+
|
|
356
|
+
- **trait actif : 2 px, `--accent`**. 2 px est l'épaisseur des filets
|
|
357
|
+
dessinés du système (filet de spectre, rail d'étapes) ; l'accent est la
|
|
358
|
+
couleur de l'action, comme l'entrée de nav courante. PAS le spectre : un
|
|
359
|
+
quatrième emploi n'existe pas.
|
|
360
|
+
- l'onglet inactif est `--ink-2` graisse 500, l'actif `--accent` graisse
|
|
361
|
+
600 — la grammaire exacte de `.zv-seg` ;
|
|
362
|
+
- la rangée porte un filet bas `--line` d'un pixel que le trait actif
|
|
363
|
+
recouvre : l'onglet se lit comme posé SUR une ligne, pas souligné en l'air.
|
|
364
|
+
|
|
365
|
+
`.zv-tabs-line` vit dans navigation.css, à l'emplacement que la note « ce
|
|
366
|
+
module ne livre rien ici » réservait. La rangée de puces (`Tabs` en variante
|
|
367
|
+
par défaut) reste le motif des filtres ; l'onglet souligné est celui des
|
|
368
|
+
VUES d'un même objet (Aperçu / Sources).
|
|
369
|
+
|
|
370
|
+
### Roue, squelette, infobulle — les trois manques assumés, livrés
|
|
371
|
+
|
|
372
|
+
feedback.css les refusait faute de matière première, et posait les
|
|
373
|
+
contraintes à respecter « le jour où la DA les tranche ». Ce jour : les
|
|
374
|
+
contraintes sont reprises telles quelles, les valeurs restantes sont
|
|
375
|
+
arbitrées ici.
|
|
376
|
+
|
|
377
|
+
- **La roue** (`zv-spinner`) : anneau de 16 px — la taille de `.zv-icon` —
|
|
378
|
+
trait de 2 (l'épaisseur du jeu d'icônes), piste `--accent-line`, secteur
|
|
379
|
+
`--accent`, rotation 0,8 s linéaire. La variante `--lg` fait 24 px, la
|
|
380
|
+
grille du jeu d'icônes. Elle ne REMPLACE pas `.zv-loading` : la phrase
|
|
381
|
+
qui dit le travail reste le motif par défaut, la roue est pour l'attente
|
|
382
|
+
courte et locale (un bouton, une cellule). `prefers-reduced-motion` la
|
|
383
|
+
fige — l'anneau interrompu reste lisible immobile. Son libellé d'annonce
|
|
384
|
+
est un texte masqué (`.zv-sr-only`, base.css), pas un `aria-label` sur un
|
|
385
|
+
span vide, que tous les lecteurs n'annoncent pas.
|
|
386
|
+
- **Le squelette** (`zv-skeleton`) : `--hairline`, comme exigé — pas de
|
|
387
|
+
balayage spectral. Pulsation d'OPACITÉ (1 → 0,55, 1,8 s) : animer la
|
|
388
|
+
couleur ferait un dégradé de gris que la charte n'a pas. La géométrie
|
|
389
|
+
vient du consommateur (largeur/hauteur en style) ; seule la variante
|
|
390
|
+
`--text` fixe une hauteur d'un cadratin de texte courant.
|
|
391
|
+
- **L'infobulle** (`zv-tooltip`) : la combinaison imposée — panneau blanc,
|
|
392
|
+
filet `--line`, ombre `--shadow-menu`, texte `--app-sm`/`--ink-2` —
|
|
393
|
+
posée AU-DESSUS de la cible, centrée, à 6 px (le pointeur vient d'en bas
|
|
394
|
+
et la masquerait dessous ; `--bas` existe pour le rare cas inverse),
|
|
395
|
+
plafonnée à 240 px et, sous le seuil, à l'écran. L'apparition attend
|
|
396
|
+
300 ms — sans quoi traverser une rangée d'icônes fait clignoter une bulle
|
|
397
|
+
par icône — la disparition est immédiate. Trois exigences de WCAG 1.4.13
|
|
398
|
+
sont tenues : elle reste tant que le pointeur ou le focus y sont, elle
|
|
399
|
+
est survolable (le masquage par `visibility` évite les zones fantômes),
|
|
400
|
+
et Échap la ferme — la seule ligne de script du composant, posée sans
|
|
401
|
+
état. L'annonce passe par `aria-describedby`, câblée en identifiants
|
|
402
|
+
EXPLICITES comme le couple `htmlFor`/`id` de `Field` — pas de `useId`,
|
|
403
|
+
qui interdirait le rendu en composant serveur. Réservée à un COMPLÉMENT
|
|
404
|
+
dispensable : une commande n'a pas le droit de cacher son nom dans une
|
|
405
|
+
infobulle.
|
|
406
|
+
|
|
407
|
+
### Le curseur (`zv-range`)
|
|
408
|
+
|
|
409
|
+
Aucune source. Dérivé de l'interrupteur redessiné : bouton CARRÉ de 14 px
|
|
410
|
+
(la taille exacte du bouton du switch), `--accent`, qui passe
|
|
411
|
+
`--accent-deep` au survol ; piste de 3 px (la hauteur de `.zv-progress`),
|
|
412
|
+
`--line`, remplie en `--accent` jusqu'au curseur. **Pas le spectre** : la
|
|
413
|
+
barre de progression est un des trois emplois, le curseur n'en est pas un.
|
|
414
|
+
Le remplissage se calcule dans la façade (pourcentage de position — une
|
|
415
|
+
géométrie, comme la largeur de `Progress`, pas une valeur de charte).
|
|
416
|
+
|
|
417
|
+
### L'affixe de champ (`zv-affix`)
|
|
418
|
+
|
|
419
|
+
« 30 », seul dans un champ, ne dit pas s'il s'agit de jours ou d'euros. La
|
|
420
|
+
grammaire est celle de `.zv-search`, le seul cadre-à-champ-nu du relevé :
|
|
421
|
+
cadre `--line`, champ nu dedans, allumage `:focus-within` identique.
|
|
422
|
+
L'affixe est en mono `--label` — une unité est un libellé, pas une donnée.
|
|
423
|
+
|
|
424
|
+
### Le dépliant (`zv-fold`)
|
|
425
|
+
|
|
426
|
+
La FAQ est le pliage de la vitrine ; l'applicatif n'en avait aucun (options
|
|
427
|
+
avancées, détail d'une ligne de journal). Construit sur `<details>` natif :
|
|
428
|
+
clavier et annonce viennent du navigateur, aucun JavaScript. Rangé dans
|
|
429
|
+
data.css — c'est du contenu qui se déplie, pas de la navigation. Le chevron
|
|
430
|
+
tourne, seule rotation du module, coupée par `prefers-reduced-motion`.
|
|
431
|
+
|
|
432
|
+
### La touche (`zv-kbd`) et le bloc de code (`zv-codeblock`)
|
|
433
|
+
|
|
434
|
+
Une documentation d'interface cite des raccourcis et des commandes ; le
|
|
435
|
+
paquet n'avait ni l'un ni l'autre.
|
|
436
|
+
|
|
437
|
+
- La touche : `--panel`, filet `--line` avec un bas de 2 px qui fait le
|
|
438
|
+
relief de la touche — géométrie, pas ombre.
|
|
439
|
+
- **Le bloc de code introduit le seul token nouveau, `--font-code`**
|
|
440
|
+
(`ui-monospace / SF Mono / Menlo`). La raison est déjà écrite deux fois
|
|
441
|
+
dans le paquet : `--font-mono` (Space Grotesk) n'est PAS à chasse fixe, et
|
|
442
|
+
`tabular-nums` n'aligne que les chiffres — du code exige la chasse fixe
|
|
443
|
+
entière. Détourner `--font-mono` aurait menti ; un hexadécimal de pile de
|
|
444
|
+
polices en dur dans data.css aurait été la première valeur de charte hors
|
|
445
|
+
tokens. Le token est reflété dans le miroir JS, comme les autres.
|
|
446
|
+
|
|
447
|
+
### Le popover (`zv-popover`)
|
|
448
|
+
|
|
449
|
+
Le menu déroulant impose ses items ; il n'existait aucune surface ancrée
|
|
450
|
+
LIBRE (aide contextuelle, mini-formulaire de filtre). Même ancre
|
|
451
|
+
(`.zv-select-anchor`), même surface que `.zv-menu` (filet `--line`, ombre
|
|
452
|
+
`--shadow-menu`), padding de panneau au lieu d'items. Fermeture par clic
|
|
453
|
+
extérieur et Échap : au composant, comme pour le menu.
|
|
454
|
+
|
|
455
|
+
### Le carrousel (`zv-carousel`)
|
|
456
|
+
|
|
457
|
+
La bande de logos de la landing défile déjà — sans composant, chaque page
|
|
458
|
+
réinvente le sien. Défilement natif `scroll-snap`, AUCUN JavaScript : pas de
|
|
459
|
+
flèches (elles exigeraient un script et un arbitrage de dessin), pas de
|
|
460
|
+
points. La barre de défilement est masquée, le clavier passe par le focus du
|
|
461
|
+
conteneur. Un carrousel reste un aveu d'espace : la règle de variété lui
|
|
462
|
+
préfère une grille tant que le contenu tient.
|
|
463
|
+
|
|
464
|
+
### Le bandeau d'annonce (`zv-banner`)
|
|
465
|
+
|
|
466
|
+
La bande au-dessus de la barre de navigation (annonce de version,
|
|
467
|
+
information réglementaire). `--accent-soft` sur filet `--accent-line` — le
|
|
468
|
+
ton information de l'alerte, en pleine largeur. Un seul par page, et
|
|
469
|
+
JAMAIS pour du marketing permanent : un bandeau qui ne part pas devient un
|
|
470
|
+
bourrelet de chrome.
|
|
471
|
+
|
|
472
|
+
### La barre d'onglets mobile (`zv-tabbar`)
|
|
473
|
+
|
|
474
|
+
Mémoire navigue au tiroir ; une application à trois ou quatre sections
|
|
475
|
+
navigue plus vite par une barre basse. N'existe que SOUS le point de
|
|
476
|
+
rupture (au-dessus, la colonne latérale est là), cibles `--tap`, icône +
|
|
477
|
+
micro-label, état courant `--accent` sur `aria-current="page"`. Cinq
|
|
478
|
+
entrées au maximum — au-delà, c'est le tiroir.
|
|
479
|
+
|
|
480
|
+
### Les formats sociaux (`zv-social`)
|
|
481
|
+
|
|
482
|
+
Les visuels LinkedIn/OpenGraph se refaisaient à la main, hors charte. Trois
|
|
483
|
+
gabarits FIGÉS en pixels — paysage 1200×630 (OpenGraph et lien LinkedIn),
|
|
484
|
+
carré 1080×1080 (post), story 1080×1920 — qui ne répondent à aucun point de
|
|
485
|
+
rupture : ce sont des planches d'export, pas des pages. Ils composent les
|
|
486
|
+
pièces existantes (bande manifeste, kicker, halo) et portent un pied
|
|
487
|
+
wordmark + adresse. La règle « jamais de faux contenu » s'y applique au
|
|
488
|
+
premier chef : un visuel social EST une publication.
|
|
489
|
+
|
|
490
|
+
### Vingt et une icônes de plus
|
|
491
|
+
|
|
492
|
+
Le jeu passe de 34 à 55. Les règles du jeu ne bougent pas : trait 2, bouts
|
|
493
|
+
et jonctions arrondis, grille 24, `currentColor`. Les ajouts comblent les
|
|
494
|
+
trous les plus fréquents — `chevron-haut` manquait au chevron près, et le
|
|
495
|
+
catalogue citait `telecharger` en exemple sans qu'elle existe — plus le
|
|
496
|
+
vocabulaire du métier : balance, livre-ouvert, diplome. Aucune icône
|
|
497
|
+
pleine, aucune couleur.
|
|
498
|
+
|
|
499
|
+
### Écarté, et pourquoi
|
|
500
|
+
|
|
501
|
+
- **Le code de vérification (OTP)** : aucun écran du groupe n'en pose. Le
|
|
502
|
+
livrer supposerait d'inventer la gestion de focus inter-cases sans aucune
|
|
503
|
+
source — le jour où un écran d'authentification à code existe, c'est lui
|
|
504
|
+
qui tranche.
|
|
505
|
+
- **Le sélecteur de date** : le natif (`.zv-input` sur `type="date"`) reste
|
|
506
|
+
le motif ; un calendrier maison est un projet, pas un complément.
|
|
507
|
+
- **La barre de commande (⌘K)** : composable avec Modal + Search + Menu ;
|
|
508
|
+
un composant dédié attendra un usage réel.
|
package/dist/actions.d.ts
CHANGED
|
@@ -1,19 +1,29 @@
|
|
|
1
1
|
import type { AnchorHTMLAttributes, ButtonHTMLAttributes, HTMLAttributes, ReactNode } from 'react';
|
|
2
|
-
/** Variantes de bouton. Une seule pleine par écran — c'est la règle de
|
|
3
|
-
|
|
2
|
+
/** Variantes de bouton. Une seule pleine par écran — c'est la règle de
|
|
3
|
+
* charte, et « danger » COMPTE comme la pleine : la règle compte les
|
|
4
|
+
* aplats, pas les couleurs. « danger » est réservée à l'action destructive
|
|
5
|
+
* (la confirmation d'une modale de suppression), jamais à une action
|
|
6
|
+
* simplement importante. */
|
|
7
|
+
export type BoutonVariante = 'plein' | 'fantome' | 'encre' | 'danger';
|
|
4
8
|
export interface ButtonProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'className'> {
|
|
5
9
|
variante?: BoutonVariante;
|
|
6
10
|
/** Hauteur réduite, pour une barre de navigation. */
|
|
7
11
|
compact?: boolean;
|
|
8
12
|
/** Pleine largeur — l'appel à l'action d'un écran mobile. */
|
|
9
13
|
bloc?: boolean;
|
|
14
|
+
/** Attente pendant l'action : pose aria-busy et aria-disabled, et AVALE
|
|
15
|
+
* le clic — sans poser `disabled`, qui sortirait le bouton du parcours
|
|
16
|
+
* clavier au moment précis où l'attente doit s'annoncer.
|
|
17
|
+
* ⚠️ Le LIBELLÉ doit changer avec elle (« Connexion… ») — c'est le motif
|
|
18
|
+
* relevé de Mémoire : l'estompement seul ne dit pas ce qu'on attend. */
|
|
19
|
+
occupe?: boolean;
|
|
10
20
|
/** Échappatoire assumée. À employer pour un ajustement de position, jamais
|
|
11
21
|
* pour redéfinir une couleur ou une taille : c'est par là que les apps
|
|
12
22
|
* recommencent à écrire leur propre charte. */
|
|
13
23
|
className?: string;
|
|
14
24
|
children?: ReactNode;
|
|
15
25
|
}
|
|
16
|
-
export declare function Button({ variante, compact, bloc, className, type, ...reste }: ButtonProps): import("react").JSX.Element;
|
|
26
|
+
export declare function Button({ variante, compact, bloc, occupe, className, type, disabled, onClick, ...reste }: ButtonProps): import("react").JSX.Element;
|
|
17
27
|
export interface ButtonLinkProps extends Omit<AnchorHTMLAttributes<HTMLAnchorElement>, 'className'> {
|
|
18
28
|
variante?: BoutonVariante;
|
|
19
29
|
compact?: boolean;
|
package/dist/actions.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../react/actions.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EACV,oBAAoB,EACpB,oBAAoB,EACpB,cAAc,EACd,SAAS,EACV,MAAM,OAAO,CAAA;AAGd
|
|
1
|
+
{"version":3,"file":"actions.d.ts","sourceRoot":"","sources":["../react/actions.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EACV,oBAAoB,EACpB,oBAAoB,EACpB,cAAc,EACd,SAAS,EACV,MAAM,OAAO,CAAA;AAGd;;;;6BAI6B;AAC7B,MAAM,MAAM,cAAc,GAAG,OAAO,GAAG,SAAS,GAAG,OAAO,GAAG,QAAQ,CAAA;AASrE,MAAM,WAAW,WACf,SAAQ,IAAI,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,EAAE,WAAW,CAAC;IAClE,QAAQ,CAAC,EAAE,cAAc,CAAA;IACzB,qDAAqD;IACrD,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,6DAA6D;IAC7D,IAAI,CAAC,EAAE,OAAO,CAAA;IACd;;;;6EAIyE;IACzE,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB;;oDAEgD;IAChD,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,QAAQ,CAAC,EAAE,SAAS,CAAA;CACrB;AAED,wBAAgB,MAAM,CAAC,EACrB,QAAkB,EAClB,OAAO,EACP,IAAI,EACJ,MAAM,EACN,SAAS,EACT,IAAe,EACf,QAAQ,EACR,OAAO,EACP,GAAG,KAAK,EACT,EAAE,WAAW,+BAyBb;AAED,MAAM,WAAW,eACf,SAAQ,IAAI,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,EAAE,WAAW,CAAC;IAClE,QAAQ,CAAC,EAAE,cAAc,CAAA;IACzB,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED;oEACoE;AACpE,wBAAgB,UAAU,CAAC,EACzB,QAAkB,EAClB,OAAO,EACP,IAAI,EACJ,SAAS,EACT,GAAG,KAAK,EACT,EAAE,eAAe,+BAYjB;AAED,MAAM,WAAW,cACf,SAAQ,IAAI,CAAC,cAAc,CAAC,cAAc,CAAC,EAAE,WAAW,CAAC;IACzD,+DAA+D;IAC/D,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,wBAAgB,SAAS,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,EAAE,cAAc,+BAOxE;AAED,MAAM,WAAW,cACf,SAAQ,IAAI,CAAC,oBAAoB,CAAC,iBAAiB,CAAC,EAAE,WAAW,CAAC;IAClE,yDAAyD;IACzD,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,QAAQ,CAAC,EAAE,SAAS,CAAA;CACrB;AAED;yEACyE;AACzE,wBAAgB,SAAS,CAAC,EACxB,SAAS,EACT,SAAS,EACT,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,cAAc,+BAiBhB"}
|
package/dist/actions.js
CHANGED
|
@@ -4,9 +4,16 @@ const VARIANTE_BOUTON = {
|
|
|
4
4
|
plein: 'zv-btn',
|
|
5
5
|
fantome: 'zv-btn--ghost',
|
|
6
6
|
encre: 'zv-btn--ink',
|
|
7
|
+
danger: 'zv-btn--danger',
|
|
7
8
|
};
|
|
8
|
-
export function Button({ variante = 'plein', compact, bloc, className, type = 'button', ...reste }) {
|
|
9
|
-
return (_jsx("button", { type: type,
|
|
9
|
+
export function Button({ variante = 'plein', compact, bloc, occupe, className, type = 'button', disabled, onClick, ...reste }) {
|
|
10
|
+
return (_jsx("button", { type: type, "aria-busy": occupe || undefined, "aria-disabled": occupe || undefined, disabled: disabled, onClick: occupe
|
|
11
|
+
? (e) => {
|
|
12
|
+
// Le clic est avalé, pas interdit : un `disabled` sortirait le
|
|
13
|
+
// bouton du parcours clavier pendant l'annonce de l'attente.
|
|
14
|
+
e.preventDefault();
|
|
15
|
+
}
|
|
16
|
+
: onClick, className: cx(VARIANTE_BOUTON[variante], compact && 'zv-btn--sm', bloc && 'zv-btn--block', className), ...reste }));
|
|
10
17
|
}
|
|
11
18
|
/** Le même bouton, mais qui navigue. Un <a> et un <button> ne s'échangent pas :
|
|
12
19
|
* l'un ouvre dans un onglet, se copie et s'indexe, l'autre non. */
|
package/dist/actions.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"actions.js","sourceRoot":"","sources":["../react/actions.tsx"],"names":[],"mappings":";AAYA,OAAO,EAAE,EAAE,EAAE,MAAM,SAAS,CAAA;
|
|
1
|
+
{"version":3,"file":"actions.js","sourceRoot":"","sources":["../react/actions.tsx"],"names":[],"mappings":";AAYA,OAAO,EAAE,EAAE,EAAE,MAAM,SAAS,CAAA;AAS5B,MAAM,eAAe,GAAmC;IACtD,KAAK,EAAE,QAAQ;IACf,OAAO,EAAE,eAAe;IACxB,KAAK,EAAE,aAAa;IACpB,MAAM,EAAE,gBAAgB;CACzB,CAAA;AAsBD,MAAM,UAAU,MAAM,CAAC,EACrB,QAAQ,GAAG,OAAO,EAClB,OAAO,EACP,IAAI,EACJ,MAAM,EACN,SAAS,EACT,IAAI,GAAG,QAAQ,EACf,QAAQ,EACR,OAAO,EACP,GAAG,KAAK,EACI;IACZ,OAAO,CACL,iBACE,IAAI,EAAE,IAAI,eACC,MAAM,IAAI,SAAS,mBACf,MAAM,IAAI,SAAS,EAClC,QAAQ,EAAE,QAAQ,EAClB,OAAO,EACL,MAAM;YACJ,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE;gBACJ,+DAA+D;gBAC/D,6DAA6D;gBAC7D,CAAC,CAAC,cAAc,EAAE,CAAA;YACpB,CAAC;YACH,CAAC,CAAC,OAAO,EAEb,SAAS,EAAE,EAAE,CACX,eAAe,CAAC,QAAQ,CAAC,EACzB,OAAO,IAAI,YAAY,EACvB,IAAI,IAAI,eAAe,EACvB,SAAS,CACV,KACG,KAAK,GACT,CACH,CAAA;AACH,CAAC;AAUD;oEACoE;AACpE,MAAM,UAAU,UAAU,CAAC,EACzB,QAAQ,GAAG,OAAO,EAClB,OAAO,EACP,IAAI,EACJ,SAAS,EACT,GAAG,KAAK,EACQ;IAChB,OAAO,CACL,YACE,SAAS,EAAE,EAAE,CACX,eAAe,CAAC,QAAQ,CAAC,EACzB,OAAO,IAAI,YAAY,EACvB,IAAI,IAAI,eAAe,EACvB,SAAS,CACV,KACG,KAAK,GACT,CACH,CAAA;AACH,CAAC;AASD,MAAM,UAAU,SAAS,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,KAAK,EAAkB;IACvE,OAAO,CACL,cACE,SAAS,EAAE,EAAE,CAAC,YAAY,EAAE,MAAM,IAAI,mBAAmB,EAAE,SAAS,CAAC,KACjE,KAAK,GACT,CACH,CAAA;AACH,CAAC;AAUD;yEACyE;AACzE,MAAM,UAAU,SAAS,CAAC,EACxB,SAAS,EACT,SAAS,EACT,QAAQ,EACR,GAAG,KAAK,EACO;IACf,OAAO,CACL,aACE,SAAS,EAAE,EAAE,CACX,eAAe,EACf,SAAS,IAAI,wBAAwB,EACrC,SAAS,CACV,KACG,KAAK,aAER,QAAQ,EACT,eAAK,OAAO,EAAC,WAAW,iBAAa,MAAM,aACzC,eAAM,CAAC,EAAC,UAAU,GAAG,EACrB,eAAM,CAAC,EAAC,eAAe,GAAG,IACtB,IACJ,CACL,CAAA;AACH,CAAC"}
|
package/dist/catalogue.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"catalogue.d.ts","sourceRoot":"","sources":["../react/catalogue.tsx"],"names":[],"mappings":"AAgBA,OAAO,EAAY,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"catalogue.d.ts","sourceRoot":"","sources":["../react/catalogue.tsx"],"names":[],"mappings":"AAgBA,OAAO,EAAY,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAyChD,MAAM,WAAW,OAAO;IACtB,sEAAsE;IACtE,EAAE,EAAE,MAAM,CAAA;IACV,GAAG,EAAE,MAAM,CAAA;IACX,oEAAoE;IACpE,MAAM,EAAE,MAAM,CAAA;IACd,sDAAsD;IACtD,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,SAAS,CAAA;IAChB,0DAA0D;IAC1D,SAAS,CAAC,EAAE,OAAO,CAAA;CACpB;AAED,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAA;IACV,GAAG,EAAE,MAAM,CAAA;IACX,MAAM,EAAE,MAAM,CAAA;IACd;+BAC2B;IAC3B,MAAM,EAAE,QAAQ,GAAG,YAAY,GAAG,SAAS,CAAA;IAC3C,8CAA8C;IAC9C,GAAG,EAAE,MAAM,CAAA;IACX,QAAQ,EAAE,OAAO,EAAE,CAAA;CACpB;AA2OD,eAAO,MAAM,SAAS,EAAE,eAAe,EA6vDtC,CAAA;AAMD,yEAAyE;AACzE,eAAO,MAAM,QAAQ,EAAE,CAAC,OAAO,GAAG;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,EAEpD,CAAA"}
|
package/dist/catalogue.js
CHANGED
|
@@ -16,15 +16,15 @@ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-run
|
|
|
16
16
|
import { useState } from 'react';
|
|
17
17
|
import { Button, ButtonLink, ButtonRow, LinkArrow } from './actions.js';
|
|
18
18
|
import { Callout, Card, Check, Divider, Ent, EntText, Faq, FaqItem, Flow, FlowStep, Glass, IndexItem, IndexList, Inset, MiniStat, MiniStatItem, Pill, Price, Quote, Rows, RowsItem, Src, SrcRow, StatCard, Tag, UiPreview, } from './content.js';
|
|
19
|
-
import { Avatar, Break, Cell, Chip, ChipRow, Cite, CiteRow, FileType, KV, KVRow, List, ListMain, ListName, ListRow, Meta, MetaRow, Row, Table, TableHead, Trunc, Unwrap, } from './data.js';
|
|
20
|
-
import { Alert, Badge, Caret, Dot, Empty, Loading, Progress, Status, } from './feedback.js';
|
|
21
|
-
import { Checkbox, Drop, Field, Input, Radio, Search, Seg, SegGroup, Select, SelectAnchor, SelectTrigger, Switch, Textarea, } from './forms.js';
|
|
19
|
+
import { Avatar, Break, Cell, Chip, ChipRow, Cite, CiteRow, Code, CodeBlock, FileType, Fold, KV, KVRow, Kbd, List, ListMain, ListName, ListRow, Meta, MetaRow, Row, Table, TableHead, Trunc, Unwrap, } from './data.js';
|
|
20
|
+
import { Alert, Badge, Caret, Dot, Empty, Loading, Progress, Skeleton, Spinner, Status, Tooltip, } from './feedback.js';
|
|
21
|
+
import { Checkbox, Drop, Field, Input, InputAffix, Radio, Range, Search, Seg, SegGroup, Select, SelectAnchor, SelectTrigger, Switch, Textarea, } from './forms.js';
|
|
22
22
|
import { ICONES, Icon, IconButton, NOMS_ICONES } from './icon.js';
|
|
23
|
-
import { CTA, Col, Footer, FooterMini, Grid, Grid12, Gutter, Hero, Nav, NavLink, NavLinks, NavLogo, ProofBar, SectionHead, SectionRule, SheetSection, Stat, Stats, Step, Steps, } from './layout.js';
|
|
24
|
-
import { ChromeButton, CitePanel, Crumbs, Menu, MenuItem, Pager, PagerArrow, PagerRank, PagerStep, Scroll, SideGroup, SideLink, Sidebar, SidebarFoot, SidebarHead, Tabs, Topbar, TopbarTitle, } from './navigation.js';
|
|
23
|
+
import { Banner, CTA, Carousel, CarouselItem, Col, Footer, FooterMini, Grid, Grid12, Gutter, Hero, Nav, NavLink, NavLinks, NavLogo, ProofBar, SectionHead, SectionRule, SheetSection, Stat, Stats, Step, Steps, } from './layout.js';
|
|
24
|
+
import { ChromeButton, CitePanel, Crumbs, Menu, MenuItem, Pager, PagerArrow, PagerRank, PagerStep, Popover, Scroll, SideGroup, SideLink, Sidebar, SidebarFoot, SidebarHead, Tabs, Topbar, TopbarTitle, } from './navigation.js';
|
|
25
25
|
import { Drawer, Modal, Toast, Toasts } from './overlays.js';
|
|
26
26
|
import { SelectMenu } from './select-menu.js';
|
|
27
|
-
import { Band, Fade, Glyph, GridFloor, Halo, PanelNavy, TextOnDark, anim } from './surfaces.js';
|
|
27
|
+
import { Band, Fade, Glyph, GridFloor, Halo, PanelNavy, SocialFrame, TextOnDark, anim, } from './surfaces.js';
|
|
28
28
|
import { Body, CardTitle, Display, Em, H1, H2, H3, Heading, Kicker, Lead, Link, Mono, Note, Rule, Spec, Tagline, } from './typography.js';
|
|
29
29
|
/* ── Démonstrations qui ont besoin d'état ─────────────────────────── */
|
|
30
30
|
function DemoSwitch() {
|
|
@@ -81,6 +81,22 @@ function DemoDrop() {
|
|
|
81
81
|
setSurvol(false);
|
|
82
82
|
} }));
|
|
83
83
|
}
|
|
84
|
+
function DemoRange() {
|
|
85
|
+
const [sources, setSources] = useState(12);
|
|
86
|
+
return (_jsx("div", { style: { maxWidth: 320 }, children: _jsx(Field, { label: "SOURCES INTERROG\u00C9ES", htmlFor: "ex-range", help: `${sources} sources sur 17`, children: _jsx(Range, { id: "ex-range", min: 1, max: 17, value: sources, onChange: (e) => setSources(Number(e.currentTarget.value)) }) }) }));
|
|
87
|
+
}
|
|
88
|
+
function DemoTabsLine() {
|
|
89
|
+
const [actif, setActif] = useState('apercu');
|
|
90
|
+
return (_jsx(Tabs, { variante: "soulignes", actif: actif, onChange: setActif, onglets: [
|
|
91
|
+
{ id: 'apercu', label: 'Aperçu' },
|
|
92
|
+
{ id: 'sources', label: 'Sources', compte: 12 },
|
|
93
|
+
{ id: 'journal', label: 'Journal' },
|
|
94
|
+
] }));
|
|
95
|
+
}
|
|
96
|
+
function DemoPopover() {
|
|
97
|
+
const [ouvert, setOuvert] = useState(false);
|
|
98
|
+
return (_jsxs(SelectAnchor, { children: [_jsx(Button, { variante: "fantome", compact: true, "aria-expanded": ouvert, onClick: () => setOuvert(!ouvert), children: "Colonnes affich\u00E9es" }), ouvert && (_jsx(Popover, { children: _jsx("div", { style: { display: 'grid', gap: 8 }, children: ['Nom', 'Taille', 'Statut'].map((c) => (_jsxs("label", { style: { display: 'flex', gap: 8, alignItems: 'center' }, children: [_jsx(Checkbox, { defaultChecked: c !== 'Taille' }), _jsx("span", { className: "zv-body zv-body--dense", children: c })] }, c))) }) }))] }));
|
|
99
|
+
}
|
|
84
100
|
/* ── Le catalogue ─────────────────────────────────────────────────── */
|
|
85
101
|
export const CATALOGUE = [
|
|
86
102
|
{
|
|
@@ -152,7 +168,7 @@ export const CATALOGUE = [
|
|
|
152
168
|
nom: 'Actions',
|
|
153
169
|
couche: 'commun',
|
|
154
170
|
css: 'components.css',
|
|
155
|
-
resume: "
|
|
171
|
+
resume: "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.",
|
|
156
172
|
exemples: [
|
|
157
173
|
{
|
|
158
174
|
id: 'boutons',
|
|
@@ -174,6 +190,15 @@ export const CATALOGUE = [
|
|
|
174
190
|
<ButtonLink href="/tarifs" variante="fantome">Voir les tarifs</ButtonLink>`,
|
|
175
191
|
rendu: (_jsxs("div", { style: { display: 'grid', gap: 10, maxWidth: 280 }, children: [_jsxs(ButtonRow, { children: [_jsx(Button, { compact: true, children: "Enregistrer" }), _jsx(ButtonLink, { href: "#", variante: "fantome", compact: true, children: "Voir les tarifs" })] }), _jsx(Button, { bloc: true, children: "Se connecter" })] })),
|
|
176
192
|
},
|
|
193
|
+
{
|
|
194
|
+
id: 'etats',
|
|
195
|
+
nom: 'États',
|
|
196
|
+
resume: '« 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.',
|
|
197
|
+
code: `<Button variante="danger">Supprimer définitivement</Button>
|
|
198
|
+
<Button occupe>Connexion…</Button>
|
|
199
|
+
<Button variante="fantome" disabled>Envoyer</Button>`,
|
|
200
|
+
rendu: (_jsxs(ButtonRow, { children: [_jsx(Button, { variante: "danger", children: "Supprimer d\u00E9finitivement" }), _jsx(Button, { occupe: true, children: "Connexion\u2026" }), _jsx(Button, { variante: "fantome", disabled: true, children: "Envoyer" })] })),
|
|
201
|
+
},
|
|
177
202
|
{
|
|
178
203
|
id: 'lien-fleche',
|
|
179
204
|
nom: 'Lien fléché',
|
|
@@ -261,6 +286,27 @@ export const CATALOGUE = [
|
|
|
261
286
|
<Switch on={on} texte="ACTIVÉ" onClick={…} />`,
|
|
262
287
|
rendu: (_jsxs("div", { style: { display: 'flex', gap: 20, alignItems: 'center', flexWrap: 'wrap' }, children: [_jsxs("label", { style: { display: 'flex', gap: 8, alignItems: 'center' }, children: [_jsx(Checkbox, { defaultChecked: true }), " ", _jsx("span", { className: "zv-body zv-body--dense", children: "Anonymiser" })] }), _jsxs("label", { style: { display: 'flex', gap: 8, alignItems: 'center' }, children: [_jsx(Radio, { name: "ex-r", defaultChecked: true }), " ", _jsx("span", { className: "zv-body zv-body--dense", children: "Tout" })] }), _jsx(DemoSwitch, {})] })),
|
|
263
288
|
},
|
|
289
|
+
{
|
|
290
|
+
id: 'affixe',
|
|
291
|
+
nom: 'Champ à affixe',
|
|
292
|
+
resume: '« 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é.',
|
|
293
|
+
code: `<Field label="HONORAIRES" htmlFor="hono">
|
|
294
|
+
<InputAffix avant="€" apres="HT" idAvant="hono-avant" idApres="hono-apres">
|
|
295
|
+
<Input nu id="hono" type="number" defaultValue={1200}
|
|
296
|
+
aria-describedby="hono-avant hono-apres" />
|
|
297
|
+
</InputAffix>
|
|
298
|
+
</Field>`,
|
|
299
|
+
rendu: (_jsxs("div", { style: { display: 'grid', gap: 16, maxWidth: 320 }, children: [_jsx(Field, { label: "D\u00C9LAI DE R\u00C9PONSE", htmlFor: "ex-delai", children: _jsx(InputAffix, { apres: "JOURS", idApres: "ex-delai-apres", children: _jsx(Input, { nu: true, id: "ex-delai", type: "number", defaultValue: 30, "aria-describedby": "ex-delai-apres" }) }) }), _jsx(Field, { label: "HONORAIRES", htmlFor: "ex-hono", children: _jsx(InputAffix, { avant: "\u20AC", apres: "HT", idAvant: "ex-hono-avant", idApres: "ex-hono-apres", children: _jsx(Input, { nu: true, id: "ex-hono", type: "number", defaultValue: 1200, "aria-describedby": "ex-hono-avant ex-hono-apres" }) }) })] })),
|
|
300
|
+
},
|
|
301
|
+
{
|
|
302
|
+
id: 'curseur',
|
|
303
|
+
nom: 'Curseur',
|
|
304
|
+
resume: '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.',
|
|
305
|
+
code: `<Field label="SOURCES INTERROGÉES" htmlFor="prof" help={\`\${sources} sources sur 17\`}>
|
|
306
|
+
<Range id="prof" min={1} max={17} value={sources} onChange={…} />
|
|
307
|
+
</Field>`,
|
|
308
|
+
rendu: _jsx(DemoRange, {}),
|
|
309
|
+
},
|
|
264
310
|
{
|
|
265
311
|
id: 'puces',
|
|
266
312
|
nom: 'Puces de filtre',
|
|
@@ -286,7 +332,7 @@ export const CATALOGUE = [
|
|
|
286
332
|
nom: 'Retours',
|
|
287
333
|
couche: 'applicatif',
|
|
288
334
|
css: 'feedback.css',
|
|
289
|
-
resume: "Rien n'
|
|
335
|
+
resume: "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.",
|
|
290
336
|
exemples: [
|
|
291
337
|
{
|
|
292
338
|
id: 'alertes',
|
|
@@ -334,6 +380,34 @@ export const CATALOGUE = [
|
|
|
334
380
|
<span>…réponse en cours<Caret /></span>`,
|
|
335
381
|
rendu: (_jsxs("div", { style: { display: 'grid', gap: 12 }, children: [_jsx(Loading, { children: "Recherche dans 4 812 documents anonymis\u00E9s\u2026" }), _jsx(Progress, { valeur: 0.62, label: "Indexation" }), _jsxs("span", { className: "zv-body zv-body--dense", children: ["La clause de non-concurrence est limit\u00E9e \u00E0 vingt-quatre mois", _jsx(Caret, {})] })] })),
|
|
336
382
|
},
|
|
383
|
+
{
|
|
384
|
+
id: 'roue',
|
|
385
|
+
nom: 'Roue',
|
|
386
|
+
resume: '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.',
|
|
387
|
+
code: `<Spinner label="Vérification du dépôt…" />
|
|
388
|
+
<Spinner grand />`,
|
|
389
|
+
rendu: (_jsxs("div", { style: { display: 'flex', gap: 16, alignItems: 'center' }, children: [_jsx(Spinner, { label: "V\u00E9rification du d\u00E9p\u00F4t\u2026" }), _jsx(Spinner, { grand: true })] })),
|
|
390
|
+
},
|
|
391
|
+
{
|
|
392
|
+
id: 'squelette',
|
|
393
|
+
nom: 'Squelette',
|
|
394
|
+
resume: '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.',
|
|
395
|
+
code: `<div aria-busy="true">
|
|
396
|
+
<Skeleton texte largeur="60%" />
|
|
397
|
+
<Skeleton texte />
|
|
398
|
+
<Skeleton hauteur={96} />
|
|
399
|
+
</div>`,
|
|
400
|
+
rendu: (_jsxs("div", { "aria-busy": "true", style: { display: 'grid', gap: 10, maxWidth: 380 }, children: [_jsx(Skeleton, { texte: true, largeur: "60%" }), _jsx(Skeleton, { texte: true }), _jsx(Skeleton, { hauteur: 96 })] })),
|
|
401
|
+
},
|
|
402
|
+
{
|
|
403
|
+
id: 'infobulle',
|
|
404
|
+
nom: 'Infobulle',
|
|
405
|
+
resume: '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.',
|
|
406
|
+
code: `<Tooltip id="th-date" contenu="Déposé le 12/08/2026 à 14 h 02">
|
|
407
|
+
<Button variante="fantome" compact aria-describedby="th-date">12 août</Button>
|
|
408
|
+
</Tooltip>`,
|
|
409
|
+
rendu: (_jsx("div", { style: { paddingTop: 44 }, children: _jsx(Tooltip, { id: "ex-th-date", contenu: "D\u00E9pos\u00E9 le 12/08/2026 \u00E0 14 h 02", children: _jsx(Button, { variante: "fantome", compact: true, "aria-describedby": "ex-th-date", children: "12 ao\u00FBt" }) }) })),
|
|
410
|
+
},
|
|
337
411
|
],
|
|
338
412
|
},
|
|
339
413
|
{
|
|
@@ -521,6 +595,22 @@ export const CATALOGUE = [
|
|
|
521
595
|
code: `<FileType format="pdf" /> <FileType format="docx" />`,
|
|
522
596
|
rendu: (_jsxs("div", { style: { display: 'flex', gap: 8 }, children: [_jsx(FileType, { format: "pdf" }), _jsx(FileType, { format: "docx" })] })),
|
|
523
597
|
},
|
|
598
|
+
{
|
|
599
|
+
id: 'depliant',
|
|
600
|
+
nom: 'Rangée dépliante',
|
|
601
|
+
resume: '<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.',
|
|
602
|
+
code: `<Fold titre="Options avancées">…</Fold>
|
|
603
|
+
<Fold titre="Journal d'indexation" ouvert>…</Fold>`,
|
|
604
|
+
rendu: (_jsxs("div", { style: { maxWidth: 420 }, children: [_jsx(Fold, { titre: "Options avanc\u00E9es", children: "P\u00E9rim\u00E8tre, profondeur et sources exclues se r\u00E8glent par dossier, jamais par requ\u00EAte." }), _jsx(Fold, { titre: "Journal d\u2019indexation", ouvert: true, children: "Re\u00E7u, OCR, indexation : chaque \u00E9tape est dat\u00E9e, et l\u2019\u00E9chec d\u2019une page n\u2019interrompt pas les suivantes." })] })),
|
|
605
|
+
},
|
|
606
|
+
{
|
|
607
|
+
id: 'code',
|
|
608
|
+
nom: 'Code et raccourcis',
|
|
609
|
+
resume: '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.',
|
|
610
|
+
code: `<Body>Lancer <Code>pnpm build</Code>, puis <Kbd>⌘</Kbd> <Kbd>K</Kbd>.</Body>
|
|
611
|
+
<CodeBlock>claude mcp add --transport http zevra-design …</CodeBlock>`,
|
|
612
|
+
rendu: (_jsxs("div", { style: { display: 'grid', gap: 12, maxWidth: 520 }, children: [_jsxs(Body, { taille: "dense", children: ["Lancer ", _jsx(Code, { children: "pnpm build" }), ", puis ouvrir la recherche avec ", _jsx(Kbd, { children: "\u2318" }), ' ', _jsx(Kbd, { children: "K" }), "."] }), _jsx(CodeBlock, { children: 'claude mcp add --transport http zevra-design \\\n https://mcp.design.zevra.tech/mcp --scope user' })] })),
|
|
613
|
+
},
|
|
524
614
|
],
|
|
525
615
|
},
|
|
526
616
|
{
|
|
@@ -563,14 +653,34 @@ export const CATALOGUE = [
|
|
|
563
653
|
},
|
|
564
654
|
{
|
|
565
655
|
id: 'onglets',
|
|
566
|
-
nom: 'Onglets',
|
|
567
|
-
resume: '
|
|
656
|
+
nom: 'Onglets en puces',
|
|
657
|
+
resume: '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.',
|
|
568
658
|
code: `<Tabs actif={actif} onChange={setActif} onglets={[
|
|
569
659
|
{ id: 'apercu', label: 'Aperçu' },
|
|
570
660
|
{ id: 'sources', label: 'Sources', compte: 12 },
|
|
571
661
|
]} />`,
|
|
572
662
|
rendu: _jsx(DemoTabs, {}),
|
|
573
663
|
},
|
|
664
|
+
{
|
|
665
|
+
id: 'onglets-soulignes',
|
|
666
|
+
nom: 'Onglets soulignés',
|
|
667
|
+
resume: '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.',
|
|
668
|
+
code: `<Tabs variante="soulignes" actif={actif} onChange={setActif} onglets={[
|
|
669
|
+
{ id: 'apercu', label: 'Aperçu' },
|
|
670
|
+
{ id: 'sources', label: 'Sources', compte: 12 },
|
|
671
|
+
]} />`,
|
|
672
|
+
rendu: _jsx(DemoTabsLine, {}),
|
|
673
|
+
},
|
|
674
|
+
{
|
|
675
|
+
id: 'popover',
|
|
676
|
+
nom: 'Popover',
|
|
677
|
+
resume: '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.',
|
|
678
|
+
code: `<SelectAnchor>
|
|
679
|
+
<Button variante="fantome" compact aria-expanded={ouvert} onClick={…}>Colonnes affichées</Button>
|
|
680
|
+
{ouvert && <Popover>…</Popover>}
|
|
681
|
+
</SelectAnchor>`,
|
|
682
|
+
rendu: _jsx(DemoPopover, {}),
|
|
683
|
+
},
|
|
574
684
|
{
|
|
575
685
|
id: 'pagination',
|
|
576
686
|
nom: 'Pagination',
|
|
@@ -650,7 +760,7 @@ export const CATALOGUE = [
|
|
|
650
760
|
nom: 'Icônes',
|
|
651
761
|
couche: 'commun',
|
|
652
762
|
css: 'icons.css',
|
|
653
|
-
resume: "
|
|
763
|
+
resume: "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.",
|
|
654
764
|
exemples: [
|
|
655
765
|
{
|
|
656
766
|
id: 'jeu',
|
|
@@ -831,6 +941,33 @@ export const CATALOGUE = [
|
|
|
831
941
|
<OnlyMobile><NavBurger aria-label="Menu">…</NavBurger></OnlyMobile>`,
|
|
832
942
|
rendu: (_jsxs("div", { style: { display: 'flex', gap: 10 }, children: [_jsx("span", { className: "zv-only-desktop", children: _jsx(Badge, { ton: "accent", children: "VISIBLE \u2265 768" }) }), _jsx("span", { className: "zv-only-mobile", children: _jsx(Badge, { ton: "accent", children: "VISIBLE < 768" }) })] })),
|
|
833
943
|
},
|
|
944
|
+
{
|
|
945
|
+
id: 'bandeau',
|
|
946
|
+
nom: 'Bandeau d’annonce',
|
|
947
|
+
resume: '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.',
|
|
948
|
+
code: `<Banner>
|
|
949
|
+
La charte 0.8 est en ligne — angles vifs sur tout le système.{' '}
|
|
950
|
+
<a href="/journal">Ce qui change</a>
|
|
951
|
+
</Banner>`,
|
|
952
|
+
rendu: (_jsxs(Banner, { children: ["La charte 0.8 est en ligne \u2014 angles vifs sur tout le syst\u00E8me.", ' ', _jsx("a", { href: "#", children: "Ce qui change" })] })),
|
|
953
|
+
},
|
|
954
|
+
{
|
|
955
|
+
id: 'carrousel',
|
|
956
|
+
nom: 'Carrousel',
|
|
957
|
+
resume: '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.',
|
|
958
|
+
code: `<Carousel label="La suite Zevra">
|
|
959
|
+
<CarouselItem style={{ width: 260 }}>
|
|
960
|
+
<Card>…</Card>
|
|
961
|
+
</CarouselItem>
|
|
962
|
+
…
|
|
963
|
+
</Carousel>`,
|
|
964
|
+
rendu: (_jsx("div", { style: { maxWidth: 560 }, children: _jsx(Carousel, { label: "La suite Zevra", children: [
|
|
965
|
+
['Mémoire', 'Votre savoir, interrogeable en une phrase.'],
|
|
966
|
+
['Lexform', 'Vos actes, anonymisés à la volée.'],
|
|
967
|
+
['Campus', 'La profession qui se rééquipe se forme.'],
|
|
968
|
+
['MCP juridique', 'Vos sources, branchées sur vos agents.'],
|
|
969
|
+
].map(([nom, phrase]) => (_jsx(CarouselItem, { style: { width: 240 }, children: _jsx(Card, { children: _jsxs("div", { style: { display: 'grid', gap: 8 }, children: [_jsx(CardTitle, { children: nom }), _jsx(Body, { taille: "dense", children: phrase })] }) }) }, nom))) }) })),
|
|
970
|
+
},
|
|
834
971
|
],
|
|
835
972
|
},
|
|
836
973
|
{
|
|
@@ -893,6 +1030,18 @@ export const CATALOGUE = [
|
|
|
893
1030
|
<div className={anim('converge', 'tr')}>…</div>`,
|
|
894
1031
|
rendu: (_jsx("div", { style: { display: 'flex', gap: 8, flexWrap: 'wrap' }, children: ['rise', 'pop', 'filet', 'glyph-in', 'converge', 'breathe', 'drift', 'dot-active', 'progress'].map((nom) => (_jsx("span", { className: anim(nom), children: _jsx(Chip, { variante: "mono", children: nom }) }, nom))) })),
|
|
895
1032
|
},
|
|
1033
|
+
{
|
|
1034
|
+
id: 'format-social',
|
|
1035
|
+
nom: 'Formats sociaux',
|
|
1036
|
+
resume: '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.',
|
|
1037
|
+
code: `<SocialFrame manifeste pied={<><Mono ton="on-dark">ZEVRA</Mono><Mono ton="on-dark">zevra.tech</Mono></>}>
|
|
1038
|
+
<Kicker surSombre><Mono ton="on-dark">Manifeste · Article 1ᵉʳ</Mono></Kicker>
|
|
1039
|
+
<Heading taille="h2" as="p">
|
|
1040
|
+
Émanciper les avocats et les juristes des outils qu'on leur <Em surSombre>impose</Em>.
|
|
1041
|
+
</Heading>
|
|
1042
|
+
</SocialFrame>`,
|
|
1043
|
+
rendu: (_jsx("div", { style: { width: 421, height: 221, overflow: 'hidden' }, children: _jsx("div", { style: { transform: 'scale(0.35)', transformOrigin: 'top left' }, children: _jsxs(SocialFrame, { manifeste: true, pied: _jsxs(_Fragment, { children: [_jsx(Mono, { ton: "on-dark", children: "ZEVRA" }), _jsx(Mono, { ton: "on-dark", children: "zevra.tech" })] }), children: [_jsx(Kicker, { surSombre: true, children: _jsx(Mono, { ton: "on-dark", children: "Manifeste \u00B7 Article 1\u1D49\u02B3" }) }), _jsxs(Heading, { taille: "h2", as: "p", children: ["\u00C9manciper les avocats et les juristes des outils qu\u2019on leur", ' ', _jsx(Em, { surSombre: true, children: "impose" }), "."] })] }) }) })),
|
|
1044
|
+
},
|
|
896
1045
|
],
|
|
897
1046
|
},
|
|
898
1047
|
];
|