mirror of
https://github.com/phranck/TUIkit.git
synced 2026-06-20 09:54:37 +00:00
plans: Add three implementation plans for View Architecture refactoring
Phase 1: ContainerView Refactoring (Low-risk, ~2-3h) - Extract _ContainerViewCore with Renderable - Make ContainerView a simple View with body - Enable modifier support Phase 2: Shared Handlers & Helpers (Moderate, ~4-5h) - FocusableItemListHandler (navigation logic) - SelectionStateManager (selection tracking) - ItemStateRenderer (styling utilities) - renderFocusableContainer() (helper function) Phase 3: List & Table Implementation (Moderate-High, ~14-18h) - Refactor List to use new architecture - Implement Table with same foundation - Both follow Box.swift pattern - Maximum code reuse Each phase gets its own branch and PR.
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
# Implementation Plan: ContainerView Refactoring
|
||||
|
||||
## Objective
|
||||
Refactor `ContainerView` from `body: Never` + `Renderable` pattern to correct `View` pattern with internal `_ContainerViewCore`.
|
||||
|
||||
## Current State
|
||||
- `ContainerView<Content, Footer>: View` with `body: Never`
|
||||
- 400+ lines of rendering logic in `renderToBuffer()`
|
||||
- Modifiers don't work on ContainerView
|
||||
|
||||
## Target State
|
||||
- `ContainerView<Content, Footer>: View` with `body: some View`
|
||||
- `_ContainerViewCore<Content, Footer>: View, Renderable` contains all logic
|
||||
- Modifiers work naturally (`.foregroundColor()`, etc.)
|
||||
- Environment values propagate to content
|
||||
|
||||
## Implementation Steps
|
||||
|
||||
### Phase 1: Extract _ContainerViewCore
|
||||
1. Create new private struct `_ContainerViewCore<Content: View, Footer: View>`
|
||||
2. Copy all properties from ContainerView to _ContainerViewCore
|
||||
3. Move `renderToBuffer()` logic to _ContainerViewCore
|
||||
4. Conform _ContainerViewCore to `Renderable`
|
||||
|
||||
### Phase 2: Simplify ContainerView
|
||||
1. Keep all public initializers on ContainerView
|
||||
2. Add `body: some View` that creates and returns `_ContainerViewCore`
|
||||
3. Remove `renderToBuffer()` from ContainerView
|
||||
4. Verify `ContainerConfig` and `ContainerStyle` helpers still work
|
||||
|
||||
### Phase 3: Testing & Verification
|
||||
1. Run all tests — verify no breakage
|
||||
2. Check users: Card, Panel, Alert, Dialog still render correctly
|
||||
3. Verify modifiers work: test `.foregroundColor()` on ContainerView
|
||||
4. Test environment propagation to nested content
|
||||
|
||||
### Phase 4: Documentation
|
||||
1. Update any comments/docs referencing the old pattern
|
||||
2. Add note about `_ContainerViewCore` being internal implementation detail
|
||||
|
||||
## Success Criteria
|
||||
- ✅ All 618 tests pass
|
||||
- ✅ No breaking changes to public API
|
||||
- ✅ Modifiers work on ContainerView
|
||||
- ✅ Environment values propagate
|
||||
- ✅ Code follows Box.swift pattern
|
||||
- ✅ swiftlint clean
|
||||
|
||||
## Estimated Effort
|
||||
**Low-risk**, mechanical refactoring. ~2-3 hours.
|
||||
|
||||
## Files Changed
|
||||
- `Sources/TUIkit/Views/ContainerView.swift` (main)
|
||||
- Possibly minimal changes to test files if needed
|
||||
|
||||
## Related Plans
|
||||
- Follows from architectural review (CLAUDE.md updates)
|
||||
- Foundation for List & Table refactoring
|
||||
- Prerequisite for proper View modifier support
|
||||
@@ -0,0 +1,95 @@
|
||||
# Implementation Plan: List & Table (Refactored)
|
||||
|
||||
## Objective
|
||||
Implement List and Table using shared handlers/helpers from Phase 2, with proper View architecture.
|
||||
|
||||
## Current State
|
||||
- List exists but uses wrong pattern (body: Never + Renderable)
|
||||
- Table doesn't exist yet
|
||||
- No shared foundation
|
||||
|
||||
## Target State
|
||||
- List: Public View with body, private _ListCore with Renderable
|
||||
- Table: Public View with body, private _TableCore with Renderable
|
||||
- Both use: FocusableItemListHandler, SelectionStateManager, renderFocusableContainer()
|
||||
- Both follow Box.swift pattern
|
||||
|
||||
## Implementation Steps
|
||||
|
||||
### Phase 1: Refactor List (Using Shared Components)
|
||||
1. Create `_ListCore` private struct
|
||||
2. Replace direct `ListHandler` with `FocusableItemListHandler`
|
||||
3. Replace ad-hoc selection logic with `SelectionStateManager`
|
||||
4. Use `renderFocusableContainer()` helper
|
||||
5. Update public List to have `body: some View` that creates _ListCore
|
||||
6. Remove `renderToBuffer()` from public List
|
||||
7. Verify all List tests still pass
|
||||
|
||||
### Phase 2: Implement Table (Using Shared Components)
|
||||
1. Create `Table<SelectionValue, Content>: View`
|
||||
2. Create `_TableCore` private struct with Renderable
|
||||
3. Use `FocusableItemListHandler` (same navigation as List)
|
||||
4. Use `SelectionStateManager` (row-based selection)
|
||||
5. Implement table-specific logic:
|
||||
- Column parsing and alignment
|
||||
- ANSI-aware column padding
|
||||
- Grid rendering (not vertical stack)
|
||||
6. Create helper: `renderTableGrid()` or use `renderFocusableContainer()`
|
||||
7. Tests: navigation, selection, column alignment
|
||||
|
||||
### Phase 3: Verify Architecture Consistency
|
||||
1. Both List and Table follow same pattern:
|
||||
- Public View with `body: some View`
|
||||
- Private Core with Renderable
|
||||
- Use shared handlers/helpers
|
||||
2. Both support modifiers naturally
|
||||
3. Environment values propagate correctly
|
||||
4. Keyboard navigation consistent
|
||||
5. Selection handling consistent
|
||||
|
||||
### Phase 4: Integration Testing
|
||||
1. Test List with all modifiers: `.foregroundColor()`, `.padding()`, `.disabled()`
|
||||
2. Test Table with all modifiers
|
||||
3. Test environment propagation through ListItem content
|
||||
4. Test selection state transitions
|
||||
5. Test keyboard navigation in both
|
||||
6. Test focus indicator rendering
|
||||
|
||||
### Phase 5: Example Apps & Docs
|
||||
1. Update ListPage to use new List
|
||||
2. Create TablePage example
|
||||
3. Document keyboard navigation
|
||||
4. Document selection patterns
|
||||
5. Add code examples to DocC
|
||||
|
||||
## Success Criteria
|
||||
- ✅ All 618 existing tests pass
|
||||
- ✅ List tests pass (updated for new pattern)
|
||||
- ✅ Table tests created and pass (>50 tests)
|
||||
- ✅ Modifiers work on both List and Table
|
||||
- ✅ Environment values propagate
|
||||
- ✅ Zero code duplication between List and Table
|
||||
- ✅ Both follow Box.swift pattern
|
||||
- ✅ swiftlint clean
|
||||
- ✅ No breaking changes to public API
|
||||
|
||||
## Estimated Effort
|
||||
**Moderate to High**, requires careful implementation. ~6-8 hours for List, ~8-10 hours for Table.
|
||||
|
||||
## Files Changed/Created
|
||||
- `Sources/TUIkit/Views/List.swift` (refactored)
|
||||
- `Sources/TUIkit/Views/Table.swift` (new)
|
||||
- `Tests/TUIkitTests/ListTests.swift` (updated)
|
||||
- `Tests/TUIkitTests/TableTests.swift` (new)
|
||||
- `Sources/TUIkitExample/Pages/ListPage.swift` (updated)
|
||||
- `Sources/TUIkitExample/Pages/TablePage.swift` (new)
|
||||
|
||||
## Dependencies
|
||||
- Phase 1: ContainerView refactoring ✓
|
||||
- Phase 2: Shared handlers/helpers ✓
|
||||
- These must be completed first
|
||||
|
||||
## Related Plans
|
||||
- Uses FocusableItemListHandler, SelectionStateManager, renderFocusableContainer()
|
||||
- Follows Box.swift pattern
|
||||
- Final implementation of View Architecture guidelines
|
||||
@@ -0,0 +1,97 @@
|
||||
# Implementation Plan: Shared Focus/Selection Handlers & Helpers
|
||||
|
||||
## Objective
|
||||
Extract and formalize reusable components needed by both List and Table:
|
||||
- Focus navigation handler
|
||||
- Selection state manager
|
||||
- Item rendering utilities
|
||||
- Container rendering helper
|
||||
|
||||
## Current State
|
||||
- List has `ListHandler: Focusable` (focus logic only)
|
||||
- No shared selection state manager
|
||||
- No standardized container helper for focusable items
|
||||
- Rendering patterns ad-hoc per control
|
||||
|
||||
## Target State
|
||||
- `FocusableItemListHandler` — shared focus/navigation logic
|
||||
- `SelectionStateManager<T>` — shared selection tracking
|
||||
- `renderFocusableContainer()` — helper similar to `renderContainer()`
|
||||
- `ItemStateRenderer` — utilities for styling items based on focus/selection
|
||||
|
||||
## Implementation Steps
|
||||
|
||||
### Phase 1: Create FocusableItemListHandler
|
||||
1. Create new file: `Sources/TUIkit/Internal/FocusableItemListHandler.swift`
|
||||
2. Extract from List's `ListHandler`:
|
||||
- `focusedIndex`, `scrollOffset`, `viewportHeight`, `rowCount`
|
||||
- `focusUp()`, `focusDown()`, `focusHome()`, `focusEnd()`, `focusPageUp()`, `focusPageDown()`
|
||||
- `ensureFocusedInView()`
|
||||
3. Conform to `Focusable` protocol
|
||||
4. Add proper documentation
|
||||
|
||||
### Phase 2: Create SelectionStateManager
|
||||
1. Create new file: `Sources/TUIkit/Internal/SelectionStateManager.swift`
|
||||
2. Generic class: `SelectionStateManager<SelectionValue: Hashable>`
|
||||
3. Properties:
|
||||
- `binding: Binding<AnyHashable>?`
|
||||
- `selectedValue: AnyHashable?`
|
||||
4. Methods:
|
||||
- `select(index: Int)` — select by index
|
||||
- `select(value: SelectionValue)` — select by value
|
||||
- `isSelected(index: Int) -> Bool`
|
||||
- `isSelected(value: SelectionValue) -> Bool`
|
||||
5. Type-erasure utilities for `Binding<SelectionValue>` → `Binding<AnyHashable>`
|
||||
|
||||
### Phase 3: Create ItemStateRenderer Utilities
|
||||
1. Create new file: `Sources/TUIkit/Internal/ItemStateRenderer.swift`
|
||||
2. Function: `renderItemWithState()`
|
||||
- Parameters: `content: String`, `isFocused: Bool`, `isSelected: Bool`, `palette: Palette`
|
||||
- Returns: styled string with background color, etc.
|
||||
3. Optionally: helper for scroll indicators
|
||||
|
||||
### Phase 4: Create renderFocusableContainer Helper
|
||||
1. Create new file: `Sources/TUIkit/Internal/FocusableContainerRenderer.swift`
|
||||
2. Function: `renderFocusableContainer()`
|
||||
- Similar signature to `renderContainer()`
|
||||
- Plus: focus handler, selection manager, item renderer
|
||||
- Returns: `FrameBuffer`
|
||||
3. Handles:
|
||||
- Extract rows from content
|
||||
- Apply focus/selection styling
|
||||
- Manage scrolling
|
||||
- Wrap in container with title, border, padding
|
||||
|
||||
### Phase 5: Testing
|
||||
1. Create unit tests for each handler/manager
|
||||
2. Test navigation logic (focusUp, focusDown, wrapping, etc.)
|
||||
3. Test selection state transitions
|
||||
4. Test item rendering with various focus/selection states
|
||||
|
||||
### Phase 6: Documentation
|
||||
1. Add doc comments to all new types
|
||||
2. Document the shared architecture in guides
|
||||
|
||||
## Success Criteria
|
||||
- ✅ All new components have comprehensive tests
|
||||
- ✅ No duplication of logic between existing and new code
|
||||
- ✅ Clean, minimal API surface
|
||||
- ✅ Ready for List and Table to use
|
||||
- ✅ swiftlint clean
|
||||
- ✅ All existing tests still pass (618 tests)
|
||||
|
||||
## Estimated Effort
|
||||
**Moderate**, requires careful design. ~4-5 hours.
|
||||
|
||||
## Files Created
|
||||
- `Sources/TUIkit/Internal/FocusableItemListHandler.swift`
|
||||
- `Sources/TUIkit/Internal/SelectionStateManager.swift`
|
||||
- `Sources/TUIkit/Internal/ItemStateRenderer.swift`
|
||||
- `Sources/TUIkit/Internal/FocusableContainerRenderer.swift`
|
||||
- `Tests/TUIkitTests/FocusableItemListHandlerTests.swift`
|
||||
- `Tests/TUIkitTests/SelectionStateManagerTests.swift`
|
||||
|
||||
## Related Plans
|
||||
- Foundation for List & Table implementation
|
||||
- Uses patterns from ContainerView refactoring
|
||||
- Enables maximum code reuse
|
||||
Reference in New Issue
Block a user