From 386e93d9c6e969ba489bb8e8872f22210f912ac6 Mon Sep 17 00:00:00 2001 From: william Date: Sun, 23 Aug 2026 20:17:21 +0200 Subject: [PATCH] Move element tree above the add-element menus, make containers collapsible MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The "Éléments de cet écran" tree now sits above "Ajouter un élément sur l'écran" / "Mes éléments de jeu" so it's the first thing visible in the left panel. Each container row gets a disclosure triangle that collapses/expands its children, independent from the row's link (which still selects the element and shows its properties whether collapsed or expanded). The collapsed state is remembered per element in localStorage. Co-Authored-By: Claude Sonnet 5 --- static/style.css | 14 +++++- templates/screen_edit.html | 87 +++++++++++++++++++++++++++++--------- 2 files changed, 78 insertions(+), 23 deletions(-) diff --git a/static/style.css b/static/style.css index 79169b6b..f4f7d29f 100644 --- a/static/style.css +++ b/static/style.css @@ -160,10 +160,20 @@ body.builderBody > main.content{ flex:1 1 auto; min-height:0; overflow:hidden; d pour rester lisible même avec beaucoup d'éléments. */ .elementTree{ display:flex; flex-direction:column; gap:1px; max-height:55vh; overflow-y:auto; margin-bottom:14px; } .treeNode{ display:flex; flex-direction:column; } +.treeRow{ display:flex; align-items:center; gap:2px; } +.treeToggle{ + flex:0 0 auto; width:16px; height:16px; padding:0; border:none; background:none; cursor:pointer; + color:var(--text-dim); font-size:10px; display:flex; align-items:center; justify-content:center; + transition:transform .12s ease; +} +.treeToggle:hover{ color:var(--text); } +.treeToggleSpacer{ flex:0 0 auto; width:16px; height:16px; } +.treeNode.collapsed > .treeRow > .treeToggle{ transform:rotate(-90deg); } +.treeNode.collapsed > .treeChildren{ display:none; } .treeRowLink{ - display:flex; align-items:center; gap:6px; padding:4px 6px; border-radius:5px; + flex:1; display:flex; align-items:center; gap:6px; padding:4px 6px; border-radius:5px; text-decoration:none; color:var(--text); font-size:12.5px; line-height:1.5; - white-space:nowrap; overflow:hidden; + white-space:nowrap; overflow:hidden; min-width:0; } .treeRowLink:hover{ background:var(--panel2); } .treeRowLink.selected{ background:var(--accent); color:#0b0e14; font-weight:600; } diff --git a/templates/screen_edit.html b/templates/screen_edit.html index f5e39591..fcc8a972 100644 --- a/templates/screen_edit.html +++ b/templates/screen_edit.html @@ -30,15 +30,22 @@ {% endif %} {% macro render_tree_node(el) %} -
- - {{ widgets.get(el.widget, {}).get('icon', '❔') }} - {{ el|elabel }} - - {% set kids = children_of.get(el.id, []) %} +{% set kids = children_of.get(el.id, []) %} +
+
+ {% if kids %} + + {% else %} + + {% endif %} + + {{ widgets.get(el.widget, {}).get('icon', '❔') }} + {{ el|elabel }} + +
{% if kids %}
{% for child in kids %} @@ -53,6 +60,17 @@ {% set el = elements|selectattr("id", "equalto", selected_id)|first if selected_id else none %}
+

Éléments de cet écran

+ {% if top_level_elements %} +
+ {% for el in top_level_elements %} + {{ render_tree_node(el) }} + {% endfor %} +
+ {% else %} +

Aucun élément pour l'instant.

+ {% endif %} +
Ajouter un élément sur l'écran
@@ -95,17 +113,6 @@ {% endif %}
- -

Éléments de cet écran

- {% if top_level_elements %} -
- {% for el in top_level_elements %} - {{ render_tree_node(el) }} - {% endfor %} -
- {% else %} -

Aucun élément pour l'instant.

- {% endif %}
@@ -579,6 +586,7 @@ function saveGeometry(id, x, y, width, height) { var SCREEN_EDIT_URL = "{{ url_for('screen_edit', slug=game.slug, screen_id=screen.id) }}"; var CURRENT_SELECTED_ID = {{ selected_id or 'null' }}; var GAME_SLUG = "{{ game.slug }}"; +var SCREEN_ID = {{ screen.id }}; // ---------- Menu contextuel (clic droit) de l'arborescence des éléments ---------- // @@ -626,6 +634,42 @@ if (!window.__forgeContextMenuBound) { document.addEventListener('scroll', hideElementContextMenu, true); } +// ---------- Arborescence : replier/déplier un conteneur ---------- +// +// Le triangle (.treeToggle) replie/déplie SANS toucher à la sélection : le +// nom de l'élément reste un lien à part (.treeRowLink) qui, lui, sélectionne +// toujours l'élément et affiche ses réglages — cliquer sur un conteneur +// replié donne donc bien accès à ses propriétés, comme demandé. L'état +// replié/déplié est mémorisé par élément dans localStorage pour survivre à +// un changement de sélection ou un rechargement de l'éditeur. +function treeCollapseKey(nodeId) { + return 'forgeTreeCollapsed:' + GAME_SLUG + ':' + SCREEN_ID + ':' + nodeId; +} + +function restoreTreeCollapsedState() { + document.querySelectorAll('.elementTree .treeNode').forEach(function (node) { + var id = node.dataset.elementId; + var collapsed = false; + try { collapsed = localStorage.getItem(treeCollapseKey(id)) === '1'; } catch (e) {} + node.classList.toggle('collapsed', collapsed); + }); +} + +if (!window.__forgeTreeToggleBound) { + window.__forgeTreeToggleBound = true; + document.addEventListener('click', function (e) { + var btn = e.target.closest('.treeToggle'); + if (!btn) return; + e.preventDefault(); + e.stopPropagation(); + var node = btn.closest('.treeNode'); + var collapsed = node.classList.toggle('collapsed'); + try { localStorage.setItem(treeCollapseKey(node.dataset.elementId), collapsed ? '1' : '0'); } catch (err) {} + }); +} + +restoreTreeCollapsedState(); + // ---------- Navigation dans l'éditeur sans AUCUN rechargement de page ---------- // // Se déplacer dans le canevas (glisser, redimensionner, cliquer un autre @@ -676,7 +720,7 @@ function refreshCanvasOnly() { // focus/curseur pendant qu'on modifie un réglage. var newTree = doc.querySelector('.builderPanel .elementTree'); var curTree = document.querySelector('.builderPanel .elementTree'); - if (newTree && curTree) curTree.innerHTML = newTree.innerHTML; + if (newTree && curTree) { curTree.innerHTML = newTree.innerHTML; restoreTreeCollapsedState(); } }); } @@ -880,6 +924,7 @@ function initBuilderPanel() { bindPropsAutosave(); bindJaugeDefinitionSelect(); + restoreTreeCollapsedState(); } // Jauge : quand on change l'objet de données à suivre SANS quitter le