mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-07-02 16:38:33 +00:00
Main Menu UI Overhaul (#2829)
## Description: Overhauls the Main Menu UI, visit https://menu.openfront.dev to see everything. ## Please complete the following: - [x] I have added screenshots for all UI updates - [x] I process any text displayed to the user through translateText() and I've added it to the en.json file - [x] I have added relevant tests to the test directory - [x] I confirm I have thoroughly tested these changes and take full responsibility for any bugs introduced ## Please put your Discord username so you can be contacted if a bug or regression is found: w.o.n
This commit is contained in:
@@ -1,105 +1,102 @@
|
||||
import { LitElement, css, html } from "lit";
|
||||
import { LitElement, html, unsafeCSS } from "lit";
|
||||
import { customElement, property, state } from "lit/decorators.js";
|
||||
import { translateText } from "../../Utils";
|
||||
import tailwindStyles from "../../styles.css?inline";
|
||||
|
||||
@customElement("o-modal")
|
||||
export class OModal extends LitElement {
|
||||
static styles = [unsafeCSS(tailwindStyles)];
|
||||
|
||||
@state() public isModalOpen = false;
|
||||
@property({ type: String }) title = "";
|
||||
@property({ type: String }) translationKey = "";
|
||||
@property({ type: Boolean }) alwaysMaximized = false;
|
||||
@property({ type: Function }) onClose?: () => void;
|
||||
|
||||
static styles = css`
|
||||
.c-modal {
|
||||
position: fixed;
|
||||
padding: 1rem;
|
||||
z-index: 9999;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
top: 0;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
overflow-y: auto;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
static openCount = 0;
|
||||
|
||||
.c-modal__wrapper {
|
||||
border-radius: 8px;
|
||||
min-width: 340px;
|
||||
max-width: 860px;
|
||||
}
|
||||
@property({ type: Boolean })
|
||||
public inline = false;
|
||||
|
||||
.c-modal__wrapper.always-maximized {
|
||||
width: 100%;
|
||||
min-width: 340px;
|
||||
max-width: 860px;
|
||||
min-height: 320px;
|
||||
/* Fallback for older browsers */
|
||||
height: 60vh;
|
||||
/* Use dvh if supported for dynamic viewport handling */
|
||||
height: 60dvh;
|
||||
}
|
||||
@property({ type: Boolean })
|
||||
public alwaysMaximized = false;
|
||||
|
||||
.c-modal__header {
|
||||
position: relative;
|
||||
border-top-left-radius: 4px;
|
||||
border-top-right-radius: 4px;
|
||||
font-size: 18px;
|
||||
background: #000000a1;
|
||||
text-align: center;
|
||||
color: #fff;
|
||||
padding: 1rem 2.4rem 1rem 1.4rem;
|
||||
}
|
||||
@property({ type: Boolean })
|
||||
public hideCloseButton = false;
|
||||
|
||||
.c-modal__close {
|
||||
cursor: pointer;
|
||||
position: absolute;
|
||||
right: 1rem;
|
||||
top: 1rem;
|
||||
}
|
||||
@property({ type: String })
|
||||
public title = "";
|
||||
|
||||
@property({ type: Boolean })
|
||||
public hideHeader = false;
|
||||
|
||||
public onClose?: () => void;
|
||||
|
||||
.c-modal__content {
|
||||
background: #23232382;
|
||||
position: relative;
|
||||
color: #fff;
|
||||
padding: 1.4rem;
|
||||
max-height: 60dvh;
|
||||
overflow-y: auto;
|
||||
backdrop-filter: blur(8px);
|
||||
}
|
||||
`;
|
||||
public open() {
|
||||
this.isModalOpen = true;
|
||||
if (!this.isModalOpen) {
|
||||
if (!this.inline) {
|
||||
OModal.openCount = OModal.openCount + 1;
|
||||
if (OModal.openCount === 1) document.body.style.overflow = "hidden";
|
||||
}
|
||||
this.isModalOpen = true;
|
||||
}
|
||||
}
|
||||
|
||||
public close() {
|
||||
if (this.isModalOpen) {
|
||||
this.isModalOpen = false;
|
||||
this.onClose?.();
|
||||
if (!this.inline) {
|
||||
OModal.openCount = Math.max(0, OModal.openCount - 1);
|
||||
if (OModal.openCount === 0) document.body.style.overflow = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
disconnectedCallback() {
|
||||
// Ensure global counter is decremented if this modal is removed while open.
|
||||
if (this.isModalOpen && !this.inline) {
|
||||
OModal.openCount = Math.max(0, OModal.openCount - 1);
|
||||
if (OModal.openCount === 0) document.body.style.overflow = "";
|
||||
}
|
||||
super.disconnectedCallback();
|
||||
}
|
||||
|
||||
render() {
|
||||
const backdropClass = this.inline
|
||||
? "relative z-10 w-full h-full flex items-stretch bg-transparent"
|
||||
: "fixed inset-0 z-[9999] bg-black/70 flex items-center justify-center overflow-hidden";
|
||||
|
||||
const wrapperClass = this.inline
|
||||
? "relative flex flex-col w-full h-full m-0 max-w-full max-h-none shadow-none"
|
||||
: `relative flex flex-col w-[90%] min-w-[400px] max-w-[900px] m-8 rounded-lg shadow-[0_20px_60px_rgba(0,0,0,0.8)] max-h-[calc(100vh-4rem)] ${
|
||||
this.alwaysMaximized ? "h-auto" : ""
|
||||
}`;
|
||||
|
||||
return html`
|
||||
${this.isModalOpen
|
||||
? html`
|
||||
<aside class="c-modal" @click=${this.close}>
|
||||
<aside
|
||||
class="${backdropClass}"
|
||||
@click=${this.inline ? null : this.close}
|
||||
>
|
||||
<div
|
||||
@click=${(e: Event) => e.stopPropagation()}
|
||||
class="c-modal__wrapper ${this.alwaysMaximized
|
||||
? "always-maximized"
|
||||
: ""}"
|
||||
class="${wrapperClass}"
|
||||
>
|
||||
<header class="c-modal__header">
|
||||
${`${this.translationKey}` === ""
|
||||
? `${this.title}`
|
||||
: `${translateText(this.translationKey)}`}
|
||||
<div class="c-modal__close" @click=${this.close}>✕</div>
|
||||
</header>
|
||||
<section class="c-modal__content">
|
||||
${this.inline || this.hideCloseButton
|
||||
? html``
|
||||
: html`<div
|
||||
class="absolute top-4 right-4 z-10 text-white cursor-pointer"
|
||||
@click=${this.close}
|
||||
>
|
||||
✕
|
||||
</div>`}
|
||||
${!this.hideHeader && this.title
|
||||
? html`<div
|
||||
class="p-[1.4rem] pb-0 text-2xl font-bold text-white"
|
||||
>
|
||||
${this.title}
|
||||
</div>`
|
||||
: html``}
|
||||
<section
|
||||
class="relative flex-1 min-h-0 p-[1.4rem] text-white bg-[#23232382] backdrop-blur-md rounded-lg overflow-y-auto"
|
||||
>
|
||||
<slot></slot>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user