@zevra/ui 0.27.1 → 0.29.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 +43 -0
- package/dist/catalogue.d.ts.map +1 -1
- package/dist/catalogue.js +31 -49
- 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/glyph-data.d.ts +2 -0
- package/dist/glyph-data.d.ts.map +1 -1
- package/dist/glyph-data.js +10 -0
- package/dist/glyph-data.js.map +1 -1
- package/dist/glyphes.d.ts +2 -2
- package/dist/glyphes.d.ts.map +1 -1
- package/dist/glyphes.js +2 -2
- package/dist/glyphes.js.map +1 -1
- package/dist/layout.d.ts +24 -3
- package/dist/layout.d.ts.map +1 -1
- package/dist/layout.js +16 -5
- package/dist/layout.js.map +1 -1
- package/logos/index.json +9 -0
- package/package.json +1 -1
- package/react/catalogue.tsx +81 -87
- package/react/css-inline.ts +1 -1
- package/react/glyph-data.ts +11 -0
- package/react/glyphes.ts +8 -2
- package/react/layout.tsx +56 -11
- package/src/layout.css +15 -0
- package/src/navigation.css +116 -12
package/react/glyph-data.ts
CHANGED
|
@@ -34,3 +34,14 @@ export const NOMS_PRODUITS: Record<GlypheId, string> = {
|
|
|
34
34
|
'supernovia': "Supernovia",
|
|
35
35
|
'zevra': "Zevra",
|
|
36
36
|
}
|
|
37
|
+
|
|
38
|
+
/** Ce que chaque produit FAIT, en deux mots — pour le lanceur d'apps. */
|
|
39
|
+
export const ACCROCHES_PRODUITS: Record<GlypheId, string> = {
|
|
40
|
+
'campus': "Formation",
|
|
41
|
+
'lexform': "Anonymisation",
|
|
42
|
+
'mcp': "Connecteur",
|
|
43
|
+
'memoire': "Recherche IA",
|
|
44
|
+
'plume': "Éditeur",
|
|
45
|
+
'supernovia': "Contenu sourcé",
|
|
46
|
+
'zevra': "La suite",
|
|
47
|
+
}
|
package/react/glyphes.ts
CHANGED
|
@@ -14,10 +14,16 @@
|
|
|
14
14
|
// elle n'existe pas encore (retirée le 24/08, à regénérer), et ces glyphes
|
|
15
15
|
// ne doivent donc pas descendre sous cette taille.
|
|
16
16
|
|
|
17
|
-
import {
|
|
17
|
+
import {
|
|
18
|
+
ACCROCHES_PRODUITS,
|
|
19
|
+
GLYPHES,
|
|
20
|
+
MOT_ZEVRA,
|
|
21
|
+
NOMS_PRODUITS,
|
|
22
|
+
type GlypheId,
|
|
23
|
+
} from './glyph-data.js'
|
|
18
24
|
|
|
19
25
|
export type { GlypheId }
|
|
20
|
-
export { GLYPHES, MOT_ZEVRA, NOMS_PRODUITS }
|
|
26
|
+
export { ACCROCHES_PRODUITS, GLYPHES, MOT_ZEVRA, NOMS_PRODUITS }
|
|
21
27
|
|
|
22
28
|
/** Les sept identifiants, triés. */
|
|
23
29
|
export const PRODUITS = Object.keys(GLYPHES) as GlypheId[]
|
package/react/layout.tsx
CHANGED
|
@@ -619,11 +619,22 @@ export function NavActions({ className, ...reste }: Div & { className?: string }
|
|
|
619
619
|
* un état se dit en prop, il ne se peint pas depuis l'app. */
|
|
620
620
|
export function Lanceur({
|
|
621
621
|
label = 'Applications Zevra',
|
|
622
|
+
titre = 'Applications',
|
|
622
623
|
ouvert,
|
|
623
624
|
className,
|
|
624
625
|
children,
|
|
625
626
|
...reste
|
|
626
|
-
}: Div & {
|
|
627
|
+
}: Div & {
|
|
628
|
+
label?: string
|
|
629
|
+
/** L'intitulé du panneau, avec le filet de spectre. Le passer à `null`
|
|
630
|
+
* pour un panneau nu — mais c'est ce filet qui fait qu'un lanceur
|
|
631
|
+
* ressemble à Zevra plutôt qu'à n'importe quel autre. */
|
|
632
|
+
titre?: ReactNode
|
|
633
|
+
ouvert?: boolean
|
|
634
|
+
className?: string
|
|
635
|
+
/** Des `LanceurApp`, éventuellement précédés de `LanceurGroupe`. */
|
|
636
|
+
children?: ReactNode
|
|
637
|
+
}) {
|
|
627
638
|
return (
|
|
628
639
|
<span className={cx('zv-lanceur', ouvert && 'zv-lanceur--ouvert', className)} {...reste}>
|
|
629
640
|
<button
|
|
@@ -637,17 +648,41 @@ export function Lanceur({
|
|
|
637
648
|
</button>
|
|
638
649
|
<span className="zv-lanceur__panneau">
|
|
639
650
|
<span className="zv-menu">
|
|
640
|
-
|
|
651
|
+
{titre && (
|
|
652
|
+
<span className="zv-lanceur__tete">
|
|
653
|
+
<span className="zv-spec" aria-hidden="true" />
|
|
654
|
+
<span className="zv-mono zv-mono--label">{titre}</span>
|
|
655
|
+
</span>
|
|
656
|
+
)}
|
|
657
|
+
{children}
|
|
641
658
|
</span>
|
|
642
659
|
</span>
|
|
643
660
|
</span>
|
|
644
661
|
)
|
|
645
662
|
}
|
|
646
663
|
|
|
664
|
+
/** Un intertitre de famille dans le panneau (« Suite Zevra »). Facultatif :
|
|
665
|
+
* avec une seule famille il n'apporte rien, et le panneau s'ouvre plus vite
|
|
666
|
+
* sans lui. */
|
|
667
|
+
export function LanceurGroupe({ className, ...reste }: Span & { className?: string }) {
|
|
668
|
+
return <span className={cx('zv-lanceur__groupe', className)} {...reste} />
|
|
669
|
+
}
|
|
670
|
+
|
|
671
|
+
/** La grille de tuiles. Elle enveloppe les `LanceurApp` d'une même famille —
|
|
672
|
+
* c'est ce qui permet à un panneau d'en porter plusieurs. */
|
|
673
|
+
export function LanceurApps({ className, ...reste }: Span & { className?: string }) {
|
|
674
|
+
return <span className={cx('zv-lanceur__apps', className)} {...reste} />
|
|
675
|
+
}
|
|
676
|
+
|
|
647
677
|
export interface LanceurAppProps
|
|
648
678
|
extends Omit<AnchorHTMLAttributes<HTMLAnchorElement>, 'className'> {
|
|
649
679
|
nom: string
|
|
650
|
-
/**
|
|
680
|
+
/** Ce que le produit FAIT, en deux mots (« Recherche IA »,
|
|
681
|
+
* « Anonymisation »). C'est elle qui rend la liste lisible à quelqu'un
|
|
682
|
+
* qui ne connaît pas encore la suite : un nom de marque seul ne dit rien
|
|
683
|
+
* à un client qui découvre. */
|
|
684
|
+
accroche?: string
|
|
685
|
+
/** Le glyphe du produit — `GLYPHES.memoire` de `@zevra/ui/glyphes`. Sans
|
|
651
686
|
* lui, la tuile porte l'initiale : une image qui ne charge pas ne doit
|
|
652
687
|
* pas laisser un trou. */
|
|
653
688
|
glyphe?: string
|
|
@@ -657,21 +692,31 @@ export interface LanceurAppProps
|
|
|
657
692
|
className?: string
|
|
658
693
|
}
|
|
659
694
|
|
|
660
|
-
export function LanceurApp({
|
|
695
|
+
export function LanceurApp({
|
|
696
|
+
nom,
|
|
697
|
+
accroche,
|
|
698
|
+
glyphe,
|
|
699
|
+
courant,
|
|
700
|
+
className,
|
|
701
|
+
...reste
|
|
702
|
+
}: LanceurAppProps) {
|
|
661
703
|
return (
|
|
662
704
|
<a
|
|
663
705
|
aria-current={courant ? 'page' : undefined}
|
|
664
706
|
className={cx('zv-lanceur__app', className)}
|
|
665
707
|
{...reste}
|
|
666
708
|
>
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
709
|
+
<span className="zv-lanceur__cadre">
|
|
710
|
+
{glyphe ? (
|
|
711
|
+
<img src={glyphe} alt="" className="zv-lanceur__glyphe" />
|
|
712
|
+
) : (
|
|
713
|
+
<span className="zv-mono zv-mono--label" aria-hidden="true">
|
|
714
|
+
{nom.slice(0, 1).toUpperCase()}
|
|
715
|
+
</span>
|
|
716
|
+
)}
|
|
717
|
+
</span>
|
|
674
718
|
<span className="zv-lanceur__nom">{nom}</span>
|
|
719
|
+
{accroche && <span className="zv-lanceur__accroche">{accroche}</span>}
|
|
675
720
|
</a>
|
|
676
721
|
)
|
|
677
722
|
}
|
package/src/layout.css
CHANGED
|
@@ -227,6 +227,21 @@
|
|
|
227
227
|
display: flex;
|
|
228
228
|
align-items: center;
|
|
229
229
|
gap: 34px;
|
|
230
|
+
/* ⚠️ LA RANGÉE SE COLLE À DROITE, elle ne se centre pas.
|
|
231
|
+
*
|
|
232
|
+
* `.zv-nav` est en space-between : avec DEUX enfants (logo, liens) la
|
|
233
|
+
* rangée se retrouvait à droite toute seule, mais dès qu'une troisième
|
|
234
|
+
* zone apparaît (`.zv-nav__actions` : lanceur, compte), space-between
|
|
235
|
+
* centrait les liens et ouvrait un trou entre l'appel à l'action et le
|
|
236
|
+
* compte. Deux apps composant la même barre se rendaient alors
|
|
237
|
+
* différemment selon qu'elles avaient ou non la zone de droite — c'est le
|
|
238
|
+
* défaut rapporté depuis Campus et Mémoire.
|
|
239
|
+
*
|
|
240
|
+
* La marge automatique absorbe l'espace libre AVANT que space-between ne
|
|
241
|
+
* s'applique : le logo reste à gauche, tout le reste se groupe à droite,
|
|
242
|
+
* dans les deux cas. C'est le rendu de landing.zevra.tech, qui fait
|
|
243
|
+
* référence. */
|
|
244
|
+
margin-left: auto;
|
|
230
245
|
}
|
|
231
246
|
|
|
232
247
|
.zv-navlink {
|
package/src/navigation.css
CHANGED
|
@@ -1148,23 +1148,66 @@ a.zv-menu__item:hover {
|
|
|
1148
1148
|
flex-direction: column;
|
|
1149
1149
|
}
|
|
1150
1150
|
|
|
1151
|
-
/* ───
|
|
1152
|
-
*
|
|
1153
|
-
*
|
|
1151
|
+
/* ─── Le panneau d'applications ─────────────────────────────────────────
|
|
1152
|
+
* QUATRE par rangée : sept produits tiennent alors en deux rangées pleines
|
|
1153
|
+
* (4 + 3), là où trois colonnes en laissaient une seule et bancale sur la
|
|
1154
|
+
* dernière ligne.
|
|
1155
|
+
*
|
|
1156
|
+
* ⚠️ PAS DE CHAMP DE RECHERCHE. Sept produits se lisent d'un coup d'œil ;
|
|
1157
|
+
* une recherche y ajouterait un contrôle à servir, un état à tenir et un
|
|
1158
|
+
* clavier à ouvrir sur téléphone, pour trouver ce qui est déjà visible. Le
|
|
1159
|
+
* jour où la suite dépasse la douzaine, c'est une autre conversation. */
|
|
1160
|
+
|
|
1161
|
+
.zv-lanceur__tete {
|
|
1162
|
+
display: flex;
|
|
1163
|
+
align-items: center;
|
|
1164
|
+
gap: 12px;
|
|
1165
|
+
padding: 14px 14px 10px;
|
|
1166
|
+
}
|
|
1167
|
+
|
|
1168
|
+
/* Le filet de spectre, PREMIER de ses trois emplois autorisés : c'est la
|
|
1169
|
+
* signature de la marque, et c'est elle qui fait qu'un panneau d'apps
|
|
1170
|
+
* ressemble à Zevra plutôt qu'à n'importe quel lanceur. */
|
|
1171
|
+
.zv-lanceur__tete .zv-spec {
|
|
1172
|
+
flex: none;
|
|
1173
|
+
}
|
|
1174
|
+
|
|
1175
|
+
/* Un intertitre par famille (« Suite Zevra », « Vos espaces »). Facultatif :
|
|
1176
|
+
* avec une seule famille, il n'apporte rien et le panneau s'ouvre plus vite
|
|
1177
|
+
* sans lui. */
|
|
1178
|
+
.zv-lanceur__groupe {
|
|
1179
|
+
display: block;
|
|
1180
|
+
padding: 6px 14px 4px;
|
|
1181
|
+
font-family: var(--font-mono);
|
|
1182
|
+
font-size: var(--mono);
|
|
1183
|
+
font-weight: 600;
|
|
1184
|
+
letter-spacing: 0.12em;
|
|
1185
|
+
text-transform: uppercase;
|
|
1186
|
+
color: var(--label);
|
|
1187
|
+
}
|
|
1188
|
+
|
|
1189
|
+
.zv-lanceur__groupe + .zv-lanceur__apps {
|
|
1190
|
+
padding-top: 0;
|
|
1191
|
+
}
|
|
1154
1192
|
|
|
1155
1193
|
.zv-lanceur__apps {
|
|
1156
1194
|
display: grid;
|
|
1157
|
-
grid-template-columns: repeat(
|
|
1158
|
-
|
|
1159
|
-
|
|
1195
|
+
grid-template-columns: repeat(4, 104px);
|
|
1196
|
+
/* 6px et pas 2 : « MCP Juridique » remplit sa colonne, et à 2px son nom
|
|
1197
|
+
* venait toucher celui de la tuile voisine. */
|
|
1198
|
+
gap: 6px;
|
|
1199
|
+
padding: 6px 8px 10px;
|
|
1160
1200
|
}
|
|
1161
1201
|
|
|
1162
1202
|
.zv-lanceur__app {
|
|
1163
1203
|
display: flex;
|
|
1164
1204
|
flex-direction: column;
|
|
1165
1205
|
align-items: center;
|
|
1166
|
-
|
|
1167
|
-
|
|
1206
|
+
/* 4px, et le nom reprend 4px de marge : le nom et son accroche forment un
|
|
1207
|
+
* bloc SERRÉ, détaché du cadre. À gap uniforme, les trois lignes flottaient
|
|
1208
|
+
* à égale distance et le nom ne se rattachait plus à rien. */
|
|
1209
|
+
gap: 4px;
|
|
1210
|
+
padding: 12px 6px;
|
|
1168
1211
|
text-align: center;
|
|
1169
1212
|
text-decoration: none;
|
|
1170
1213
|
color: var(--ink-2);
|
|
@@ -1191,8 +1234,34 @@ a.zv-menu__item:hover {
|
|
|
1191
1234
|
color: var(--accent);
|
|
1192
1235
|
}
|
|
1193
1236
|
|
|
1194
|
-
/* Le glyphe
|
|
1195
|
-
* à
|
|
1237
|
+
/* Le glyphe vit dans un CADRE, et pas nu sur le fond : c'est lui qui donne
|
|
1238
|
+
* à la tuile son assise et qui permet au survol de répondre autrement que
|
|
1239
|
+
* par un aplat. Angle vif, comme tout le reste. */
|
|
1240
|
+
.zv-lanceur__cadre {
|
|
1241
|
+
display: flex;
|
|
1242
|
+
align-items: center;
|
|
1243
|
+
justify-content: center;
|
|
1244
|
+
width: 46px;
|
|
1245
|
+
height: 46px;
|
|
1246
|
+
border: 1px solid var(--line);
|
|
1247
|
+
background: var(--white);
|
|
1248
|
+
transition:
|
|
1249
|
+
border-color 140ms var(--zv-easing, cubic-bezier(0.2, 0.7, 0.2, 1)),
|
|
1250
|
+
background-color 140ms var(--zv-easing, cubic-bezier(0.2, 0.7, 0.2, 1));
|
|
1251
|
+
}
|
|
1252
|
+
|
|
1253
|
+
.zv-lanceur__app:hover .zv-lanceur__cadre {
|
|
1254
|
+
border-color: var(--accent-line);
|
|
1255
|
+
background: var(--white);
|
|
1256
|
+
}
|
|
1257
|
+
|
|
1258
|
+
.zv-lanceur__app--on .zv-lanceur__cadre,
|
|
1259
|
+
.zv-lanceur__app[aria-current='page'] .zv-lanceur__cadre {
|
|
1260
|
+
border-color: var(--accent-line);
|
|
1261
|
+
}
|
|
1262
|
+
|
|
1263
|
+
/* 28px : la taille de .zv-icon--xl, pour qu'une tuile à image et une tuile à
|
|
1264
|
+
* icône tracée se posent sur la même ligne. */
|
|
1196
1265
|
.zv-lanceur__glyphe {
|
|
1197
1266
|
display: block;
|
|
1198
1267
|
width: 28px;
|
|
@@ -1201,14 +1270,35 @@ a.zv-menu__item:hover {
|
|
|
1201
1270
|
}
|
|
1202
1271
|
|
|
1203
1272
|
.zv-lanceur__nom {
|
|
1273
|
+
margin-top: 4px;
|
|
1204
1274
|
font-size: var(--app-sm);
|
|
1205
|
-
font-weight:
|
|
1275
|
+
font-weight: 600;
|
|
1206
1276
|
line-height: 1.3;
|
|
1277
|
+
color: var(--ink);
|
|
1207
1278
|
/* Un nom de produit trop long ne doit pas élargir la colonne : il se coupe
|
|
1208
1279
|
* plutôt que de déformer la grille. */
|
|
1209
1280
|
overflow-wrap: anywhere;
|
|
1210
1281
|
}
|
|
1211
1282
|
|
|
1283
|
+
/* L'accroche : ce que le produit FAIT, en deux mots. C'est elle qui rend la
|
|
1284
|
+
* liste lisible à quelqu'un qui ne connaît pas encore la suite — un nom de
|
|
1285
|
+
* marque seul ne dit rien à un client qui découvre. */
|
|
1286
|
+
.zv-lanceur__accroche {
|
|
1287
|
+
font-size: var(--mono);
|
|
1288
|
+
line-height: 1.3;
|
|
1289
|
+
color: var(--muted);
|
|
1290
|
+
/* PAS de `overflow-wrap: anywhere` ici, contrairement au nom : un nom de
|
|
1291
|
+
* marque qu'on coupe reste reconnaissable, une accroche coupée en plein
|
|
1292
|
+
* mot ne se lit plus. Si elle ne tient pas, c'est la colonne qui est trop
|
|
1293
|
+
* étroite — et c'est la colonne qu'on corrige. */
|
|
1294
|
+
text-wrap: balance;
|
|
1295
|
+
}
|
|
1296
|
+
|
|
1297
|
+
.zv-lanceur__app--on .zv-lanceur__nom,
|
|
1298
|
+
.zv-lanceur__app[aria-current='page'] .zv-lanceur__nom {
|
|
1299
|
+
color: var(--accent);
|
|
1300
|
+
}
|
|
1301
|
+
|
|
1212
1302
|
/* ─── L'en-tête du panneau de compte ────────────────────────────────────
|
|
1213
1303
|
* Qui l'on est, avant ce qu'on peut faire. Non connecté, il porte l'invite
|
|
1214
1304
|
* de connexion : la zone de compte existe TOUJOURS, connecté ou non — une
|
|
@@ -1264,7 +1354,21 @@ a.zv-menu__item:hover {
|
|
|
1264
1354
|
max-width: calc(100vw - 32px);
|
|
1265
1355
|
}
|
|
1266
1356
|
|
|
1357
|
+
/* DEUX colonnes, et pas trois. Sur un iPhone SE (320px), trois colonnes
|
|
1358
|
+
* donnent 63px par tuile : « Anonymisation » s'y coupait en plein mot et
|
|
1359
|
+
* « Connecteur » perdait son r sur la ligne suivante. À deux, chaque tuile
|
|
1360
|
+
* dispose d'une centaine de pixels — assez pour son accroche, qui est
|
|
1361
|
+
* précisément ce dont un client a besoin sur le petit écran où il connaît
|
|
1362
|
+
* le moins la suite. Sept produits font alors quatre rangées, et le
|
|
1363
|
+
* panneau défile. */
|
|
1267
1364
|
.zv-lanceur__apps {
|
|
1268
|
-
grid-template-columns: repeat(
|
|
1365
|
+
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
1366
|
+
}
|
|
1367
|
+
|
|
1368
|
+
/* Quatre rangées dépassent la hauteur d'un téléphone : le panneau se
|
|
1369
|
+
* plafonne et défile, plutôt que de sortir sous le pli sans le dire. */
|
|
1370
|
+
.zv-lanceur__panneau .zv-menu {
|
|
1371
|
+
max-height: calc(100vh - 96px);
|
|
1372
|
+
overflow-y: auto;
|
|
1269
1373
|
}
|
|
1270
1374
|
}
|