mirror of
https://github.com/stackblitz/bolt.new
synced 2024-11-27 22:42:21 +00:00
134 lines
3.9 KiB
TypeScript
134 lines
3.9 KiB
TypeScript
import * as RadixDialog from '@radix-ui/react-dialog';
|
|
import { motion, type Variants } from 'framer-motion';
|
|
import React, { memo, type ReactNode } from 'react';
|
|
import { classNames } from '~/utils/classNames';
|
|
import { cubicEasingFn } from '~/utils/easings';
|
|
import { IconButton } from './IconButton';
|
|
|
|
export { Close as DialogClose, Root as DialogRoot } from '@radix-ui/react-dialog';
|
|
|
|
const transition = {
|
|
duration: 0.15,
|
|
ease: cubicEasingFn,
|
|
};
|
|
|
|
export const dialogBackdropVariants = {
|
|
closed: {
|
|
opacity: 0,
|
|
transition,
|
|
},
|
|
open: {
|
|
opacity: 1,
|
|
transition,
|
|
},
|
|
} satisfies Variants;
|
|
|
|
export const dialogVariants = {
|
|
closed: {
|
|
x: '-50%',
|
|
y: '-40%',
|
|
scale: 0.96,
|
|
opacity: 0,
|
|
transition,
|
|
},
|
|
open: {
|
|
x: '-50%',
|
|
y: '-50%',
|
|
scale: 1,
|
|
opacity: 1,
|
|
transition,
|
|
},
|
|
} satisfies Variants;
|
|
|
|
interface DialogButtonProps {
|
|
type: 'primary' | 'secondary' | 'danger';
|
|
children: ReactNode;
|
|
onClick?: (event: React.UIEvent) => void;
|
|
}
|
|
|
|
export const DialogButton = memo(({ type, children, onClick }: DialogButtonProps) => {
|
|
return (
|
|
<button
|
|
className={classNames(
|
|
'inline-flex h-[35px] items-center justify-center rounded-lg px-4 text-sm leading-none focus:outline-none',
|
|
{
|
|
'bg-bolt-elements-button-primary-background text-bolt-elements-button-primary-text hover:bg-bolt-elements-button-primary-backgroundHover':
|
|
type === 'primary',
|
|
'bg-bolt-elements-button-secondary-background text-bolt-elements-button-secondary-text hover:bg-bolt-elements-button-secondary-backgroundHover':
|
|
type === 'secondary',
|
|
'bg-bolt-elements-button-danger-background text-bolt-elements-button-danger-text hover:bg-bolt-elements-button-danger-backgroundHover':
|
|
type === 'danger',
|
|
},
|
|
)}
|
|
onClick={onClick}
|
|
>
|
|
{children}
|
|
</button>
|
|
);
|
|
});
|
|
|
|
export const DialogTitle = memo(({ className, children, ...props }: RadixDialog.DialogTitleProps) => {
|
|
return (
|
|
<RadixDialog.Title
|
|
className={classNames(
|
|
'px-5 py-4 flex items-center justify-between border-b border-bolt-elements-borderColor text-lg font-semibold leading-6 text-bolt-elements-textPrimary',
|
|
className,
|
|
)}
|
|
{...props}
|
|
>
|
|
{children}
|
|
</RadixDialog.Title>
|
|
);
|
|
});
|
|
|
|
export const DialogDescription = memo(({ className, children, ...props }: RadixDialog.DialogDescriptionProps) => {
|
|
return (
|
|
<RadixDialog.Description
|
|
className={classNames('px-5 py-4 text-bolt-elements-textPrimary text-md', className)}
|
|
{...props}
|
|
>
|
|
{children}
|
|
</RadixDialog.Description>
|
|
);
|
|
});
|
|
|
|
interface DialogProps {
|
|
children: ReactNode | ReactNode[];
|
|
className?: string;
|
|
onBackdrop?: (event: React.UIEvent) => void;
|
|
onClose?: (event: React.UIEvent) => void;
|
|
}
|
|
|
|
export const Dialog = memo(({ className, children, onBackdrop, onClose }: DialogProps) => {
|
|
return (
|
|
<RadixDialog.Portal>
|
|
<RadixDialog.Overlay onClick={onBackdrop} asChild>
|
|
<motion.div
|
|
className="bg-black/50 fixed inset-0 z-max"
|
|
initial="closed"
|
|
animate="open"
|
|
exit="closed"
|
|
variants={dialogBackdropVariants}
|
|
/>
|
|
</RadixDialog.Overlay>
|
|
<RadixDialog.Content asChild>
|
|
<motion.div
|
|
className={classNames(
|
|
'fixed top-[50%] left-[50%] z-max max-h-[85vh] w-[90vw] max-w-[450px] translate-x-[-50%] translate-y-[-50%] border border-bolt-elements-borderColor rounded-lg bg-bolt-elements-background-depth-2 shadow-lg focus:outline-none overflow-hidden',
|
|
className,
|
|
)}
|
|
initial="closed"
|
|
animate="open"
|
|
exit="closed"
|
|
variants={dialogVariants}
|
|
>
|
|
{children}
|
|
<RadixDialog.Close asChild onClick={onClose}>
|
|
<IconButton icon="i-ph:x" className="absolute top-[10px] right-[10px]" />
|
|
</RadixDialog.Close>
|
|
</motion.div>
|
|
</RadixDialog.Content>
|
|
</RadixDialog.Portal>
|
|
);
|
|
});
|