feat: add settings menu
All checks were successful
Deploy to VPS (dist) / deploy (push) Successful in 1m40s

This commit is contained in:
Hewston Fox
2026-03-22 04:08:56 +02:00
parent 2a1115b66f
commit 5e9acffa09
89 changed files with 3412 additions and 216 deletions

View File

@@ -1,11 +1,27 @@
@layer base {
.overlay {
position: fixed;
inset: 0;
z-index: 100;
}
.modalContainer {
width: 100%;
position: fixed;
inset: 0;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
z-index: 100;
z-index: 102;
}
.modalInner {
display: flex;
flex-direction: column;
align-items: center;
width: 100%;
max-width: 320px;
}
.modal {
@@ -13,7 +29,19 @@
flex-direction: column;
gap: 6px;
width: 100%;
max-width: 320px;
max-height: calc(
var(--safe-area-height) - var(--header-total) - var(--navigation-total) - 70px
);
overflow: auto;
padding: 13px;
}
.title {
color: #ffffff;
-webkit-text-stroke: 0.7px #331b01;
font-weight: 700;
font-size: 24px;
margin-bottom: 12px;
text-align: center;
}
}

View File

@@ -1,36 +1,85 @@
import { useEffect, useRef } from "react";
import type { ReactNode } from "react";
import { AnimatePresence, motion } from "motion/react";
import SectionSurface from "../../surface/SectionSurface/SectionSurface";
import SectionSurface from "@components/surface/SectionSurface";
import { useLift } from "@components/lift";
import classes from "./Modal.module.css";
import { clsx, type ClassValue } from "clsx";
type Props = {
open: boolean;
children: ReactNode;
onClose: () => void;
liftIds?: string[];
title?: ReactNode;
className?: ClassValue;
};
export default function Modal({ open, children, onClose }: Props) {
export default function Modal({ open, children, onClose, liftIds, title, className }: Props) {
const { setLiftedIds } = useLift();
const prevLiftIdsRef = useRef<string>("");
useEffect(() => {
const key = liftIds?.join(",") ?? "";
if (open && key) {
if (key !== prevLiftIdsRef.current) {
prevLiftIdsRef.current = key;
setLiftedIds(liftIds!);
}
}
if (!open && prevLiftIdsRef.current) {
prevLiftIdsRef.current = "";
setLiftedIds([]);
}
}, [open, liftIds, setLiftedIds]);
useEffect(() => {
return () => {
if (prevLiftIdsRef.current) {
setLiftedIds([]);
}
};
}, [setLiftedIds]);
return (
<AnimatePresence>
{open && (
<motion.div
className={classes.overlay}
initial={{ backdropFilter: "blur(0px)" }}
animate={{ backdropFilter: "blur(8px)" }}
exit={{ backdropFilter: "blur(0px)" }}
transition={{ duration: 0.2 }}
onClick={onClose}
>
<SectionSurface
className={classes.modal}
exit={{ scale: 0 }}
transition={{ duration: 0.2, type: "spring" }}
onClick={(e) => e.stopPropagation()}
<>
<motion.div
className={classes.overlay}
initial={{ backdropFilter: "blur(0px)" }}
animate={{ backdropFilter: "blur(8px)" }}
exit={{ backdropFilter: "blur(0px)" }}
transition={{ duration: 0.2 }}
onClick={onClose}
/>
<motion.div
className={classes.modalContainer}
initial={{ opacity: 1 }}
exit={{ opacity: 0 }}
transition={{ duration: 0.2 }}
onClick={onClose}
>
{children}
</SectionSurface>
</motion.div>
{/* oxlint-disable-next-line jsx_a11y/no-static-element-interactions*/}
<div
className={classes.modalInner}
// oxlint-disable-next-line jsx_a11y/click-events-have-key-events
onClick={(e) => e.stopPropagation()}
>
{title && <div className={classes.title}>{title}</div>}
<SectionSurface
className={clsx(classes.modal, className)}
exit={{ scale: 0 }}
transition={{ duration: 0.2, type: "spring" }}
>
{children}
</SectionSurface>
</div>
</motion.div>
</>
)}
</AnimatePresence>
);