Files
artcraft/app/components/reusable/LoadingBar.tsx
T
2024-10-11 11:28:31 +07:00

101 lines
2.7 KiB
TypeScript

import { Transition } from "@headlessui/react";
import { twMerge } from "tailwind-merge";
import { LoadingSpinner } from "~/components";
interface LoadingBarProps {
id?: string;
wrapperClassName?: string;
innerWrapperClassName?: string;
progressBackgroundClassName?: string;
progressClassName?: string;
variant?: string;
show?: boolean;
hasSpinner?: boolean;
progressData: {
progress: number;
label?: string;
message?: string;
};
}
export const LoadingBar = ({
wrapperClassName: propsWrapperClassName,
innerWrapperClassName: propsInnerWrapperClassName,
progressBackgroundClassName: propsProgressBackgroundClassName,
progressClassName: propsProgressClassName,
progressData,
hasSpinner,
variant = "primary",
show = true,
...rest
}: LoadingBarProps) => {
function getVariantClassNames(variant: string) {
switch (variant) {
case "secondary": {
return " bg-brand-secondary text-white ";
}
case "primary":
default: {
return " bg-brand-primary text-white ";
}
}
}
const wrapperClassName = twMerge(
"w-full h-full relative bg-ui-background",
propsWrapperClassName,
);
const innerWrapperClassName = twMerge(
"w-full h-full p-4 gap-6 m-auto flex flex-col justify-center items-center",
propsInnerWrapperClassName,
);
const progressBackgroundClassName = twMerge(
"w-full bg-brand-secondary-800 rounded-full h-2.5",
propsProgressBackgroundClassName,
);
const progressClassName = twMerge(
"h-2.5 rounded-full transition-all duration-1000",
getVariantClassNames(variant),
propsProgressClassName,
);
return (
<Transition
className={wrapperClassName}
show={show}
enter="transition-opacity duration-150"
enterFrom="opacity-0"
enterTo="opacity-100"
leave="transition-opacity duration-1000"
leaveFrom="opacity-100"
leaveTo="opacity-0"
{...rest}
>
<div className={innerWrapperClassName}>
<div className="flex flex-col items-center gap-3">
<div className="flex items-center gap-2.5">
{hasSpinner && <LoadingSpinner className="h-5" />}
{progressData.label && (
<label className="text-lg font-medium">
{progressData.label}
</label>
)}
</div>
</div>
<div className={progressBackgroundClassName}>
<div
className={progressClassName}
style={{ width: progressData.progress + "%" }}
/>
</div>
{progressData.message && (
<p className="text-center text-sm opacity-75">
{progressData.message}
</p>
)}
</div>
</Transition>
);
};