Tweak orientation helper to prevent popups from going off screen
This commit is contained in:
@@ -27,13 +27,13 @@
|
|||||||
&:where(.popup--align-left),
|
&:where(.popup--align-left),
|
||||||
&.orient-left {
|
&.orient-left {
|
||||||
inset-inline: auto 0;
|
inset-inline: auto 0;
|
||||||
transform: translateX(0);
|
transform: translateX(var(--orient-offset, 0px));
|
||||||
}
|
}
|
||||||
|
|
||||||
&:where(.popup--align-right),
|
&:where(.popup--align-right),
|
||||||
&.orient-right {
|
&.orient-right {
|
||||||
inset-inline: 0 auto;
|
inset-inline: 0 auto;
|
||||||
transform: translateX(0);
|
transform: translateX(var(--orient-offset, 0px));
|
||||||
}
|
}
|
||||||
|
|
||||||
form {
|
form {
|
||||||
|
|||||||
@@ -20,12 +20,12 @@
|
|||||||
|
|
||||||
&.orient-right {
|
&.orient-right {
|
||||||
inset-inline: 0 auto;
|
inset-inline: 0 auto;
|
||||||
translate: 0 -100%;
|
translate: var(--orient-offset, 0px) -100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.orient-left {
|
&.orient-left {
|
||||||
inset-inline: auto 0;
|
inset-inline: auto 0;
|
||||||
translate: 0 -100%;
|
translate: var(--orient-offset, 0px) -100%;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ export default class extends Controller {
|
|||||||
this.dialogTarget.showModal()
|
this.dialogTarget.showModal()
|
||||||
} else {
|
} else {
|
||||||
this.dialogTarget.show()
|
this.dialogTarget.show()
|
||||||
orient(this.dialogTarget)
|
orient({ target: this.dialogTarget, anchor: this.element })
|
||||||
}
|
}
|
||||||
|
|
||||||
this.loadLazyFrames()
|
this.loadLazyFrames()
|
||||||
@@ -46,7 +46,7 @@ export default class extends Controller {
|
|||||||
this.dialogTarget.close()
|
this.dialogTarget.close()
|
||||||
this.dialogTarget.setAttribute("aria-hidden", "true")
|
this.dialogTarget.setAttribute("aria-hidden", "true")
|
||||||
this.dialogTarget.blur()
|
this.dialogTarget.blur()
|
||||||
orient(this.dialogTarget, false)
|
orient({ target: this.dialogTarget, reset: true })
|
||||||
this.dispatch("close")
|
this.dispatch("close")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,11 +15,11 @@ export default class extends Controller {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mouseEnter(event) {
|
mouseEnter(event) {
|
||||||
orient(this.#tooltipElement)
|
orient({ target: this.#tooltipElement, anchor: this.element })
|
||||||
}
|
}
|
||||||
|
|
||||||
mouseOut(event) {
|
mouseOut(event) {
|
||||||
orient(this.#tooltipElement, false)
|
orient({ target: this.#tooltipElement, reset: true })
|
||||||
}
|
}
|
||||||
|
|
||||||
get #tooltipElement() {
|
get #tooltipElement() {
|
||||||
|
|||||||
@@ -1,24 +1,30 @@
|
|||||||
const EDGE_THRESHOLD = 16
|
const EDGE_THRESHOLD = 16
|
||||||
|
|
||||||
export function orient(el, orient = true) {
|
export function orient({ target, anchor = null, reset = false }) {
|
||||||
el.classList.remove("orient-left", "orient-right")
|
target.classList.remove("orient-left", "orient-right")
|
||||||
|
target.style.removeProperty("--orient-offset")
|
||||||
|
|
||||||
if (!orient) return
|
if (reset) return
|
||||||
|
|
||||||
const rightSpace = spaceOnRight(el)
|
const targetGeometry = geometry(target)
|
||||||
const leftSpace = spaceOnLeft(el)
|
const anchorGeometry = geometry(anchor)
|
||||||
|
|
||||||
if (rightSpace < EDGE_THRESHOLD && rightSpace < leftSpace) {
|
if (targetGeometry.spaceOnRight < EDGE_THRESHOLD && targetGeometry.spaceOnRight < targetGeometry.spaceOnLeft) {
|
||||||
el.classList.add("orient-left")
|
const offset = Math.min(0, anchorGeometry.spaceOnLeft + anchorGeometry.width - targetGeometry.width) * -1
|
||||||
} else if (leftSpace < EDGE_THRESHOLD && leftSpace < rightSpace) {
|
target.classList.add("orient-left")
|
||||||
el.classList.add("orient-right")
|
target.style.setProperty("--orient-offset", `${offset}px`)
|
||||||
|
} else if (targetGeometry.spaceOnLeft < EDGE_THRESHOLD && targetGeometry.spaceOnLeft < targetGeometry.spaceOnRight) {
|
||||||
|
const offset = Math.max(0, anchorGeometry.spaceOnLeft + targetGeometry.width - window.innerWidth) * -1
|
||||||
|
target.classList.add("orient-right")
|
||||||
|
target.style.setProperty("--orient-offset", `${offset}px`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function spaceOnLeft(el) {
|
function geometry(el) {
|
||||||
return el.getBoundingClientRect().left
|
const rect = el.getBoundingClientRect()
|
||||||
}
|
return {
|
||||||
|
spaceOnLeft: rect.left,
|
||||||
function spaceOnRight(el) {
|
spaceOnRight: window.innerWidth - rect.right,
|
||||||
return window.innerWidth - el.getBoundingClientRect().right
|
width: rect.width
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user