# NewWrapper Keyboard Handling Implementation ## ๐Ÿ“‹ Problem Statement NewWrapper saat ini memiliki masalah keyboard handling pada Android: - Footer terangkat saat keyboard close - Muncul area putih di bawah - Input terpotong saat keyboard muncul - Tidak ada auto-scroll ke focused input ## ๐Ÿ” Root Cause Analysis ### Current NewWrapper Structure ```typescript // โ† MASALAH 1: flex: 0 {children} // โ† MASALAH 2: position absolute {footerComponent} ``` ### Issues Identified | Issue | Impact | Severity | |-------|--------|----------| | `behavior="height"` di Android | View di-resize, content terpotong | ๐Ÿ”ด High | | `flex: 0` pada View wrapper | ScrollView tidak expand dengan benar | ๐Ÿ”ด High | | Footer dengan `position: absolute` | Footer tidak ikut layout flow | ๐ŸŸก Medium | | Tidak ada keyboard event handling | Tidak ada auto-scroll ke input | ๐ŸŸก Medium | --- ## ๐Ÿ’ก Proposed Solutions ### Option A: Full Integration (Breaking Changes) Replace entire KeyboardAvoidingView logic dengan keyboard handling baru. ```typescript // NewWrapper.tsx export function NewWrapper({ children, footerComponent }: Props) { const { scrollViewRef, createFocusHandler } = useKeyboardForm(); return ( {children} {footerComponent} ); } ``` **Pros:** - โœ… Clean implementation - โœ… Consistent behavior across all screens - โœ… Single source of truth **Cons:** - โŒ **Breaking changes** - Semua screen yang pakai NewWrapper akan affected - โŒ **Need to add onFocus handlers** to all TextInput/TextArea components - โŒ **High risk** - May break existing screens - โŒ **Requires testing** all screens that use NewWrapper **Impact:** - All existing screens using NewWrapper will be affected - Need to add `onFocus` handlers to all inputs - Need to wrap inputs with `View onStartShouldSetResponder` --- ### Option B: Opt-in Feature (Recommended) โญ Add flag to enable keyboard handling optionally (backward compatible). ```typescript // NewWrapper.tsx interface NewWrapperProps { // ... existing props enableKeyboardHandling?: boolean; // Default: false keyboardScrollOffset?: number; // Default: 100 } export function NewWrapper(props: NewWrapperProps) { const { enableKeyboardHandling = false, keyboardScrollOffset = 100, ...rest } = props; // Use keyboard hook if enabled const keyboardForm = enableKeyboardHandling ? useKeyboardForm(keyboardScrollOffset) : null; // Render different structure based on flag if (enableKeyboardHandling && keyboardForm) { return renderWithKeyboardHandling(rest, keyboardForm); } return renderOriginal(rest); } ``` **Pros:** - โœ… **Backward compatible** - No breaking changes - โœ… **Opt-in** - Screens yang butuh bisa enable - โœ… **Safe** - Existing screens tetap bekerja - โœ… **Gradual migration** - Bisa migrate screen by screen - โœ… **Low risk** - Can test with new screens first **Cons:** - โš ๏ธ More code (duplicate logic) - โš ๏ธ Need to maintain 2 implementations temporarily **Usage Example:** ```typescript // Existing screens - No changes needed! }> // New screens with forms - Enable keyboard handling } > true}> ``` --- ### Option C: Create New Component (Safest) Keep NewWrapper as is, create separate component for forms. ```typescript // Keep NewWrapper unchanged // Use FormWrapper for forms (already created!) ``` **Pros:** - โœ… **Zero risk** - NewWrapper tidak berubah - โœ… **Clear separation** - Old vs New - โœ… **Safe for existing screens** - โœ… **FormWrapper already exists!** **Cons:** - โš ๏ธ Multiple wrapper components - โš ๏ธ Confusion which one to use **Usage:** ```typescript // For regular screens {content} // For form screens }> ``` --- ## ๐Ÿ“Š Comparison Matrix | Criteria | Option A | Option B | Option C | |----------|----------|----------|----------| | **Backward Compatible** | โŒ | โœ… | โœ… | | **Implementation Effort** | High | Medium | Low | | **Risk Level** | ๐Ÿ”ด High | ๐ŸŸก Medium | ๐ŸŸข Low | | **Code Duplication** | None | Temporary | Permanent | | **Migration Required** | Yes | Gradual | No | | **Testing Required** | All screens | New screens only | New screens only | | **Recommended For** | Greenfield projects | Existing projects | Conservative teams | --- ## ๐ŸŽฏ Recommended Approach: Option B (Opt-in) ### Implementation Plan #### Phase 1: Add Keyboard Handling to NewWrapper (Week 1) ```typescript // Add to NewWrapper interface interface NewWrapperProps { enableKeyboardHandling?: boolean; keyboardScrollOffset?: number; } // Implement dual rendering logic if (enableKeyboardHandling) { return renderWithKeyboardHandling(props); } return renderOriginal(props); ``` #### Phase 2: Test with New Screens (Week 2) - Test with Job Create 2 screen - Verify auto-scroll works - Verify footer stays in place - Test on iOS and Android #### Phase 3: Gradual Migration (Week 3-4) Migrate screens one by one: 1. Event Create 2. Donation Create 3. Investment Create 4. Voting Create 5. Profile Create/Edit #### Phase 4: Make Default (Next Major Version) After thorough testing: - Make `enableKeyboardHandling` default to `true` - Deprecate old behavior - Remove old code in next major version --- ## ๐Ÿ“ Technical Requirements ### For NewWrapper with Keyboard Handling ```typescript // 1. Import hook import { useKeyboardForm } from "@/hooks/useKeyboardForm"; // 2. Use hook in component const { scrollViewRef, createFocusHandler } = useKeyboardForm(100); // 3. Pass ref to ScrollView // 4. Wrap inputs with View true}> ``` ### Required Changes per Screen For each screen that enables keyboard handling: 1. **Add `enableKeyboardHandling` prop** 2. **Wrap all TextInput/TextArea with View** 3. **Add `onFocus` handler to inputs** 4. **Test thoroughly** --- ## ๐Ÿงช Testing Checklist ### For Each Screen - [ ] Tap Input 1 โ†’ Auto-scroll to input - [ ] Tap Input 2 โ†’ Auto-scroll to input - [ ] Tap Input 3 โ†’ Auto-scroll to input - [ ] Dismiss keyboard โ†’ Footer returns to position - [ ] No white area at bottom - [ ] Footer not raised - [ ] Smooth transitions - [ ] iOS compatibility - [ ] Android compatibility ### Platforms to Test - [ ] Android with navigation buttons - [ ] Android with gesture navigation - [ ] iOS with home button - [ ] iOS with gesture (notch) - [ ] Various screen sizes --- ## ๐Ÿ“‹ Decision Factors ### Choose Option A if: - โœ… Project is new (few existing screens) - โœ… Team has time for full migration - โœ… Want clean codebase immediately - โœ… Accept short-term disruption ### Choose Option B if: โญ - โœ… Existing project with many screens - โœ… Want zero disruption to users - โœ… Prefer gradual migration - โœ… Want to test thoroughly first ### Choose Option C if: - โœ… Very conservative team - โœ… Cannot risk any changes to existing screens - โœ… OK with multiple wrapper components - โœ… FormWrapper is sufficient --- ## ๐Ÿš€ Next Steps 1. **Review this document** with team 2. **Decide on approach** (A, B, or C) 3. **Create implementation ticket** 4. **Start with Phase 1** 5. **Test thoroughly** 6. **Roll out gradually** --- ## ๐Ÿ“š Related Files - `components/_ShareComponent/NewWrapper.tsx` - Current wrapper - `components/_ShareComponent/FormWrapper.tsx` - New form wrapper - `hooks/useKeyboardForm.ts` - Keyboard handling hook - `screens/Job/ScreenJobCreate2.tsx` - Example implementation --- ## ๐Ÿ“ž Discussion Points 1. **Which option do you prefer?** (A, B, or C) 2. **How many screens use NewWrapper?** 3. **Team capacity for migration?** 4. **Timeline for implementation?** 5. **Risk tolerance level?** --- **Last Updated:** 2026-04-01 **Status:** ๐Ÿ“ Under Discussion