enhancement
major
minor
major
minor
major
#29599
TL Views: Wizard-/Stepper-Element für mehrstufige Dialogflüsse (statische und dynamische Schritte, Fortschritt, Übergänge, Auto-Weiter)
Kontext
Mehrstufige Abläufe (Registrierung in drei Schritten, ein KI-"Concierge", der Frage für Frage vom Server bestimmt wird, kurze Zwischenbildschirme, die nach einer festen Zeit weiterschalten) lassen sich in der React-Oberfläche nur von Hand aus <switch> über einen Schritt-Kanal, <progress> und Buttons zusammensetzen. Es gibt keine Schrittanzeige, keine Vor-/Zurück-Navigation und keine Übergänge zwischen Schritten.
Erweiterung
Neues Element <wizard>:
- Schritte als Kind-Elemente <step id="…" label="…"> mit beliebigem Inhalt; alternativ eine dynamische Schrittliste aus einem Kanal (der Server liefert die Schritte, z. B. aus einem Agenten-Dialog), deren Einträge über <switch> nach Art dargestellt werden. Statische und dynamische Schritte sind in einer Liste beliebig mischbar.
- Kanal für den aktuellen Schritt (current-step), optional als Routen-Parameter für Deep-Links und Browser-Zurück.
- Kommandos für Weiter/Zurück/Springen, mit Ausführbarkeitsregeln (z. B. form-valid) für "Weiter".
- Anzeige: Schrittzähler ("01 — 03"), Fortschrittsleiste, optional Schrittliste.
- Übergänge: Ein-/Ausblenden beim Schrittwechsel über CSS-übergangsfähige Zustandsklassen; prefers-reduced-motion wird beachtet.
- auto-advance: ein Schritt schaltet nach einer konfigurierten Zeit selbst weiter (Zwischenbildschirme).
Lösung
Neues Paket com.top_logic.layout.view.wizard im Modul tl-layout-view, nach dem Muster von <tile-stack> (Kanal als einzige Wahrheit, ambienter Scope für Kommandos) und <switch> (Aufbau und Verwerfen des aktiven Inhalts). Client-Komponente TLWizard in tl-layout-react.
== Element <wizard current-step="ch"> ==
- Der Kanal current-step hält die Identität des aktuellen Schritts: die id eines statischen Schritts bzw. das Listenelement eines dynamischen Schritts. null oder ein unbekannter Wert bedeutet den ersten Schritt. (Die Eigenschaft heißt current-step, weil step mit dem Kind-Tag <step> kollidiert.) Deep-Links und Browser-Zurück ergeben sich aus der vorhandenen Routen-Bindung (<param-bindings>): Der Kanalwert steht als Text in der URL, ein Schritt mit String-Schlüssel ist also verlinkbar (/view/wizard/profile).
- Die Schritte sind eine geordnete, polymorphe Liste von Schrittquellen (WizardStepSource), beliebig mischbar:
- <step id="…" label="…" icon="…" auto-advance="2s">…</step> liefert genau einen Schritt; der Inhalt wird beim Betreten aufgebaut und beim Verlassen verworfen.
- <dynamic-steps steps="listCh" element-channel="element" label="e -> …" icon="e -> …" auto-advance="e -> …"><content>…</content></dynamic-steps> liefert je Listenelement einen Schritt; das aktuelle Element wird auf dem element-channel veröffentlicht, der Inhalt ist eine Vorlage (z. B. <switch> nach Art des Elements). Ändert sich die Liste, wird die Folge innerhalb der Kanal-Benachrichtigung neu berechnet; der aktuelle Schritt bleibt samt Inhalt, solange sein Element noch enthalten ist. Eine Kommandokette "Element anhängen, dann <wizard-next/>" sieht den angehängten Schritt daher sofort.
- Die Laufzeitfolge ist die Verkettung der Beiträge aller Quellen. Zähler, Fortschritt, Schrittliste und die Regeln arbeiten auf dieser Folge, so dass "Begrüßung → N serverbestimmte Fragen → Zusammenfassung" ein Wizard ist.
- Anzeige-Optionen (boolesch): counter (Schrittzähler "01 — 03"), progress (Fortschrittsleiste, ReactProgressControl als Kind-Control), step-list (Schrittliste mit den Zuständen erledigt/aktuell/ausstehend; ein erledigter Schritt ist anklickbar und springt zurück).
Kommandos und Regeln
- <wizard-next/>, <wizard-back/>, <wizard-goto step="id"/> sind Ketten-Aktionen und Kommandos unter demselben Tag (wie <navigate-pop>); sie reichen den Kettenwert durch. <wizard-goto> ohne step springt zum Kettenwert (dynamisches Element).
- Sie finden ihren Wizard über einen WizardScope, den das Element in den Kontext seiner Schritte legt (ViewContext.withScope), aufgelöst wie TileStackScope.lookup.
- Ausführbarkeitsregeln <wizard-has-next/> und <wizard-has-back/> blenden einen Button auf dem letzten bzw. ersten Schritt aus.
- Die Navigation wird von der Anwendung komponiert, nicht vom Wizard gerendert: Buttons stehen im Inhalt eines Schritts (nur dort ist der Scope sichtbar) oder werden per <slot-content> in eine gemeinsame Fußzeile (<slot> neben dem Wizard) gehoben; ein "Weiter" mit <form-valid/> steht dazu im Formular des Schritts.
Ausführbarkeitsregeln melden Änderungen selbst (`ObservableRule`)
Ein ViewCommandModel verfolgte bisher nur den Eingabe-Kanal des Kommandos. Eine Regel, die von anderem abhängt (dem Schritt des Wizards, dem Validierungszustand des Formulars), wurde nicht neu ausgewertet: <form-valid/> an einem per <slot-content> herausgehobenen Button blieb aktiv, obwohl der Fehler sichtbar war. Neues Mix-in ObservableRule (Runnable observe(Runnable revalidate)) im Paket command: FormValid (Listener am Formularmodell), WizardHasNext/`WizardHasBack` (Listener am Schrittkanal) und CombinedViewExecutabilityRule (Aggregation) implementieren es; das Kommandomodell registriert sich beim Anhängen und meldet sich beim Abhängen ab.
Übergänge
Die Engine liefert Zustandsklassen, die Anwendung die Animation (dieselbe Teilung wie beim Element-Index des Repeaters, #29597): Richtungsklasse tlWizard--forward/`tlWizard--backward` vom Server, tlWizard__step--entering auf dem neu eingeblendeten Schritt, und der verlassene Schritt bleibt als inerte DOM-Kopie (aria-hidden, inert, ohne IDs) mit tlWizard__step--exiting stehen, bis seine Animation endet (Fallback nach 1 s), so dass ein echtes Ausblenden ohne Weiterleben des verworfenen Controls möglich ist. Das Engine-Stylesheet enthält ein dezentes Standard-Ein-/Ausblenden mit seitlichem Versatz, das prefers-reduced-motion: reduce abschaltet; eine Anwendung überschreibt die vier Regeln. Diese Konvention kann #29596 (Phase 6) für Dialoge und tile-stack übernehmen.
Auto-Weiter
auto-advance (Dauer im MillisFormat, z. B. 2s; bei <dynamic-steps> als Funktion des Elements). Der Client startet beim Anzeigen des Schritts einen Timer, der beim Schrittwechsel oder Abbau abgebrochen wird, und sendet nach Ablauf das technische Kommando advanceStep mit dem Schritt-Schlüssel; der Server schaltet nur weiter, wenn dieser Schritt noch der aktuelle ist. Die Zeit läuft nur beim Betreten vorwärts: Ein Schritt, zu dem der Benutzer zurückkehrt, wartet auf ihn (sonst wäre "Zurück" hinter einem Zwischenbildschirm wirkungslos).
Verifikation
Unit-Tests TestWizardScope, TestWizardConfig, TestDynamicSteps in tl-layout-view (Scope, Konfiguration, Live-Folge, Regeln über ein echtes ViewCommandModel, Auto-Weiter-Kommando). Demo-Seite demo/wizard-demo.view.xml in tl-demo-react (Navigation "Assistent"): Begrüßung → Profil (Formular, <form-valid/>) → Zwischenbildschirm (auto-advance="2s") → dynamische Fragen ("Weiter" hängt eine Frage an) → Zusammenfassung; Schritt an die URL gebunden; Fußzeile per Slot. Abschnitt "Multi-step flows with <wizard>" in docs/faq/react-view-layer.md.
Nicht Teil dieses Tickets: Übergänge für Dialoge und tile-stack (#29596), generisches css-class, vom Wizard selbst gerenderte Vor-/Zurück-Buttons, @Key-Adressierung einzelner Schritte durch Overlays (die polymorphe Liste hat keinen gemeinsamen id-Schlüssel).