popup progress

This commit is contained in:
Jakob Pinterits
2024-10-13 18:53:33 +02:00
parent aafc52bb13
commit 7fca0ff056
3 changed files with 26 additions and 96 deletions
+17 -45
View File
@@ -4,6 +4,7 @@ import {
} from "../componentManagement";
import { ComponentId } from "../dataModels";
import { markEventAsHandled } from "../eventHandling";
import { PopupManager, positionFullscreen } from "../popupManager";
import { callRemoteMethodDiscardResponse } from "../rpc";
import { commitCss } from "../utils";
import { ComponentBase, ComponentState } from "./componentBase";
@@ -19,55 +20,26 @@ export type DialogContainerState = ComponentState & {
export class DialogContainerComponent extends ComponentBase {
declare state: Required<DialogContainerState>;
private contentContainer: HTMLElement;
// Dialogs are displayed via a popup manager. While this isn't strictly
// necessary, this allows sharing the code for whether the dialog is modal,
// user-closable and general styling.
private popupManager: PopupManager;
createElement(): HTMLElement {
// Create the element
// Create the HTML elements
let element = document.createElement("div");
element.classList.add("rio-dialog-container", "rio-switcheroo-neutral");
element.classList.add("rio-dialog-container");
// Since dialog containers aren't part of the component tree, they're
// themselves responsible for adding themselves to the DOM.
document.body.appendChild(element);
this.contentContainer = document.createElement("div");
// Animate the element
requestAnimationFrame(() => {
commitCss(element);
element.classList.add("rio-dialog-container-enter");
});
// Listen for outside clicks
element.addEventListener("click", (event) => {
markEventAsHandled(event);
// Don't close the dialog if the click was inside the dialog. This
// is a bit tricky, because of various cases:
//
// - The click was handled by a component inside of the dialog (e.g.
// a Button). This is simple, since the event will never reach the
// dialog container.
// - The click was onto a component in the dialog, but not handled.
// (Think a `rio.Card`). This must be detected and the dialog NOT
// closed.
// - The click was technically into a component, but that component
// doesn't accept clicks. (Think the spacing of a `rio.Row`.)
// Since no component was technically clicked, the dialog should
// close.
if (event.target !== element) {
return;
}
// Is the dialog user-closable?
if (!this.state.is_user_closable) {
return;
}
// Yes! Close it. First, inform the server.
callRemoteMethodDiscardResponse("dialogClosed", {
dialogRootComponentId: this.id,
});
// Clean up
recursivelyDeleteComponent(this);
});
// Set up the popup manager
this.popupManager = new PopupManager(
element,
this.contentContainer,
positionFullscreen
);
return element;
}
+8 -18
View File
@@ -58,14 +58,14 @@ export function positionDropdown(
content.style.left = "0";
content.style.top = "0";
content.style.width = `${windowWidth}px`;
content.style.height = `${windowHeight}px`;
content.style.width = "100vw";
content.style.height = "100vh";
anchor.classList.add("rio-dropdown-popup-mobile-fullscreen");
content.classList.add("rio-dropdown-popup-mobile-fullscreen");
return;
}
anchor.classList.remove("rio-dropdown-popup-mobile-fullscreen");
content.classList.remove("rio-dropdown-popup-mobile-fullscreen");
// TODO
//
@@ -77,7 +77,7 @@ export function positionDropdown(
content.style.left = `${anchorRect.left}px`;
content.style.top = `${DESKTOP_WINDOW_MARGIN}px`;
content.style.width = `${anchorRect.width}px`;
content.style.height = `${windowHeight - 2 * DESKTOP_WINDOW_MARGIN}px`;
content.style.height = `calc(100vh - ${2 * DESKTOP_WINDOW_MARGIN}px)`;
return;
}
@@ -88,10 +88,9 @@ export function positionDropdown(
) {
content.style.left = `${anchorRect.left}px`;
content.style.top = `${anchorRect.bottom}px`;
content.style.width = `${anchorRect.width}px`;
content.style.height = `${contentHeight}px`;
content.style.width = `max(min-content, ${anchorRect.width}px)`;
content.style.height = `min-content`;
content.style.maxHeight = `${contentHeight}px`;
content.style.overflowY = "hidden";
return;
}
// Popup fits above the dropdown
@@ -106,7 +105,6 @@ export function positionDropdown(
content.style.width = `${anchorRect.width}px`;
content.style.height = `${contentHeight}px`;
content.style.maxHeight = `${contentHeight}px`;
content.style.overflowY = "hidden";
}
// Popup doesn't fit above or below the dropdown. Center it as much
// as possible
@@ -123,7 +121,7 @@ export function positionDropdown(
content.style.width = `${anchorRect.width}px`;
content.style.height = `${contentHeight}px`;
content.style.maxHeight = `${contentHeight}px`;
content.style.overflowY = "hidden";
content.style.overflowY = "auto";
return;
}
@@ -196,14 +194,6 @@ export function positionOnSide({
content.style.top = `${contentTop}px`;
content.style.width = `${contentWidth}px`;
content.style.height = `${contentHeight}px`;
// return {
// leftPx: contentLeft,
// topPx: contentTop,
// widthPx: contentWidth,
// heightPx: contentHeight,
// additionalCss: {},
// };
}
export function makePositionLeft(
+1 -33
View File
@@ -3619,6 +3619,7 @@ html.picking-component * {
.rio-popup-manager-animation-slide-from-top {
transition: max-height 0.2s ease-in-out;
overflow: hidden;
}
.rio-popup-manager-shade:not(.rio-popup-manager-open)
@@ -3874,39 +3875,6 @@ html.picking-component * {
@include single-container(); // FIXME: Should we do this?
}
// Dialogs
.rio-dialog-container {
pointer-events: none;
position: fixed;
left: 0;
top: 0;
right: 0;
bottom: 0;
z-index: $z-index-popup;
background-color: transparent;
opacity: 0;
// Theses durations are also referenced in code!
transition: opacity 0.2s ease-in-out, background-color 0.5s ease-in-out;
& > * {
transform: translateY(-2rem);
transition: transform 0.2s $transition-timing-overshoot;
}
@include single-container();
}
.rio-dialog-container-enter {
background-color: $modal-shade;
opacity: 1;
& > * {
transform: translateY(0);
}
}
// Upload Area
.rio-file-picker-area {