26 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 | 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) | offen |
| 4d | Panel um variant-Prop erweitern (card, table, dashboard, toolbar, editor, wizard) |
erledigt |
| 5a | Doku-Sync: layout.md (erstellt, Defaults gefixt), formgenerator.md, TOPICS.md (erstellt), Region-Specs vervollstaendigen | teilw. erledigt |
| 5-pre | GATE Generische Infrastruktur bauen (L2/L7/L8/L10/L11 + Keep-Alive-Remeasure) — MUSS vor 5b stehen | offen |
| 6b | vorgezogen vor 5d/5e/5j: PanelLayout-MVP (config-getriebener Split-Tree) ODER Interim-Split-Pattern dokumentieren | offen |
| 5b | Trustee-Views migrieren (8 geroutete Seiten; eingebettete separat in 5i) | offen |
| 5c | Admin-Seiten migrieren (21 Seiten) | offen |
| 5d | Basedata-Seiten migrieren (3 Seiten; FilesPage Split -> 6b) | offen |
| 5e | Feature-Views migrieren: Commcoach (5 geroutet), Teamsbot (5), RealEstate (2 geroutet + pek-Subkomp.), Redmine (4), Neutralization (1), Chatworkflow (3) | offen |
| 5f | Billing-Seiten migrieren (nur geroutete; siehe Dead-Code-Verifikation) | offen |
| 5g | Top-Level-Seiten migrieren (8 Seiten) | offen |
| 5g2 | Auth-Seiten pruefen (5 Seiten, eigenes Layout) | offen |
| 5h | WorkflowAutomation: Hub-Chrome + WorkflowsTab/RunsTab + Views + Sub-Tabs | offen |
| 5i | Trustee Sub-Komponenten (TrusteeDataTab, eingebettete Positions/Documents-Views als Panel-Body-only) | offen |
| 5j | Workspace-Views migrieren (9 Seiten; Split -> 6b) | offen |
| 6a | Navigation: Desktop-Sidebar collapse + resize | offen |
| 7 | Cleanup: grep-gated Loeschen alter Layout-Klassen, UiComponents/Tabs, tote Seiten (siehe Dead-Code-Verifikation) | offen |
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.tableContainerentfernen - WorkflowsTab:
styles.tableContainerentfernen - Hub-Kontextfilter
selectedMandateIdvonuseStateauf 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.mderstellt (Scroll-Modi, Layout-Kette, Primitive, Migrations-Checkliste); Defaults an Code angeglichenwiki/b-reference/ui-nyla/formgenerator.mdaktualisieren (Page Layout Chain, hookData.refetch, FK-Labels)wiki/TOPICS.mdaktualisiert- 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}. MUSS sichtbarkeits-/aktiv-route-gated sein (nur setzen wenn eigene Route aktiv) — sonst ueberschreibt eine versteckte Keep-Alive-Seite mit SSE/State-Updates den Titel der sichtbaren Seite. Hardcoded Auth-Titel (Login/Register/Reset) auf Hook +t()umstellen.- Scroll-Restoration (L2): generischer Mechanismus (Hook/Layout) — Position merken, bei fehlendem Ziel auf Top. Fuer document- UND bounded-Scroll.
- ViewStack URL-Validierung + Toast (L8): bei ungueltiger
view/entity-Kombi Toast + sauberer Fallback (statt stillem Resolve). - Detail-Breadcrumb (L7, niedrige Prio): generisch im ViewStack/Header-Slot (NICHT FeatureLayout). ViewStack hat bereits
detailHeader; nur ergaenzen falls Crumb-Kette gewuenscht. - Filter/Search-Persistenz-Contract (L10): FormGeneratorTable-Filter in localStorage (scoped key).
- Keep-Alive Re-Measure-Hook: generischer
useVisibilityRemeasurestatt ad-hoc in FormGeneratorTable (Hoehe nachdisplay:none-> 0). - 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 — inline Layout -> StackLayout (Routing pruefen: nicht in Registry)
- TrusteeScanUploadView.tsx — inline Layout -> StackLayout (Routing pruefen: nicht in Registry)
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+Bzum Toggling (wie VS Code) - CSS-Transition: Smooth animation fuer Collapse (200-300ms ease)
- Content-Bereich reagiert:
flex: 1auf 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/tableContainerLayout-Klassen (inkl.adminPageohne 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 muessenselectedMandateIdenthalten. - 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:
apiEndpointnur 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=), nichtuseState(Referenz: Hub). - Panel-Collapse-State optional via
collapseKeyin 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.tsxregistriert 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-
keybeibehalten (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 |
Links
- 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