Apply the real frosted .glass surface (blur) to the few large chrome surfaces — the nav sidebar, the header and all Modal-based dialogs (was glass-card / plain surfaces) — and enrich the ambient backdrop a touch (three soft accent pools) so the glass has more to refract app-wide. Popovers (notifications, language, account, add-to-playlist) were already glass. Bulk feed cards stay glass-card (no per-card blur) for performance; the existing perf-mode still disables blur. Phase 2 (ambient thumbnail mosaic / bg image + toggle) deferred to end-of-project polish.
56 lines
1.6 KiB
TypeScript
56 lines
1.6 KiB
TypeScript
import { useEffect, type ReactNode } from "react";
|
|
import { createPortal } from "react-dom";
|
|
import { X } from "lucide-react";
|
|
|
|
// Small centered modal shell (portaled to <body>): backdrop + ESC + scroll-lock close.
|
|
export default function Modal({
|
|
title,
|
|
onClose,
|
|
children,
|
|
maxWidth = "max-w-lg",
|
|
}: {
|
|
title: ReactNode;
|
|
onClose: () => void;
|
|
children: ReactNode;
|
|
maxWidth?: string;
|
|
}) {
|
|
useEffect(() => {
|
|
const onKey = (e: KeyboardEvent) => {
|
|
if (e.key === "Escape") onClose();
|
|
};
|
|
window.addEventListener("keydown", onKey);
|
|
const prev = document.body.style.overflow;
|
|
document.body.style.overflow = "hidden";
|
|
return () => {
|
|
window.removeEventListener("keydown", onKey);
|
|
document.body.style.overflow = prev;
|
|
};
|
|
}, [onClose]);
|
|
|
|
return createPortal(
|
|
<div
|
|
className="fixed inset-0 z-50 flex items-center justify-center p-4 sm:p-6 bg-black/70 backdrop-blur-sm"
|
|
onClick={onClose}
|
|
role="dialog"
|
|
aria-modal="true"
|
|
>
|
|
<div
|
|
className={`glass relative w-full ${maxWidth} max-h-full overflow-y-auto rounded-2xl shadow-2xl`}
|
|
onClick={(e) => e.stopPropagation()}
|
|
>
|
|
<div className="flex items-start justify-between gap-3 p-5 pb-3">
|
|
<h2 className="text-lg font-semibold leading-snug">{title}</h2>
|
|
<button
|
|
onClick={onClose}
|
|
title="Close"
|
|
className="shrink-0 p-1.5 rounded-lg text-muted hover:text-fg hover:bg-surface transition"
|
|
>
|
|
<X className="w-4 h-4" />
|
|
</button>
|
|
</div>
|
|
<div className="px-5 pb-5">{children}</div>
|
|
</div>
|
|
</div>,
|
|
document.body
|
|
);
|
|
}
|