SPB Git forge

spb/fetcha

Public
11commits 1branches 0releases
1.5 MBsize
maindefault branch
16 days agolast push
TypeScript 97.5% SQL 1.4% Python 0.8%
2.3 KB · 57 lines tsx
Raw Blame History
1import * as React from "react";2import { Slot } from "@radix-ui/react-slot";3import { cva, type VariantProps } from "class-variance-authority";4import { Loader2 } from "lucide-react";5import { cn } from "@/lib/utils";67const buttonVariants = cva(8  "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-[background-color,border-color,color,box-shadow,transform] duration-150 select-none disabled:pointer-events-none disabled:opacity-50 active:translate-y-px [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",9  {10    variants: {11      variant: {12        default: "bg-fg text-bg hover:bg-fg/90 shadow-xs",13        primary: "bg-accent text-accent-fg hover:brightness-110 shadow-xs",14        secondary: "bg-bg-muted text-fg hover:bg-border",15        outline: "border border-border bg-bg hover:bg-bg-subtle text-fg shadow-xs",16        ghost: "hover:bg-bg-muted text-fg-muted hover:text-fg",17        danger: "bg-danger text-white hover:brightness-110 shadow-xs",18        link: "text-accent underline-offset-4 hover:underline h-auto p-0",19      },20      size: {21        default: "h-9 px-3.5",22        sm: "h-8 px-3 text-[13px] rounded-md",23        xs: "h-7 px-2.5 text-xs rounded-sm",24        lg: "h-10 px-5 text-[15px] rounded-lg",25        icon: "size-9",26        "icon-sm": "size-8",27      },28    },29    defaultVariants: { variant: "default", size: "default" },30  },31);3233export interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement>, VariantProps<typeof buttonVariants> {34  asChild?: boolean;35  loading?: boolean;36}3738export const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(({ className, variant, size, asChild = false, loading, children, disabled, ...props }, ref) => {39  if (asChild) {40    // Slot requires exactly one child element; the loader is not rendered in asChild mode.41    return (42      <Slot className={cn(buttonVariants({ variant, size, className }))} ref={ref} {...props}>43        {children}44      </Slot>45    );46  }47  return (48    <button className={cn(buttonVariants({ variant, size, className }))} ref={ref} disabled={disabled || loading} {...props}>49      {loading ? <Loader2 className="animate-spin" aria-hidden /> : null}50      {children}51    </button>52  );53});54Button.displayName = "Button";5556export { buttonVariants };57