dev #4

Merged
nessi merged 25 commits from dev into main 2026-02-06 13:36:47 +00:00
3 changed files with 127 additions and 75 deletions
Showing only changes of commit 52ace41ac4 - Show all commits

View File

@@ -2,7 +2,19 @@ import React, { useEffect, useState } from "react";
import { api } from "../api/client"; import { api } from "../api/client";
import { styles } from "../styles/styles"; import { styles } from "../styles/styles";
import { stylesTokens } from "../styles/theme"; import { stylesTokens } from "../styles/theme";
import { createPortal } from "react-dom";
useEffect(() => {
if (!open) return;
const prev = document.body.style.overflow;
document.body.style.overflow = "hidden";
return () => {
document.body.style.overflow = prev;
};
}, [open]);
export default function AdminPanel() { export default function AdminPanel() {
const [users, setUsers] = useState([]); const [users, setUsers] = useState([]);
@@ -112,7 +124,8 @@ export default function AdminPanel() {
))} ))}
</div> </div>
{open && ( {open &&
createPortal(
<div style={styles.modalOverlay} onMouseDown={closeModal}> <div style={styles.modalOverlay} onMouseDown={closeModal}>
<div style={styles.modalCard} onMouseDown={(e) => e.stopPropagation()}> <div style={styles.modalCard} onMouseDown={(e) => e.stopPropagation()}>
<div style={styles.modalHeader}> <div style={styles.modalHeader}>
@@ -175,8 +188,10 @@ export default function AdminPanel() {
</div> </div>
</div> </div>
</div> </div>
</div> </div>,
)} document.body
)
}
</div> </div>
); );
} }

View File

@@ -0,0 +1,40 @@
import React, { useEffect } from "react";
import { createPortal } from "react-dom";
import { styles } from "../styles/styles";
export default function ModalPortal({ open, onClose, children }) {
useEffect(() => {
if (!open) return;
const onKeyDown = (e) => {
if (e.key === "Escape") onClose?.();
};
// Scroll der Seite sperren
const prev = document.body.style.overflow;
document.body.style.overflow = "hidden";
window.addEventListener("keydown", onKeyDown);
return () => {
window.removeEventListener("keydown", onKeyDown);
document.body.style.overflow = prev;
};
}, [open, onClose]);
if (!open) return null;
return createPortal(
<div
style={styles.modalOverlay}
onMouseDown={(e) => {
// Klick außerhalb schließt
if (e.target === e.currentTarget) onClose?.();
}}
>
<div style={styles.modalCard} onMouseDown={(e) => e.stopPropagation()}>
{children}
</div>
</div>,
document.body
);
}

View File

@@ -188,32 +188,29 @@ export const styles = {
// Modal // Modal
modalOverlay: { modalOverlay: {
position: "fixed", position: "fixed",
inset: 0, top: 0,
background: "rgba(0,0,0,0.78)", // stärker abdunkeln left: 0,
backdropFilter: "blur(6px)", // Hintergrund weich (macht viel aus) right: 0,
bottom: 0,
width: "100vw",
height: "100vh",
display: "flex", display: "flex",
alignItems: "center", alignItems: "center",
justifyContent: "center", justifyContent: "center",
padding: 16, padding: 16,
zIndex: 9999, zIndex: 2147483647, // wirklich ganz oben
animation: "fadeIn 160ms ease-out", background: "rgba(0,0,0,0.72)",
overflowY: "auto", // falls Viewport zu klein overflowY: "auto",
}, },
modalCard: { modalCard: {
width: "100%", width: "min(560px, 100%)",
maxWidth: 560,
borderRadius: 18, borderRadius: 18,
border: `1px solid rgba(233,216,166,0.18)`, border: `1px solid rgba(233,216,166,0.18)`,
background: "linear-gradient(180deg, rgba(20,20,24,0.95), rgba(12,12,14,0.92))", background: "rgba(12,12,14,0.96)",
boxShadow: "0 18px 55px rgba(0,0,0,0.70)", boxShadow: "0 18px 55px rgba(0,0,0,0.70)",
padding: 14, padding: 14,
backdropFilter: "blur(8px)", maxHeight: "calc(100vh - 32px)",
animation: "popIn 160ms ease-out",
color: stylesTokens.textMain,
// neu: damit es nie “kaputt” aussieht
maxHeight: "calc(100dvh - 32px)",
overflow: "auto", overflow: "auto",
}, },
modalHeader: { modalHeader: {