Skip to content

Fix frequent map locking on landing page (#4301)#4307

Open
Akshat1931 wants to merge 4 commits intoOWASP:mainfrom
Akshat1931:fix-map-locking-4301
Open

Fix frequent map locking on landing page (#4301)#4307
Akshat1931 wants to merge 4 commits intoOWASP:mainfrom
Akshat1931:fix-map-locking-4301

Conversation

@Akshat1931
Copy link

@Akshat1931 Akshat1931 commented Mar 18, 2026

Proposed change

Resolves #4301

This PR fixes the frequent map locking issue on the landing page by removing the automatic lock-on-mouseleave behavior and adding an explicit lock button.

Why this change is needed:
Poor UX: The map re-locks every time the cursor leaves the map container, making it impossible to pan/zoom smoothly.
Accessibility: Users with motor impairments or slow movements get frustrated by constant re-locking.

Technical Implementation:
frontend/src/components/ChapterMap.tsx: Removed onMouseLeave handler that auto-locked the map. Added a lock button (FaLock icon) next to the location sharing button, visible when the map is unlocked.

Checklist

  • Required: I followed the contributing workflow
  • Required: I verified that my code works as intended and resolves the issue as described
  • Required: I ran make check-test locally: all warnings addressed, tests passed
  • I used AI for code, documentation, tests, or communication related to this PR

cubic-dev-ai[bot]
cubic-dev-ai bot previously approved these changes Mar 18, 2026
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

No issues found across 1 file

Confidence score: 5/5

  • Automated review surfaced no issues in the provided summaries.
  • No files require special attention.

Since this is your first cubic review, here's how it works:

  • cubic automatically reviews your code and comments on bugs and improvements
  • Teach cubic by replying to its comments. cubic learns from your replies and gets better over time
  • Add one-off context when rerunning by tagging @cubic-dev-ai with guidance or docs links (including llms.txt)
  • Ask questions if you need clarification on any suggestion

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 19, 2026

Summary by CodeRabbit

  • New Features

    • Updated active-map toolbar layout and positioned the share-location control alongside the unlock UI.
  • Bug Fixes

    • Map deactivation now only occurs when the pointer truly leaves the map area, preventing premature locking.
  • Tests

    • Unit tests updated to validate pointer-leave behavior, including a negative test ensuring the map remains unlocked when the pointer stays within bounds.

Walkthrough

Replace unconditional section onMouseLeave deactivation with pointer-leave handling that deactivates only when the pointer truly leaves the section bounds; add section ref and containment checks. Update active-toolbar layout and adjust tests to use pointer events and assert boundary-sensitive behavior.

Changes

Cohort / File(s) Summary
ChapterMap component
frontend/src/components/ChapterMap.tsx
Replace outer onMouseLeave with onPointerLeave that checks section bounding rect and relatedTarget containment before calling setIsMapActive(false); add section ref; adjust active-toolbar layout (w-fitflex gap-2) and import usage.
ChapterMap tests
frontend/__tests__/unit/components/ChapterMap.test.tsx
Switch tests from fireEvent.mouseLeave on container child to fireEvent.pointerLeave on the section with synthetic clientX/clientY derived from getBoundingClientRect; rename tests and add a negative test asserting pointer-leave inside bounds does not relock map or call teardown methods.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • arkid15r
  • kasya
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main change: fixing the frequent map locking issue on the landing page by referencing the linked issue #4301.
Description check ✅ Passed The description is clearly related to the changeset, explaining the problem (frequent map locking), the solution (removing auto-lock on mouse leave, adding explicit lock button), and the technical rationale.
Linked Issues check ✅ Passed The PR successfully addresses issue #4301 by replacing the problematic onMouseLeave handler with onPointerLeave boundary detection and adding an explicit lock button, resolving the movement-based re-locking behavior.
Out of Scope Changes check ✅ Passed All changes are directly related to fixing the map locking issue: pointer-leave boundary detection logic, explicit lock button UI, and corresponding unit tests validating the new behavior.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
📝 Coding Plan
  • Generate coding plan for human review comments

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.

cubic-dev-ai[bot]
cubic-dev-ai bot previously approved these changes Mar 19, 2026
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

0 issues found across 2 files (changes from recent commits).

Copy link
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

🤖 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/src/components/ChapterMap.tsx`:
- Around line 160-176: The component currently re-locks the map automatically in
handlePointerLeave by calling setIsMapActive(false) which conflicts with the new
explicit locking behavior; remove that automatic deactivation from
handlePointerLeave (stop calling setIsMapActive(false) there) and add an
explicit lock state (e.g. const [isMapLocked, setIsMapLocked] = useState(false))
in ChapterMap; render a lock/unlock button beside the existing ShareLocation UI
(the share-location area rendered around the previous lines 309-332) that
toggles isMapLocked, and update any logic that would automatically change
isMapActive to check isMapLocked first (only allow deactivation when isMapLocked
is false). Ensure handlers reference handlePointerLeave, setIsMapActive and
isMapActive so the new lock state prevents auto-relock and provides explicit
user control.
🪄 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: cf491a94-1d87-4ce7-aad5-795dfd3facd4

📥 Commits

Reviewing files that changed from the base of the PR and between b1087f9 and 86c55a4.

📒 Files selected for processing (2)
  • frontend/__tests__/unit/components/ChapterMap.test.tsx
  • frontend/src/components/ChapterMap.tsx

@codecov
Copy link

codecov bot commented Mar 19, 2026

Codecov Report

❌ Patch coverage is 70.00000% with 6 lines in your changes missing coverage. Please review.
✅ Project coverage is 99.35%. Comparing base (b1087f9) to head (86c55a4).
⚠️ Report is 2 commits behind head on main.

Files with missing lines Patch % Lines
frontend/src/components/ChapterMap.tsx 70.00% 0 Missing and 6 partials ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             main    #4307      +/-   ##
==========================================
- Coverage   99.39%   99.35%   -0.04%     
==========================================
  Files         520      520              
  Lines       16444    16462      +18     
  Branches     2294     2300       +6     
==========================================
+ Hits        16344    16356      +12     
  Misses         62       62              
- Partials       38       44       +6     
Flag Coverage Δ
backend 99.83% <ø> (ø)
frontend 98.02% <70.00%> (-0.14%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
frontend/src/components/ChapterMap.tsx 95.58% <70.00%> (-4.42%) ⬇️

Continue to review full report in Codecov by Sentry.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update b1087f9...86c55a4. Read the comment docs.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@Akshat1931 Akshat1931 force-pushed the fix-map-locking-4301 branch from 24245ab to b98c952 Compare March 19, 2026 05:45
Copy link
Collaborator

@kasya kasya left a comment

Choose a reason for hiding this comment

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

@Akshat1931 thanks for opening this issue!

I’m not fully convinced a "lock map" button is the right approach. We originally added the auto-lock on mouseleave to prevent scroll conflicts—users would scroll the page, get stuck on the map, and unintentionally zoom in, making it difficult to move past. If the map stays unlocked unless users manually relock it, we could run into the same issue again.

While looking into this, I noticed a pattern: the map sometimes locks unexpectedly when the cursor moves over pin/zone areas. It seems like Leaflet overlays or popups can trigger a mouseleave-like event even when the cursor is still within the map container. Instead of adding a button, we might want to address this directly—for example, by checking whether the cursor is actually outside the map bounds before locking it.


I can see you reverted my changes by pushing your updates again. Could you please revert that?

@Akshat1931 Akshat1931 force-pushed the fix-map-locking-4301 branch from b98c952 to 76b3aa3 Compare March 19, 2026 15:26
@Akshat1931
Copy link
Author

@kasya Thanks for the feedback! I’ve reverted my previous changes that introduced the lock button and aligned with your approach.

I’ll now focus on fixing the pointer leave detection issue so that the map only locks when the cursor actually exits the container, avoiding unintended locks caused by Leaflet overlays or popups.

coderabbitai[bot]
coderabbitai bot previously approved these changes Mar 19, 2026
Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

1 issue found across 2 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="frontend/__tests__/unit/components/ChapterMap.test.tsx">

<violation number="1" location="frontend/__tests__/unit/components/ChapterMap.test.tsx:280">
P2: The new pointer-boundary test does not control element bounds, so its "inside section" coordinates can be outside in jsdom and fail to validate the intended branch.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.

@sonarqubecloud
Copy link

Copy link
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

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

0 issues found across 1 file (changes from recent commits).

@Akshat1931
Copy link
Author

Updated this so the map only relocks when the pointer actually exits the map container bounds, while preserving the existing auto-lock behavior. I verified it locally, and it stays unlocked over pins/overlay areas inside the map and relocks when the pointer leaves the container.

@Akshat1931 Akshat1931 requested a review from kasya March 19, 2026 18:41
Copy link
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.

🧹 Nitpick comments (2)
frontend/__tests__/unit/components/ChapterMap.test.tsx (2)

272-300: Consider adding an exact-edge boundary test.

A case with clientX/clientY exactly on left/right/top/bottom would lock in the inclusive boundary contract and prevent subtle regressions.

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

In `@frontend/__tests__/unit/components/ChapterMap.test.tsx` around lines 272 -
300, Add a new unit test case to ChapterMap.test.tsx that mirrors the existing
"keeps map unlocked when pointer leave fires but pointer is still inside section
bounds" test but uses clientX/clientY values exactly equal to one or more of the
mocked DOMRect edges (left, right, top, bottom) to assert the inclusive-boundary
behavior; reuse the same setup (render(<ChapterMap {...defaultProps} />), click
Unlock map, mock section.getBoundingClientRect on the same section element,
fireEvent.pointerLeave with clientX/clientY set to 100/300/200 as appropriate
for each edge, then assert queryByText('Unlock map') is not present and that
mockMap.scrollWheelZoom.disable and mockZoomControl.remove were not called to
ensure the map remains unlocked on exact-edge coordinates.

231-237: Guard section lookup before dispatching pointer events.

Line 231 and Line 257 use section!; if <section> markup changes, the test fails with a low-signal runtime error. Prefer an explicit existence check, then reuse the guaranteed element.

Proposed refactor
+const getSectionOrThrow = (container: HTMLElement): HTMLElement => {
+  const section = container.querySelector('section')
+  if (!section) throw new Error('Expected ChapterMap root <section> to exist')
+  return section as HTMLElement
+}
...
-const section = container.querySelector('section')
-const rect = section?.getBoundingClientRect() ?? { left: 0, top: 0, right: 0, bottom: 0 }
-fireEvent.pointerLeave(section!, {
+const section = getSectionOrThrow(container)
+const rect = section.getBoundingClientRect()
+fireEvent.pointerLeave(section, {
   clientX: rect.left - 10,
   clientY: rect.top - 10,
   relatedTarget: null,
 })
...
-const section = container.querySelector('section')
-const rect = section?.getBoundingClientRect() ?? { left: 0, top: 0, right: 0, bottom: 0 }
-fireEvent.pointerLeave(section!, {
+const section = getSectionOrThrow(container)
+const rect = section.getBoundingClientRect()
+fireEvent.pointerLeave(section, {
   clientX: rect.left - 10,
   clientY: rect.top - 10,
   relatedTarget: null,
 })

Also applies to: 257-263

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

In `@frontend/__tests__/unit/components/ChapterMap.test.tsx` around lines 231 -
237, The test is using non-null assertions on the DOM node (section!) which can
cause low-signal runtime errors if the <section> markup changes; modify the test
to explicitly query and guard the element before dispatching events: assign
const section = container.querySelector('section'), assert its existence (e.g.
if (!section) throw new Error('expected <section> in ChapterMap render') or use
expect(section).not.toBeNull()), then reuse the guaranteed section variable when
calling fireEvent.pointerLeave and the similar pointer event block (the lines
using section! around fireEvent.pointerLeave and the other block at 257-263) so
you no longer rely on the non-null assertion.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@frontend/__tests__/unit/components/ChapterMap.test.tsx`:
- Around line 272-300: Add a new unit test case to ChapterMap.test.tsx that
mirrors the existing "keeps map unlocked when pointer leave fires but pointer is
still inside section bounds" test but uses clientX/clientY values exactly equal
to one or more of the mocked DOMRect edges (left, right, top, bottom) to assert
the inclusive-boundary behavior; reuse the same setup (render(<ChapterMap
{...defaultProps} />), click Unlock map, mock section.getBoundingClientRect on
the same section element, fireEvent.pointerLeave with clientX/clientY set to
100/300/200 as appropriate for each edge, then assert queryByText('Unlock map')
is not present and that mockMap.scrollWheelZoom.disable and
mockZoomControl.remove were not called to ensure the map remains unlocked on
exact-edge coordinates.
- Around line 231-237: The test is using non-null assertions on the DOM node
(section!) which can cause low-signal runtime errors if the <section> markup
changes; modify the test to explicitly query and guard the element before
dispatching events: assign const section = container.querySelector('section'),
assert its existence (e.g. if (!section) throw new Error('expected <section> in
ChapterMap render') or use expect(section).not.toBeNull()), then reuse the
guaranteed section variable when calling fireEvent.pointerLeave and the similar
pointer event block (the lines using section! around fireEvent.pointerLeave and
the other block at 257-263) so you no longer rely on the non-null assertion.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 87ac9cfc-fbe0-4f4f-a105-170b44ef2a92

📥 Commits

Reviewing files that changed from the base of the PR and between d7b8156 and b727d8a.

📒 Files selected for processing (1)
  • frontend/__tests__/unit/components/ChapterMap.test.tsx

@pUrGe12
Copy link

pUrGe12 commented Mar 20, 2026

@Akshat1931 @kasya Thanks guys!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

landing page map is locking very frequently

3 participants