nextuiq
Version:
NextUIQ is a modern, lightweight, and developer-friendly UI component library for React and Next.js. Built with TypeScript and Tailwind CSS, it offers customizable, accessible, and performance-optimized components with built-in dark mode, theme customizat
126 lines (123 loc) • 4.13 kB
JavaScript
import { j as jsxRuntimeExports } from './index46.mjs';
import { useRef, useEffect } from 'react';
import { FiX } from './index47.mjs';
import { cn } from './index38.mjs';
const Modal = ({
isOpen,
onClose,
children,
className = "",
showCloseButton = true,
isFullscreen = false,
size = "md",
position = "center",
title,
description,
initialFocus
}) => {
const modalRef = useRef(null);
const previousActiveElement = useRef(null);
useEffect(() => {
if (isOpen) {
previousActiveElement.current = document.activeElement;
if (initialFocus?.current) {
initialFocus.current.focus();
} else {
modalRef.current?.focus();
}
document.addEventListener("keydown", handleEscape);
document.body.style.overflow = "hidden";
} else {
document.body.style.overflow = "unset";
previousActiveElement.current?.focus();
}
return () => {
document.removeEventListener("keydown", handleEscape);
document.body.style.overflow = "unset";
};
}, [isOpen, initialFocus]);
const handleEscape = (event) => {
if (event.key === "Escape") {
onClose();
}
};
if (!isOpen) return null;
const sizeClasses = {
sm: "max-w-sm",
md: "max-w-md",
lg: "max-w-lg",
xl: "max-w-xl",
full: "max-w-full"
};
const positionClasses = {
center: "items-center",
top: "items-start mt-16"
};
return /* @__PURE__ */ jsxRuntimeExports.jsxs(
"div",
{
className: cn(
"fixed inset-0 flex justify-center",
positionClasses[position],
"overflow-y-auto z-50",
"animate-in fade-in duration-200"
),
role: "presentation",
children: [
/* @__PURE__ */ jsxRuntimeExports.jsx(
"div",
{
className: "fixed inset-0 bg-[oklch(var(--theme-background)/0.8)] backdrop-blur-sm transition-opacity",
onClick: onClose,
"aria-hidden": "true"
}
),
/* @__PURE__ */ jsxRuntimeExports.jsxs(
"div",
{
ref: modalRef,
className: cn(
"relative w-full m-4",
!isFullscreen && [
sizeClasses[size],
"rounded-lg bg-[oklch(var(--theme-background))]",
"shadow-lg",
"border border-[oklch(var(--theme-border))]"
],
isFullscreen && "w-full h-full bg-[oklch(var(--theme-background))]",
"animate-in zoom-in-95 duration-200",
className
),
onClick: (e) => e.stopPropagation(),
role: "dialog",
"aria-modal": "true",
"aria-labelledby": title ? "modal-title" : void 0,
"aria-describedby": description ? "modal-description" : void 0,
tabIndex: -1,
children: [
showCloseButton && /* @__PURE__ */ jsxRuntimeExports.jsx(
"button",
{
onClick: onClose,
className: cn(
"absolute right-4 top-4 z-10 rounded-sm p-2",
"text-[oklch(var(--theme-muted-foreground))] hover:text-[oklch(var(--theme-foreground))]",
"transition-colors hover:bg-[oklch(var(--theme-muted))]"
),
"aria-label": "Close modal",
children: /* @__PURE__ */ jsxRuntimeExports.jsx(FiX, { className: "h-5 w-5", "aria-hidden": "true" })
}
),
/* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "p-6", children: [
title && /* @__PURE__ */ jsxRuntimeExports.jsx("h2", { id: "modal-title", className: "text-xl font-semibold mb-2 text-[oklch(var(--theme-foreground))]", children: title }),
description && /* @__PURE__ */ jsxRuntimeExports.jsx("p", { id: "modal-description", className: "text-[oklch(var(--theme-muted-foreground))] mb-4", children: description }),
children
] })
]
}
)
]
}
);
};
export { Modal };