mirror of
https://github.com/rzmk/learnhouse.git
synced 2025-12-19 04:19:25 +00:00
158 lines
No EOL
4.6 KiB
TypeScript
158 lines
No EOL
4.6 KiB
TypeScript
'use client';
|
|
import React from 'react';
|
|
import * as Dialog from '@radix-ui/react-dialog';
|
|
import { styled, keyframes } from '@stitches/react';
|
|
import { violet, blackA, mauve, green } from '@radix-ui/colors';
|
|
import { ButtonBlack } from '../Form/Form';
|
|
|
|
type ModalParams = {
|
|
dialogTitle: string;
|
|
dialogDescription: string;
|
|
dialogContent: React.ReactNode;
|
|
dialogClose?: React.ReactNode | null;
|
|
dialogTrigger?: React.ReactNode;
|
|
addDefCloseButton?: boolean;
|
|
onOpenChange: any;
|
|
isDialogOpen?: boolean;
|
|
minHeight?: "sm" | "md" | "lg" | "xl" | "no-min";
|
|
};
|
|
|
|
const Modal = (params: ModalParams) => (
|
|
<Dialog.Root open={params.isDialogOpen} onOpenChange={params.onOpenChange}>
|
|
{params.dialogTrigger ? (
|
|
<Dialog.Trigger asChild>
|
|
{params.dialogTrigger}
|
|
</Dialog.Trigger>
|
|
) : null}
|
|
|
|
<Dialog.Portal>
|
|
<DialogOverlay />
|
|
<DialogContent className='overflow-auto scrollbar-w-2 scrollbar-h-2 scrollbar scrollbar-thumb-black/20 scrollbar-thumb-rounded-full scrollbar-track-rounded-full' minHeight={params.minHeight}>
|
|
<DialogTopBar className='-space-y-1'>
|
|
<DialogTitle>{params.dialogTitle}</DialogTitle>
|
|
<DialogDescription>
|
|
{params.dialogDescription}
|
|
</DialogDescription>
|
|
</DialogTopBar>
|
|
{params.dialogContent}
|
|
{params.dialogClose ? (
|
|
<Flex css={{ marginTop: 25, justifyContent: 'flex-end' }}>
|
|
<Dialog.Close asChild>
|
|
{params.dialogClose}
|
|
</Dialog.Close>
|
|
</Flex>
|
|
) : null}
|
|
{params.addDefCloseButton ? (
|
|
<Flex css={{ marginTop: 25, justifyContent: 'flex-end' }}>
|
|
<Dialog.Close asChild>
|
|
<ButtonBlack type="submit" css={{ marginTop: 10 }}>Close</ButtonBlack>
|
|
</Dialog.Close>
|
|
</Flex>
|
|
) : null}
|
|
|
|
</DialogContent>
|
|
|
|
</Dialog.Portal>
|
|
</Dialog.Root>
|
|
);
|
|
|
|
const overlayShow = keyframes({
|
|
'0%': { opacity: 0 },
|
|
'100%': { opacity: 1 },
|
|
});
|
|
|
|
const overlayClose = keyframes({
|
|
'0%': { opacity: 1 },
|
|
'100%': { opacity: 0 },
|
|
});
|
|
|
|
const contentShow = keyframes({
|
|
'0%': { opacity: 0, transform: 'translate(-50%, -50%) scale(.96)' },
|
|
'100%': { opacity: 1, transform: 'translate(-50%, -50%) scale(1)' },
|
|
});
|
|
|
|
const contentClose = keyframes({
|
|
'0%': { opacity: 1, transform: 'translate(-50%, -50%) scale(1)' },
|
|
'100%': { opacity: 0, transform: 'translate(-50%, -52%) scale(.96)' },
|
|
});
|
|
|
|
const DialogOverlay = styled(Dialog.Overlay, {
|
|
backgroundColor: blackA.blackA9,
|
|
position: 'fixed',
|
|
zIndex: 500,
|
|
inset: 0,
|
|
animation: `${overlayShow} 150ms cubic-bezier(0.16, 1, 0.3, 1)`,
|
|
'&[data-state="closed"]': {
|
|
animation: `${overlayClose} 150ms cubic-bezier(0.16, 1, 0.3, 1)`,
|
|
},
|
|
});
|
|
|
|
const DialogContent = styled(Dialog.Content, {
|
|
|
|
variants: {
|
|
minHeight: {
|
|
'no-min': {
|
|
minHeight: '0px',
|
|
},
|
|
'sm': {
|
|
minHeight: '300px',
|
|
},
|
|
'md': {
|
|
minHeight: '500px',
|
|
},
|
|
'lg': {
|
|
minHeight: '700px',
|
|
},
|
|
'xl': {
|
|
minHeight: '900px',
|
|
},
|
|
},
|
|
},
|
|
|
|
backgroundColor: 'white',
|
|
borderRadius: 18,
|
|
zIndex: 501,
|
|
boxShadow: 'hsl(206 22% 7% / 35%) 0px 10px 38px -10px, hsl(206 22% 7% / 20%) 0px 10px 20px -15px',
|
|
position: 'fixed',
|
|
top: '50%',
|
|
left: '50%',
|
|
transform: 'translate(-50%, -50%)',
|
|
width: '90vw',
|
|
maxHeight: '85vh',
|
|
minHeight: '300px',
|
|
maxWidth: '600px',
|
|
padding: 11,
|
|
animation: `${contentShow} 150ms cubic-bezier(0.16, 1, 0.3, 1)`,
|
|
'&:focus': { outline: 'none' },
|
|
|
|
'&[data-state="closed"]': {
|
|
animation: `${contentClose} 150ms cubic-bezier(0.16, 1, 0.3, 1)`,
|
|
},
|
|
transition: "max-height 0.3s ease-out",
|
|
});
|
|
|
|
const DialogTopBar = styled('div', {
|
|
background: "#F7F7F7",
|
|
padding: "8px 14px ",
|
|
borderRadius: 14,
|
|
});
|
|
const DialogTitle = styled(Dialog.Title, {
|
|
margin: 0,
|
|
fontWeight: 700,
|
|
letterSpacing: "-0.05em",
|
|
padding: 0,
|
|
color: mauve.mauve12,
|
|
fontSize: 21,
|
|
});
|
|
|
|
const DialogDescription = styled(Dialog.Description, {
|
|
color: mauve.mauve11,
|
|
letterSpacing: "-0.03em",
|
|
fontSize: 15,
|
|
padding: 0,
|
|
margin: 0,
|
|
});
|
|
|
|
const Flex = styled('div', { display: 'flex' });
|
|
|
|
export default Modal; |