Skip to content

Commit

Permalink
Fixes #439: create dialog element
Browse files Browse the repository at this point in the history
  • Loading branch information
calmense committed Feb 21, 2025
1 parent 1ecbed7 commit 9d9e51c
Show file tree
Hide file tree
Showing 3 changed files with 256 additions and 0 deletions.
124 changes: 124 additions & 0 deletions awatif-ui/src/dialog/dialog.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
import { html, render, TemplateResult } from "lit-html";
import { createRef, ref } from "lit-html/directives/ref.js";
import van, { State } from "vanjs-core";
import "./style.css";

export function dialog({
template,
data,
content,
}: {
template: (data: State<object>) => TemplateResult;
data: State<object>;
content: any;
}): HTMLElement {
const container = document.createElement("div");

// report button
const button = document.createElement("input-button");
button.textContent = "Dialog";
button.classList.add("input-button");

// dialog
let dialogElm = createRef<HTMLDialogElement>();
let dialogBodyElm = createRef<HTMLDivElement>();

// dialog template
const dialogTemp = html`
<dialog class="dialog-input" ref=${ref(dialogElm)}>
<div class="resize-handle resize-handle-right"></div>
<div class="resize-handle resize-handle-top"></div>
<div class="dialog-header">
<span class="close" @click=${() => dialogElm.value?.close()}>&times;</span>
</div>
<div class="dialog-body" ref=${ref(dialogBodyElm)}>
<div class="input-content">
<!-- Content generated from the template -->
</div>
</div>
<div class="dialog-body" style="display: flex; justify-content: center;">
<div class="sheets-container">
<!-- Include the sheetsElm here -->
${content}
</div>
</div>
</dialog>
`;

render(dialogTemp, container);
container.append(button);

// Open the dialog when the Report button is clicked
button.addEventListener("click", () => {
dialogElm.value?.showModal();
});

// Add resizing functionality
addResizeListeners(dialogElm.value);

// Render report content inside the dialog
van.derive(() => {
render(template(data), dialogBodyElm.value);
});

return container;
}
function addResizeListeners(dialog: HTMLDialogElement | null) {
if (!dialog) return;

const rightHandle = dialog.querySelector(".resize-handle-right")!;
const topHandle = dialog.querySelector(".resize-handle-top")!;
let isResizing = false;
let startX = 0;
let startY = 0;
let startWidth = 0;
let startHeight = 0;
let startTop = 0;

// Resize from the right
rightHandle.addEventListener("mousedown", (e) => {
isResizing = true;
startX = e.clientX;
startWidth = dialog.offsetWidth;
document.body.style.cursor = "ew-resize";
e.preventDefault();
});

// Resize from the top
topHandle.addEventListener("mousedown", (e) => {
isResizing = true;
startY = e.clientY;
startHeight = dialog.offsetHeight;
startTop = parseFloat(getComputedStyle(dialog).top) || 0; // Track initial top position
document.body.style.cursor = "ns-resize";
e.preventDefault();
});

document.addEventListener("mousemove", (e) => {
if (!isResizing) return;

// Resizing from the right
if (document.body.style.cursor === "ew-resize") {
const newWidth = startWidth + (e.clientX - startX);
dialog.style.width = `${newWidth}px`;
}

// Resizing from the top
if (document.body.style.cursor === "ns-resize") {
const deltaY = e.clientY - startY; // Difference in vertical movement
const newHeight = startHeight - deltaY;
const newTop = startTop + deltaY;

if (newHeight > 100) { // Prevent collapsing below 100px height
dialog.style.height = `${newHeight}px`;
dialog.style.top = `${newTop}px`;
}
}
});

document.addEventListener("mouseup", () => {
isResizing = false;
document.body.style.cursor = "default";
});
}

24 changes: 24 additions & 0 deletions awatif-ui/src/dialog/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Awatif UI - Dialog</title>
<script type="module">
import { dialog } from "./dialog";
import { html } from "lit-html";
import van from "vanjs-core";

const template = (nodes) => {
return html`<p>This is a dialog.</p>`;
};

const dialogObj = dialog({
template,
});

document.body.appendChild(dialogObj);
</script>
</head>
<body></body>
</html>
108 changes: 108 additions & 0 deletions awatif-ui/src/dialog/styles.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
/* General Canvas Styling */
canvas {
position: absolute;
}

/* Top Bar */
.topBar {
position: absolute;
top: 0.3rem;
right: 1rem;
}

.topBar a {
text-decoration: none;
color: white;
}

/* Dialog Input */
dialog.dialog-input {
position: absolute;
top: 400px;
bottom: 5px;
width: 60%;
height: 45%;
margin: 2rem 1rem 0;
padding: 0;
overflow: auto;
resize: both;
}

.dialog-input .dialog-header {
background: lightgray;
padding: 20px;
font-size: 1.2rem;
display: flex;
justify-content: flex-end;
}

.dialog-header .close {
color: #000000;
font-size: 1.2rem;
font-weight: bold;
cursor: pointer;
}

.dialog-input .dialog-body {
padding: 20px;
}

/* Resizing Handles */
.resize-handle {
position: absolute;
background: #ccc;
z-index: 10;
opacity: 0.8;
}

.resize-handle-right {
width: 5px;
height: 100%;
top: 0;
right: 0;
cursor: ew-resize;
}

.resize-handle-top {
height: 5px;
width: 100%;
top: 0;
left: 0;
cursor: ns-resize;
}

/* Input Button */
.input-button {
position: absolute;
bottom: 20px;
left: 20px;
width: 80px;
height: 40px;
color: #fefafa;
background-color: #46474C; /* Dark gray */
border-radius: 10px;
font-family: "Arial", sans-serif;
font-size: 13px;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
transition: background-color 0.3s, transform 0.2s;
}

.input-button:hover {
background-color: #333333; /* Darker gray on hover */
color: #fff;
}

.input-button:active {
transform: scale(0.95);
}

/* Responsive Adjustments */
@media only screen and (max-width: 600px) {
dialog.dialog-input {
width: calc(100% - 2rem);
height: 100%;
}
}

0 comments on commit 9d9e51c

Please sign in to comment.