Skip to content

Fix/price picker keyboard avoidance#94

Merged
jaydonkc merged 11 commits intodevfrom
fix/price-picker-keyboard-avoidance
Apr 21, 2026
Merged

Fix/price picker keyboard avoidance#94
jaydonkc merged 11 commits intodevfrom
fix/price-picker-keyboard-avoidance

Conversation

@dfed25
Copy link
Copy Markdown
Collaborator

@dfed25 dfed25 commented Apr 17, 2026

Linked Issues

Closes #94
Linear: POLY-83 (e.g., POLY-123)

Summary

Briefly explain the change and why.

How to Test

Steps to verify locally:

  • npm run lint
  • npm run typecheck
  • npm test
  • Manual flow:
    1. npm run dev:backend (in terminal A)
    2. npm run dev (in terminal B)
    3. Verify the change: <describe expected behavior/screens>

Checklist

  • Tests added/updated (if applicable)
  • Lint/tests pass locally (npm run lint)
  • Docs updated (README/ADR/changelog if needed)
  • Follows conventional commit format
  • No merge conflicts with dev

Screenshots / Demos

(if UI or visible behavior - attach images, videos, or GIFs)

Summary by CodeRabbit

  • Bug Fixes

    • Improved price range modal layout, keyboard handling, and dismissal for more reliable visibility and interactions.
    • Made sheet content scrollable and updated safe-area behavior so controls remain accessible on devices with notches.
    • Enhanced composer and message-list keyboard behavior and padding to prevent overlap during typing.
  • New Features

    • Added a dismissible Safety banner with a close control and updated header layout.
  • Refactor

    • Reworked modal and composer structure for more predictable scrolling and keyboard support.

dfed25 added 4 commits April 13, 2026 21:59
Expo resolves @sentry/react-native/expo relative to the frontend package; it was only on the root workspace so Vercel installs did not expose the plugin and expo export failed.

Made-with: Cursor
- KeyboardAvoidingView (iOS padding, Android height) above bottom sheet
- ScrollView so presets, inputs, and Apply stay reachable when keyboard is open
- Backdrop as sibling Pressable so sheet scrolling is not blocked
- Safe-area padding on scroll content; cap sheet height for smaller screens

Made-with: Cursor
@vercel
Copy link
Copy Markdown

vercel Bot commented Apr 17, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
poly-buys Ready Ready Preview, Comment Apr 21, 2026 6:11am

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 17, 2026

Warning

Rate limit exceeded

@jaydonkc has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 12 minutes and 54 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 12 minutes and 54 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

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.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 30ca8def-faa0-4d94-a43c-509ab8974f85

📥 Commits

Reviewing files that changed from the base of the PR and between 388dd69 and e5fad59.

📒 Files selected for processing (2)
  • frontend/components/PriceRangePicker.tsx
  • frontend/components/SafetyBanner.tsx
📝 Walkthrough

Walkthrough

Reworks PriceRangePicker modal to a backdrop + sheet with keyboard listeners, animated sheet translation, and scrollable content; adds keyboard-aware padding/behavior to conversations composer; makes SafetyBanner dismissible with a close button and header layout.

Changes

Cohort / File(s) Summary
PriceRangePicker modal & keyboard
frontend/components/PriceRangePicker.tsx
Replaced single overlay with full-screen dimming backdrop and dedicated sheet container; added Keyboard listeners, Animated translate for sheet, scrollable sheet content (ScrollView + scrollViewRef), input-focus driven auto-scroll, safe-area bottom padding via useSafeAreaInsets(), and new styles (backdrop, sheetContainer, sheetLift, scrollContent).
Conversations composer keyboard/layout
frontend/app/conversations/[id].tsx
Added isKeyboardVisible state and platform-aware keyboard listeners; derived composerBottomPadding from keyboard/insets; adjusted KeyboardAvoidingView behavior and keyboardVerticalOffset per platform; set FlatList keyboardDismissMode conditionally; introduced MESSAGES_BOTTOM_PADDING and composer container styles.
SafetyBanner UI / dismissal
frontend/components/SafetyBanner.tsx
Added isVisible state to allow dismissal; replaced single title row with header row including a Pressable Close button and pressed-state feedback; updated title styling and header layout.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant PriceRangePicker
    participant Keyboard
    participant ScrollView

    User->>PriceRangePicker: open modal
    PriceRangePicker->>PriceRangePicker: render backdrop + sheet, attach keyboard listeners
    User->>PriceRangePicker: focus TextInput
    PriceRangePicker->>Keyboard: await show event
    Keyboard-->>PriceRangePicker: show(height)
    PriceRangePicker->>PriceRangePicker: animate sheet translateY (Animated.Value)
    PriceRangePicker->>ScrollView: scrollToEnd / ensure focused input visible
    User->>PriceRangePicker: tap backdrop
    PriceRangePicker->>Keyboard: dismiss
    PriceRangePicker->>PriceRangePicker: reset keyboard state, close modal
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • jaydonkc
  • SamanSP1386

Poem

🐰
I nudged the sheet when keys arise,
Backdrop deep and scrolling skies,
Insets snug so inputs stay in view,
Tap to close — the layout’s new,
Hopping off with a joyful chew.

🚥 Pre-merge checks | ✅ 2 | ❌ 3

❌ Failed checks (2 warnings, 1 inconclusive)

Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description follows the template structure but the 'Summary' section is left unfilled with only placeholder text 'Briefly explain the change and why.' No detailed explanation of the keyboard avoidance fix is provided. Complete the Summary section with a clear explanation of the keyboard avoidance changes, the problem being solved, and why these modifications improve the user experience.
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Out of Scope Changes check ❓ Inconclusive The PR includes changes to SafetyBanner (adding dismiss functionality) and conversations/[id].tsx (keyboard behavior updates) which appear related to keyboard handling improvements, though not explicitly mentioned in the issue title. Clarify whether the SafetyBanner and composer keyboard changes are intentional scope additions or should be separated into a different PR for focused review.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Fix/price picker keyboard avoidance' directly aligns with the main changes: reworking the PriceRangePicker component to handle keyboard appearance with scrollable content and improved layout.
Linked Issues check ✅ Passed The code changes directly address the linked issue requirements: the PriceRangePicker now includes keyboard listeners, scrollable sheet content, safe-area adjustments, and improved keyboard dismissal behavior as specified.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/price-picker-keyboard-avoidance

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
frontend/package.json (1)

17-23: ⚠️ Potential issue | 🟡 Minor

Remove duplicate @sentry/react-native entry.

@sentry/react-native is now declared twice (line 17 and line 23) with the same version. Biome flags this as a duplicate object key, and strict JSON parsers / npm pkg operations may behave inconsistently. Since the dependency already exists on line 23, the newly added line 17 is redundant and should be dropped (the PR goal of declaring it in the frontend workspace is already satisfied).

🔧 Proposed fix
   "dependencies": {
-    "@sentry/react-native": "^8.3.0",
     "@convex-dev/auth": "^0.0.90",
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/package.json` around lines 17 - 23, Remove the duplicate dependency
entry for "@sentry/react-native" so only one declaration of that package remains
in package.json; open the dependencies object, delete the redundant
"@sentry/react-native" line (the earlier duplicate), ensure the JSON stays valid
(commas updated) and then reinstall dependencies (npm/yarn/pnpm) to verify no
package-manager warnings.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@frontend/components/PriceRangePicker.tsx`:
- Around line 202-205: The backdrop style (backdrop) currently uses
StyleSheet.absoluteFillObject with backgroundColor: 'transparent', removing the
dim modal affordance; change the dimming to the sibling backdrop element instead
of this sheet-level backdrop so the sheet can still scroll above it—update the
style for the sibling backdrop (where the overlay element is rendered) to use
the dim color (e.g., rgba(...) or theme overlay token) and keep the existing
backdrop style (backdrop) as absoluteFillObject but transparent so it doesn't
block interaction; ensure the sibling backdrop's zIndex/position places it below
the sheet so the sheet remains scrollable above it.

---

Outside diff comments:
In `@frontend/package.json`:
- Around line 17-23: Remove the duplicate dependency entry for
"@sentry/react-native" so only one declaration of that package remains in
package.json; open the dependencies object, delete the redundant
"@sentry/react-native" line (the earlier duplicate), ensure the JSON stays valid
(commas updated) and then reinstall dependencies (npm/yarn/pnpm) to verify no
package-manager warnings.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 2a31b227-29a5-4080-bf2d-64d255bfa891

📥 Commits

Reviewing files that changed from the base of the PR and between 5dfa982 and 9be1e09.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (2)
  • frontend/components/PriceRangePicker.tsx
  • frontend/package.json

Comment on lines +202 to +205
backdrop: {
...StyleSheet.absoluteFillObject,
backgroundColor: 'transparent',
},
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Restore the dimmed modal backdrop.

The overlay no longer has a background color, and the new backdrop is fully transparent, so opening the picker loses the modal/dismiss affordance. Put the dim color on the sibling backdrop instead; it won’t block sheet scrolling because the sheet renders above it.

🎨 Proposed fix
  backdrop: {
    ...StyleSheet.absoluteFillObject,
-   backgroundColor: 'transparent',
+   backgroundColor: 'rgba(0, 0, 0, 0.35)',
  },
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
backdrop: {
...StyleSheet.absoluteFillObject,
backgroundColor: 'transparent',
},
backdrop: {
...StyleSheet.absoluteFillObject,
backgroundColor: 'rgba(0, 0, 0, 0.35)',
},
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/components/PriceRangePicker.tsx` around lines 202 - 205, The
backdrop style (backdrop) currently uses StyleSheet.absoluteFillObject with
backgroundColor: 'transparent', removing the dim modal affordance; change the
dimming to the sibling backdrop element instead of this sheet-level backdrop so
the sheet can still scroll above it—update the style for the sibling backdrop
(where the overlay element is rendered) to use the dim color (e.g., rgba(...) or
theme overlay token) and keep the existing backdrop style (backdrop) as
absoluteFillObject but transparent so it doesn't block interaction; ensure the
sibling backdrop's zIndex/position places it below the sheet so the sheet
remains scrollable above it.

- Remove duplicate @sentry/react-native from package.json
- Restore modal scrim on PriceRangePicker backdrop (rgba 0.35)

Made-with: Cursor
@jaydonkc
Copy link
Copy Markdown
Collaborator

@copilot resolve the merge conflicts in this pull request

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (2)
frontend/app/conversations/[id].tsx (2)

395-395: Avoid defining the same bottom padding twice.

styles.messagesContent already sets paddingBottom: MESSAGES_BOTTOM_PADDING, so the inline override at Line 395 is redundant.

🧹 Proposed cleanup
-        contentContainerStyle={[styles.messagesContent, { paddingBottom: MESSAGES_BOTTOM_PADDING }]}
+        contentContainerStyle={styles.messagesContent}

Also applies to: 553-557

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/app/conversations/`[id].tsx at line 395, Remove the redundant
padding by keeping a single source of truth for MESSAGES_BOTTOM_PADDING: either
delete the inline paddingBottom from the contentContainerStyle prop where you
currently pass contentContainerStyle={[styles.messagesContent, { paddingBottom:
MESSAGES_BOTTOM_PADDING }]} (so it just uses styles.messagesContent) or remove
paddingBottom from styles.messagesContent and keep the inline override—apply the
same change for the second occurrence around lines 553–557; reference symbols:
styles.messagesContent and MESSAGES_BOTTOM_PADDING.

194-228: Consider extracting the keyboard visibility logic into the shared keyboard-aware path.

This duplicates the keyboard/safe-area handling already represented by frontend/components/ui/KeyboardAwareScreen.tsx. A small shared hook, or reusing that wrapper where practical, would keep chat and future screens from drifting in keyboard behavior.

Also applies to: 334-343

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/app/conversations/`[id].tsx around lines 194 - 228, The keyboard
visibility and safe-area handling in the useEffect that registers
Keyboard.addListener and computes composerBottomPadding duplicates logic in
frontend/components/ui/KeyboardAwareScreen.tsx; extract this into a shared hook
(e.g., useKeyboardAware or useKeyboardVisibility) or wrap this page with the
existing KeyboardAwareScreen component, move the show/hide listener logic
(Keyboard.addListener, setIsKeyboardVisible) and bottom-padding computation
(composerBottomPadding) into that shared implementation, then replace the local
useEffect and composerBottomPadding usage in this file and the other occurrence
(lines ~334-343) with the shared hook or wrapper to avoid duplication.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@frontend/components/PriceRangePicker.tsx`:
- Around line 182-204: The sheet is being translated up by keyboardOffset (see
keyboardOffset used in styles.sheetLift/Animated.View and entranceStyle) but its
height/ScrollView (see ScrollView, scrollViewRef, contentContainerStyle and
styles.sheet) still measures to 100% causing content to be pushed off-screen;
fix by constraining the sheet/ScrollView maxHeight when the keyboard is
open—create an animated maxHeight value (e.g., Animated.subtract(screenHeight,
keyboardOffset) or interpolate keyboardOffset into a maxHeight) and apply it to
the Animated.View with styles.sheet (or the ScrollView container) so the visible
sheet height shrinks as it is lifted, ensuring header/presets remain reachable.

In `@frontend/components/SafetyBanner.tsx`:
- Around line 10-27: The SafetyBanner component currently uses local state
(isVisible/setIsVisible) so dismissal doesn't persist across remounts and the
close Pressable may be below the 44×44pt touch target; to fix, change the
dismissal to persist (e.g., store a "safetyBannerDismissed" flag in AsyncStorage
or your global store/context and read it on mount inside SafetyBanner) and
update the close control to ensure a minimum touch target by adding hitSlop to
the Pressable or applying explicit minWidth/minHeight (or larger padding) in the
styles referenced by styles.closeButton/styles.closeButtonText; keep the
existing setIsVisible for immediate UI feedback but also write the persistent
flag when the close handler runs and read that flag to initialize visibility on
mount.

---

Nitpick comments:
In `@frontend/app/conversations/`[id].tsx:
- Line 395: Remove the redundant padding by keeping a single source of truth for
MESSAGES_BOTTOM_PADDING: either delete the inline paddingBottom from the
contentContainerStyle prop where you currently pass
contentContainerStyle={[styles.messagesContent, { paddingBottom:
MESSAGES_BOTTOM_PADDING }]} (so it just uses styles.messagesContent) or remove
paddingBottom from styles.messagesContent and keep the inline override—apply the
same change for the second occurrence around lines 553–557; reference symbols:
styles.messagesContent and MESSAGES_BOTTOM_PADDING.
- Around line 194-228: The keyboard visibility and safe-area handling in the
useEffect that registers Keyboard.addListener and computes composerBottomPadding
duplicates logic in frontend/components/ui/KeyboardAwareScreen.tsx; extract this
into a shared hook (e.g., useKeyboardAware or useKeyboardVisibility) or wrap
this page with the existing KeyboardAwareScreen component, move the show/hide
listener logic (Keyboard.addListener, setIsKeyboardVisible) and bottom-padding
computation (composerBottomPadding) into that shared implementation, then
replace the local useEffect and composerBottomPadding usage in this file and the
other occurrence (lines ~334-343) with the shared hook or wrapper to avoid
duplication.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 8d21f7f7-6ba7-40eb-9a37-b09d5dd34114

📥 Commits

Reviewing files that changed from the base of the PR and between b701a2c and 0a50033.

📒 Files selected for processing (3)
  • frontend/app/conversations/[id].tsx
  • frontend/components/PriceRangePicker.tsx
  • frontend/components/SafetyBanner.tsx

Comment thread frontend/components/PriceRangePicker.tsx
Comment thread frontend/components/SafetyBanner.tsx Outdated
…ard-avoidance

# Conflicts:
#	frontend/app/conversations/[id].tsx

Co-authored-by: jaydonkc <79879038+jaydonkc@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 21, 2026

@copilot resolve the merge conflicts in this pull request

Resolved. The merge conflict in frontend/app/conversations/[id].tsx has been fixed in commit 388dd69. The resolution combines:

  • HEAD's keyboard avoidance improvements (process.env.EXPO_OS platform checks, keyboardDismissMode, composerBottomPadding)
  • dev's reporting features (ReportableMessageRow, ReportModal, TouchableWithoutFeedback wrapper, onScrollBeginDrag)
  • Also restored the missing Platform import that was dropped during auto-merge.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@frontend/app/conversations/`[id].tsx:
- Around line 664-667: The stylesheet contains an unused entry
composerContainer; either remove composerContainer from the styles object to
satisfy react-native/no-unused-styles, or merge its intent into the active style
used by the composer View (styles.composerWrap) by adding flexShrink: 0 and
backgroundColor: colors.surface to composerWrap so the composer isn’t
squeezed—update the styles object accordingly and remove the unused
composerContainer symbol if you merge.
- Around line 284-314: Replace all uses of the build-time constant
process.env.EXPO_OS with the runtime Platform.OS in this component: update the
useEffect that registers Keyboard listeners (the function using
Keyboard.addListener and setIsKeyboardVisible), update the KeyboardAvoidingView
props block that currently branches on EXPO_OS, and update the FlatList's
keyboardDismissMode to branch on Platform.OS instead; ensure you keep the
existing iOS-specific listeners (keyboardWillShow/WillHide) and the default
DidShow/DidHide listeners for other platforms. Also remove the unused style
named composerContainer from the component's styles object to clean up dead
code.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 8c7f2f3a-69f7-474f-8509-74f035f83782

📥 Commits

Reviewing files that changed from the base of the PR and between 0a50033 and 388dd69.

📒 Files selected for processing (1)
  • frontend/app/conversations/[id].tsx

Comment thread frontend/app/conversations/[id].tsx Outdated
Comment thread frontend/app/conversations/[id].tsx Outdated
@jaydonkc jaydonkc merged commit a4b8459 into dev Apr 21, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants