# 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