major
#29787
React UI: Atomare Bausteine (Schaltflächen, Menü-Auslöser, Checkboxen, Eingabefelder, Chips, …) sehen überall gleich aus und lassen sich durch eine Komponentenbibliothek (z.B. Material UI) ersetzen
Die React-Oberfläche lässt sich mit der Komponentenbibliothek eines Kunden darstellen (com.top_logic.layout.react.mui für Material UI): über replace() aus tl-react-bridge ersetzt ein Anpassungsmodul ein TopLogic-Control durch eine Komponente der Bibliothek.
Viele atomare Elemente wurden aber von den Kompositionen selbst gezeichnet, nicht über die Komponenten-Registry: die Menü-Auslöser von TLMenuRegion (Benutzermenü) und TLToolbar (Menü "Entwicklung", Überlauf "…"), die Schaltflächen im Kopf von Panels und Drawern, die Leiste der Tabelle, die Auswahl-Checkboxen der Tabelle, Auf-/Zuklapp-Schalter von Baum, Tabelle, Formulargruppe und Seitenleiste, Suchfelder, Filter- und Datei-Chips, Badges der Seitenleiste, Trennlinien und Ladeanzeigen. Sie behielten deshalb mit Material UI das TopLogic-Aussehen (z.B. auf einer dunklen, vom Kunden ersetzten App-Leiste unlesbarer dunkler Text der Menü-Auslöser), und dasselbe Element (eine Checkbox, ein Chip) sah innerhalb einer Tabelle anders aus als als eigenes Control.
Lösung
Die Oberfläche hat zwei Ebenen:
- Teile (Atome) zeichnen nur; sie haben einen typisierten Props-Vertrag und keinen Server-Zustand. tl-react-bridge hat dazu neben der Registry der Controls eine typisierte Registry der Teile: registerPart (TopLogic-Standard, vom Controls-Bundle registriert), replacePart (Anpassungsmodul; gewinnt unabhängig von der Ladereihenfolge), usePart. Die Teile: Button (auch nur Icon, Umschalter, Menüeintrag, Link), MenuTrigger, DisclosureToggle, Checkbox (auch Schalter), TextInput (Text, Passwort, Zahl, Suche, mehrzeilig), FieldValue (schreibgeschützter Wert), Chip, Badge, Divider, ProgressBar, Spinner.
- Controls bilden den Server-Zustand auf die Props der Teile ab und senden die Kommandos (Tastenkürzel, Navigation, Sichtbarkeit). Die atomaren Controls (TLButton, TLToggleButton, TLCheckbox, TLTextInput, TLPasswordInput, TLNumberInput, TLOptionChips, TLProgress) und die Kompositionen (Toolbar, Menü-Region, Panel, Drawer, Tabelle, Baum, Seitenleiste, Formulargruppe und -feld, Auswahlfelder, Datei-Chips, Popups, …) zeichnen dieselben Teile. Ein Element sieht damit überall gleich aus, und eine Ersetzung erreicht alle Stellen. Die schreibgeschützte Anzeige von Auswahlwerten ist eine gemeinsame Implementierung (OptionValues).
- com.top_logic.layout.react.mui ersetzt alle Teile durch MUI-Komponenten (Menü-Auslöser mit derselben Abbildung appearance → variant wie die Schaltflächen); zusammengesetzte Controls (Fenster, Dialog, Menü, Formularfeld, …) ersetzt es weiterhin als Ganzes.
Nebenbei behoben: Auf-/Zuklapp-Schalter der Baumtabelle ohne type, aria-expanded und Beschriftung; Auswahl-Checkboxen der Tabelle ohne Beschriftung; unbeschriftetes "Reset Zoom" im Diagramm; aria-checked="mixed" der unbestimmten MUI-Checkbox fehlte.
Dokumentation: Entwicklerartikel view-layer/parts, view-layer/customer-component-library, view-layer/mui-customer-theme.
Migration
- installMui({ replace }): Die atomaren Bausteine werden mit den Namen der Teile ausgewählt, nicht mehr mit Control-Namen. 'TLButton' und 'TLToggleButton' → 'Button', 'TLCheckbox' → 'Checkbox', 'TLTextInput', 'TLPasswordInput' und 'TLNumberInput' → 'TextInput' (schreibgeschützte Werte: 'FieldValue'), 'TLOptionChips' → 'Chip', 'TLProgress' → 'ProgressBar'; neu wählbar sind 'MenuTrigger', 'DisclosureToggle', 'Badge', 'Divider', 'Spinner'. Ein alter Name führt beim Start zu einem Fehler (unbekannte Komponente). Mit replace: 'all' ist nichts zu tun.
- Eigene Anpassungsmodule, die TLButton, TLToggleButton, TLCheckbox, TLTextInput, TLPasswordInput, TLNumberInput, TLOptionChips oder TLProgress mit replace() ersetzen, ersetzen stattdessen das entsprechende Teil mit replacePart() und implementieren dessen Props-Vertrag (ButtonPartProps, CheckboxPartProps, …, siehe Artikel view-layer/parts). Kommando-, Tastatur- und Sichtbarkeitslogik übernimmt das Control.
- Konfigurierte CSS-Klasse von Text-, Passwort- und Zahlfeldern sitzt am äußersten Element des Feldes (tl-field-group), nicht mehr am <input>. Anwendungs-CSS der Form input.meineKlasse wird zu .meineKlasse input.