Skip to content

Commit 7eca56a

Browse files
update(OUT-2100): Dropdowns extend beyond screen content
- [X] created a custom hook that compares the dropdown with viewport and add the styles to show the dropdown inside viewport
1 parent ce31b2d commit 7eca56a

2 files changed

Lines changed: 40 additions & 0 deletions

File tree

src/components/dashboard/settings/sections/product/ProductMappingTable.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { ProductMappingComponentType } from '@/components/dashboard/settings/sections/product/ProductMapping'
22
import { ProductMappingItemType } from '@/db/schema/qbProductSync'
33
import useClickOutside from '@/hook/useClickOutside'
4+
import { useDropdownPosition } from '@/hook/useDropdown'
45
import {
56
ProductDataType,
67
useMapItem,
@@ -78,6 +79,8 @@ export default function ProductMappingTable({
7879
Object.values(buttonRefs.current).map((el) => ({ current: el })), // Exclude the button from outside click detection
7980
)
8081

82+
useDropdownPosition(openDropdowns, dropdownRef)
83+
8184
return (
8285
<>
8386
<div className="product-mapping-table bg-white border border-gray-200 text-left">

src/hook/useDropdown.ts

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import { useEffect } from 'react'
2+
3+
export function useDropdownPosition(
4+
openDropdowns: {
5+
[key: number]: boolean
6+
},
7+
dropdownRef: React.RefObject<HTMLElement | null>,
8+
) {
9+
useEffect(() => {
10+
Object.entries(openDropdowns).forEach(([index, isOpen]) => {
11+
if (isOpen) {
12+
const dropdown = dropdownRef.current
13+
if (dropdown) {
14+
const rect = dropdown.getBoundingClientRect()
15+
const buffer = 10 // small padding from edge
16+
// Check if it's going off the screen at the bottom
17+
if (rect.bottom > window.innerHeight) {
18+
dropdown.style.top = 'auto'
19+
dropdown.style.bottom = '100%' // position it above
20+
dropdown.style.marginTop = '0'
21+
dropdown.style.marginBottom = '4px'
22+
} else {
23+
dropdown.style.top = '100%' // position it below
24+
dropdown.style.bottom = 'auto'
25+
dropdown.style.marginTop = '4px'
26+
dropdown.style.marginBottom = '0'
27+
}
28+
// Optionally check horizontal overflow too
29+
if (rect.right > window.innerWidth - buffer) {
30+
dropdown.style.left = 'auto'
31+
dropdown.style.right = '0'
32+
}
33+
}
34+
}
35+
})
36+
}, [openDropdowns])
37+
}

0 commit comments

Comments
 (0)