Allow showing popover above & tweaks

This commit is contained in:
Svilen Markov 2024-08-20 13:29:44 +01:00
parent 984f26807e
commit 8860f4591b
2 changed files with 53 additions and 14 deletions

View File

@ -36,7 +36,7 @@ function handleMouseEnter(event) {
if (activeTarget !== null) { if (activeTarget !== null) {
if (activeTarget !== target) { if (activeTarget !== target) {
hidePopover(); hidePopover();
setTimeout(showPopover, 5); requestAnimationFrame(showPopover);
} }
return; return;
@ -96,28 +96,45 @@ function showPopover() {
} }
function repositionContainer() { function repositionContainer() {
const activeTargetBounds = activeTarget.getBoundingClientRect(); const targetBounds = activeTarget.getBoundingClientRect();
const containerBounds = containerElement.getBoundingClientRect(); const containerBounds = containerElement.getBoundingClientRect();
const containerInlinePadding = parseInt(containerComputedStyle.getPropertyValue("padding-inline")); const containerInlinePadding = parseInt(containerComputedStyle.getPropertyValue("padding-inline"));
const activeTargetBoundsWidthOffset = activeTargetBounds.width * (activeTarget.dataset.popoverOffset || 0.5); const activeTargetBoundsWidthOffset = targetBounds.width * (activeTarget.dataset.popoverOffset || 0.5);
const left = activeTargetBounds.left + activeTargetBoundsWidthOffset - (containerBounds.width / 2); const position = activeTarget.dataset.popoverPosition || "below";
const left = targetBounds.left + activeTargetBoundsWidthOffset - (containerBounds.width / 2) + 1;
if (left < 0) { if (left < 0) {
containerElement.style.left = 0; containerElement.style.left = 0;
containerElement.style.removeProperty("right"); containerElement.style.removeProperty("right");
containerElement.style.setProperty("--triangle-offset", activeTargetBounds.left - containerInlinePadding + activeTargetBoundsWidthOffset + "px"); containerElement.style.setProperty("--triangle-offset", targetBounds.left - containerInlinePadding + activeTargetBoundsWidthOffset + "px");
} else if (left + containerBounds.width > window.innerWidth) { } else if (left + containerBounds.width > window.innerWidth) {
containerElement.style.removeProperty("left"); containerElement.style.removeProperty("left");
containerElement.style.right = 0; containerElement.style.right = 0;
containerElement.style.setProperty("--triangle-offset", containerBounds.width - containerInlinePadding - (window.innerWidth - activeTargetBounds.left - activeTargetBoundsWidthOffset) + "px"); containerElement.style.setProperty("--triangle-offset", containerBounds.width - containerInlinePadding - (window.innerWidth - targetBounds.left - activeTargetBoundsWidthOffset) + "px");
} else { } else {
containerElement.style.removeProperty("right"); containerElement.style.removeProperty("right");
containerElement.style.left = left + "px"; containerElement.style.left = left + "px";
containerElement.style.removeProperty("--triangle-offset"); containerElement.style.removeProperty("--triangle-offset");
} }
frameElement.style.marginTop = activeTarget.dataset.popoverMargin || defaultDistanceFromTarget; const distanceFromTarget = activeTarget.dataset.popoverMargin || defaultDistanceFromTarget;
containerElement.style.top = activeTargetBounds.top + window.scrollY + activeTargetBounds.height + "px"; const topWhenAbove = targetBounds.top + window.scrollY - containerBounds.height;
const topWhenBelow = targetBounds.top + window.scrollY + targetBounds.height;
if (
position === "above" && topWhenAbove > window.scrollY ||
(position === "below" && topWhenBelow + containerBounds.height > window.scrollY + window.innerHeight)
) {
containerElement.classList.add("position-above");
frameElement.style.removeProperty("margin-top");
frameElement.style.marginBottom = distanceFromTarget;
containerElement.style.top = topWhenAbove + "px";
} else {
containerElement.classList.remove("position-above");
frameElement.style.removeProperty("margin-bottom");
frameElement.style.marginTop = distanceFromTarget;
containerElement.style.top = topWhenBelow + "px";
}
} }
function hidePopover() { function hidePopover() {

View File

@ -34,8 +34,8 @@
--color-separator: hsl(var(--bghs), calc(var(--scheme) ((var(--scheme) var(--bgl)) + 4% * var(--cm)))); --color-separator: hsl(var(--bghs), calc(var(--scheme) ((var(--scheme) var(--bgl)) + 4% * var(--cm))));
--color-widget-content-border: hsl(var(--bghs), calc(var(--scheme) (var(--scheme) var(--bgl) + 4%))); --color-widget-content-border: hsl(var(--bghs), calc(var(--scheme) (var(--scheme) var(--bgl) + 4%)));
--color-widget-background-highlight: hsl(var(--bghs), calc(var(--scheme) (var(--scheme) var(--bgl) + 4%))); --color-widget-background-highlight: hsl(var(--bghs), calc(var(--scheme) (var(--scheme) var(--bgl) + 4%)));
--color-popover-background: hsl(var(--bgh), calc(var(--bgs) + 3%), calc(var(--bgl) + 2%)); --color-popover-background: hsl(var(--bgh), calc(var(--bgs) + 3%), calc(var(--bgl) + 3%));
--color-popover-border: hsl(var(--bghs), calc(var(--scheme) (var(--scheme) var(--bgl) + 7%))); --color-popover-border: hsl(var(--bghs), calc(var(--scheme) (var(--scheme) var(--bgl) + 10%)));
--ths: var(--bgh), calc(var(--bgs) * var(--tsm)); --ths: var(--bgh), calc(var(--bgs) * var(--tsm));
--color-text-base: hsl(var(--ths), calc(var(--scheme) var(--cm) * 58%)); --color-text-base: hsl(var(--ths), calc(var(--scheme) var(--cm) * 58%));
@ -439,20 +439,32 @@ kbd:active {
.popover-container { .popover-container {
--triangle-size: 10px; --triangle-size: 10px;
--triangle-offset: 50%; --triangle-offset: 50%;
--triangle-margin: calc(var(--triangle-size) + 3px);
--entrance-y-offset: 8px;
--entrance-direction: calc(var(--entrance-y-offset) * -1);
z-index: 20; z-index: 20;
position: absolute; position: absolute;
padding-top: calc(var(--triangle-size) + 3px); padding-top: var(--triangle-margin);
padding-inline: var(--content-bounds-padding); padding-inline: var(--content-bounds-padding);
} }
.popover-container.position-above {
--entrance-direction: var(--entrance-y-offset);
padding-top: 0;
padding-bottom: var(--triangle-margin);
}
.popover-frame { .popover-frame {
--shadow-properties: 0 15px 20px -10px;
--shadow-color: hsla(var(--bghs), calc(var(--bgl) * 0.2), 0.5);
position: relative; position: relative;
padding: 10px; padding: 10px;
background: var(--color-popover-background); background: var(--color-popover-background);
border: 1px solid var(--color-popover-border); border: 1px solid var(--color-popover-border);
border-radius: 5px; border-radius: 5px;
animation: popoverFrameEntrance 0.3s backwards cubic-bezier(0.16, 1, 0.3, 1); animation: popoverFrameEntrance 0.3s backwards cubic-bezier(0.16, 1, 0.3, 1);
box-shadow: 0 15px 30px -5px hsla(var(--bghs), calc(var(--bgl) * 0.2), 0.5); box-shadow: var(--shadow-properties) var(--shadow-color);
} }
.popover-frame::before { .popover-frame::before {
@ -462,17 +474,27 @@ kbd:active {
height: var(--triangle-size); height: var(--triangle-size);
transform: rotate(45deg); transform: rotate(45deg);
background-color: var(--color-popover-background); background-color: var(--color-popover-background);
border-top-left-radius: 4px; border-top-left-radius: 2px;
border-left: 1px solid var(--color-popover-border); border-left: 1px solid var(--color-popover-border);
border-top: 1px solid var(--color-popover-border); border-top: 1px solid var(--color-popover-border);
left: calc(var(--triangle-offset) - (var(--triangle-size) / 2)); left: calc(var(--triangle-offset) - (var(--triangle-size) / 2));
top: calc(var(--triangle-size) / 2 * -1 - 1px); top: calc(var(--triangle-size) / 2 * -1 - 1px);
} }
.popover-container.position-above .popover-frame::before {
transform: rotate(-135deg);
top: auto;
bottom: calc(var(--triangle-size) / 2 * -1 - 1px);
}
.popover-container.position-above .popover-frame {
--shadow-properties: 0 10px 20px -10px;
}
@keyframes popoverFrameEntrance { @keyframes popoverFrameEntrance {
from { from {
opacity: 0; opacity: 0;
transform: translateY(-8px); transform: translateY(var(--entrance-direction));
} }
} }