Modularized Loading on buttons

This commit is contained in:
Lucas Oliveira 2024-06-04 09:12:28 -03:00
commit 1f2cd32340

View file

@ -2,6 +2,7 @@ import { Slot } from "@radix-ui/react-slot";
import { cva, type VariantProps } from "class-variance-authority";
import * as React from "react";
import { cn } from "../../utils/utils";
import ForwardedIconComponent from "../genericIconComponent";
const buttonVariants = cva(
"inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:opacity-50 disabled:pointer-events-none ring-offset-background",
@ -32,13 +33,14 @@ const buttonVariants = cva(
variant: "default",
size: "default",
},
}
},
);
export interface ButtonProps
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
VariantProps<typeof buttonVariants> {
asChild?: boolean;
loading?: boolean;
}
function toTitleCase(text: string) {
@ -49,21 +51,36 @@ function toTitleCase(text: string) {
}
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
({ className, variant, size, asChild = false, children, ...props }, ref) => {
(
{ className, variant, size, loading, asChild = false, children, ...props },
ref,
) => {
const Comp = asChild ? Slot : "button";
let newChildren = children;
if (typeof children === "string") {
newChildren = toTitleCase(children);
}
return (
<Comp
className={cn(buttonVariants({ variant, size, className }))}
ref={ref}
children={newChildren}
{...props}
/>
<Comp className={"relative"} ref={ref} {...props}>
<div
className={cn(
loading ? "opacity-100" : "opacity-0",
"absolute self-center",
)}
>
<ForwardedIconComponent name={"Loader2"} className={"animate-spin"} />
</div>
<div
className={cn(
loading ? "opacity-0" : "opacity-100",
buttonVariants({ variant, size, className }),
)}
>
{newChildren}
</div>
</Comp>
);
}
},
);
Button.displayName = "Button";