Ein- und ausklappbare Unterkategorien in der Seitenleiste

Ich habe einige Beiträge dazu gesehen, aber keiner hat definitive Antworten.

Hat die Unreal Engine Discourse (auf der „Entdecken“-Seite von Discourse vorgestellt) ein komplett eigenes Theme oder gibt es Komponenten, die dies erreichen können?

Ich bemerke auch, dass die Unterkategorien als Top-Level-Links angezeigt werden, wenn man in eine hineinklickt, und darunter werden alle Themen aufgelistet. Es sieht so aus, als ob hier „Subcategory List Style“ auf „Rows“ für die übergeordnete Kategorie gesetzt wird, um dies zu erreichen?

1 „Gefällt mir“

Es sieht so aus, als ob dies vielleicht nicht mit einer Komponente lösbar ist.

Ich konnte jedoch JS und CSS generieren, die dies mit etwas KI-Unterstützung erreichen. Wenn Interesse besteht, teile ich es gerne.

3 „Gefällt mir“

Das hast du sicher gesehen:

Und das:

Teile ruhig deinen Code. Natürlich ist die Herausforderung bei solchen Dingen die laufende Wartung.

2 „Gefällt mir“

Ja, es scheint, dass vieles von dem, was sie tun, benutzerdefinierte Sachen sind.

Mein Skript sieht so aus:

import { apiInitializer } from "discourse/lib/api";
import { ajax } from "discourse/lib/ajax";

export default apiInitializer("0.11.1", (api) = {
  ajax("/site.json").then((data) = {
    const categories = data.categories;

    // Erstelle eine Karte von parent_id = [child_category_ids]
    const childMap = {};
    categories.forEach((cat) = {
      if (cat.parent_category_id) {
        if (!childMap[cat.parent_category_id]) {
          childMap[cat.parent_category_id] = [];
        }
        childMap[cat.parent_category_id].push(cat.id);
      }
    });

    const collapseState = {}; // Verfolgt den Kollapszustand pro Elternteil

    function applyCollapseState(parentId, childIds, collapsed) {
      childIds.forEach((childId) = {
        const childEl = document.querySelector(
          `.sidebar-section-link-wrapper[data-category-id="${childId}"]`
        );
        if (childEl) {
          childEl.classList.toggle("is-collapsed", collapsed);
          childEl.classList.add("is-subcategory");
        }
      });
    }

    function ensureToggleExists(parentId, childIds) {
      const parentEl = document.querySelector(
        `.sidebar-section-link-wrapper[data-category-id="${parentId}"]`
      );
      if (!parentEl || parentEl.classList.contains("has-toggle")) return;

      const toggle = document.createElement("span");
      toggle.innerText = collapseState[parentId] ? "▸" : "▾";
      toggle.className = "toggle-subcategories";
      toggle.style.cursor = "pointer";
      toggle.style.marginLeft = "0.5em";

      toggle.onclick = () = {
        const isNowCollapsed = !collapseState[parentId];
        applyCollapseState(parentId, childIds, isNowCollapsed);
        toggle.innerText = isNowCollapsed ? "▸" : "▾";
        collapseState[parentId] = isNowCollapsed;
      };

      parentEl.classList.add("has-toggle");
      const link = parentEl.querySelector(".sidebar-section-link");
      if (link) link.appendChild(toggle);
    }

    api.onPageChange(() = {
      Object.entries(childMap).forEach(([parentId, childIds]) = {
        // Standard-Kollapszustand festlegen
        if (collapseState[parentId] === undefined) {
          collapseState[parentId] = true;
        }

        applyCollapseState(parentId, childIds, collapseState[parentId]);
        ensureToggleExists(parentId, childIds);
      });

      const container = document.querySelector('[data-section-name="categories"]');
      if (!container) return;

      const observer = new MutationObserver(() = {
        Object.entries(childMap).forEach(([parentId, childIds]) = {
          applyCollapseState(parentId, childIds, collapseState[parentId]);
          ensureToggleExists(parentId, childIds); // -- Wiederherstellen der Toggles
        });
      });

      observer.observe(container, {
        childList: true,
        subtree: true,
      });
    });
  });
});

Ich habe das nur in das JS-panel des Themes eingefügt. Das entsprechende CSS:

.sidebar-section-link-wrapper.is-collapsed {
  display: none !important;
}

.sidebar-section-link-wrapper.is-subcategory {
  padding-left: 1.5em;
}

.toggle-subcategories {
    float: right;
    display: flex;
    width: 30px;
    align-items: center;
    font-size: .9em;
    line-height: 1;
    height: 30px;
}

Es funktioniert ziemlich gut für meine Zwecke, aber ich würde das nicht empfehlen, wenn du viele Unterkategorien hast.