| |
1 | +#!/usr/bin/env python3 |
| |
2 | +"""KA Nav v2 — correctif ✕ (2026-08-25) : le bouton de fermeture vivait dans le |
| |
3 | +header (burger→✕) ; si le header n'est pas épinglé (bas de page), il est hors |
| |
4 | +écran alors que le panneau fixed est visible. On met un ✕ FIXE dans le panneau |
| |
5 | +et on masque le burger à l'ouverture (une seule commande de fermeture). |
| |
6 | +Usage : fix-mm-close.py <racine app> <has|menu-open>""" |
| |
7 | +import sys |
| |
8 | + |
| |
9 | +root, variant = sys.argv[1], sys.argv[2] |
| |
10 | +tsx_path = f"{root}/frontend/src/App.tsx" |
| |
11 | +css_path = f"{root}/frontend/src/styles.css" |
| |
12 | + |
| |
13 | +# --- App.tsx : ✕ premier enfant du panneau ------------------------------- |
| |
14 | +tsx = open(tsx_path).read() |
| |
15 | +if "mm-close" in tsx: |
| |
16 | + print("App.tsx: deja fait") |
| |
17 | +else: |
| |
18 | + anchor = '<div className={`mobile-menu ${open ? "open" : ""}`} role="navigation" aria-label="Menu mobile">' |
| |
19 | + assert anchor in tsx, "ancre mobile-menu introuvable" |
| |
20 | + btn = anchor + ( |
| |
21 | + "\n {/* ✕ fixe du panneau : visible peu importe le scroll," |
| |
22 | + " le burger du header est masqué à l'ouverture */}" |
| |
23 | + '\n <button type="button" className="mm-close" aria-label="Fermer le menu"' |
| |
24 | + "\n onClick={() => setOpen(false)}>✕</button>" |
| |
25 | + ) |
| |
26 | + tsx = tsx.replace(anchor, btn, 1) |
| |
27 | + open(tsx_path, "w").write(tsx) |
| |
28 | + print("App.tsx: OK") |
| |
29 | + |
| |
30 | +# --- styles.css : burger masqué à l'ouverture + style du ✕ ---------------- |
| |
31 | +css = open(css_path).read() |
| |
32 | +old_comment = "/* le rang du header (marque + burger devenu X) reste au-dessus du panneau */\n" |
| |
33 | +old_has = old_comment + ".header:has(.mobile-menu.open) .header-inner { position: relative; z-index: 60; }" |
| |
34 | +old_mo = old_comment + ".header.menu-open .header-inner { position: relative; z-index: 60; }" |
| |
35 | +hide = ("/* burger masque a l'ouverture : la fermeture passe par le X fixe du panneau */\n" |
| |
36 | + + (".header:has(.mobile-menu.open) .menu-btn { visibility: hidden; }" |
| |
37 | + if variant == "has" else |
| |
38 | + ".header.menu-open .menu-btn { visibility: hidden; }")) |
| |
39 | +mm_close = hide + """ |
| |
40 | +/* bouton de fermeture du panneau : fixe en haut a droite du viewport */ |
| |
41 | +.mm-close { |
| |
42 | + position: fixed; top: 10px; right: 14px; z-index: 2; |
| |
43 | + width: 44px; height: 44px; display: flex; align-items: center; justify-content: center; |
| |
44 | + border: 1.5px solid var(--ink); border-radius: 999px; |
| |
45 | + background: var(--ink); color: var(--paper); |
| |
46 | + font-size: 17px; font-weight: 700; line-height: 1; cursor: pointer; padding: 0; |
| |
47 | +}""" |
| |
48 | +done = False |
| |
49 | +for old in (old_has, old_mo): |
| |
50 | + if old in css: |
| |
51 | + css = css.replace(old, mm_close, 1) |
| |
52 | + done = True |
| |
53 | + break |
| |
54 | +if not done and ".mm-close" in css: |
| |
55 | + print("styles.css: deja fait") |
| |
56 | +elif not done: |
| |
57 | + raise SystemExit("regle header-inner z-60 introuvable") |
| |
58 | +else: |
| |
59 | + open(css_path, "w").write(css) |
| |
60 | + print("styles.css: OK") |
| |
61 | |