forked from
slices.network/slices
Highly ambitious ATProtocol AppView service and sdks
1import { ComponentChildren } from "preact";
2import { Text } from "./Text.tsx";
3import { cn } from "../../utils/cn.ts";
4
5type ModalSize = "sm" | "md" | "lg" | "xl";
6
7interface ModalProps {
8 title: string;
9 description?: string;
10 children: ComponentChildren;
11 size?: ModalSize;
12 onClose?: string; // Hyperscript for close action, defaults to clearing modal-container
13}
14
15const sizeClasses = {
16 sm: "max-w-sm",
17 md: "max-w-lg",
18 lg: "max-w-3xl",
19 xl: "max-w-5xl",
20};
21
22export function Modal({
23 title,
24 description,
25 children,
26 size = "lg",
27 onClose = "on click set #modal-container's innerHTML to ''",
28}: ModalProps) {
29 return (
30 <div
31 className="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center z-50"
32 /* @ts-ignore - Hyperscript attribute */
33 _={`on click if event.target === me then ${
34 onClose.replace("on click ", "")
35 }`}
36 >
37 <div className={cn("bg-white dark:bg-zinc-900 border border-zinc-200 dark:border-zinc-700 rounded-md p-6 w-full max-h-[90vh] overflow-y-auto", sizeClasses[size])}>
38 <div className="flex justify-between items-start mb-4">
39 <div>
40 <Text as="h2" size="2xl" className="font-semibold">{title}</Text>
41 {description && <Text as="p" variant="secondary" className="mt-2">{description}</Text>}
42 </div>
43 <button
44 type="button"
45 /* @ts-ignore - Hyperscript attribute */
46 _={onClose}
47 className="text-gray-400 dark:text-zinc-500 hover:text-gray-600 dark:hover:text-zinc-400 text-2xl leading-none"
48 >
49 ✕
50 </button>
51 </div>
52 {children}
53 </div>
54 </div>
55 );
56}