Skip to content

Commit ebc2153

Browse files
feat: close CurrencySelect dropdown when it leaves the viewport using IntersectionObserver
Signed-off-by: darshitdudhaiya <darshitdudhaiya201@gmail.com>
1 parent 38c616b commit ebc2153

File tree

1 file changed

+74
-7
lines changed

1 file changed

+74
-7
lines changed

src/sections/Pricing/index.js

Lines changed: 74 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { useState } from "react";
1+
import React, { useState, useRef, useEffect } from "react";
22
import PricingWrapper from "./pricing.style";
33
import Comparison from "./comparison";
44
import FAQ from "../General/Faq";
@@ -42,8 +42,72 @@ const getCustomToggleButtonStyle = (isActive, baseStyle) => ({
4242
});
4343

4444
export const CurrencySelect = ({ currency, setCurrency }) => {
45+
const [open, setOpen] = useState(false);
46+
47+
const containerRef = useRef(null);
48+
const toggleRef = useRef(null);
49+
50+
useEffect(() => {
51+
if (!open) return;
52+
53+
const el = toggleRef.current ?? containerRef.current;
54+
if (!el) return;
55+
56+
if ("IntersectionObserver" in window) {
57+
const observer = new IntersectionObserver(
58+
(entries) => {
59+
entries.forEach((entry) => {
60+
if (!entry.isIntersecting) {
61+
setOpen(false);
62+
}
63+
});
64+
},
65+
{ root: null, threshold: 0.1 }
66+
);
67+
68+
observer.observe(el);
69+
return () => observer.disconnect();
70+
}
71+
72+
let ticking = false;
73+
const checkRect = () => {
74+
const currentEl = toggleRef.current ?? containerRef.current;
75+
if (!currentEl) return;
76+
77+
const rect = currentEl.getBoundingClientRect();
78+
const isOutOfView =
79+
rect.bottom < 0 ||
80+
rect.top > window.innerHeight ||
81+
rect.right < 0 ||
82+
rect.left > window.innerWidth;
83+
84+
if (isOutOfView) {
85+
setOpen(false);
86+
}
87+
};
88+
89+
const onScroll = () => {
90+
if (!ticking) {
91+
ticking = true;
92+
window.requestAnimationFrame(() => {
93+
checkRect();
94+
ticking = false;
95+
});
96+
}
97+
};
98+
99+
window.addEventListener("scroll", onScroll, { passive: true, capture: true });
100+
window.addEventListener("resize", checkRect, { passive: true });
101+
102+
return () => {
103+
window.removeEventListener("scroll", onScroll, { capture: true });
104+
window.removeEventListener("resize", checkRect);
105+
};
106+
}, [open]);
107+
45108
return (
46109
<FormControl
110+
ref={containerRef}
47111
variant="outlined"
48112
size="small"
49113
sx={{
@@ -70,12 +134,15 @@ export const CurrencySelect = ({ currency, setCurrency }) => {
70134
}}
71135
>
72136
<InputLabel id="currency-selector-label">Currency</InputLabel>
137+
73138
<Select
139+
ref={toggleRef}
74140
labelId="currency-selector-label"
75141
value={currency}
76-
onChange={(e) => {
77-
setCurrency(e.target.value);
78-
}}
142+
open={open}
143+
onOpen={() => setOpen(true)}
144+
onClose={() => setOpen(false)}
145+
onChange={(e) => setCurrency(e.target.value)}
79146
label="Currency"
80147
renderValue={(value) => (
81148
<Box sx={{ display: "flex", alignItems: "center", gap: 1, color: "#fff" }}>
@@ -84,7 +151,8 @@ export const CurrencySelect = ({ currency, setCurrency }) => {
84151
</Box>
85152
)}
86153
MenuProps={{
87-
disablePortal: true, // Render menu inside parent so it scrolls perfectly
154+
disablePortal: true,
155+
disableScrollLock: true,
88156
PaperProps: {
89157
sx: {
90158
backgroundColor: "#1E1E1E",
@@ -97,9 +165,7 @@ export const CurrencySelect = ({ currency, setCurrency }) => {
97165
anchorOrigin: { vertical: "bottom", horizontal: "left" },
98166
transformOrigin: { vertical: "top", horizontal: "left" },
99167
marginThreshold: 0,
100-
disableScrollLock: true,
101168
}}
102-
103169
>
104170
{Object.entries(Currencies).map(([code, { symbol, name }]) => (
105171
<MenuItem key={code} value={code}>
@@ -114,6 +180,7 @@ export const CurrencySelect = ({ currency, setCurrency }) => {
114180
);
115181
};
116182

183+
117184
const Pricing = () => {
118185
// const [monthly, setMonthly] = useState(false);
119186
const [isYearly, setIsYearly] = useState(false);

0 commit comments

Comments
 (0)