feat: responsive popovers & menus (#1323)
This commit is contained in:
@@ -0,0 +1,54 @@
|
||||
import { CSSProperties } from 'react'
|
||||
import { PopoverAlignment, PopoverSide } from './Types'
|
||||
import { OppositeSide, checkCollisions, getNonCollidingSide, getNonCollidingAlignment } from './Utils/Collisions'
|
||||
import { getPositionedPopoverRect } from './Utils/Rect'
|
||||
|
||||
const getStylesFromRect = (rect: DOMRect): CSSProperties => {
|
||||
return {
|
||||
willChange: 'transform',
|
||||
transform: `translate(${rect.x}px, ${rect.y}px)`,
|
||||
}
|
||||
}
|
||||
|
||||
type Options = {
|
||||
align: PopoverAlignment
|
||||
anchorRect?: DOMRect
|
||||
documentRect: DOMRect
|
||||
popoverRect?: DOMRect
|
||||
side: PopoverSide
|
||||
}
|
||||
|
||||
export const getPositionedPopoverStyles = ({
|
||||
align,
|
||||
anchorRect,
|
||||
documentRect,
|
||||
popoverRect,
|
||||
side,
|
||||
}: Options): [CSSProperties | null, PopoverSide, PopoverAlignment] => {
|
||||
if (!popoverRect || !anchorRect) {
|
||||
return [null, side, align]
|
||||
}
|
||||
|
||||
const matchesMediumBreakpoint = matchMedia('(min-width: 768px)').matches
|
||||
|
||||
if (!matchesMediumBreakpoint) {
|
||||
return [null, side, align]
|
||||
}
|
||||
|
||||
const rectForPreferredSide = getPositionedPopoverRect(popoverRect, anchorRect, side, align)
|
||||
const preferredSideRectCollisions = checkCollisions(rectForPreferredSide, documentRect)
|
||||
|
||||
const oppositeSide = OppositeSide[side]
|
||||
const rectForOppositeSide = getPositionedPopoverRect(popoverRect, anchorRect, oppositeSide, align)
|
||||
const oppositeSideRectCollisions = checkCollisions(rectForOppositeSide, documentRect)
|
||||
|
||||
const finalSide = getNonCollidingSide(side, preferredSideRectCollisions, oppositeSideRectCollisions)
|
||||
const finalAlignment = getNonCollidingAlignment(finalSide, align, preferredSideRectCollisions, {
|
||||
popoverRect,
|
||||
buttonRect: anchorRect,
|
||||
documentRect,
|
||||
})
|
||||
const finalPositionedRect = getPositionedPopoverRect(popoverRect, anchorRect, finalSide, finalAlignment)
|
||||
|
||||
return [getStylesFromRect(finalPositionedRect), finalSide, finalAlignment]
|
||||
}
|
||||
Reference in New Issue
Block a user