|
|
@ -1,12 +1,14 @@ |
|
|
|
import { ReactNode, useRef } from "react"; |
|
|
|
import { ReactNode } from "react"; |
|
|
|
import { CSSTransition } from "react-transition-group"; |
|
|
|
import { |
|
|
|
import { CSSTransitionClassNames } from "react-transition-group/CSSTransition"; |
|
|
|
Transition as HeadlessTransition, |
|
|
|
|
|
|
|
TransitionClasses, |
|
|
|
|
|
|
|
} from "@headlessui/react"; |
|
|
|
|
|
|
|
|
|
|
|
type TransitionAnimations = "slide-down" | "slide-up" | "fade" | "fade-inverse"; |
|
|
|
type TransitionAnimations = "slide-down" | "slide-up" | "fade"; |
|
|
|
|
|
|
|
|
|
|
|
interface Props { |
|
|
|
interface Props { |
|
|
|
show: boolean; |
|
|
|
show: boolean; |
|
|
|
durationClass?: string; |
|
|
|
durationClass?: "duration-200" | string; // default is specified so tailwind doesnt remove the class in prod builds
|
|
|
|
animation: TransitionAnimations; |
|
|
|
animation: TransitionAnimations; |
|
|
|
className?: string; |
|
|
|
className?: string; |
|
|
|
children?: ReactNode; |
|
|
|
children?: ReactNode; |
|
|
@ -15,44 +17,37 @@ interface Props { |
|
|
|
function getClasses( |
|
|
|
function getClasses( |
|
|
|
animation: TransitionAnimations, |
|
|
|
animation: TransitionAnimations, |
|
|
|
duration: number |
|
|
|
duration: number |
|
|
|
): CSSTransitionClassNames { |
|
|
|
): TransitionClasses { |
|
|
|
if (animation === "slide-down") { |
|
|
|
if (animation === "slide-down") { |
|
|
|
return { |
|
|
|
return { |
|
|
|
exit: `transition-[transform,opacity] translate-y-0 duration-${duration} opacity-100`, |
|
|
|
leave: `transition-[transform,opacity] duration-${duration}`, |
|
|
|
exitActive: "!-translate-y-4 !opacity-0", |
|
|
|
leaveFrom: "opacity-100 translate-y-0", |
|
|
|
exitDone: "hidden", |
|
|
|
leaveTo: "-translate-y-4 opacity-0", |
|
|
|
enter: `transition-[transform,opacity] -translate-y-4 duration-${duration} opacity-0`, |
|
|
|
enter: `transition-[transform,opacity] duration-${duration}`, |
|
|
|
enterActive: "!translate-y-0 !opacity-100", |
|
|
|
enterFrom: "opacity-0 -translate-y-4", |
|
|
|
|
|
|
|
enterTo: "translate-y-0 opacity-100", |
|
|
|
}; |
|
|
|
}; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (animation === "slide-up") { |
|
|
|
if (animation === "slide-up") { |
|
|
|
return { |
|
|
|
return { |
|
|
|
exit: `transition-[transform,opacity] translate-y-0 duration-${duration} opacity-100`, |
|
|
|
leave: `transition-[transform,opacity] duration-${duration}`, |
|
|
|
exitActive: "!translate-y-4 !opacity-0", |
|
|
|
leaveFrom: "opacity-100 translate-y-0", |
|
|
|
exitDone: "hidden", |
|
|
|
leaveTo: "translate-y-4 opacity-0", |
|
|
|
enter: `transition-[transform,opacity] translate-y-4 duration-${duration} opacity-0`, |
|
|
|
enter: `transition-[transform,opacity] duration-${duration}`, |
|
|
|
enterActive: "!translate-y-0 !opacity-100", |
|
|
|
enterFrom: "opacity-0 translate-y-4", |
|
|
|
|
|
|
|
enterTo: "translate-y-0 opacity-100", |
|
|
|
}; |
|
|
|
}; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (animation === "fade") { |
|
|
|
if (animation === "fade") { |
|
|
|
return { |
|
|
|
return { |
|
|
|
exit: `transition-[transform,opacity] duration-${duration} opacity-100`, |
|
|
|
leave: `transition-[transform,opacity] duration-${duration}`, |
|
|
|
exitActive: "!opacity-0", |
|
|
|
leaveFrom: "opacity-100", |
|
|
|
exitDone: "hidden", |
|
|
|
leaveTo: "opacity-0", |
|
|
|
enter: `transition-[transform,opacity] duration-${duration} opacity-0`, |
|
|
|
enter: `transition-[transform,opacity] duration-${duration}`, |
|
|
|
enterActive: "!opacity-100", |
|
|
|
enterFrom: "opacity-0", |
|
|
|
}; |
|
|
|
enterTo: "opacity-100", |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (animation === "fade-inverse") { |
|
|
|
|
|
|
|
return { |
|
|
|
|
|
|
|
enter: `transition-[transform,opacity] duration-${duration} opacity-100`, |
|
|
|
|
|
|
|
enterActive: "!opacity-0", |
|
|
|
|
|
|
|
exit: `transition-[transform,opacity] duration-${duration} opacity-0`, |
|
|
|
|
|
|
|
exitActive: "!opacity-100", |
|
|
|
|
|
|
|
enterDone: "hidden", |
|
|
|
|
|
|
|
}; |
|
|
|
}; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -60,25 +55,16 @@ function getClasses( |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
export function Transition(props: Props) { |
|
|
|
export function Transition(props: Props) { |
|
|
|
const ref = useRef<HTMLDivElement>(null); |
|
|
|
|
|
|
|
const duration = props.durationClass |
|
|
|
const duration = props.durationClass |
|
|
|
? parseInt(props.durationClass.split("-")[1], 10) |
|
|
|
? parseInt(props.durationClass.split("-")[1], 10) |
|
|
|
: 200; |
|
|
|
: 200; |
|
|
|
const classes = getClasses(props.animation, duration); |
|
|
|
const classes = getClasses(props.animation, duration); |
|
|
|
|
|
|
|
|
|
|
|
return ( |
|
|
|
return ( |
|
|
|
<CSSTransition |
|
|
|
<div className={props.className}> |
|
|
|
nodeRef={ref} |
|
|
|
<HeadlessTransition show={props.show} {...classes}> |
|
|
|
in={props.show} |
|
|
|
|
|
|
|
timeout={duration} |
|
|
|
|
|
|
|
classNames={classes} |
|
|
|
|
|
|
|
> |
|
|
|
|
|
|
|
<div |
|
|
|
|
|
|
|
ref={ref} |
|
|
|
|
|
|
|
className={[props.className ?? "", classes.enter ?? ""].join(" ")} |
|
|
|
|
|
|
|
> |
|
|
|
|
|
|
|
{props.children} |
|
|
|
{props.children} |
|
|
|
</div> |
|
|
|
</HeadlessTransition> |
|
|
|
</CSSTransition> |
|
|
|
</div> |
|
|
|
); |
|
|
|
); |
|
|
|
} |
|
|
|
} |
|
|
|