|
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 |
|