Skip to content
This repository was archived by the owner on Nov 25, 2021. It is now read-only.

Commit 208b7b8

Browse files
committed
fix(overlayposition): check if overlay is overflowing relativeElement
1 parent 1ed28e6 commit 208b7b8

File tree

2 files changed

+45
-20
lines changed

2 files changed

+45
-20
lines changed

src/overlay_position.test.ts

Lines changed: 42 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -110,28 +110,53 @@ describe('overlay_position', () => {
110110
beforeEach(() => {
111111
relativeElement.style.height = '600px'
112112
relativeElement.style.overflow = 'auto'
113+
})
114+
describe('not scrolled', () => {
115+
beforeEach(() => {
116+
const content = document.createElement('div')
117+
content.style.height = '500px'
118+
content.style.width = '700px'
119+
relativeElement.appendChild(content)
120+
})
113121

114-
const content = document.createElement('div')
115-
content.style.height = '3000px'
116-
content.style.width = '3000px'
117-
relativeElement.appendChild(content)
122+
it('should return a position above the given target if the overlay fits above', () => {
123+
const target = createTarget({ left: 100, top: 200 })
124+
const position = calculateOverlayPosition({ relativeElement, target, hoverOverlayElement })
125+
applyOffsets(hoverOverlayElement, position)
126+
assert.deepStrictEqual(position, { left: 100, top: 50 })
127+
})
118128

119-
relativeElement.scrollTop = 400
120-
relativeElement.scrollLeft = 200
129+
it('should return a position below the a given target if the overlay does not fit above', () => {
130+
const target = createTarget({ left: 100, top: 140 })
131+
const position = calculateOverlayPosition({ relativeElement, target, hoverOverlayElement })
132+
applyOffsets(hoverOverlayElement, position)
133+
assert.deepStrictEqual(position, { left: 100, top: 156 })
134+
})
121135
})
136+
describe('scrolled', () => {
137+
beforeEach(() => {
138+
const content = document.createElement('div')
139+
content.style.height = '3000px'
140+
content.style.width = '3000px'
141+
relativeElement.appendChild(content)
122142

123-
it('should return a position above the given target if the overlay fits above', () => {
124-
const target = createTarget({ left: 300, top: 600 })
125-
const position = calculateOverlayPosition({ relativeElement, target, hoverOverlayElement })
126-
applyOffsets(hoverOverlayElement, position)
127-
assert.deepStrictEqual(position, { left: 300, top: 450 })
128-
})
143+
relativeElement.scrollTop = 400
144+
relativeElement.scrollLeft = 200
145+
})
129146

130-
it('should return a position below the a given target if the overlay does not fit above', () => {
131-
const target = createTarget({ left: 300, top: 450 })
132-
const position = calculateOverlayPosition({ relativeElement, target, hoverOverlayElement })
133-
applyOffsets(hoverOverlayElement, position)
134-
assert.deepStrictEqual(position, { left: 300, top: 466 })
147+
it('should return a position above the given target if the overlay fits above', () => {
148+
const target = createTarget({ left: 300, top: 600 })
149+
const position = calculateOverlayPosition({ relativeElement, target, hoverOverlayElement })
150+
applyOffsets(hoverOverlayElement, position)
151+
assert.deepStrictEqual(position, { left: 300, top: 450 })
152+
})
153+
154+
it('should return a position below the a given target if the overlay does not fit above', () => {
155+
const target = createTarget({ left: 300, top: 450 })
156+
const position = calculateOverlayPosition({ relativeElement, target, hoverOverlayElement })
157+
applyOffsets(hoverOverlayElement, position)
158+
assert.deepStrictEqual(position, { left: 300, top: 466 })
159+
})
135160
})
136161
})
137162
})

src/overlay_position.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
interface CalculateOverlayPositionOptions {
1+
export interface CalculateOverlayPositionOptions {
22
/** The closest parent element that is `position: relative` */
33
relativeElement: HTMLElement
44
/** The DOM Node that was hovered */
@@ -31,8 +31,8 @@ export const calculateOverlayPosition = ({
3131
const relativeHoverOverlayLeft = targetBounds.left + relativeElement.scrollLeft - relativeElementBounds.left
3232

3333
let relativeHoverOverlayTop: number
34-
// If the top of the hover overlay would be outside of the viewport (top negative)
35-
if (targetBounds.top - hoverOverlayBounds.height < 0) {
34+
// Check if the top of the hover overlay would be outside of the relative element or the viewport
35+
if (targetBounds.top - hoverOverlayBounds.height < Math.max(relativeElementBounds.top, 0)) {
3636
// Position it below the target
3737
// If the relativeElement is scrolled, we need to account for the offset (if not scrollTop will be 0)
3838
relativeHoverOverlayTop = targetBounds.bottom - relativeElementBounds.top + relativeElement.scrollTop

0 commit comments

Comments
 (0)