Fixed gap between input and keyboard (swiftkey keyboard)#1650
Conversation
|
Warning Rate limit exceeded@ragnep has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 15 minutes and 12 seconds before requesting another review. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. 📒 Files selected for processing (1)
WalkthroughDebounced Android keyboard handling (50ms) was added to the keyboard hook; layout height calculation no longer subtracts keyboard height and now uses capacitorSpace; AppLayout and BottomNavigation gain keyboard-aware behavior (hide nav and adjust safe-area); tests updated to use fake timers and assert debounce semantics. Changes
Sequence Diagram(s)sequenceDiagram
participant Capacitor as Capacitor Plugin
participant Hook as useAndroidKeyboard
participant Timer as Debounce Timer
participant State as Hook State / CSS Var
participant Layout as LayoutContext
participant UI as AppLayout / BottomNavigation
rect rgb(200,220,240)
note over Capacitor,Hook: Keyboard Show Event
Capacitor->>Hook: keyboardWillShow(height)
Hook->>Timer: schedule debouncedShow(height) (50ms)
Timer->>Timer: wait DEBOUNCE_MS
Timer->>State: set isVisible=true, keyboardHeight, update --android-keyboard-height
State->>Layout: capSpace recalculated (capSpace=0 when visible)
Layout->>UI: recalc height/styles -> re-render
end
rect rgb(240,220,200)
note over Capacitor,Hook: Keyboard Hide Event
Capacitor->>Hook: keyboardWillHide()
Hook->>Timer: schedule debouncedHide() (50ms), cancel pending show if present
Timer->>Timer: wait DEBOUNCE_MS
Timer->>State: set isVisible=false, reset CSS var
State->>Layout: capSpace updated (reserved 128 when hidden)
Layout->>UI: recalc height/styles -> re-render (bottom nav may show)
end
rect rgb(220,240,220)
note over Hook,Timer: Unmount Cleanup
UI->>Hook: unmount
Hook->>Timer: clear pending timeouts, reset CSS var
Hook->>State: ensure cleaned state
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes
Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (2 warnings)
✅ Passed checks (1 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (7)
components/layout/AppLayout.tsx (2)
52-54: Remove explanatory comments per coding guidelines.The coding guidelines specify that code should be self-explanatory without comments. The variable name
shouldHideBottomNavalready conveys the intent clearly.- // Hide bottom nav when Android keyboard is open to prevent it sliding up with viewport const shouldHideBottomNav = isAndroid && isKeyboardVisible; -
63-65: Remove comment and simplify the conditional expression.Per coding guidelines, code should be self-explanatory. Consider a more descriptive variable name or inline the ternary.
- // Remove safe-area padding when keyboard is open on Android (to avoid gap) - const safeAreaClass = shouldHideBottomNav ? "" : "tw-pb-[env(safe-area-inset-bottom,0px)]"; - + const safeAreaClass = shouldHideBottomNav + ? "" + : "tw-pb-[env(safe-area-inset-bottom,0px)]";hooks/useAndroidKeyboard.ts (2)
34-64: Consider removing inline comments per coding guidelines.The debounce logic is well-implemented with proper race condition prevention. However, per coding guidelines, code should be self-explanatory without comments. The function names
debouncedShowanddebouncedHidealready convey intent.- // Debounced show handler - prevents rapid state updates from aggressive keyboards (e.g., SwiftKey) const debouncedShow = (height: number) => { - // Cancel any pending hide to prevent race conditions if (hideTimeoutRef.current) { clearTimeout(hideTimeoutRef.current); hideTimeoutRef.current = null; } if (showTimeoutRef.current) clearTimeout(showTimeoutRef.current); showTimeoutRef.current = setTimeout(() => { if (!mounted) return; setKeyboardHeight(height); setIsVisible(true); document.documentElement.style.setProperty('--android-keyboard-height', `${height}px`); }, DEBOUNCE_MS); }; - // Debounced hide handler const debouncedHide = () => { - // Cancel any pending show to prevent race conditions if (showTimeoutRef.current) { clearTimeout(showTimeoutRef.current); showTimeoutRef.current = null; } if (hideTimeoutRef.current) clearTimeout(hideTimeoutRef.current); hideTimeoutRef.current = setTimeout(() => { if (!mounted) return; setKeyboardHeight(0); setIsVisible(false); document.documentElement.style.setProperty('--android-keyboard-height', '0px'); }, DEBOUNCE_MS); };
23-26: Remove explanatory comment.Per coding guidelines, code should be self-explanatory. The variable names clearly indicate their purpose.
- // Refs for debounce timeouts const showTimeoutRef = useRef<NodeJS.Timeout | null>(null); const hideTimeoutRef = useRef<NodeJS.Timeout | null>(null); -components/brain/my-stream/layout/LayoutContext.tsx (1)
382-403: Consider removing explanatory comments per coding guidelines.The implementation logic is correct - setting
capSpaceto 0 when the keyboard is visible eliminates the gap. The 75ms transition matchesBottomNavigationfor visual consistency.- // Reserve space for input area + bottom nav - // When keyboard is open on Android, bottom nav is hidden so we need less space let capSpace = 0; if (isAndroid) { - // 128px when keyboard closed (input visible), 0 when open (no gap) capSpace = isKeyboardVisible ? 0 : 128; } else if (isIos || isCapacitor) { capSpace = 20; }__tests__/hooks/useAndroidKeyboard.test.ts (2)
1-1: Unused import:waitForThe
waitForimport appears to be unused after the refactor to use fake timers withjest.advanceTimersByTime().-import { renderHook, act, waitFor } from '@testing-library/react'; +import { renderHook, act } from '@testing-library/react';
385-406: Consider adding an explicit assertion.This test validates that no errors occur when timeouts fire after unmount, but it has no
expect()statement. While Jest will pass tests that don't throw, adding an explicit assertion makes the test's intent clearer.// Advance time after unmount act(() => { jest.advanceTimersByTime(DEBOUNCE_MS * 2); }); - // No errors should occur + // No errors should occur - test passes if no exception is thrown + expect(true).toBe(true); });
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (6)
__tests__/components/brain/my-stream/layout/LayoutContext.test.tsx(2 hunks)__tests__/hooks/useAndroidKeyboard.test.ts(6 hunks)components/brain/my-stream/layout/LayoutContext.tsx(3 hunks)components/layout/AppLayout.tsx(4 hunks)components/navigation/BottomNavigation.tsx(3 hunks)hooks/useAndroidKeyboard.ts(3 hunks)
🧰 Additional context used
📓 Path-based instructions (11)
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (.cursorrules)
**/*.{ts,tsx,js,jsx}: Do not include any comments in the code; it should be self-explanatory
Write correct, up-to-date, bug-free, fully componentized, secure, and efficient code
Include all required imports and ensure proper naming of key components
Use NextJS features that match the current version
**/*.{ts,tsx,js,jsx}: Replace<img>elements with<Image />fromnext/imageto satisfy@next/next/no-img-elementESLint rule
Use<Link href="/path">from Next.js for internal navigation instead of plain HTML links to satisfy@next/next/no-html-link-for-pagesESLint rule
Files:
__tests__/components/brain/my-stream/layout/LayoutContext.test.tsxcomponents/navigation/BottomNavigation.tsxcomponents/brain/my-stream/layout/LayoutContext.tsxhooks/useAndroidKeyboard.ts__tests__/hooks/useAndroidKeyboard.test.tscomponents/layout/AppLayout.tsx
**/*.{tsx,jsx}
📄 CodeRabbit inference engine (.cursorrules)
**/*.{tsx,jsx}: Use FontAwesome for icons in React components
Use TailwindCSS for styling in React components
Use react-query for data fetching
Always addreadonlybefore props in React components
Files:
__tests__/components/brain/my-stream/layout/LayoutContext.test.tsxcomponents/navigation/BottomNavigation.tsxcomponents/brain/my-stream/layout/LayoutContext.tsxcomponents/layout/AppLayout.tsx
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{js,jsx,ts,tsx}: Code must satisfy ESLint (Next's Core Web Vitals + React Hooks)
Use framework APIs: internal links should use<Link>, images should usenext/image, and adopt Next's ESLint rules (Core Web Vitals)
**/*.{js,jsx,ts,tsx}: Code must satisfy ESLint (Next's Core Web Vitals + React Hooks rules)
Follow existing code style and naming conventions; maintain clean code standards (measured by SonarQube)
Files:
__tests__/components/brain/my-stream/layout/LayoutContext.test.tsxcomponents/navigation/BottomNavigation.tsxcomponents/brain/my-stream/layout/LayoutContext.tsxhooks/useAndroidKeyboard.ts__tests__/hooks/useAndroidKeyboard.test.tscomponents/layout/AppLayout.tsx
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx}: Must passtsc --noEmittype checking
Prefer direct named imports for React hooks and types (import { useMemo, useRef, FC, etc. } from "react") overReact.namespace usage (React.useMemo,React.useRef, etc.)
If thereact-hooks/exhaustive-depslint rule is triggered: if the Effect only derives state, remove the Effect and compute during render; if listening to an external system and needing fresh props/state, wrap non-reactive logic inuseEffectEvent
**/*.{ts,tsx}: Must passtsc --noEmitfor TypeScript type checking
Prefer Server Components over Client Components; use Server Functions/Server Actions ('use server') for mutations
Remove unnecessary Effects; if Effect only derives state, compute during render instead
UseuseEffectEventfor non-reactive logic inside Effects to avoid unnecessary re-runs
Use framework APIs:<Link>for internal links,next/imagefor images, adopt Next's ESLint rules
Use'use cache'directive and Cache Components features for explicit opt-in caching in Next.js 16
Use TypeScript and React functional components with hooks
When parsing Seize URLs or similar, fail fast if base origin is unavailable; do not fall back to placeholder origins
Replace<img>elements with<Image />fromnext/image
Use<Link href="/path">for internal navigation instead of plain HTML links
Move data fetches to Server Components; handle mutations through Server Functions/Server Actions with'use server'directive
Files:
__tests__/components/brain/my-stream/layout/LayoutContext.test.tsxcomponents/navigation/BottomNavigation.tsxcomponents/brain/my-stream/layout/LayoutContext.tsxhooks/useAndroidKeyboard.ts__tests__/hooks/useAndroidKeyboard.test.tscomponents/layout/AppLayout.tsx
**/@(__tests__|*.test).{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Tests should live in
__tests__/orComponentName.test.tsx; mock external dependencies and APIs in tests
Files:
__tests__/components/brain/my-stream/layout/LayoutContext.test.tsx__tests__/hooks/useAndroidKeyboard.test.ts
**/__tests__/**/*.{ts,tsx}
📄 CodeRabbit inference engine (GEMINI.md)
Place tests in
__tests__/directory or asComponentName.test.tsxalongside components
Files:
__tests__/components/brain/my-stream/layout/LayoutContext.test.tsx__tests__/hooks/useAndroidKeyboard.test.ts
**/*.test.{ts,tsx}
📄 CodeRabbit inference engine (GEMINI.md)
Mock external dependencies and APIs in tests
Files:
__tests__/components/brain/my-stream/layout/LayoutContext.test.tsx__tests__/hooks/useAndroidKeyboard.test.ts
__tests__/**/*.test.{ts,tsx}
📄 CodeRabbit inference engine (tests/AGENTS.md)
Use Jest +
ts-jestfor TypeScript testing
Files:
__tests__/components/brain/my-stream/layout/LayoutContext.test.tsx__tests__/hooks/useAndroidKeyboard.test.ts
__tests__/**/*.{ts,tsx}
📄 CodeRabbit inference engine (tests/AGENTS.md)
Functions must have ≤ 15 cognitive complexity; extract deep ternaries (>3 levels) and break down complex logic
Files:
__tests__/components/brain/my-stream/layout/LayoutContext.test.tsx__tests__/hooks/useAndroidKeyboard.test.ts
__tests__/**/*.{ts,tsx,js}
📄 CodeRabbit inference engine (tests/AGENTS.md)
__tests__/**/*.{ts,tsx,js}: Preferfor...ofloops overforEachas it allowsbreak/continueand works with async/await
Usearray.at(-1)andarray.at(-2)instead of index-based array access for negative indexing
UseString.prototype.replaceAll()instead ofreplace()for global string replacements
UseglobalThis.fetch()instead of directfetch()calls
Organize imports with one import per module in order: external → internal → types, with no duplicates
Useelement.remove()instead ofparent.removeChild(element)for DOM manipulation
Catch errors only when meaningful; no empty catch blocks; log errors with context
Avoid double negatives in code; prefer explicit logic and remove redundant annotations; use optional chaining (?.)
Files:
__tests__/components/brain/my-stream/layout/LayoutContext.test.tsx__tests__/hooks/useAndroidKeyboard.test.ts
__tests__/**/{components,contexts,hooks}/**/*.{ts,tsx}
📄 CodeRabbit inference engine (tests/AGENTS.md)
Use semantic HTML elements (
<label>,<output>) over ARIA attributes when possible; every form control must have a label
Files:
__tests__/components/brain/my-stream/layout/LayoutContext.test.tsx__tests__/hooks/useAndroidKeyboard.test.ts
🧠 Learnings (10)
📚 Learning: 2025-12-05T10:55:43.476Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __tests__/AGENTS.md:0-0
Timestamp: 2025-12-05T10:55:43.476Z
Learning: Applies to __tests__/**/__tests__/**/components/**/*.test.{ts,tsx} : Test accessibility with keyboard navigation and screen reader compatibility
Applied to files:
__tests__/components/brain/my-stream/layout/LayoutContext.test.tsx__tests__/hooks/useAndroidKeyboard.test.tscomponents/layout/AppLayout.tsx
📚 Learning: 2025-12-05T10:55:43.476Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __tests__/AGENTS.md:0-0
Timestamp: 2025-12-05T10:55:43.476Z
Learning: Applies to __tests__/**/*.{ts,tsx,js} : Avoid double negatives in code; prefer explicit logic and remove redundant annotations; use optional chaining (`?.`)
Applied to files:
__tests__/components/brain/my-stream/layout/LayoutContext.test.tsx__tests__/hooks/useAndroidKeyboard.test.ts
📚 Learning: 2025-12-05T10:55:43.476Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __tests__/AGENTS.md:0-0
Timestamp: 2025-12-05T10:55:43.476Z
Learning: Applies to __tests__/**/{components,contexts,hooks}/**/*.{ts,tsx} : Use semantic HTML elements (`<label>`, `<output>`) over ARIA attributes when possible; every form control must have a label
Applied to files:
__tests__/components/brain/my-stream/layout/LayoutContext.test.tsx
📚 Learning: 2025-12-03T14:52:34.271Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-03T14:52:34.271Z
Learning: Applies to **/*.{ts,tsx} : Prefer direct named imports for React hooks and types (`import { useMemo, useRef, FC, etc. } from "react"`) over `React.` namespace usage (`React.useMemo`, `React.useRef`, etc.)
Applied to files:
hooks/useAndroidKeyboard.ts
📚 Learning: 2025-12-03T14:52:34.271Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-03T14:52:34.271Z
Learning: Fix with modernization (no `// eslint-disable` unless explicitly instructed); prefer refactors aligned with React 19.2, React Compiler, and Next.js 16 conventions
Applied to files:
hooks/useAndroidKeyboard.ts
📚 Learning: 2025-12-05T10:55:30.871Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: GEMINI.md:0-0
Timestamp: 2025-12-05T10:55:30.871Z
Learning: Applies to **/*.{ts,tsx} : Use TypeScript and React functional components with hooks
Applied to files:
hooks/useAndroidKeyboard.ts
📚 Learning: 2025-12-05T10:55:30.871Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: GEMINI.md:0-0
Timestamp: 2025-12-05T10:55:30.871Z
Learning: Applies to **/*.test.{ts,tsx} : Mock external dependencies and APIs in tests
Applied to files:
__tests__/hooks/useAndroidKeyboard.test.ts
📚 Learning: 2025-12-05T10:55:43.476Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __tests__/AGENTS.md:0-0
Timestamp: 2025-12-05T10:55:43.476Z
Learning: Applies to __tests__/**/__tests__/**/components/**/*.test.{ts,tsx} : Use testing-library/react + user-event for React component tests
Applied to files:
__tests__/hooks/useAndroidKeyboard.test.ts
📚 Learning: 2025-12-03T14:52:34.271Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-03T14:52:34.271Z
Learning: Applies to **/@(__tests__|*.test).{ts,tsx} : Tests should live in `__tests__/` or `ComponentName.test.tsx`; mock external dependencies and APIs in tests
Applied to files:
__tests__/hooks/useAndroidKeyboard.test.ts
📚 Learning: 2025-12-05T10:55:43.476Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __tests__/AGENTS.md:0-0
Timestamp: 2025-12-05T10:55:43.476Z
Learning: Applies to __tests__/**/__tests__/**/*.test.{ts,tsx,js} : Test high-risk areas including happy path workflows, invalid input errors, edge cases/boundaries, component & API interactions, and performance/security when relevant
Applied to files:
__tests__/hooks/useAndroidKeyboard.test.ts
🧬 Code graph analysis (2)
components/brain/my-stream/layout/LayoutContext.tsx (1)
hooks/useAndroidKeyboard.ts (1)
useAndroidKeyboard(16-128)
__tests__/hooks/useAndroidKeyboard.test.ts (1)
hooks/useAndroidKeyboard.ts (1)
useAndroidKeyboard(16-128)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (10)
components/layout/AppLayout.tsx (1)
84-86: LGTM!The conditional rendering with the
hiddenprop correctly integrates with the new keyboard visibility logic, ensuring the bottom navigation is hidden when the Android keyboard is open.components/navigation/BottomNavigation.tsx (2)
72-76: LGTM!The props interface follows the coding guideline of using
readonlyfor props, and the default value pattern is clean.
106-113: LGTM!The visibility transition implementation is well-designed:
- Uses
tw-pointer-events-noneto prevent interaction when hidden- The 75ms transition duration complements the 50ms debounce for a responsive feel
- Transform-based hiding (
tw-translate-y-full) is performant__tests__/components/brain/my-stream/layout/LayoutContext.test.tsx (1)
85-100: LGTM!The test correctly validates the updated behavior where
capSpaceis removed (set to 0) when the Android keyboard is visible. The assertions properly verify that- 128pxis not present and- 0px)is included in the height calculation.hooks/useAndroidKeyboard.ts (1)
94-101: LGTM!The cleanup logic is thorough: it clears both debounce timeouts and resets the CSS variable, preventing memory leaks and stale state.
components/brain/my-stream/layout/LayoutContext.tsx (2)
65-76: LGTM!The refactored
calculateHeightStylefunction with the explicitcapacitorSpaceparameter is cleaner and more intentional than the previous keyboard-height-based approach.
396-402: LGTM!The Android-specific transition ensures smooth height adjustments when the keyboard state changes. The 75ms duration is consistent with the
BottomNavigationcomponent's transition timing.__tests__/hooks/useAndroidKeyboard.test.ts (3)
28-51: LGTM!The fake timer setup with proper teardown in
afterEachand the promise-based mock foraddListenercorrectly reflects the async nature of the Capacitor Keyboard API.
78-218: LGTM!The debounce tests properly validate timing behavior including the race condition where a show event cancels a pending hide. The consistent pattern of awaiting async listener setup before triggering callbacks is correct.
238-346: LGTM!The
getContainerStyletests provide comprehensive coverage including edge cases like negative transform prevention, existing transform combination, and transition preservation. The assertions correctly validate the transform calculation logic.
There was a problem hiding this comment.
Actionable comments posted: 0
♻️ Duplicate comments (1)
__tests__/hooks/useAndroidKeyboard.test.ts (1)
4-5: Add a comment documenting the DEBOUNCE_MS timing dependency.
DEBOUNCE_MSis not exported from the implementation, so it cannot be imported. The test duplicates the constant value independently. Add a comment noting that this timing must stay synchronized with the implementation'sDEBOUNCE_MSvalue to ensure tests remain valid if the debounce duration changes.
🧹 Nitpick comments (1)
__tests__/hooks/useAndroidKeyboard.test.ts (1)
385-405: Refactor the assertion to make test intent clearer.The assertion
expect(true).toBe(true)at line 404 is a no-op. The real test is that unmounting with pending timeouts doesn't throw. Consider restructuring to make the intent explicit.Apply this diff:
- it('clears pending timeouts on unmount', async () => { + it('safely clears pending timeouts on unmount without throwing', async () => { const { result, unmount } = renderHook(() => useAndroidKeyboard()); await act(async () => { await Promise.resolve(); }); - // Start a show that hasn't completed act(() => { showCallback({ keyboardHeight: 350 }); - // Don't advance time - timeout is pending }); - unmount(); + expect(() => unmount()).not.toThrow(); act(() => { jest.advanceTimersByTime(DEBOUNCE_MS * 2); }); - - expect(true).toBe(true); });
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
__tests__/hooks/useAndroidKeyboard.test.ts(6 hunks)components/brain/my-stream/layout/LayoutContext.tsx(3 hunks)components/layout/AppLayout.tsx(4 hunks)hooks/useAndroidKeyboard.ts(3 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- components/brain/my-stream/layout/LayoutContext.tsx
- components/layout/AppLayout.tsx
🧰 Additional context used
📓 Path-based instructions (10)
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (.cursorrules)
**/*.{ts,tsx,js,jsx}: Do not include any comments in the code; it should be self-explanatory
Write correct, up-to-date, bug-free, fully componentized, secure, and efficient code
Include all required imports and ensure proper naming of key components
Use NextJS features that match the current version
**/*.{ts,tsx,js,jsx}: Replace<img>elements with<Image />fromnext/imageto satisfy@next/next/no-img-elementESLint rule
Use<Link href="/path">from Next.js for internal navigation instead of plain HTML links to satisfy@next/next/no-html-link-for-pagesESLint rule
Files:
__tests__/hooks/useAndroidKeyboard.test.tshooks/useAndroidKeyboard.ts
**/*.{js,jsx,ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{js,jsx,ts,tsx}: Code must satisfy ESLint (Next's Core Web Vitals + React Hooks)
Use framework APIs: internal links should use<Link>, images should usenext/image, and adopt Next's ESLint rules (Core Web Vitals)
**/*.{js,jsx,ts,tsx}: Code must satisfy ESLint (Next's Core Web Vitals + React Hooks rules)
Follow existing code style and naming conventions; maintain clean code standards (measured by SonarQube)
Files:
__tests__/hooks/useAndroidKeyboard.test.tshooks/useAndroidKeyboard.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
**/*.{ts,tsx}: Must passtsc --noEmittype checking
Prefer direct named imports for React hooks and types (import { useMemo, useRef, FC, etc. } from "react") overReact.namespace usage (React.useMemo,React.useRef, etc.)
If thereact-hooks/exhaustive-depslint rule is triggered: if the Effect only derives state, remove the Effect and compute during render; if listening to an external system and needing fresh props/state, wrap non-reactive logic inuseEffectEvent
**/*.{ts,tsx}: Must passtsc --noEmitfor TypeScript type checking
Prefer Server Components over Client Components; use Server Functions/Server Actions ('use server') for mutations
Remove unnecessary Effects; if Effect only derives state, compute during render instead
UseuseEffectEventfor non-reactive logic inside Effects to avoid unnecessary re-runs
Use framework APIs:<Link>for internal links,next/imagefor images, adopt Next's ESLint rules
Use'use cache'directive and Cache Components features for explicit opt-in caching in Next.js 16
Use TypeScript and React functional components with hooks
When parsing Seize URLs or similar, fail fast if base origin is unavailable; do not fall back to placeholder origins
Replace<img>elements with<Image />fromnext/image
Use<Link href="/path">for internal navigation instead of plain HTML links
Move data fetches to Server Components; handle mutations through Server Functions/Server Actions with'use server'directive
Files:
__tests__/hooks/useAndroidKeyboard.test.tshooks/useAndroidKeyboard.ts
**/@(__tests__|*.test).{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Tests should live in
__tests__/orComponentName.test.tsx; mock external dependencies and APIs in tests
Files:
__tests__/hooks/useAndroidKeyboard.test.ts
**/__tests__/**/*.{ts,tsx}
📄 CodeRabbit inference engine (GEMINI.md)
Place tests in
__tests__/directory or asComponentName.test.tsxalongside components
Files:
__tests__/hooks/useAndroidKeyboard.test.ts
**/*.test.{ts,tsx}
📄 CodeRabbit inference engine (GEMINI.md)
Mock external dependencies and APIs in tests
Files:
__tests__/hooks/useAndroidKeyboard.test.ts
__tests__/**/*.test.{ts,tsx}
📄 CodeRabbit inference engine (tests/AGENTS.md)
Use Jest +
ts-jestfor TypeScript testing
Files:
__tests__/hooks/useAndroidKeyboard.test.ts
__tests__/**/*.{ts,tsx}
📄 CodeRabbit inference engine (tests/AGENTS.md)
Functions must have ≤ 15 cognitive complexity; extract deep ternaries (>3 levels) and break down complex logic
Files:
__tests__/hooks/useAndroidKeyboard.test.ts
__tests__/**/*.{ts,tsx,js}
📄 CodeRabbit inference engine (tests/AGENTS.md)
__tests__/**/*.{ts,tsx,js}: Preferfor...ofloops overforEachas it allowsbreak/continueand works with async/await
Usearray.at(-1)andarray.at(-2)instead of index-based array access for negative indexing
UseString.prototype.replaceAll()instead ofreplace()for global string replacements
UseglobalThis.fetch()instead of directfetch()calls
Organize imports with one import per module in order: external → internal → types, with no duplicates
Useelement.remove()instead ofparent.removeChild(element)for DOM manipulation
Catch errors only when meaningful; no empty catch blocks; log errors with context
Avoid double negatives in code; prefer explicit logic and remove redundant annotations; use optional chaining (?.)
Files:
__tests__/hooks/useAndroidKeyboard.test.ts
__tests__/**/{components,contexts,hooks}/**/*.{ts,tsx}
📄 CodeRabbit inference engine (tests/AGENTS.md)
Use semantic HTML elements (
<label>,<output>) over ARIA attributes when possible; every form control must have a label
Files:
__tests__/hooks/useAndroidKeyboard.test.ts
🧠 Learnings (8)
📚 Learning: 2025-12-05T10:55:43.476Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __tests__/AGENTS.md:0-0
Timestamp: 2025-12-05T10:55:43.476Z
Learning: Applies to __tests__/**/__tests__/**/components/**/*.test.{ts,tsx} : Test accessibility with keyboard navigation and screen reader compatibility
Applied to files:
__tests__/hooks/useAndroidKeyboard.test.ts
📚 Learning: 2025-12-05T10:55:30.871Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: GEMINI.md:0-0
Timestamp: 2025-12-05T10:55:30.871Z
Learning: Applies to **/*.test.{ts,tsx} : Mock external dependencies and APIs in tests
Applied to files:
__tests__/hooks/useAndroidKeyboard.test.ts
📚 Learning: 2025-12-03T14:52:34.271Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-03T14:52:34.271Z
Learning: Applies to **/@(__tests__|*.test).{ts,tsx} : Tests should live in `__tests__/` or `ComponentName.test.tsx`; mock external dependencies and APIs in tests
Applied to files:
__tests__/hooks/useAndroidKeyboard.test.ts
📚 Learning: 2025-12-05T10:55:43.476Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __tests__/AGENTS.md:0-0
Timestamp: 2025-12-05T10:55:43.476Z
Learning: Applies to __tests__/**/__tests__/**/components/**/*.test.{ts,tsx} : Use testing-library/react + user-event for React component tests
Applied to files:
__tests__/hooks/useAndroidKeyboard.test.ts
📚 Learning: 2025-12-05T10:55:43.476Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: __tests__/AGENTS.md:0-0
Timestamp: 2025-12-05T10:55:43.476Z
Learning: Applies to __tests__/**/*.{ts,tsx,js} : Avoid double negatives in code; prefer explicit logic and remove redundant annotations; use optional chaining (`?.`)
Applied to files:
__tests__/hooks/useAndroidKeyboard.test.ts
📚 Learning: 2025-12-05T10:55:30.871Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: GEMINI.md:0-0
Timestamp: 2025-12-05T10:55:30.871Z
Learning: Applies to **/*.{ts,tsx} : Use TypeScript and React functional components with hooks
Applied to files:
__tests__/hooks/useAndroidKeyboard.test.tshooks/useAndroidKeyboard.ts
📚 Learning: 2025-12-03T14:52:34.271Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-03T14:52:34.271Z
Learning: Fix with modernization (no `// eslint-disable` unless explicitly instructed); prefer refactors aligned with React 19.2, React Compiler, and Next.js 16 conventions
Applied to files:
__tests__/hooks/useAndroidKeyboard.test.tshooks/useAndroidKeyboard.ts
📚 Learning: 2025-12-03T14:52:34.271Z
Learnt from: CR
Repo: 6529-Collections/6529seize-frontend PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-03T14:52:34.271Z
Learning: Applies to **/*.{ts,tsx} : Prefer direct named imports for React hooks and types (`import { useMemo, useRef, FC, etc. } from "react"`) over `React.` namespace usage (`React.useMemo`, `React.useRef`, etc.)
Applied to files:
hooks/useAndroidKeyboard.ts
🧬 Code graph analysis (1)
__tests__/hooks/useAndroidKeyboard.test.ts (1)
hooks/useAndroidKeyboard.ts (1)
useAndroidKeyboard(16-123)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (9)
hooks/useAndroidKeyboard.ts (4)
3-3: LGTM! Clean debounce setup.The
useRefimport,DEBOUNCE_MSconstant, and timeout refs are properly structured for implementing debounced keyboard handling.Also applies to: 14-15, 23-24
33-59: LGTM! Robust debounce implementation.The mutual cancellation logic ensures that rapid show/hide events don't cause race conditions. The
mountedguard prevents state updates after unmount, and the CSS variable stays synchronized with the keyboard state.
67-67: LGTM! Proper listener integration and cleanup.The keyboard event listeners correctly delegate to the debounced functions, and the cleanup logic ensures pending timeouts are cleared to prevent memory leaks.
Also applies to: 71-71, 93-94
99-120: LGTM! Container style logic is debounce-aware.The
getContainerStylecallback correctly usesisVisibleandkeyboardHeightin its dependencies, ensuring that style transforms align with the debounced keyboard state.__tests__/hooks/useAndroidKeyboard.test.ts (5)
29-29: LGTM! Proper fake timer setup.The fake timer setup and teardown follows Jest best practices, ensuring tests don't interfere with each other and timers are properly controlled for debounce testing.
Also applies to: 49-51
45-45: LGTM! Mock matches async implementation.The mock correctly returns a Promise to match the async listener setup in the implementation.
78-93: LGTM! Comprehensive debounce testing.The tests correctly wait for async listener setup, advance timers by the debounce period, and verify state transitions. Good coverage of show, hide, and fallback scenarios.
Also applies to: 95-119, 121-149
187-218: LGTM! Cancellation logic well-tested.This test correctly verifies that a pending hide is cancelled when show is called mid-debounce, ensuring the mutual cancellation logic works as intended.
238-346: LGTM! Thorough testing of styles and cleanup.The
getContainerStyletests comprehensively cover different keyboard states with proper debounce timing, and the cleanup tests verify that listeners are removed and CSS variables are reset correctly.Also applies to: 349-383
|



Summary by CodeRabbit
✏️ Tip: You can customize this high-level summary in your review settings.