From cc0442ef5feb59836d80e8dfa56ed85e519ab0d9 Mon Sep 17 00:00:00 2001 From: william Date: Mon, 24 Aug 2026 19:10:25 +0200 Subject: [PATCH] Add a Font Awesome icon gallery to the properties panel, draggable onto the screen MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit New "Icône" widget (, color/size customizable exactly like any other widget) plus a curated set of ~250 verified Font Awesome 5 Free solid icon names (fontawesome_icons.py) — not the full ~1500-icon catalog, since an embedded list needs to be guaranteed accurate (a wrong class name silently renders as a blank glyph); any other valid FA5 class still works by typing it directly into the widget's "Icône" setting. The gallery lives in the (now always-visible) top of the right floating panel, searchable, with each tile both clickable and HTML5-draggable onto the canvas — either action posts to element_add with the chosen icon_class, which now seeds the new element's class instead of leaving it on the generic default. Available in the element-type template editor too, since it reuses screen_edit.html. Loads Font Awesome 5.15.4 (cdnjs) alongside the existing animate.css/Bulma links, in both the editor and /play. Verified end to end: gallery renders with real icon glyphs, clicking/simulated-drop creates a correctly-classed element, and the actual /play route renders it with Font Awesome loaded. Full suite green (89). --- routes/elements/element_add.py | 7 +++ routes/screens/screen_edit.py | 1 + screens/__init__.py | 1 + screens/widgets/fontawesome_icons.py | 46 ++++++++++++++++ screens/widgets/registry.py | 16 ++++++ static/style.css | 12 +++++ templates/play.html | 1 + templates/screen_edit.html | 78 ++++++++++++++++++++++++++++ 8 files changed, 162 insertions(+) create mode 100644 screens/widgets/fontawesome_icons.py diff --git a/routes/elements/element_add.py b/routes/elements/element_add.py index 40786900..615ddf1f 100644 --- a/routes/elements/element_add.py +++ b/routes/elements/element_add.py @@ -17,4 +17,11 @@ def element_add(slug, screen_id): et = types.get(int(element_type_id)) widget = et["default_widget"] if et else "conteneur" new_id = screens.add_element(slug, screen_id, widget, element_type_id) + icon_class = request.form.get("icon_class") + if widget == "icone" and icon_class: + # Posé depuis la galerie d'icônes (voir le panneau de propriétés, + # section "Icônes") : la classe Font Awesome choisie remplace celle + # posée par défaut à la création plutôt que de repartir d'une icône + # neutre que l'utilisateur devrait ensuite retaper à la main. + screens.save_element_controls(slug, new_id, {"ctrl_icon_class": icon_class}) return redirect(url_for("screen_edit", slug=slug, screen_id=screen_id, selected=new_id)) diff --git a/routes/screens/screen_edit.py b/routes/screens/screen_edit.py index 468a179b..ed2ea7a9 100644 --- a/routes/screens/screen_edit.py +++ b/routes/screens/screen_edit.py @@ -73,4 +73,5 @@ def screen_edit(slug, screen_id): animation_clips=animation_clips, animation_clips_json=json.dumps(animation_clips), animate_css_catalog=screens.ANIMATE_CSS_CATALOG, animate_css_labels_json=json.dumps(screens.ANIMATE_CSS_LABELS), + fontawesome_icons=screens.FONTAWESOME_ICONS, ) diff --git a/screens/__init__.py b/screens/__init__.py index e40b97f5..7427a388 100644 --- a/screens/__init__.py +++ b/screens/__init__.py @@ -41,6 +41,7 @@ from .widgets.registry import WIDGETS from .widgets.container_widgets import CONTAINER_WIDGETS from .widgets.layout_capable_widgets import LAYOUT_CAPABLE_WIDGETS from .widgets.font_options import GOOGLE_FONTS_LINK +from .widgets.fontawesome_icons import FONTAWESOME_ICONS from .widgets.widget_meta import widget_meta from .widgets.controls_with_values import controls_with_values from .widgets.data_definition_options import data_definition_options diff --git a/screens/widgets/fontawesome_icons.py b/screens/widgets/fontawesome_icons.py new file mode 100644 index 00000000..75d12431 --- /dev/null +++ b/screens/widgets/fontawesome_icons.py @@ -0,0 +1,46 @@ +# Sélection large mais CURATÉE d'icônes Font Awesome 5 Free (style "solid") +# pour la galerie du widget Icône (voir bulma_controls.py/registry.py et la +# section "Icônes" du panneau de propriétés dans screen_edit.html) — +# volontairement PAS le catalogue Font Awesome 5 Free complet (~1500 icônes) : +# une liste embarquée doit être garantie exacte (une classe qui n'existe pas +# affiche une case vide dans la police), donc on limite ici aux icônes dont +# le nom est sûr plutôt que de deviner l'exhaustif. N'importe quelle autre +# icône Font Awesome 5 reste utilisable en tapant directement sa classe dans +# le réglage "Icône" du panneau de propriétés. +FONTAWESOME_ICONS = [ + "star", "heart", "check", "times", "plus", "minus", "search", "cog", "cogs", "wrench", + "hammer", "tools", "trash", "trash-alt", "edit", "pen", "pencil-alt", "save", "download", + "upload", "share", "share-alt", "link", "unlink", "lock", "lock-open", "key", "eye", + "eye-slash", "bell", "bell-slash", "bookmark", "flag", "flag-checkered", "thumbtack", + "filter", "sort", "sort-up", "sort-down", "list", "list-ul", "list-ol", "th", "th-list", + "th-large", "bars", "ellipsis-h", "ellipsis-v", "expand", "compress", "sync", "sync-alt", + "redo", "undo", "home", "user", "users", "user-circle", "user-plus", "user-minus", + "user-friends", "sign-in-alt", "sign-out-alt", "question-circle", "info-circle", + "exclamation-circle", "exclamation-triangle", "times-circle", "check-circle", "ban", + "shield-alt", "gem", "coins", "money-bill", "wallet", "credit-card", "gift", "trophy", + "medal", "award", "crown", "dice", "dice-d6", "dice-d20", "chess", "chess-king", + "chess-queen", "chess-knight", "chess-bishop", "chess-rook", "chess-pawn", "puzzle-piece", + "gamepad", "rocket", "bomb", "fire", "bolt", "snowflake", "sun", "moon", "cloud", + "cloud-rain", "wind", "umbrella", "tree", "leaf", "seedling", "paw", "spider", "skull", + "skull-crossbones", "map", "map-marker-alt", "map-marked-alt", "compass", "mountain", + "water", "globe", "globe-americas", "flask", "vial", "syringe", "pills", "heartbeat", + "dumbbell", "running", "walking", "swimmer", "futbol", "basketball-ball", "volleyball-ball", + "football-ball", "baseball-ball", "table-tennis", "bowling-ball", "horse", "dove", "cat", + "dog", "fish", "frog", "hippo", "otter", "kiwi-bird", "book", "book-open", "graduation-cap", + "school", "chalkboard", "chalkboard-teacher", "pencil-ruler", "ruler", "ruler-combined", + "calculator", "laptop", "desktop", "mobile-alt", "tablet-alt", "keyboard", "mouse", + "headphones", "microphone", "video", "camera", "image", "images", "film", "music", "play", + "pause", "stop", "step-forward", "step-backward", "volume-up", "volume-down", "volume-mute", + "volume-off", "envelope", "envelope-open", "comment", "comments", "comment-dots", "phone", + "phone-alt", "calendar", "calendar-alt", "calendar-check", "clock", "hourglass", + "hourglass-half", "stopwatch", "car", "car-side", "truck", "plane", "plane-departure", + "ship", "anchor", "subway", "train", "bus", "bicycle", "taxi", "road", "traffic-light", + "gas-pump", "screwdriver", "toolbox", "hard-hat", "building", "city", "industry", + "warehouse", "store", "shopping-cart", "shopping-bag", "box", "boxes", "dolly", "pallet", + "archive", "folder", "folder-open", "file", "file-alt", "file-pdf", "file-word", + "file-excel", "file-image", "file-video", "file-audio", "database", "server", + "network-wired", "wifi", "signal", "satellite", "satellite-dish", "robot", "microchip", + "memory", "hdd", "print", "cut", "paste", "copy", "clipboard", "clipboard-list", + "clipboard-check", "sticky-note", "paperclip", "paint-brush", "palette", "magic", + "fire-extinguisher", "first-aid", "briefcase", "suitcase", +] diff --git a/screens/widgets/registry.py b/screens/widgets/registry.py index 354cbf6d..606adcc4 100644 --- a/screens/widgets/registry.py +++ b/screens/widgets/registry.py @@ -315,4 +315,20 @@ WIDGETS = { "w": 60, "h": 40, "default_content": "", "controls": BULMA_TABS_CONTROLS, }, + "icone": { + # La classe Font Awesome ("fa-solid fa-xxx") EST le contenu visuel de + # ce widget — posée soit en cliquant/glissant une icône depuis la + # galerie du panneau de propriétés (voir routes/elements/element_add.py, + # qui pré-remplit ce réglage), soit tapée à la main ici pour n'importe + # quelle icône Font Awesome 5 hors de la sélection curatée de la + # galerie (voir fontawesome_icons.py). + "label": "Icône", "icon": "🔤", "tag": "i", "has_content": False, + "w": 15, "h": 15, "default_content": "", + "controls": [ + c_text("icon_class", "Icône (classe Font Awesome 5)", "attr:class", + default="fa-solid fa-star", placeholder="fa-solid fa-heart", group="Contenu"), + c_slider("font-size", "Taille", "style:font-size", min=10, max=160, default=32, group="Texte"), + c_color("color", "Couleur", "style:color", "#e8eaf0", group="Texte"), + ], + }, } diff --git a/static/style.css b/static/style.css index 2a5ec86b..c486ee65 100644 --- a/static/style.css +++ b/static/style.css @@ -183,6 +183,18 @@ body.builderBody > main.content{ flex:1 1 auto; min-height:0; overflow:hidden; d #propsPanelReopenBtn{ right:24px; } .widgetGrid{ display:grid; grid-template-columns:1fr 1fr; gap:8px; } + +/* Galerie d'icônes Font Awesome (panneau de propriétés) — voir + fontawesome_icons.py et addIconElement()/filterIconGallery() plus bas. */ +.iconGallery{ display:grid; grid-template-columns:repeat(6, 1fr); gap:6px; max-height:220px; overflow-y:auto; margin-top:8px; } +.iconGalleryTile{ + aspect-ratio:1; display:flex; align-items:center; justify-content:center; + background:var(--panel2); border:1px solid var(--border); border-radius:6px; + color:var(--text); cursor:grab; font-size:15px; padding:0; +} +.iconGalleryTile:hover{ border-color:var(--accent); color:var(--accent); } +.iconGalleryTile.dragging{ opacity:0.4; } +.iconGalleryTile.iconHidden{ display:none; } .widgetBtnForm{ margin:0; } .widgetBtn{ width:100%; display:flex; flex-direction:column; align-items:center; gap:4px; diff --git a/templates/play.html b/templates/play.html index 940b0497..4e0ffbf9 100644 --- a/templates/play.html +++ b/templates/play.html @@ -8,6 +8,7 @@ +