Teil von #29650 (TopLogic UI on MUI), Richtung 1: Komponenten, die TL fehlen.
Ziel
Ein Container <accordion> für .view.xml, der gestapelte Abschnitte mit Kopfzeile zeigt, von denen jeder auf- und zugeklappt werden kann (MUI-Gegenstück: Accordion, AccordionSummary, AccordionDetails).
Heute gibt es Einklappen nur als Eigenschaft von TLFormGroup (innerhalb eines Formulars, gebunden an das Formular-Subgrid) und als Minimieren eines TLPanel. Für Inhalte außerhalb von Formularen (FAQ-artige Seiten, Einstellungsgruppen, Detailbereiche) fehlt ein eigenständiger Container.
Anforderungen
- Abschnitte als Kind-Elemente mit Titel (optional Icon und Aktionen im Kopf) und beliebigem Inhalt.
- Konfigurierbar: mehrere Abschnitte gleichzeitig offen oder nur einer (exklusiv); anfangs geöffnete Abschnitte.
- Der Offen-Zustand wird serverseitig gehalten (Kommando beim Umschalten), optional personalisiert.
- Inhalte eines geschlossenen Abschnitts werden erst beim ersten Öffnen erzeugt (lazy).
- Tastaturbedienung und ARIA nach dem WAI-ARIA-Accordion-Muster.
- Zustandsvertrag in state.proto (siehe #29643), damit eine Kundenbibliothek die Komponente ersetzen kann.
- Gestaltung über die Theme-Tokens.
Lösung
Element `<accordion>` (`com.top_logic.layout.view`)
{{{#!xml <accordion exclusive="false">
<section id="general" icon="css:bi bi-gear" expanded="true">
<label><en>General</en><de>Allgemein</de></label>
<commands>...</commands>
...Inhalt...
</section>
<section id="advanced">...</section>
</accordion> }}}
- Abschnitte sind wie die Reiter von <tab-bar> über ihre id geschlüsselt (ein Fragment kann Abschnitte ergänzen oder überschreiben), haben label, icon (kodiertes Theme-Image), eine Zugriffsprüfung und beliebigen Inhalt. Reiter und Abschnitt teilen sich diese Konfiguration (ContentSectionConfig) und ihre Auswertung (ContentSection: Beschriftung je Sitzung, Zugriffsprüfung, Inhaltskontext); die XML-Form von <tab-bar> bleibt unverändert.
- expanded je Abschnitt legt fest, ob er anfangs offen ist; exclusive am Accordion lässt höchstens einen Abschnitt offen (alle zu ist erlaubt).
- Jeder Abschnitt ist wie ein <panel> ein Befehlsbereich (CommandScope): Die Kopfzeile zeigt die eigenen <commands> des Abschnitts und die Befehle, die sein Inhalt beiträgt (z.B. Bearbeiten/Speichern eines Formulars), auch während der Abschnitt zugeklappt ist. Da ein Abschnitt keine Fußleiste hat, erscheinen Befehle mit placement="BUTTON_BAR" in der Kopfzeile nach denen mit TOOLBAR. Dazu baut ToolbarBuilder eine Toolbar aus mehreren Platzierungen und hält sie mit dem Befehlsbereich aktuell (buildLive, auch von CommandScopeElement genutzt). command-display (Standard icon-only) steuert die Darstellung der Kopfzeilen-Schaltflächen.
- Der Offen-Zustand ist immer personalisiert (abschaltbar mit personalize="false"). Schlüssel ist der konfigurierte personalization-key oder der Kontextschlüssel der View mit Segment accordion; gespeichert wird eine Zuordnung Abschnitt-ID → offen, ein gespeicherter Eintrag hat Vorrang vor expanded. Beim Speichern wird nur der Eintrag des geänderten Abschnitts aktualisiert, so dass zwei Accordions mit gleichem Schlüssel und verschiedenen Abschnitts-IDs sich nicht überschreiben.
- Wird ein Control in einem geschlossenen Abschnitt angesteuert (Validierungsfehler, Reveal, Scripted Test), öffnet sich der Abschnitt (RevealRegistry, wie bei <tab-bar>).
Control `TLAccordion` (`com.top_logic.layout.react`)
- ReactAccordionControl: Der Offen-Zustand liegt im Server; der Client meldet das Umschalten per Kommando toggleSection, im exklusiven Modus schließt der Server die übrigen Abschnitte. Änderungen werden an registrierte AccordionExpansionListener gemeldet.
- Der Inhalt eines Abschnitts wird beim ersten Öffnen erzeugt und danach beim Schließen nur verborgen, so dass sein Zustand (z.B. eine begonnene Bearbeitung, Editor-Inhalt) erhalten bleibt.
- Zustandsvertrag AccordionState in state.proto, die Komponente ist damit per replace('TLAccordion', …) ersetzbar (Tabelle in docs/faq/customer-component-library.md).
- Darstellung nach dem WAI-ARIA-Accordion-Muster: Kopf als Schaltfläche in einer Überschrift mit aria-expanded/`aria-controls`, Inhalt als region; Enter/Leertaste schalten um, Pfeil hoch/runter (umlaufend), Pos1/Ende wechseln zwischen den Köpfen. Gestaltung über die Theme-Tokens in tlReactControls.css.
Nicht enthalten
- URL-Routing für geöffnete Abschnitte, Animation des Auf-/Zuklappens.
- Umstellung von TLFormGroup oder des Panel-Minimierens auf diese Komponente.
Dokumentation: docs/faq/react-view-layer.md, Abschnitt "Collapsible sections: <accordion>". Demo: tl-demo-react, Demos → Akkordeon.