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 { cva, type VariantProps } from "class-variance-authority";
import * as React from "react"; import * as React from "react";
import { cn } from "../../utils/utils"; import { cn } from "../../utils/utils";
import ForwardedIconComponent from "../genericIconComponent";
const buttonVariants = cva( 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", "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", variant: "default",
size: "default", size: "default",
}, },
} },
); );
export interface ButtonProps export interface ButtonProps
extends React.ButtonHTMLAttributes<HTMLButtonElement>, extends React.ButtonHTMLAttributes<HTMLButtonElement>,
VariantProps<typeof buttonVariants> { VariantProps<typeof buttonVariants> {
asChild?: boolean; asChild?: boolean;
loading?: boolean;
} }
function toTitleCase(text: string) { function toTitleCase(text: string) {
@ -49,21 +51,36 @@ function toTitleCase(text: string) {
} }
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>( 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"; const Comp = asChild ? Slot : "button";
let newChildren = children; let newChildren = children;
if (typeof children === "string") { if (typeof children === "string") {
newChildren = toTitleCase(children); newChildren = toTitleCase(children);
} }
return ( return (
<Comp <Comp className={"relative"} ref={ref} {...props}>
className={cn(buttonVariants({ variant, size, className }))} <div
ref={ref} className={cn(
children={newChildren} loading ? "opacity-100" : "opacity-0",
{...props} "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"; Button.displayName = "Button";