2023-02-07 18:19:31 +01:00
|
|
|
import {
|
|
|
|
Transition as HeadlessTransition,
|
|
|
|
TransitionClasses,
|
|
|
|
} from "@headlessui/react";
|
2023-10-21 21:44:08 +02:00
|
|
|
import { CSSProperties, Fragment, ReactNode } from "react";
|
2023-02-04 01:01:54 +01:00
|
|
|
|
2023-10-11 22:09:28 +02:00
|
|
|
export type TransitionAnimations =
|
2023-02-28 23:36:46 +01:00
|
|
|
| "slide-down"
|
|
|
|
| "slide-full-left"
|
|
|
|
| "slide-full-right"
|
|
|
|
| "slide-up"
|
|
|
|
| "fade"
|
|
|
|
| "none";
|
2023-02-04 01:01:54 +01:00
|
|
|
|
|
|
|
interface Props {
|
2023-02-19 19:54:34 +01:00
|
|
|
show?: boolean;
|
2023-02-07 19:40:53 +01:00
|
|
|
durationClass?: string;
|
2023-02-04 01:01:54 +01:00
|
|
|
animation: TransitionAnimations;
|
|
|
|
className?: string;
|
|
|
|
children?: ReactNode;
|
2023-02-19 19:54:34 +01:00
|
|
|
isChild?: boolean;
|
2023-10-21 21:44:08 +02:00
|
|
|
style?: CSSProperties;
|
2023-02-04 01:01:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
function getClasses(
|
|
|
|
animation: TransitionAnimations,
|
2023-02-07 19:40:53 +01:00
|
|
|
duration: string
|
2023-02-07 18:19:31 +01:00
|
|
|
): TransitionClasses {
|
2023-02-04 01:01:54 +01:00
|
|
|
if (animation === "slide-down") {
|
|
|
|
return {
|
2023-02-07 20:03:01 +01:00
|
|
|
leave: `transition-[transform,opacity] ${duration}`,
|
2023-02-07 18:19:31 +01:00
|
|
|
leaveFrom: "opacity-100 translate-y-0",
|
|
|
|
leaveTo: "-translate-y-4 opacity-0",
|
2023-02-07 20:03:01 +01:00
|
|
|
enter: `transition-[transform,opacity] ${duration}`,
|
2023-02-07 18:19:31 +01:00
|
|
|
enterFrom: "opacity-0 -translate-y-4",
|
|
|
|
enterTo: "translate-y-0 opacity-100",
|
2023-02-04 01:01:54 +01:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
if (animation === "slide-up") {
|
|
|
|
return {
|
2023-02-07 20:03:01 +01:00
|
|
|
leave: `transition-[transform,opacity] ${duration}`,
|
2023-02-07 18:19:31 +01:00
|
|
|
leaveFrom: "opacity-100 translate-y-0",
|
|
|
|
leaveTo: "translate-y-4 opacity-0",
|
2023-02-07 20:03:01 +01:00
|
|
|
enter: `transition-[transform,opacity] ${duration}`,
|
2023-02-07 18:19:31 +01:00
|
|
|
enterFrom: "opacity-0 translate-y-4",
|
|
|
|
enterTo: "translate-y-0 opacity-100",
|
2023-02-04 01:01:54 +01:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2023-02-28 23:36:46 +01:00
|
|
|
if (animation === "slide-full-left") {
|
|
|
|
return {
|
|
|
|
leave: `transition-[transform] ${duration}`,
|
|
|
|
leaveFrom: "translate-x-0",
|
|
|
|
leaveTo: "-translate-x-full",
|
|
|
|
enter: `transition-[transform] ${duration}`,
|
|
|
|
enterFrom: "-translate-x-full",
|
|
|
|
enterTo: "translate-x-0",
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
if (animation === "slide-full-right") {
|
|
|
|
return {
|
|
|
|
leave: `transition-[transform] ${duration}`,
|
|
|
|
leaveFrom: "translate-x-0",
|
|
|
|
leaveTo: "translate-x-full",
|
|
|
|
enter: `transition-[transform] ${duration}`,
|
|
|
|
enterFrom: "translate-x-full",
|
|
|
|
enterTo: "translate-x-0",
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2023-02-04 01:01:54 +01:00
|
|
|
if (animation === "fade") {
|
|
|
|
return {
|
2023-02-07 20:03:01 +01:00
|
|
|
leave: `transition-[transform,opacity] ${duration}`,
|
2023-02-07 18:19:31 +01:00
|
|
|
leaveFrom: "opacity-100",
|
|
|
|
leaveTo: "opacity-0",
|
2023-02-07 20:03:01 +01:00
|
|
|
enter: `transition-[transform,opacity] ${duration}`,
|
2023-02-07 18:19:31 +01:00
|
|
|
enterFrom: "opacity-0",
|
|
|
|
enterTo: "opacity-100",
|
2023-02-07 17:49:05 +01:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2023-02-04 01:01:54 +01:00
|
|
|
return {};
|
|
|
|
}
|
|
|
|
|
|
|
|
export function Transition(props: Props) {
|
2023-02-07 19:40:53 +01:00
|
|
|
const duration = props.durationClass ?? "duration-200";
|
2023-02-07 20:03:01 +01:00
|
|
|
const classes = getClasses(props.animation, duration);
|
2023-02-04 01:01:54 +01:00
|
|
|
|
2023-02-19 19:54:34 +01:00
|
|
|
if (props.isChild) {
|
|
|
|
return (
|
2023-02-19 22:22:01 +01:00
|
|
|
<HeadlessTransition.Child as={Fragment} {...classes}>
|
2023-10-21 21:44:08 +02:00
|
|
|
<div className={props.className} style={props.style}>
|
|
|
|
{props.children}
|
|
|
|
</div>
|
2023-02-19 19:54:34 +01:00
|
|
|
</HeadlessTransition.Child>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2023-02-04 01:01:54 +01:00
|
|
|
return (
|
2023-02-19 22:22:01 +01:00
|
|
|
<HeadlessTransition show={props.show} as={Fragment} {...classes}>
|
2023-10-21 21:44:08 +02:00
|
|
|
<div className={props.className} style={props.style}>
|
|
|
|
{props.children}
|
|
|
|
</div>
|
2023-02-07 19:40:53 +01:00
|
|
|
</HeadlessTransition>
|
2023-02-04 01:01:54 +01:00
|
|
|
);
|
|
|
|
}
|