wiki/c-work/4-done/2026-06-layout-foundation.md
2026-06-11 15:44:54 +02:00

25 KiB

Layout Foundation — Gesamtplan

Beschreibung und Kontext

Auf kleinen Viewports/Mobile fuellt der statische Header die Seite komplett aus. Die FormGeneratorTable wird unbedienbar. Ursache: die gesamte Ahnenkette ist overflow:hidden mit flex-shrink:0 fuer Chrome-Bereiche.

Strukturproblem: Manuelles Layout-Pattern (adminPage/adminPageFill/pageHeader/tableContainer), 15+ Ad-hoc-Tab-Implementierungen, Workspace komplett Inline mit lokalem _useResizable, keine Persistenz.

Strategisches Ziel: Einheitliche Layout-Architektur fuer alle Seiten (Feature-Views, Admin, Basedata, Systemkomponenten). Die Solution-Schicht L3/L4 wird als separater Plan umgesetzt.

Referenz-Plan: pagelayout_component_system_fd9fde3a.plan.md (v3)

Region-Zuordnung pro Seite: 2026-06-layout-regions.md — definiert fuer jede Seite explizit, welche Panel-Varianten und LayoutTabs eingesetzt werden.

Fokus und kritische Details

  • Scroll-Mode ist das hoechste Risiko — Phase 0 war gating (erledigt)
  • Doppeltes Padding (featureContent + viewContent je 1.5rem) frisst Platz (erledigt)
  • FormGeneratorTable braucht bounded height fuer internen Scroll (Desktop) aber natural height (Mobile)
  • Master->Detail auf derselben Seite: Liste UND Detail-Formular muessen bedienbar sein
  • Keep-Alive-Routes (Workspace) sind position:absolute — Phase 6 (eigener Scope)
  • Migrations-Checkliste (Abschnitt unten) bei JEDER Seite abarbeiten — Lessons aus Phase 4

Ziel und Nicht-Ziele

  • Ziel: Alle Seiten auf StackLayout/LayoutTabs/Panel migrieren
  • Ziel: UiComponents/Tabs und Ad-hoc-Tab-Implementierungen eliminieren
  • Ziel: Admin.module.css Layout-Klassen eliminieren (Button/Form/Modal bleiben)
  • Explizit NICHT in diesem Plan: SolutionsView (eigener Plan als Systemkomponente)

Betroffene Module

  • Frontend: Layout-Kette (MainLayout, FeatureLayout, FeatureView), Admin.module.css, FormGeneratorTable
  • Primitives: ui-nyla/src/components/Layout/* (bereits erstellt)
  • Hooks: ui-nyla/src/hooks/useScrollMode.ts (bereits erstellt)
  • DB-Migration: nein
  • Andere Komponenten: nein

Entscheidungen

Datum Entscheidung Begruendung
2026-06-10 scrollMode via data-scroll-mode auf <html> + CSS :global() CSS-Module-kompatibel, keine Prop-Drilling, ein Hook steuert alles
2026-06-10 Breakpoints: max-width:1024px OR max-height:500px -> document mode Matching bestehender Mobile-Breakpoint + extrem kurze Desktop-Fenster
2026-06-10 SolutionsView als Systemkomponente, nicht Feature-View Solutions ist mandantuebergreifend wie WorkflowAutomation
2026-06-10 SolutionsView-Stub entfernen, Neuaufbau in eigenem Plan Kein Placeholder-Code ohne Backend
2026-06-10 composer-2.5-fast fuer repetitive Seiten-Migrationen Schnell und guenstig fuer Pattern-Anwendung auf viele Dateien
2026-06-10 Desktop-Sidebar: collapsible + resizable Mehr Platz fuer Content, User-Kontrolle ueber Sidebar-Breite
2026-06-10 Panel bekommt variant-Prop (card/table/dashboard/toolbar/editor/wizard) Generische Styles pro Regionstyp, systemweite Aenderungen an einem Ort
2026-06-10 Generische Infra (5-pre) + PanelLayout (6b) VOR Massenmigration Subagenten koennen Checkliste sonst nicht erfuellen; verhindert inkonsistente Layouts
2026-06-10 ViewStack verwaltet nur eigene URL-Params (kein tab-Delete) Behebt Back-Bug bei in LayoutTabs verschachtelten ViewStacks
2026-06-10 Kontextfilter via URL (?context=) statt useState URL-als-Source-of-Truth konsequent; teilbare Links
2026-06-10 Tote/nicht-geroutete Seiten -> Phase 7, nicht Migration Keine Arbeit an Dead-Code; erst Routing klaeren

Scroll-Vertrag

Modi

Modus Bedingung Verhalten
bounded viewport > 1024px Breite UND > 500px Hoehe overflow:hidden-Kette intakt, Tabelle scrollt intern, Header bleibt sichtbar
document viewport <= 1024px ODER <= 500px Hoehe overflow:visible-Kette, Seite scrollt als Dokument, Header scrollt weg, Tabelle waechst natuerlich

CSS-Mechanismus

Hook useScrollMode() setzt document.documentElement.dataset.scrollMode. CSS-Module nutzen :global(html[data-scroll-mode="document"]) als Selektor-Prefix.

Phasen-Uebersicht

Phase Inhalt Status
0 Scroll-Mode-Spike erledigt
1 Feature-Chrome-Budget erledigt
2 Primitive (Panel, LayoutTabs, ViewStack, StackLayout, Persistence) erledigt
3 SolutionsView MVP entfernt (falsch als Feature-View, eigener Plan)
4a TrusteeDataTablesView -> StackLayout + LayoutTabs erledigt
4b WorkflowAutomationHubPage -> StackLayout + LayoutTabs + ViewStack erledigt
4c GATE Korrekturen: RunsTab/WorkflowsTab tableContainer, SolutionsView loeschen, Hub-Filter in URL (erledigt), ViewStack tab-delete-Fix (erledigt) erledigt
4d Panel um variant-Prop erweitern (card, table, dashboard, toolbar, editor, wizard) erledigt
5a Doku-Sync: layout.md, formgenerator.md, TOPICS.md, Region-Specs erledigt
5-pre GATE Generische Infrastruktur bauen (L2/L7/L8/L10/L11 + Keep-Alive-Remeasure) — MUSS vor 5b stehen erledigt
6b vorgezogen vor 5d/5e/5j: PanelLayout-MVP (config-getriebener Split-Tree) ODER Interim-Split-Pattern dokumentieren erledigt
5b Trustee-Views migrieren (8 geroutete Seiten; eingebettete separat in 5i) erledigt
5c Admin-Seiten migrieren (21 Seiten) erledigt
5d Basedata-Seiten migrieren (3 Seiten; FilesPage Split -> 6b) erledigt
5e Feature-Views migrieren (geroutet; Chatworkflow Placeholder skip) erledigt
5f Billing-Seiten migrieren (nur geroutete) erledigt
5g Top-Level-Seiten migrieren (8 Seiten) erledigt
5g2 Auth-Seiten pruefen (5 Seiten, eigenes Layout) erledigt
5h WorkflowAutomation Views + Sub-Tabs erledigt
5i Trustee Sub-Komponenten erledigt
5j Workspace-Views migrieren (9 Seiten; Split -> 6b) erledigt
6a Navigation: Desktop-Sidebar collapse + resize erledigt
7 Cleanup: Layout-Klassen, UiComponents/Tabs, tote Seiten erledigt

Umsetzungs-Checkliste

Phase 4c — Korrekturen (sofort)

  • SolutionsView aus FeatureView.tsx deregistrieren (Import + Map-Eintrag trustee.solutions)
  • src/pages/views/solutions/ komplett loeschen (SolutionsView.tsx + .module.css)
  • RunsTab: styles.tableContainer entfernen → Panel variant="table"
  • WorkflowsTab: styles.tableContainer entfernen → Panel variant="table"
  • Hub-Kontextfilter selectedMandateId von useState auf URL (?context=) — erledigt
  • ViewStack: pauschales next.delete('tab') entfernt (Back-Bug bei nested Tabs) — erledigt
  • TypeScript-Build pruefen

Phase 5a — Dokumentation

  • wiki/b-reference/ui-nyla/layout.md erstellt (Scroll-Modi, Layout-Kette, Primitive, Migrations-Checkliste); Defaults an Code angeglichen
  • wiki/b-reference/ui-nyla/formgenerator.md aktualisieren (Page Layout Chain, hookData.refetch, FK-Labels)
  • wiki/TOPICS.md aktualisiert
  • CHANGELOG-Eintraege (laufend)
  • Region-Specs vervollstaendigen (StackLayout-Variant pro tabbed Seite explizit)

Phase 5-pre — Generische Infrastruktur (GATE, vor allen Massenmigrationen)

Diese Bausteine MUESSEN existieren, bevor Subagenten die Migrations-Checkliste erfuellen koennen. Sonst entscheidet jeder Subagent anders bzw. die Checkliste ist nicht umsetzbar.

  • useDocumentTitle-Hook (L11): setzt ${appName} - ${seitentitel}. Route-gated via isActive/routeMatch. Auth-Seiten (Login/Register/Reset/PasswordResetRequest) auf Hook + t() umgestellt.
  • Scroll-Restoration (L2): useScrollRestoration in StackLayout integriert — Position merken, bei fehlendem Ziel auf Top. Document- und bounded-Scroll.
  • ViewStack URL-Validierung + Toast (L8): bei ungueltiger view/entity-Kombi Toast + URL-Sanitisierung (statt stillem Resolve).
  • Detail-Breadcrumb (L7, niedrige Prio): ViewStack detailHeader (Back + Titel) bleibt ausreichend — keine zusaetzliche Crumb-Kette noetig.
  • Filter/Search-Persistenz-Contract (L10): tableFilterPersistence.ts + filterScopeKey-Prop an FormGeneratorTable (fail-closed ohne Scope).
  • Keep-Alive Re-Measure-Hook: useVisibilityRemeasure in FormGeneratorTable fuer Container-Breite nach display:none.
  • Referenz-Migration als Gold-Standard fixieren — nur AEUSSERE Struktur (StackLayout-Variant, LayoutTabs, ViewStack, Kontext-via-URL): TrusteeDataTablesView + WorkflowAutomationHubPage. Die Panel-isierung der Tab-Bodies (RunsTab/WorkflowsTab in 4c/5h, TrusteeDataTab in 5i) ist NICHT Teil des Freeze, da sie erst spaeter migriert werden.

Phase 5b — Trustee-Views (geroutet; Subagent composer-2.5-fast)

Nur via FeatureView-Registry geroutete Views. Eingebettete (Positions/Documents) siehe 5i. Tote siehe Dead-Code-Verifikation.

  • TrusteeAbschlussView.tsx — inline Tab-Buttons -> LayoutTabs
  • TrusteeAccountingSettingsView.tsx — inline Tab-Buttons -> LayoutTabs
  • TrusteeAnalyseView.tsx — inline Tab-Buttons -> LayoutTabs
  • TrusteeDashboardView.tsx — dashboardView CSS -> StackLayout
  • TrusteeImportProcessView.tsx — inline Tab-Buttons -> LayoutTabs
  • TrusteeInstanceRolesView.tsx — viewContainer CSS -> StackLayout
  • TrusteeExpenseImportView.tsx — embedded in ImportProcess; standalone StackLayout bei embedded=false
  • TrusteeScanUploadView.tsx — embedded in ImportProcess; standalone StackLayout bei embedded=false

Phase 5c — Admin-Seiten (21 Seiten, Subagent composer-2.5-fast)

  • AdminUsersPage.tsx
  • AdminUserMandatesPage.tsx
  • AdminUserAccessOverviewPage.tsx — manuelle Tab-Buttons -> LayoutTabs
  • AdminMandatesPage.tsx
  • AdminMandateRolesPage.tsx
  • AdminMandateRolePermissionsPage.tsx
  • AdminLogsPage.tsx
  • AdminLanguagesPage.tsx
  • AdminInvitationsPage.tsx
  • AdminFeatureRolesPage.tsx
  • AdminFeatureInstanceUsersPage.tsx
  • AdminFeatureAccessPage.tsx
  • AdminDemoConfigPage.tsx
  • AdminDatabaseHealthPage.tsx — UiComponents/Tabs -> LayoutTabs
  • AccessManagementHub.tsx
  • PermissionMatrix.tsx
  • InstanceHierarchyView.tsx
  • InstanceDetailModal.tsx
  • wizards/AdminMandateWizardPage.tsx
  • wizards/AdminInvitationWizardPage.tsx
  • wizards/FeatureInstanceWizard.tsx

Phase 5d — Basedata-Seiten (3 Seiten, Subagent composer-2.5-fast)

  • ConnectionsPage.tsx — adminPage/adminPageFill -> StackLayout
  • FilesPage.tsx — adminPage/adminPageFill -> StackLayout
  • PromptsPage.tsx — adminPage/adminPageFill -> StackLayout

Phase 5e — Weitere Feature-Views (Subagent composer-2.5-fast)

Nur geroutete Views (FeatureView-Registry). Tote siehe Dead-Code-Verifikation.

Commcoach (5 geroutet):

  • CommcoachAssistantView.tsx
  • CommcoachDashboardView.tsx
  • CommcoachModulesView.tsx
  • CommcoachSessionView.tsx ([KEEP-ALIVE]; Split -> 6b)
  • CommcoachSettingsView.tsx — manuelle Tabs -> LayoutTabs

Teamsbot (5):

  • TeamsbotAssistantView.tsx
  • TeamsbotDashboardView.tsx
  • TeamsbotModulesView.tsx
  • TeamsbotSessionView.tsx ([KEEP-ALIVE NEU]; Split -> 6b)
  • TeamsbotSettingsView.tsx — manuelle Tabs -> LayoutTabs

RealEstate (2 geroutet + Subkomponenten):

  • RealEstatePekView.tsx (Registry: dashboard)
  • RealEstateInstanceRolesPlaceholder.tsx (Registry: instance-roles)
  • pek/PekMapView.tsx — Subkomponente von PekView
  • pek/PekLocationInput.tsx — Subkomponente von PekView

Chatworkflow (3 geroutet, aber reine PlaceholderViews in FeatureView):

  • NICHT migrieren solange Platzhalter — entweder echte Implementierung abwarten oder Phase 7. In Dead-Code-Verifikation aufgenommen.

Redmine (4):

  • RedmineBrowserView.tsx ([KEEP-ALIVE NEU]; Split -> 6b)
  • RedmineSettingsView.tsx
  • RedmineStatsView.tsx
  • RedmineTicketEditor.tsx — Subkomponente von BrowserView

Neutralization (1):

  • NeutralizationView.tsx — UiComponents/Tabs -> LayoutTabs

Phase 5f — Billing-Seiten (nur geroutete, Subagent composer-2.5-fast)

Geroutet in App.tsx: BillingDataView, BillingAdmin, BillingMandateView, AdminSubscriptionsPage. BillingDashboard/BillingTransactions/BillingUserView sind tot (siehe Dead-Code-Verifikation) -> Phase 7, NICHT migrieren.

  • BillingDataView.tsx
  • BillingAdmin.tsx
  • BillingMandateView.tsx
  • AdminSubscriptionsPage.tsx
  • BillingNav.tsx — Subkomponente (von BillingMandateView genutzt), KEIN eigenes StackLayout
  • SubscriptionTab.tsx — Subkomponente von AdminSubscriptionsPage
  • EnterpriseDialog.tsx — Modal, nur falls vom Modal-Plan beruehrt

Phase 5g — Top-Level-Seiten (8 Seiten)

  • Dashboard.tsx (export DashboardPage)
  • Settings.tsx (export SettingsPage)
  • Store.tsx (export StorePage)
  • IntegrationsOverviewPage.tsx
  • ComplianceAuditPage.tsx
  • RagInventoryPage.tsx
  • GDPR.tsx (export GDPRPage)
  • FeatureView.tsx — View-Router/Container, CSS pruefen

Phase 5g2 — Auth-Seiten (5 Seiten, eigenes Layout ohne MainLayout)

  • Login.tsx — Standalone, kein Feature-Chrome
  • Register.tsx — Standalone, kein Feature-Chrome
  • PasswordResetRequest.tsx — Standalone, kein Feature-Chrome
  • Reset.tsx — Standalone, kein Feature-Chrome
  • InvitePage.tsx — Standalone, kein Feature-Chrome

Phase 5h — WorkflowAutomation Views + Sub-Tabs (6 Seiten)

  • views/workflowAutomation/WorkflowTemplatesPage.tsx — adminPage -> StackLayout
  • views/workflowAutomation/WorkflowEditorPage.tsx — inline flex -> StackLayout
  • tabs/TemplatesTab.tsx
  • tabs/EditorTab.tsx
  • tabs/TasksTab.tsx — Admin.module.css -> StackLayout
  • tabs/RunDetailTab.tsx — Admin.module.css -> StackLayout

Phase 5i — Trustee Sub-Komponenten

  • dataTables/TrusteeDataTab.tsx — eingebettet in TrusteeDataTablesView
  • components/index.ts — leer, ggf. loeschen in Phase 7

Phase 5j — Workspace-Views (9 Seiten)

  • WorkspacePage.tsx — Custom 3-Column Split -> StackLayout + PanelLayout-Vorbereitung
  • WorkspaceEditorPage.tsx — inline flex -> StackLayout
  • WorkspaceSettingsPage.tsx — inline flex -> StackLayout
  • WorkspaceGeneralSettings.tsx — Settings-Layout
  • WorkspaceInput.tsx — Chat-Input-Komponente
  • ChatStream.tsx — Chat-Stream-Panel
  • FilePreview.tsx — Datei-Vorschau-Panel
  • NeutralizationPanel.tsx — Neutralisierungs-Panel
  • ToolActivityLog.tsx — Tool-Activity-Log-Panel

Phase 6a — Navigation: Desktop-Sidebar collapse + resize

Aktueller Stand: Sidebar ist fix 280px, nicht ausblendbar (Desktop), nicht breitenverstellbar. Mobile (<=1024px) hat bereits Overlay-Hamburger-Menu — das bleibt.

  • Collapse-Toggle: Button im Sidebar-Header oder am Rand, klappt Sidebar auf Icon-Only-Breite (~60px)
  • Resize-Handle: Drag-Handle am rechten Rand der Sidebar, Breite zwischen min (~180px) und max (~400px) einstellbar
  • Persistenz: Collapse-State und Breite in localStorage speichern (sidebar-collapsed, sidebar-width)
  • Keyboard-Shortcut: z.B. Ctrl+B zum Toggling (wie VS Code)
  • CSS-Transition: Smooth animation fuer Collapse (200-300ms ease)
  • Content-Bereich reagiert: flex: 1 auf Content bleibt, passt sich automatisch an
  • Logo-Bereich: Im collapsed State nur Icon, kein Text
  • Navigation-Items: Im collapsed State nur Icons, Tooltip bei Hover
  • UserSection: Im collapsed State kompakt (nur Avatar)
  • Betrifft: MainLayout.tsx, MainLayout.module.css, MandateNavigation.tsx, UserSection.tsx

Phase 7 — Cleanup (nach Phase 5)

  • grep-Pruefung: Null-Nutzung von adminPage/adminPageFill/pageHeader/tableContainer Layout-Klassen (inkl. adminPage ohne Suffix)
  • Tote Seiten aus Dead-Code-Verifikation loeschen oder integrieren
  • Admin.module.css: Layout-Klassen entfernen (Button/Form/Modal bleiben)
  • UiComponents/Tabs: Null-Nutzung pruefen, dann loeschen
  • Finale TypeScript-Build-Pruefung
  • Finale Lint-Pruefung aller geaenderter Dateien
  • Aenderungs-Zusammenfassung erstellen

Dead-Code-Verifikation (vor Migration klaeren, NICHT migrieren)

Diese Dateien sind weder via FeatureView-Registry geroutet noch irgendwo importiert (Stand 2026-06-10). Sie gehoeren NICHT in die Migrations-Batches, sondern in Phase 7 Cleanup — entweder loeschen oder bewusst (re-)integrieren.

Datei Befund Aktion
views/realestate/RealEstateDashboardView.tsx Registry mappt dashboard -> RealEstatePekView; nirgends importiert loeschen ODER integrieren
views/realestate/RealEstateParcelsView.tsx Nicht in Registry, nirgends importiert loeschen ODER integrieren
views/realestate/RealEstateProjectsView.tsx Nicht in Registry, nirgends importiert loeschen ODER integrieren
views/commcoach/CommcoachDossierView.tsx Nicht in Registry; nur CSS von SessionView genutzt loeschen ODER integrieren
views/trustee/TrusteePositionDocumentsView.tsx Nicht in Registry, nirgends importiert loeschen ODER integrieren
billing/BillingDashboard.tsx Nicht in App.tsx-Routen, nirgends importiert Routing klaeren / loeschen
billing/BillingTransactions.tsx Nicht in App.tsx-Routen, nirgends importiert Routing klaeren / loeschen
billing/BillingUserView.tsx Nicht in App.tsx-Routen, nirgends importiert Routing klaeren / loeschen
views/solutions/SolutionsView.tsx Noch in trustee-Registry (solutions); eigener Plan in 4c deregistrieren + loeschen
chatworkflow Dashboard/Runs/Files Geroutet, aber reine PlaceholderViews erst bei echter Implementierung migrieren

Eingebettet (KEIN eigenes StackLayout, als Panel-Body in 5i behandeln): TrusteePositionsView, TrusteeDocumentsView (Tab-Inhalte in TrusteeDataTablesView via Wrapper).

Migrations-Checkliste pro Seite

Erfahrungen aus der Migration von TrusteeDataTablesView und WorkflowAutomationHubPage.

1. Daten & API

  • Mandantenfilter: "Alle" = kein mandateId-Param, Backend filtert per User-Mandatsliste.
  • Daten-Reload bei Kontextwechsel: useEffect/useCallback-Dependencies muessen selectedMandateId enthalten.
  • Metriken/Dashboard konsistent mit Tabelle: Gleicher Scope fuer Dashboard-Zahlen und Tabelle.

2. FK-Label-Resolution

  • displayField-Konvention: {fieldName}Label (z.B. workflowId -> workflowIdLabel).
  • enrichRowsWithFkLabels in ALLEN Pfaden: Standard + filterValues.
  • Cross-Mandate FK-Lookup: getRecord() statt mandate-scoped Methoden.

3. FormGeneratorTable Integration

  • hookData.refetch als einziger Datenpfad: apiEndpoint nur fuer CSV/Filtervalues.
  • Keine redundanten Filter-Buttons: FormGeneratorTable hat eingebaute Filter.
  • Kein RBAC im UI: Sichtbarkeit via Backend-Flags.

4. Backend RBAC (bei jeder Migration pruefen)

  • Kein isPlatformAdmin-Bypass fuer Lesezugriffe.
  • Fail-closed: Fehlender Filter = leeres Ergebnis (__impossible__-Sentinel).
  • mandateId-Validierung gegen userMandateIds.

5. Fehlende API-Routen

  • Alle Frontend-API-Aufrufe pruefen: Keine 405 Method Not Allowed.

6. Layout & UI

  • StackLayout + LayoutTabs verwenden: URL als Source-of-Truth.
  • Panel fuer collapsible Bloecke.
  • scrollMode-Integration: min-height im document-Mode.
  • Grouped Tabs: Kategorie-Titel auf eigener Zeile.
  • Loading/Error/Empty-States (L1): pro Seite als Parameter belassen, NICHT generisch standardisieren.
  • Scroll-Position (L2): Position merken; wenn Ziel nicht mehr existiert, auf Top.
  • Dark-Theme-Tokens (L5): NUR CSS-Tokens, keine hardcoded Farben. Bestehende hardcoded Farben der beruehrten Seite gleich mitbereinigen.

7. Persistenz & State

  • Tab-State via URL, nicht useState.
  • Kontext-/Mandantenfilter via URL (?context=), nicht useState (Referenz: Hub).
  • Panel-Collapse-State optional via collapseKey in localStorage.
  • Keine stale Closures bei Mandant-Wechsel.
  • Tabellen-Filter/Suche (L10): in localStorage persistieren. Key MUSS mandateId:instanceId (bzw. scopeKey) enthalten — sonst werden bei Mandantenwechsel fremde Filterwerte (FK-IDs) wiederhergestellt = Tenant-Leakage. Fail-closed: kein Scope -> keine Persistenz.

8. Keep-Alive (nur registrierte Seiten)

  • Pruefen ob Seite in config/keepAliveRoutes.tsx registriert ist.
  • Re-Measure beim Wiedereinblenden (Hoehe war display:none -> 0) via generischem Hook (5-pre).
  • matchLocation-Bedingung erhalten (z.B. ?tab=editor).
  • scopeKey als React-key beibehalten (Scope-Wechsel = Neu-Mount).
  • Listener-Cleanup zerstoert persistenten State nicht.

9. i18n (HARTE REGEL)

  • Keine hardcoded Strings (L4): ALLE Chrome-Texte via t(). Subagenten duerfen niemals Klartext-Strings einsetzen.

10. Modals (NICHT in diesem Plan anfassen)

  • modalOverlay/Modal-Code NICHT migrieren — laeuft im separaten Modal-Konsolidierungsplan. Nur Seiten-Layout (StackLayout/Panel/Tabs) anfassen, Modals unveraendert lassen, um Doppel-Diffs/Merge-Konflikte zu vermeiden.

Entschiedene Logik-Fragen

# Thema Entscheidung
L1 Loading/Error/Empty-States Pro Seite als Parameter belassen, nicht generisch standardisieren
L2 Scroll-Position Position merken; wenn Ziel nicht mehr existiert -> Top
L3 PanelLayout / verstellbare Splits Collapse/Expand ist bereits generisch (Panel/LayoutTabs). Verstellbare Splits einmal generisch in Phase 6b bauen, danach keine Seitenanpassung mehr noetig
L4 i18n HART: keine hardcoded Strings, alles via t()
L5 Dark-Theme-Tokens Token-Pflicht, hardcoded Farben beruehrter Seiten gleich bereinigen
L6 ARIA/Focus Generisch in den Primitiven (LayoutTabs/ViewStack/PanelLayout), nicht pro Seite
L7 Detail-Breadcrumb ViewStack rendert bereits eigenen detailHeader (Back + Titel). Breadcrumb-Erweiterung NICHT in FeatureLayout (Hub ist Top-Level ohne FeatureLayout) — generisch im ViewStack/StackLayout.Header-Slot loesen, damit auch Top-Level-Seiten greifen. Niedrige Prio (aktuell nur Hub betroffen)
L8 ViewStack Toast Generisch: Toast bei ungueltiger URL-Kombi nachruesten
L9 LayoutTabs lazy vs Keep-Alive Generisch: Komponenten-Default bleibt lazy=false (nur aktiver Tab gemountet). Pro Seite lazy SETZEN bei Tab-Sets mit Formularen/Streams/State, da lazy=true besuchte Tabs gemountet haelt (State bleibt). Referenz: WorkflowAutomationHubPage setzt lazy
L10 Filter/Search-Persistenz In localStorage persistieren; Key MUSS Scope (mandateId:instanceId) enthalten, sonst Tenant-Leakage. Fail-closed ohne Scope
L11 document.title Generischer useDocumentTitle-Hook; setzt pro Seite den Zusatz, Ergebnis immer ${appName} - ${seitentitel}. Hardcoded Auth-Titel (Login/Register/Reset) dabei bereinigen (auch i18n)

Alle Logik-Fragen entschieden.

Subagent-Strategie

Fuer Phase 5b-5j werden composer-2.5-fast Subagenten eingesetzt (ERST nach 5-pre + 6b):

  • Jeder Subagent migriert eine Batch von Seiten (z.B. alle Trustee-Views)
  • Auftrag pro Subagent: konkretes Pattern anwenden (adminPage -> StackLayout, manuelle Tabs -> LayoutTabs)
  • Migrations-Checkliste + Region-Spec (2026-06-layout-regions.md) als verbindliche Referenz mitgeben
  • Ergebnis: Liste aller geaenderter Dateien + Beschreibung
  • Hauptagent prueft Build + Lint nach jeder Batch

Harte Regeln im Subagent-Auftrag (sonst inkonsistent):

  • Keine hardcoded Strings — alles via t() (L4).
  • modalOverlay/Modals NICHT anfassen (separater Plan).
  • Tote Seiten (Dead-Code-Verifikation) NICHT migrieren.
  • StackLayout-Variant + Panel-Varianten exakt aus der Region-Spec uebernehmen, nicht raten.
  • Tab-/Kontext-State via URL, Filter via localStorage — nie useState.
  • Nur CSS-Tokens, keine hardcoded Farben (L5).

Akzeptanzkriterien

# Kriterium (Given-When-Then) Prio
1 Given Feature-Route auf iPhone SE (375x667) When Seite laedt Then Header scrollt weg, Tabelle bedienbar must
2 Given Feature-Route auf Desktop (1920x1080) When Seite laedt Then Tabelle scrollt intern, Header sichtbar must
3 Given Resize von Desktop zu schmalem Fenster When Breakpoint ueberschritten Then scrollMode wechselt live must
4 Given beliebige migrierte Seite When Tab gewechselt Then URL wird aktualisiert, kein useState fuer Tab must
5 Given npx tsc --noEmit When nach Abschluss Then 0 Fehler must
6 Given grep adminPage|adminPageFill|pageHeader|tableContainer When nach Phase 7 Then 0 Treffer in Layout-Nutzung must
7 Given grep UiComponents/Tabs When nach Phase 7 Then 0 Treffer must
  • Plan v3: pagelayout_component_system_fd9fde3a.plan.md
  • Solution-Plaene (eigener Scope): c-work/0-ideas/2026-06-CustomerCases-step3-*

Abschluss

  • b-reference/ui-nyla/layout.md erstellt
  • formgenerator.md "Page Layout Chain" aktualisiert
  • TOPICS.md aktualisiert
  • Aenderungs-Zusammenfassung aller migrierten Seiten
  • Dieses Dokument -> 4-done/ verschoben