From 7a98d30321097ff5abe0829ef947d30b06e3e71d Mon Sep 17 00:00:00 2001 From: phranck Date: Fri, 6 Feb 2026 21:59:52 +0100 Subject: [PATCH] plan: ContainerView refactoring to follow View pattern ContainerView currently uses body: Never + direct Renderable (WRONG). Should be refactored to: - Public View with real body: some View - Private _ContainerViewCore with Renderable - Enables modifiers to work naturally - Consistent with Box and SwiftUI patterns This should be done BEFORE List/Table implementation so they follow the correct pattern from the start. Impact: Card, Panel, Alert, Dialog use renderContainer() helper, so they won't be directly affected. Low-risk refactoring. --- .../open/2026-02-06-containerview-refactor.md | 93 +++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 plans/open/2026-02-06-containerview-refactor.md diff --git a/plans/open/2026-02-06-containerview-refactor.md b/plans/open/2026-02-06-containerview-refactor.md new file mode 100644 index 0000000..b111c54 --- /dev/null +++ b/plans/open/2026-02-06-containerview-refactor.md @@ -0,0 +1,93 @@ +# ContainerView Refactoring Plan + +## Current (WRONG) Pattern +```swift +public struct ContainerView: View { + var body: Never { fatalError() } +} + +extension ContainerView: Renderable { + func renderToBuffer() { ... } // 400+ lines of rendering logic +} +``` + +**Problems:** +- No modifiers work (`.foregroundColor()`, `.padding()`, etc.) +- Can't chain modifiers naturally +- Implementation detail exposed to public API +- Inconsistent with SwiftUI/Box pattern + +## New (CORRECT) Pattern + +```swift +public struct ContainerView: View { + let title: String? + let content: Content + let footer: Footer? + let config: ContainerConfig + + public var body: some View { + _ContainerViewCore( + title: title, + content: content, + footer: footer, + config: config + ) + } +} + +private struct _ContainerViewCore: View, Renderable { + // All the complex rendering logic goes here + + var body: some View { + // Or: extension _ContainerViewCore: Renderable { func renderToBuffer() } + } + + func renderToBuffer(context: RenderContext) -> FrameBuffer { + // Current 400+ lines of logic + } +} +``` + +## Impact Analysis + +### What Uses ContainerView? +```bash +grep -r "ContainerView" Sources/TUIkit/Views/ --include="*.swift" | grep -v "ContainerView.swift" +``` + +Likely users: +- Card (via renderContainer helper) +- Panel (via renderContainer helper) +- Alert (via renderContainer helper) +- Dialog (via renderContainer helper) + +These are already using `renderContainer()` helper, so they won't be directly affected. + +### Breaking Changes? +- ContainerView is internal-ish (used via `renderContainer()` helper) +- Direct users are unlikely, but need to check +- The helper function `renderContainer()` doesn't need to change + +## Refactoring Steps + +1. **Create _ContainerViewCore** — private struct with Renderable +2. **Move all rendering logic** from ContainerView to _ContainerViewCore +3. **Make ContainerView a simple View** with body that creates _ContainerViewCore +4. **Verify modifiers work** — test `.foregroundColor()`, `.padding()`, etc. +5. **Check all users** — Card, Panel, Alert, Dialog still work +6. **Update tests** if needed + +## Benefits After Refactoring + +✅ Modifiers work naturally +✅ Environment values propagate correctly +✅ Consistent with SwiftUI patterns +✅ Cleaner public API +✅ Implementation detail hidden +✅ Pattern reusable for List, Table, etc. + +## Timeline Note + +This is NOT urgent but IMPORTANT for long-term consistency. +Should be done BEFORE List & Table implementation, so they follow the correct pattern from the start.