headplane/app/components/Dialog.tsx

87 lines
2.3 KiB
TypeScript
Raw Normal View History

import React, { Dispatch, ReactNode, SetStateAction } from 'react';
import Button, { ButtonProps } from '~/components/Button';
import Title from '~/components/Title';
import {
Button as AriaButton,
Dialog as AriaDialog,
DialogTrigger,
Heading as AriaHeading,
Modal,
2024-12-31 10:30:14 +05:30
ModalOverlay,
} from 'react-aria-components';
import { cn } from '~/utils/cn';
interface ActionProps extends ButtonProps {
variant: 'cancel' | 'confirm';
}
2024-12-31 10:30:14 +05:30
function Action(props: ActionProps) {
return (
<Button
2024-12-31 10:30:14 +05:30
{...props}
type={props.variant === 'confirm' ? 'submit' : 'button'}
variant={props.variant === 'cancel' ? 'light' : 'heavy'}
/>
2024-12-31 10:30:14 +05:30
);
}
2024-12-31 10:30:14 +05:30
function Text(props: React.HTMLProps<HTMLParagraphElement>) {
return (
2024-12-31 10:30:14 +05:30
<p {...props} className={cn('text-base leading-6 my-0', props.className)} />
);
}
2024-12-31 10:30:14 +05:30
interface PanelProps {
children: (close: () => void) => ReactNode;
control?: [boolean, Dispatch<SetStateAction<boolean>>];
className?: string;
}
2024-12-31 10:30:14 +05:30
function Panel({ children, control, className }: PanelProps) {
return (
<ModalOverlay
2024-12-31 10:30:14 +05:30
aria-hidden="true"
className={cn(
'fixed inset-0 h-screen w-screen z-50 bg-black/30',
'flex items-center justify-center dark:bg-black/70',
'entering:animate-in exiting:animate-out',
'entering:fade-in entering:duration-200 entering:ease-out',
'exiting:fade-out exiting:duration-100 exiting:ease-in',
2024-12-31 10:30:14 +05:30
className,
)}
isOpen={control ? control[0] : undefined}
onOpenChange={control ? control[1] : undefined}
>
<Modal
className={cn(
'w-full max-w-md overflow-hidden rounded-2xl p-4',
'bg-ui-50 dark:bg-ui-900 shadow-lg',
'entering:animate-in exiting:animate-out',
'dark:border dark:border-ui-700',
'entering:zoom-in-95 entering:ease-out entering:duration-200',
2024-12-31 10:30:14 +05:30
'exiting:zoom-out-95 exiting:ease-in exiting:duration-100',
)}
>
2024-12-31 10:30:14 +05:30
<AriaDialog role="alertdialog" className="outline-none relative">
{({ close }) => children(close)}
</AriaDialog>
</Modal>
</ModalOverlay>
2024-12-31 10:30:14 +05:30
);
}
2024-12-31 10:30:14 +05:30
interface DialogProps {
children: ReactNode;
control?: [boolean, Dispatch<SetStateAction<boolean>>];
}
2024-12-31 10:30:14 +05:30
function Dialog({ children, control }: DialogProps) {
if (control) {
2024-12-31 10:30:14 +05:30
return children;
}
2024-12-31 10:30:14 +05:30
return <DialogTrigger>{children}</DialogTrigger>;
}
2024-12-31 10:30:14 +05:30
export default Object.assign(Dialog, { Button, Title, Text, Panel, Action });