shadimage
avertra-ui
uibuttonsource: ok · hit

Button

A reusable button component.

npx shadcn add "https://micomponents.micustomer.io/r/button.json"
free

No selection tags yet — empty means no evidence, not lack of support.

Files1 · source cached 10/9/2026, 11:05:30 PM

src/components/ui/button.tsx
import * as React from "react";
import { Slot } from "@radix-ui/react-slot";
import { cva, type VariantProps } from "class-variance-authority";

import { cn } from "@/stories/lib/utils";

const buttonVariants = cva(
  "p-3 rounded-sm inline-flex items-center justify-center gap-2 whitespace-nowrap text-sm font-medium transition-all disabled:pointer-events-none disabled:bg-[#F3F4F5] disabled:text-[#A6ADB5] disabled:border-0 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive rounded-sm w-full sm:w-auto",
  {
    variants: {
      variant: {
        primary:
          "bg-primary text-primary-foreground hover:bg-primary/90 focus:outline-3 focus:outline-offset-0 focus:outline-secondary",
        secondary:
          "bg-secondary text-secondary-foreground hover:bg-secondary/90 focus:outline-3 focus:outline-offset-0 focus:outline-primary",
        tertiary:
          "bg-tertiary text-tertiary-foreground hover:bg-tertiary/90 focus:outline-3 focus:outline-offset-0 focus:outline-secondary",
        accent1:
          "bg-accent1 text-accent1-foreground hover:bg-accent1/90 focus:outline-3 focus:outline-offset-0 focus:outline-secondary",
        accent2:
          "bg-accent2 text-accent2-foreground hover:bg-accent2/90 focus:outline-3 focus:outline-offset-0 focus:outline-secondary",
        success:
          "bg-success text-success-foreground hover:bg-success/90 focus:outline-3 focus:outline-offset-0 focus:outline-secondary",
        warning:
          "bg-warning text-warning-foreground hover:bg-warning/90 focus:outline-3 focus:outline-offset-0 focus:outline-secondary",
        error:
          "bg-error text-error-foreground hover:bg-error/90 focus:outline-3 focus:outline-offset-0 focus:outline-secondary",
        white:
          "bg-white text-black hover:bg-gray-200 focus:outline-3 focus:outline-offset-0 focus:outline-secondary",
        black:
          "bg-black text-white hover:bg-gray-900 focus:outline-3 focus:outline-offset-0 focus:outline-secondary",
      },
      size: {
        micro: "h-6",
        xs: "h-7 ",
        sm: "h-9 ",
        md: "h-11 ",
        lg: "h-12 ",
        xl: "h-14 ",
      },
      stylebtn: {
        filled: "",
        outlined: "bg-transparent border bg-transparent hover:bg-transparent",
        text: "bg-transparent border-0 hover:underline hover:bg-transparent",
      },
    },
    compoundVariants: [
      {
        stylebtn: "outlined",
        variant: "primary",
        className:
          "text-primary border-primary hover:border-primary/80 hover:text-primary/80",
      },
      {
        stylebtn: "outlined",
        variant: "secondary",
        className:
          "text-secondary border-secondary hover:border-secondary/80 hover:text-secondary/80",
      },
      {
        stylebtn: "outlined",
        variant: "tertiary",
        className:
          "text-tertiary border-tertiary hover:border-tertiary/80 hover:text-tertiary/80",
      },
      {
        stylebtn: "outlined",
        variant: "accent1",
        className:
          "text-accent1 border-accent1 hover:border-accent1/80 hover:text-accent1/80",
      },
      {
        stylebtn: "outlined",
        variant: "accent2",
        className:
          "text-accent2 border-accent2 hover:border-accent2/80 hover:text-accent2/80",
      },
      {
        stylebtn: "outlined",
        variant: "success",
        className:
          "text-success border-success hover:border--success/80 hover:text-success/80",
      },
      {
        stylebtn: "outlined",
        variant: "warning",
        className:
          "text-warning border-warning hover:border-warning/80 hover:text-warning/80",
      },
      {
        stylebtn: "outlined",
        variant: "error",
        className:
          "text-error border-error hover:border-error/80 hover:text-error/80",
      },
      {
        stylebtn: "outlined",
        variant: "white",
        className:
          "text-white border-white hover:border-gray-200/80 hover:text-gray-200/80",
      },
      {
        stylebtn: "outlined",
        variant: "black",
        className:
          "text-black border-black hover:border-gray-900/50 hover:text-gray-900/50",
      },
      {
        stylebtn: "text",
        variant: "primary",
        className: "text-primary hover:text-primary/80 ",
      },
      {
        stylebtn: "text",
        variant: "secondary",
        className: "text-secondary hover:text-secondary/80",
      },
      {
        stylebtn: "text",
        variant: "tertiary",
        className: "text-tertiary hover:text-tertiary/80",
      },
      {
        stylebtn: "text",
        variant: "accent1",
        className: "text-accent1 hover:text-accent1/80",
      },
      {
        stylebtn: "text",
        variant: "accent2",
        className: "text-accent2 hover:text-accent2/80",
      },
      {
        stylebtn: "text",
        variant: "success",
        className: "text-success hover:text-success/80",
      },
      {
        stylebtn: "text",
        variant: "warning",
        className: "text-warning hover:text-warning/80",
      },
      {
        stylebtn: "text",
        variant: "error",
        className: "text-error hover:text-error/80",
      },
      {
        stylebtn: "text",
        variant: "white",
        className: "text-white hover:text-gray-200/80",
      },
      {
        stylebtn: "text",
        variant: "black",
        className: "text-black hover:text-gray-900/50",
      },
    ],
    defaultVariants: {
      variant: "primary",
      size: "md",
      stylebtn: "filled",
    },
  },
);

interface ButtonProps
  extends
    React.ButtonHTMLAttributes<HTMLButtonElement>,
    VariantProps<typeof buttonVariants> {
  asChild?: boolean;
  iconBefore?: React.ReactNode;
  iconAfter?: React.ReactNode;
  label?: string;
}

const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
  (
    {
      className,
      variant,
      size,
      stylebtn,
      asChild = false,
      iconBefore,
      iconAfter,
      children,
      label,
      ...props
    },
    ref,
  ) => {
    const Comp = asChild ? Slot : "button";

    return (
      <Comp
        ref={ref}
        data-slot="button"
        className={cn(buttonVariants({ stylebtn, size, variant, className }))}
        {...props}
      >
        {iconBefore && <span className="flex items-center">{iconBefore}</span>}
        {children}
        {label}
        {iconAfter && <span className="flex items-center">{iconAfter}</span>}
      </Comp>
    );
  },
);

Button.displayName = "Button";

export { Button, buttonVariants };

More from avertra-ui

Browse all components in this library →