Le widget "Superposition / boîte de dialogue" gagne les classes Bulma "modal is-active" (sur le voile plein écran) et "box" (sur la boîte centrée), en PLUS du style inline existant — jamais à sa place : tout le positionnement/masquage critique (position:fixed, z-index, display) reste en inline, qui gagne toujours sur une règle de classe. Si Bulma (chargé depuis un CDN, voir play.html) ne se charge pas (hors-ligne), la boîte de dialogue continue de fonctionner exactement pareil — ces classes n'ajoutent qu'un habillage visuel (ombre, base de police/espacement Bulma) qui se dégrade sans rien casser. Pas de ".modal-background" séparé (convention Bulma habituelle) : le voile semi-transparent est déjà posé en inline sur la même balise (background:rgba(...)), un second calque tout aussi transparent par-dessus n'aurait ajouté qu'un assombrissement redondant. 137 tests toujours au vert (changement purement visuel, aucune assertion cassée) ; jeu de démo régénéré et vérifié (classes bien présentes dans le rendu). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
71 lines
3.8 KiB
Python
71 lines
3.8 KiB
Python
import html as html_lib
|
|
|
|
from .visible_attrs import _visible_attrs
|
|
from .style_string import _style_string
|
|
from .render_children import _render_children
|
|
|
|
|
|
def _render_overlay(el, meta, slug, children_map=None, ctx=None, parent_flex_direction=None):
|
|
"""3.4 (Confort) — overlay/modale réutilisable : une boîte de dialogue
|
|
prête à l'emploi, par-dessus TOUT le reste de l'écran, fermeture
|
|
manuelle uniquement (aucun clic-en-dehors-pour-fermer volontairement,
|
|
conformément au manque documenté). Contrairement aux autres widgets, sa
|
|
position ne dépend PAS de x/y/width/height (glissé-déposé sur le
|
|
canevas) : `position:fixed; inset:0` la fait toujours couvrir tout
|
|
l'écran, quel que soit l'endroit où elle a été posée dans l'éditeur —
|
|
seul un voile semi-transparent + une boîte centrée, contenant les
|
|
éléments posés à l'intérieur (comme un conteneur normal).
|
|
|
|
Ouverture/fermeture : PAS de mécanisme dédié — elle réutilise l'action
|
|
existante "Modifier un élément → Visibilité" (masquer/rendre visible),
|
|
exactement comme n'importe quel autre élément. C'est pour ça qu'on
|
|
fusionne le style de positionnement fixe ci-dessous AVEC le style normal
|
|
de l'élément (_style_string) : si l'élément est réglé "Masqué" dans ses
|
|
propriétés, ou si une action "Modifier un élément" le cache plus tard,
|
|
ce masquage continue de fonctionner normalement.
|
|
|
|
Classes Bulma ("modal is-active" / "box") posées en PLUS du style
|
|
inline existant, jamais à sa place : tout le positionnement/masquage
|
|
critique (position:fixed, z-index, display) reste en inline, qui gagne
|
|
toujours sur une règle de classe — si Bulma (chargé depuis un CDN, voir
|
|
play.html) ne se charge pas (hors-ligne), la boîte de dialogue continue
|
|
de fonctionner exactement pareil, ces classes n'ajoutant qu'un habillage
|
|
visuel (ombre, base de police) qui se dégrade sans casser quoi que ce
|
|
soit. Pas de ".modal-background" séparé : le voile semi-transparent est
|
|
déjà posé en inline sur cette même balise (background:rgba(...)) — un
|
|
second calque tout aussi transparent par-dessus n'ajouterait rien."""
|
|
attrs_raw = el.get("attributes") or {}
|
|
box_color = attrs_raw.get("_couleur_boite") or "#1f2430"
|
|
radius = attrs_raw.get("_arrondi") or "12"
|
|
|
|
attrs = _visible_attrs(el, meta, ctx)
|
|
base_overlay_style = (
|
|
"position:fixed; inset:0; z-index:9999; display:flex; "
|
|
"align-items:center; justify-content:center; background:rgba(0,0,0,0.6);"
|
|
)
|
|
style = base_overlay_style + " " + _style_string(el, parent_flex_direction=parent_flex_direction)
|
|
|
|
attr_parts = [f'style="{html_lib.escape(style)}"']
|
|
for k, v in attrs.items():
|
|
if v in (None, "", False):
|
|
continue
|
|
attr_parts.append(
|
|
html_lib.escape(str(k)) if v is True else f'{html_lib.escape(str(k))}="{html_lib.escape(str(v))}"'
|
|
)
|
|
|
|
box_style = (
|
|
f"background:{html_lib.escape(str(box_color))}; border-radius:{html_lib.escape(str(radius))}px; "
|
|
# max-width en min(...) plutôt qu'un simple pourcentage : sur un
|
|
# écran de jeu large (desktop), "90%" seul donnait une boîte étirée
|
|
# bord à bord peu lisible comme dialogue — 560px reste une largeur
|
|
# de boîte de dialogue confortable, tout en retombant sur 90% sur un
|
|
# écran de jeu étroit (mobile/portrait) pour ne jamais déborder.
|
|
"padding:24px; width:100%; max-width:min(560px, 90%); max-height:90%; overflow:auto; box-sizing:border-box;"
|
|
)
|
|
child_html = _render_children(el, slug, children_map, ctx)
|
|
return (
|
|
f'<div class="modal is-active" {" ".join(attr_parts)}>'
|
|
f'<div class="box forgeOverlayBox" style="{html_lib.escape(box_style)}">{child_html}</div>'
|
|
f"</div>"
|
|
)
|